Дорога пока
Мой вариант использования был таким:
- Я синхронизирую версию и собираю номера по нескольким целям.
- Я синхронизирую версию и номера сборки с целью
Settigns.bundle
- Я читаю и изменяю номер сборки с CI-сервера.
Раньше я выполнял точки 1 и 2 как целевой сценарий сборки, а точку 3 - как собственный сценарий на самом CI.
Новый способ хранения версии и сборки в настройках сборки Xcode вызывал проблемы со сценариями, потому что они больше не могли эффективно изменять значения. По крайней мере, чтение было возможно.
К сожалению, я не смог найти законный способ запретить Xcode хранить версию и номера сборки в настройках сборки проекта, однако мне удалось создать обходной путь.
Оказывается, что при сборке или архиве используется значение, записанное в Info.plist
. Это означает, что значение подставляется во время сборки, что не позволяет нам изменять его в течение того же времени сборки.
Я также пытался изменить проект с помощью xcodeproj
cli, однако любые изменения в проекте приводили к остановке любых сборок, поэтому это решение не работало.
В конце концов, после множества различных подходов, которые я попробовал, мне наконец удалось найти компромисс, который не нарушал бы новое поведение XCode.
Короткий ответ:
В качестве мишени предварительного действия, скрипт выполняется , который записывает соответствующие значения CFBundleShortVersionString
и CFBundleVersion
к цели наInfo.plist
В качестве источника правды я использую настройки сборки XCode, чтобы прочитать значения MARKETING_VERSION
и CURRENT_PROJECT_VERSION
желаемой цели.
Таким образом, когда вы изменяете значения из настроек проекта - при следующей сборке / архиве - они будут записаны в Info.plist
, что позволит продолжить работу любой существующей логики сценариев.
Подробный ответ
Единственный способ изменить ресурс при выполнении действия сборки - использовать pre-action
скрипт. Если вы попытаетесь сделать это из скрипта сборки - изменения не вступят в силу немедленно и не будут присутствовать в конце сборки / архива.
Чтобы добавить действие перед сборкой - перейдите к редактированию схемы.
Затем разверните разделы «Сборка» и «Архив». Под Pre-action
, щелкните Provide build and settings from
раскрывающийся список и выберите источник истинной цели, из которого вы хотите прочитать значения.
Добавьте следующий скрипт:
# 1)
cd ${PROJECT_DIR}
# 2)
exec > Pruvit-Int.prebuild.sync_project_version_and_build_with_info_plists.log 2>&1
# 3)
./sync_project_version_and_build_with_info_plists.sh $MARKETING_VERSION $CURRENT_PROJECT_VERSION
Строки сценария делают следующее:
- Перейдите в каталог, где находится скрипт синхронизации, чтобы выполнить его
- Позволяет записывать журнал во время предварительного действия, иначе любой вывод по умолчанию отключается
- Выполните сценарий синхронизации, предоставив
MARKETING_VERSION
иCURRENT_PROJECT_VERSION
Последний шаг заключается в написании собственного сценария синхронизации, который считывает значения предоставленных MARKETING_VERSION
и CURRENT_PROJECT_VERSION
соответствующих целей / целей и в любое другое время.
В моем случае скрипт выглядит следующим образом:
#!/bin/bash
#IMPORTANT - this script must run as pre-action of each target's Build and Archive actions
version_number=$1
build_number=$2
echo "version_number is $version_number"
echo "build_number is $build_number"
#update Pruvit/Info.plist
pruvitInfoPlist="Pruvit/Info.plist"
/usr/libexec/PlistBuddy -c "Set CFBundleShortVersionString $version_number" $pruvitInfoPlist
/usr/libexec/PlistBuddy -c "Set CFBundleVersion $build_number" $pruvitInfoPlist
#update Pruvit/Settings.bundle
settingsPlist="Pruvit/Settings.bundle/Root.plist"
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:0:DefaultValue $version_number" $settingsPlist
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:1:DefaultValue $build_number" $settingsPlist
#update BadgeCounter/Info.plist
badgeCounterInfoPlist="BadgeCounter/Info.plist"
/usr/libexec/PlistBuddy -c "Set CFBundleShortVersionString $version_number" $badgeCounterInfoPlist
/usr/libexec/PlistBuddy -c "Set CFBundleVersion $build_number" $badgeCounterInfoPlist
Я использую общий доступ Info.plist
и Settings.bundle
между обоими целями приложения, поэтому мне нужно обновить его один раз.
Также я использую расширение службы уведомлений BadgeCounter
, которое должно иметь ту же версию и сборку, что и цель, в которую оно встроено. Так что я тоже обновляю это.