25 июня 2026 года Apple опубликовала запись о выпуске Xcode 26.6; границу между стабильной версией и предварительными сборками нужно проверять по официальной странице релизов Apple. Если после обновления появляется сбой разрешения Swift Package Manager в Xcode 26.6, не начинайте с удаления всех кэшей. Сначала зафиксируйте Xcode, Package.resolved и команду разрешения, затем раздельно проверьте граф версий, доступ к Git и состояние кэша.
Симптом → самый быстрый путь: пакет не разрешается — сравните первую ошибку в Xcode и xcodebuild; локальная сборка проходит, а удалённый Mac ломается — проверьте пользователя задачи, SSH, Git и рабочий каталог; разрешение прошло, но продукт отсутствует — исследуйте граф и Package Product, а не сеть.
Последняя проверка актуальности выполнена 23 августа 2026 года по примечаниям к выпуску Xcode 26.6, документации Apple по CI и материалам Swift Package Manager. Xcode 27 в этом тексте не рассматривается как стабильная замена: на указанную дату он относится к предварительным версиям.
Эта статья предназначена для вас, если после перехода на Xcode 26.6 появились ошибки разрешения пакетов, missing package product или неожиданные версии зависимостей. Она также пригодится при работе с закрытыми Swift Package на удалённом Mac и при обслуживании постоянной машины сборки, где нельзя скачивать и обновлять зависимости заново при каждом запуске.
Зафиксируйте диагностическую точку до исправлений
Ошибка «не удалось разрешить пакет» может скрывать несколько разных состояний. Репозиторий может быть недоступен. Версия может нарушать ограничение. Разрешение может пройти, но продукт не подключится к цели. Наконец, пакет может разрешиться, а компиляция или Archive завершатся уже по другой причине.
Поэтому до очистки и изменения проекта сохраните:
- версию Xcode, которой реально выполняется команда;
- активный путь к каталогу разработчика;
- имя проекта или рабочей области;
- схему и конфигурацию сборки;
- коммит исходного репозитория;
- содержимое
Package.resolvedбез секретов; - первую содержательную строку ошибки;
- способ запуска: интерфейс Xcode, локальный Shell или CI-задача.
Проверяйте не только установленный Xcode, но и тот, который выбран процессом:
xcodebuild -version
xcode-select -p
xcodebuild -list -project "<PROJECT>.xcodeproj"
xcodebuild -list -workspace "<WORKSPACE>.xcworkspace"
Названия проекта, пути и рабочей области здесь и далее являются placeholders. Не подставляйте в журналы реальные токены, имена пользователей, адреса частных репозиториев или содержимое SSH-ключей.
Затем повторите разрешение отдельно от сборки. Для проекта используйте явный параметр:
xcodebuild \
-resolvePackageDependencies \
-project "<PROJECT>.xcodeproj" \
-scheme "<SCHEME>"
Для рабочей области:
xcodebuild \
-resolvePackageDependencies \
-workspace "<WORKSPACE>.xcworkspace" \
-scheme "<SCHEME>"
Точные параметры зависят от структуры проекта. В документации Apple по сборке Swift Package и приложений в CI приведён официальный контекст для автоматизированного запуска. Сопоставляйте не весь шум журнала, а первую ошибку, после которой граф уже не может быть построен.
Сравните два независимых результата
Запустите разрешение через Xcode и через xcodebuild, не меняя коммит между попытками.
- Оба способа падают одинаково — ищите ограничение версии, повреждённую запись или доступ к репозиторию.
- Xcode проходит, а Shell падает — проверяйте активный Xcode, переменные среды, пользователя и каталог запуска.
xcodebuildпроходит, а интерфейс показывает ошибку — проверяйте рабочую область, схему и состояние проекта.- Разрешение проходит в обоих случаях, но сборка не проходит — это уже не обязательно ошибка Swift Package Manager.
Сохраните обезличенные журналы до исправления и после него. Так вы получите сравнимую базовую линию, а не субъективное «после очистки вроде заработало».
Проверьте граф версий и Package.resolved
Package.swift задаёт зависимости и ограничения. Проект или рабочая область подключает их к целям. Package.resolved фиксирует выбранный граф для приложения. Эти файлы должны описывать совместимую систему, а не три независимых списка.
Проверьте:
- присутствует ли
Package.resolvedтам, где его ожидает приложение; - соответствует ли файл текущему коммиту;
- не осталось ли конфликтных маркеров после слияния веток;
- нет ли повторяющейся записи одного пакета с несовместимыми состояниями;
- укладывается ли зафиксированная версия в ограничения
Package.swift; - не запускает ли скрипт автоматическое обновление перед сборкой.
Документация Apple по ограничениям версий зависимостей и руководство Swift Package Manager по разрешению версий полезны именно здесь: они помогают отделить допустимый граф от ошибки доступа.
Для приложения зафиксированный Package.resolved обычно имеет смысл хранить в Git. Это делает результат CI проверяемым: одна и та же ревизия проекта получает один и тот же набор выбранных версий, пока вы намеренно не изменили файл. Для библиотеки граница иная. Библиотека должна объявлять ограничения, а приложение-потребитель разрешает собственный граф. Не переносите правило приложения на каждый пакет без проверки процесса публикации.
Особенно внимательно проверяйте ветки. Типичный сбой выглядит так: ветка разработки обновила зависимость, затем частичное слияние вернуло старый Package.swift, но оставило новый Package.resolved. Обратная ситуация тоже возможна. В обоих случаях удаление кэша не исправит противоречие в репозитории.
Внимание:
Package.resolvedне является заменой проверки коммита. В журнале фиксируйте ревизию исходников и хэш или содержимое файла после удаления секретных URL и токенов.
Отделите доступ к репозиторию от ошибки разрешения
Открытый пакет и закрытый пакет ломаются по разным причинам. Для каждого URL проверяйте цепочку отдельно:
- корректен ли Git URL;
- разрешается ли DNS-имя;
- доступен ли прокси;
- устанавливается ли SSH-соединение;
- принят ли отпечаток узла;
- загружен ли ключ в агент;
- имеет ли пользователь право читать конкретный репозиторий.
Не вставляйте секреты в команды и отчёты. Используйте формы вроде <PRIVATE_GIT_URL>, <SSH_HOST>, <CI_USER> и <TOKEN_REDACTED>.
Пример безопасной проверки соединения:
git ls-remote "<PRIVATE_GIT_URL>"
ssh -T "git@<SSH_HOST>"
Эти команды показывают состояние доступа, но не доказывают, что Xcode запустит их с теми же настройками. Процесс сборки может идти от другого пользователя, в другом домашнем каталоге и с другим SSH_AUTH_SOCK. На удалённом Mac это одна из самых частых причин расхождения с локальной машиной.
Сравните:
whoami
printf '%s\n' "$HOME"
printf '%s\n' "$SSH_AUTH_SOCK"
git config --show-origin --list
Не считайте вывод этих команд публичным логом. В нём могут присутствовать адреса, пути и имена учётных записей. В CI сохраняйте только обезличенные признаки: пользователь совпадает или нет, конфигурация найдена или нет, ключ доступен или нет.
Также учитывайте различие между Git, вызываемым инструментами Apple, и системной командой Git. Если git ls-remote проходит в интерактивном терминале, это ещё не подтверждает доступ из xcodebuild. Запустите диагностику тем же пользователем и из того же рабочего каталога, что и автоматическую задачу.
Решите, какой слой кэша действительно повреждён
Слово «кэш» объединяет несколько разных объектов. Их нельзя бездумно удалять одним скриптом.
| Слой | Что он хранит | На какой симптом указывает | Риск очистки |
|---|---|---|---|
| Кэш репозиториев Swift Package | Загруженные сведения и копии репозиториев | Повторяющаяся ошибка загрузки или устаревший источник | Повторное скачивание и нагрузка на сеть |
| Каталог checkout зависимостей | Рабочие исходники выбранных ревизий | Несовпадение ревизии или неполный checkout | Повторная проверка и загрузка пакета |
DerivedData |
Промежуточные результаты проекта | Ошибки старых продуктов, модулей или индексации | Полная повторная подготовка сборки |
| Архивы и продукты | Результаты предыдущих сборок | Не относится напрямую к разрешению | Потеря локальных артефактов |
Сначала сравните существующий запуск с холодным запуском в отдельном рабочем каталоге. Если холодный запуск падает на соединении, причина вероятнее связана с доступом. Если старый кэш падает, а чистый граф разрешается, исследуйте конкретный слой и восстановите только его.
Не удаляйте сертификаты, профили подписи, связки ключей и каталог с архивами вместе с кэшем. Они относятся к другой части процесса. Сброс Package Cache не должен превращаться в потерю материалов для подписи приложения.
После каждой операции записывайте изменение:
- какой слой затронут;
- какой коммит и
Package.resolvedиспользованы; - изменилась ли первая ошибка;
- сколько пакетов пришлось получить заново;
- проходит ли повторный запуск после перезапуска Mac.
Если сообщение осталось абсолютно тем же, очистка не дала диагностической ценности. Переходите к графу или доступу.
Проверьте Package Product и бинарные зависимости после разрешения
Успешное разрешение не означает успешное подключение продукта к цели. Разделяйте четыре состояния:
- зависимости разрешены;
- исходники пакетов извлечены;
- граф продуктов построен;
- нужный
Package Productсвязан с target и компилируется.
Сообщение о пропавшем продукте может быть связано с неправильным именем продукта, изменением манифеста, локальным переопределением пакета или конкретной схемой. Если ошибка появляется только в одной ветке или одной схеме, создайте минимальный проект с той же зависимостью. Это быстрее, чем повторять очистку всей машины.
Для бинарных пакетов проверьте контрольную сумму и доступность артефакта. Apple отдельно описывает идентификацию бинарных зависимостей в Xcode. Если архив недоступен или его контрольная сумма не совпадает, проблема находится после выбора версии, но до нормальной линковки.
Полезная последовательность проверки:
xcodebuild \
-resolvePackageDependencies \
-workspace "<WORKSPACE>.xcworkspace" \
-scheme "<SCHEME>"
xcodebuild \
-workspace "<WORKSPACE>.xcworkspace" \
-scheme "<SCHEME>" \
-configuration Release \
build
xcodebuild \
-workspace "<WORKSPACE>.xcworkspace" \
-scheme "<SCHEME>" \
-configuration Release \
archive \
-archivePath "<ARCHIVE_PATH>"
Не называйте результат «исправленным», пока не проверены обычная сборка и Archive. Последняя команда может выявить отличия подписи, схемы, окружения или продукта, которых не было на этапе разрешения.
Выберите следующий шаг по диагностическим условиям
Используйте условия, а не универсальный скрипт очистки:
- Если один и тот же коммит и
Package.resolvedпадают и в Xcode, и вxcodebuild, то сначала исправляйте граф версий или доступ к репозиторию. - Если локальный запуск проходит, а задача на удалённом Mac падает, то сравните пользователя,
HOME,SSH_AUTH_SOCK, Git-конфигурацию и рабочий каталог. - Если после холодного запуска появляется другая ошибка, то восстанавливайте только затронутый слой кэша и повторяйте проверку.
- Если разрешение проходит, но отсутствует продукт, то анализируйте манифест, target, схему и бинарную зависимость.
- Если один проект нестабилен, а минимальный проект проходит, то ищите ошибку в структуре рабочей области или локальном переопределении.
- Если тот же проект не восстанавливается в чистой среде, то готовьте миграцию окружения; не тратьте время на бесконечную очистку.
- Если локальный и удалённый Mac дают одинаковый результат после перезапуска, то среду можно принимать для постоянной сборки.
Проведите приёмку удалённого Mac как воспроизводимой среды
Удалённый Mac полезен не потому, что одна команда однажды завершилась успешно. Его ценность — в повторяемости. На странице MACCOME вы можете рассматривать удалённую машину именно как среду проверки: сначала воспроизведите проблему, затем зафиксируйте рабочий вариант.
Проведите приёмку в пять проходов:
- Получите один и тот же коммит приложения и тот же
Package.resolved. - Запустите разрешение через явный
xcodebuildот пользователя автоматической задачи. - Выполните обычную сборку с той же схемой и конфигурацией.
- Создайте Archive, не меняя исходники и граф зависимостей.
- Очистите рабочий каталог, перезапустите хост и повторите получение репозитория и три команды.
Дополнительно проверьте, что закрытые репозитории доступны без интерактивного ввода. Если задача ожидает пароль, подтверждение отпечатка или локальное окно Xcode, это не автоматическая сборка, а ручной запуск, замаскированный под CI.
Сохраните обезличенный отчёт: версия Xcode, активный путь инструментов, пользователь, коммит, состояние Package.resolved, тип пакетов, первая ошибка и результат после перезапуска. Не добавляйте в него реальные адреса репозиториев и ключи. Для небольшого проекта такой отчёт часто ценнее длинного журнала на несколько тысяч строк.
Если вам нужно закрепить постоянную машину для iOS-сборки, сначала протестируйте её на реальном проекте и Archive. Страница заказа Mac mini для удалённой работы подходит для следующего шага только после проверки доступа к вашим зависимостям и процесса подписи.
Почему текущая схема иногда проигрывает удалённому Mac
Если проблема возникает на личном Mac, который используется одновременно для разработки, тестов и автоматической сборки, у вас появляются три постоянных недостатка: состояние рабочего окружения меняется вручную, кэш зависит от конкретного пользователя, а очистка или обновление Xcode может остановить публикацию. На Windows или Linux к этому добавляется отсутствие нативного Xcode и необходимость передавать финальный этап другому окружению.
Если отдельный Mac покупается только как сборочная машина, деньги и обслуживание привязаны к оборудованию, которое может простаивать между релизами. Удалённая машина не устраняет ошибки графа или доступа к Git, но даёт контролируемую macOS-среду, которую можно проверять после перезапуска и использовать для временного проекта или постоянного CI. Поэтому аренда Mac в MACCOME разумна, когда вам нужны удалённый Mac, root-доступ и заранее проверяемый цикл resolve → build → archive, но не оправдана для длительной тяжёлой нагрузки, физических подключений или полностью автономной локальной лаборатории.
Начните с диагностики на вашем коммите. Если среда проходит повторную проверку, её можно оставить как резервный или постоянный сервер сборки; если нет — сначала исправьте доступ и зависимости, а не переносите нестабильность на другую машину.
Частые вопросы
Что проверить, если Xcode не может разрешить зависимости Swift Package?
Сначала зафиксируйте версию Xcode, активный путь к инструментам, проект или рабочую область и первую содержательную ошибку. Затем отдельно повторите разрешение через интерфейс Xcode и через xcodebuild. После этого проверьте Package.resolved, URL репозиториев, DNS, SSH или токен, а уже затем — состояние кэша. Полное удаление кэшей не должно быть первым действием.
Нужно ли хранить Package.resolved в репозитории?
Для приложения, которое должно собираться одинаково на рабочих станциях и в CI, зафиксированный Package.resolved обычно следует хранить в Git и проверять при изменениях зависимостей. Для библиотеки политика иная: файл может не быть частью публикуемой зависимости, поскольку потребитель разрешает собственный граф. Решение зависит от типа проекта и принятого процесса ревью.
Почему локальная сборка проходит, а удалённый Mac не разрешает зависимость?
На машинах часто различаются пользователь процесса, активный Xcode, рабочий каталог и настройки Git или SSH. Локальная сессия может видеть загруженный ключ, известный отпечаток узла или уже заполненный кэш, тогда как автоматическая задача запускается без них. Сравните переменные среды, путь к Xcode, права на каталог и доступ к каждому закрытому репозиторию.
Как зафиксировать версии Swift Package через xcodebuild?
Сначала зафиксируйте граф в Package.resolved и передайте xcodebuild тот же проект или рабочую область из того же коммита. Для диагностики используйте отдельную команду разрешения зависимостей с явным -project или -workspace, затем обычную сборку и Archive. Не добавляйте автоматическое обновление пакетов в каждый запуск CI: обновление должно быть отдельным контролируемым изменением.
Что делать, если после сброса Package Cache ошибка остаётся?
Считайте это признаком того, что причина может находиться не в кэше. Проверьте доступ к репозиторию, ограничения версий, конфликт записей Package.resolved, локальные пакеты, бинарные зависимости и привязку Package Product. Сравните холодный и обычный запуск, сохранив журналы. Если ошибка повторяется в чистом рабочем каталоге на том же коммите, исследуйте проект или серверную конфигурацию.