Типичный поисковый запрос звучит как «vcpkg binary cache или зеркало при трансграничном CI на Mac» или «FetchContent офлайн после префетча». Здесь мы не повторяем гайды по Git/npm/Docker: фокус — связка C++‑манифест vcpkg и внешние CMake-проекты через FetchContent на удалённом Apple Silicon CI, где узкое место чаще в egress, TLS и APFS IO, а не в компиляторе. Ниже — матрица прямой / зеркало / собственный binary cache, исполняемые команды, пошаговый чеклист и приёмка lockfile. Внутренние точки входа без авторизации: главная, список блога, материал про SSH-реле и стабильность канала — если нужно сначала выровнять маршрут до раннера.
Шаблоны meta title / description (подставьте сегменты в фигурных скобках)

Meta title (шаблон, ≤60–65 символов):

{Год} Mac CI: vcpkg + FetchContent — {binary cache|lockfile|трансграничный pull} | MacPull

Meta description (шаблон, 140–160 символов):

Матрица: прямой канал / зеркало / свой binary cache для vcpkg на удалённом Mac. {VCPKG_BINARY_SOURCES|X_VCPKG_ASSET_SOURCES}. FetchContent: {FULLY_DISCONNECTED|TLS}. Чеклист lockfile и параллельных job.

Три типовых узких места перед матрицей сборки

Симптомы смешивают сеть, диск и lockfile; без классификации бессмысленно крутить параллелизм vcpkg install. На трансграничном канале полезно заранее отделить ошибку TLS/прокси от истощения диска: первое лечится доверенным CA и корректным CMAKE_TLS_VERIFY, второе — выносом buildtrees и каталогов FetchContent на быстрый том и лимитом одновременных job (см. FAQ пула и диска).

Если в репозитории уже есть vcpkg.json с baseline, а FetchContent тянет те же библиотеки по плавающей ветке, вы получите «зелёный» прогон на закешированном агенте и красный на чистом — это не сеть, а дрейф версий. Такой класс проблем удобно ловить на арендованном удалённом Mac с тем же egress, что у продакшн-раннера, до масштабирования матрицы.

  • Долгий asset-cache и обрывы tarball: трансграничный RTT бьёт по X_VCPKG_ASSET_SOURCES и зеркалам портов; поднимайте таймауты загрузчика и повторяйте только шаг зависимостей.
  • Несколько job в один каталог buildtrees: гонки при распаковке портов и временных файлах FetchContent; выделяйте префикс на пайплайн или сериализуйте префетч.
  • Расхождение тегов Git в FetchContent и baseline в vcpkg.json: configure проходит, а воспроизводимость ломается на чистом агенте; лечится явной приёмкой lockfile до матрицы.

Матрица решений: прямой канал, зеркало и собственный binary cache

Режим Когда выбирать Плюсы / минусы Риски для lockfile
Прямой доступ к реестрам портов и GitHub/GitLab Низкая политика egress, доверенный регион раннера Простая отладка; чувствительность к флапам маршрута Меньше, если закреплён baseline и теги
Зеркало (asset mirror, прокси артефактов) Длинный RTT, квоты на исходящий канал Стабильнее скорость; нужна проверка целостности и доверие к origin зеркала Смена базового URL требует нового ключа кеша
Собственный binary cache (NuGet/az/blob/S3-совместимый backend) Повторяющиеся triplet и тяжёлые порты Повторные job почти без компиляции; нужна дисциплина версий ABI и ключей Сверяйте хеш коммита vcpkg и список overlay-портов

Параллелизм: на одном томе с VCPKG_ROOT лимитируют и CPU, и IO-wait; пороги — в FAQ пула сборок.

Ключ восстановления кеша в оркестраторе (GitHub Actions, GitLab, TeamCity и т.д.) должен включать как минимум: triplet, хеш коммита vcpkg или baseline, версию CMake, идентификатор зеркала/asset source и флаг overlay-портов. Иначе после смены зеркала вы получите «тихое» несоответствие ABI между job.

Быстрое решение «на салфетке»: низкий RTT и либеральный egress → прямой канал; длинный RTT и квоты → зеркало + HTTP binary cache read-only; повторяющиеся тяжёлые порты на одном triplet → собственный binary cache с явной политикой записи.

Исполняемые параметры и примеры команд

Закрепите VCPKG_ROOT, triplet и toolchain до CMake. Примеры shell для macOS; пути — под APFS.

# Префетч портов с binary caching (пример: read-only HTTP + запись в локальный каталог) export VCPKG_FEATURE_FLAGS="binarycaching,manifests" export VCPKG_BINARY_SOURCES="clear;default,readwrite" ./vcpkg install --triplet arm64-osx --binarycaching
# CMake: FetchContent и офлайн после префетча cmake -S . -B build \ -DCMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" \ -DFETCHCONTENT_FULLY_DISCONNECTED=ON \ -DFETCHCONTENT_UPDATES_DISCONNECTED=ON \ -DCMAKE_TLS_VERIFY=ON
# Пример: удалённый read-only binary cache + локальная запись (подставьте URL бэкенда) export VCPKG_BINARY_SOURCES='clear;nuget,https://YOUR_CACHE/nuget/v3/index.json,readwrite'
# Закрепление baseline манифеста (перед review зависимостей) ./vcpkg x-update-baseline --add-initial-baseline

Для FetchContent на отладке включайте FETCHCONTENT_QUIET=OFF и отдельный FETCHCONTENT_BASE_DIR на job (например, под $CI_JOB_ID), чтобы не делить распаковку между параллельными воркфлоу. FETCHCONTENT_UPDATES_DISCONNECTED=ON полезен, когда вы хотите запретить «тихие» обновления тегов между стейджами, но ещё не готовы к полному FULLY_DISCONNECTED на первом проходе.

MITM без доверенного корпоративного CA ломает TLS независимо от зеркала: сначала выровняйте доверие, затем оптимизируйте X_VCPKG_ASSET_SOURCES.

Пошаговый чеклист внедрения (≥5 шагов)

  • Шаг 1. Зафиксируйте коммит vcpkg, версию CMake и triplet в README пайплайна; исключите «плавающий» toolchain.
  • Шаг 2. Выберите строку VCPKG_BINARY_SOURCES и при необходимости X_VCPKG_ASSET_SOURCES; прогоните пробный vcpkg install на пустом кеше с логом загрузок.
  • Шаг 3. Настройте отдельный VCPKG_DEFAULT_BINARY_CACHE или удалённый backend; ключ кеша включайте triplet, хост зеркала и хеш baseline.
  • Шаг 4. Для FetchContent выполните префетч, затем включайте FETCHCONTENT_FULLY_DISCONNECTED на «чистых» стейджах; держите синхрон тегов с vcpkg.json.
  • Шаг 5. Включите матрицу параллельных job только после зелёного dry-run cmake --preset с --fresh если политика требует; мониторьте IO wait.
  • Шаг 6. Задокументируйте порог повторов только для стейджа зависимостей с бэкоффом 2/4/8 с, без массового рестарта всего пайплайна.

Приёмка согласованности lockfile и кеша

Минимальный список проверок перед merge
  • vcpkg.json + lock (если используете) совпадают с фактическими версиями портов в логе vcpkg install.
  • Теги/SHA для FetchContent_Declare не новее и не старее записей в манифесте; нет скрытого GIT_TAG main в релизных ветках.
  • Ключ restore кеша CI содержит triplet, версию CMake и идентификатор зеркала; после смены зеркала старые ключи инвалидированы.
  • Пробный прогон с FETCHCONTENT_FULLY_DISCONNECTED=ON зелёный на чистом воркере.

Сопоставьте эту приёмку с подходом к внешним репозиториям в гайде по Bazel: там те же компромиссы между удалённым кешем и локальным диском, но другой стек — удобно для кросс-командного согласования. Для политики «сначала префетч, потом строгий стейдж» без привязки к конкретному пакетному менеджеру см. предзагрузка и согласованность версий в CI.

FAQ: binary cache, FetchContent и повторы

Совместимы ли параллельные job и один binary cache?

Чтение из общего read-only кеша обычно безопасно; избегайте совместной записи в один каталог buildtrees без изоляции. Публикуйте бинарники в удалённый кеш сериализованным шагом.

Когда включать FETCHCONTENT_FULLY_DISCONNECTED?

После успешного префетча всех внешних проектов и при готовности жёстко запретить сеть на configure; до этого держите выключенным и собирайте трассировку URL.

Что делать при расхождении vcpkg baseline и тегов FetchContent?

Обновите baseline осознанно, зафиксируйте diff в ревью и прогоните lockfile-приёмку; не смешивайте ручные override без записи в манифест.

Зачем отдельный удалённый Mac для проверки?

Реальный Apple Silicon и маршрут до зеркала воспроизводят таймауты vcpkg и TLS так же, как у целевых разработчиков; это дешевле, чем ловить флапы только в облачной матрице Linux.

Чем отличаются FETCHCONTENT_UPDATES_DISCONNECTED и FETCHCONTENT_FULLY_DISCONNECTED?

Первый режим подавляет автоматические обновления уже объявленных внешних проектов между переконфигурациями. Второй требует, чтобы все артефакты FetchContent были доступны локально до шага configure. На CI типична цепочка: префетч с сетью → контрольный прогон с FULLY на чистом воркере.

Обязателен ли vcpkg.lock, если есть только vcpkg.json?

Для строгой воспроизводимости в матрице — да, либо эквивалентный механизм фиксации baseline и контрольных сумм портов. Иначе «зелёный» кеш может скрыть обновление порта на стороне registry.

Как безопасно публиковать бинарники в общий binary cache из нескольких веток?

Разносите префиксы по защищённым веткам или используйте сериализованный шаг записи; чтение может быть общим read-only. Не переиспользуйте один и тот же локальный каталог buildtrees без изоляции по job.

Внутренние ссылки и точки входа

Итог: в 2026 году связка vcpkg + CMake FetchContent на удалённом Mac CI держится на трёх опорах — выбранном канале pull (прямой, зеркало или собственный binary cache), дисциплине параллельных job и жёсткой приёмке lockfile до расширения матрицы. Проверьте сценарий на арендованном Apple Silicon-узле с тем же egress, что у команды; без входа доступны главная, тарифы, оформление аренды, центр помощи и каталог блога с родственной матрицей Bazel.

Проверьте трансграничный pull на удалённом Mac до продакшн-матрицы

Аренда узла Mac Mini M4 даёт тот же macOS и APFS, что и у целевого CI: вы заранее видите флапы vcpkg и FetchContent. Откройте главную, сравните пакеты на странице цен, оформите доступ через покупку / аренду; справочные материалы — в центре помощи. Другие CI-матрицы — в блоге, например Bazel и внешние зависимости.

Быстрая выдача
SSH / VNC
Кеш на NVMe