Как остановить Xcode 11 от изменения CFBundleVersion и CFBundleShortVersionString в $ (CURRENT_PROJECT_VERSION) и $ (MARKETING_VERSION)?

14

Начиная с версии 11, XCode устанавливает мое CFBundleVersionзначение в значение $(CURRENT_PROJECT_VERSION)и мое CFBundleShortVersionStringв значение $(MARKETING_VERSION)всякий раз, когда я ввожу значения версии или сборки в целевых настройках (вкладка «Общие»).

Фактическая версия и значения сборки, которые я ввожу, теперь хранятся в файле project.pbxproj. Я не хочу или не люблю это поведение, так как я использую сценарии оболочки для изменения значений во время сборки.

Я могу вручную установить правильные значения в файле Info.plist, но как только я изменяю номера версий или сборок в целевых настройках, файл Info.plist снова изменяется Xcode.

Как мне остановить Xcode 11 от этого?

Когда я изменяю свой скрипт сборки для изменения самого файла проекта, Xcode немедленно отменяет сборку, как только файл проекта изменяется.

Мистер Зистем
источник
Почему вы хотите, чтобы Xcode 11 прекратил это делать, вместо того, чтобы модифицировать скрипт оболочки для получения значения?
Мануэль
1
@Manuel Я думаю, что изменение plist с помощью plistbuddy- это хорошо и чисто, в то время как изменение файла проекта гораздо более грязное, ненадежное и подвержено непредвиденным изменениям в формате файла.
Мистер Зистем
1
Манипулирование файлом project.pbxproj не является беспорядочным, когда вы понимаете формат файла. Это просто список следующего стиля, который хорошо документирован. Вы даже можете изменить файл с помощью plistbuddy, он совместим с этим форматом.
Мануэль
Я обновил свой ответ предложением для вашего варианта использования.
Мануэль

Ответы:

1

Дорога пока

Мой вариант использования был таким:

  1. Я синхронизирую версию и собираю номера по нескольким целям.
  2. Я синхронизирую версию и номера сборки с целью Settigns.bundle
  3. Я читаю и изменяю номер сборки с CI-сервера.

Раньше я выполнял точки 1 и 2 как целевой сценарий сборки, а точку 3 - как собственный сценарий на самом CI.

Новый способ хранения версии и сборки в настройках сборки Xcode вызывал проблемы со сценариями, потому что они больше не могли эффективно изменять значения. По крайней мере, чтение было возможно.

К сожалению, я не смог найти законный способ запретить Xcode хранить версию и номера сборки в настройках сборки проекта, однако мне удалось создать обходной путь.

Оказывается, что при сборке или архиве используется значение, записанное в Info.plist. Это означает, что значение подставляется во время сборки, что не позволяет нам изменять его в течение того же времени сборки.

Я также пытался изменить проект с помощью xcodeprojcli, однако любые изменения в проекте приводили к остановке любых сборок, поэтому это решение не работало.

В конце концов, после множества различных подходов, которые я попробовал, мне наконец удалось найти компромисс, который не нарушал бы новое поведение 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

Строки сценария делают следующее:

  1. Перейдите в каталог, где находится скрипт синхронизации, чтобы выполнить его
  2. Позволяет записывать журнал во время предварительного действия, иначе любой вывод по умолчанию отключается
  3. Выполните сценарий синхронизации, предоставив 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, которое должно иметь ту же версию и сборку, что и цель, в которую оно встроено. Так что я тоже обновляю это.

KoCMoHaBTa
источник
1

Не.

Предположительно, есть причина, по которой это поведение изменилось. Если более поздние функции XCode основываются на этом поведении, все становится все более и более «сконструированным» в дальнейшем.

Вместо того, чтобы пытаться согнуть XCode, измените, как сценарий сборки получает эти значения:

Как прочитать текущую версию приложения в Xcode 11 с помощью скрипта

Если вам нужно манипулировать project.pbxprojфайлом, это список требований следующего стиля, который хорошо документирован. Вы можете использовать plistbuddyкоторый совместим с этим старым форматом. Вы также можете использовать awkс большим количеством сценариев, если у вас есть более сложные манипуляции.

Если я понимаю ваш вариант использования, вы можете написать сценарий, который получает самые высокие номера версий, awkа затем обновляет все более низкие номера версий, которые он может найти в файле sed.

Manuel
источник
печать значений с, PlistBuddy кажется, работает нормально, но когда я использую setкоманду, весь project.pbxproj преобразуется в файл XML .plist и больше не может быть прочитан Xcode. пример:PlistBuddy -c "Set :objects:$configurationId:buildSettings:CURRENT_PROJECT_VERSION $newProjectVersion" "$projectFile"
г-н Zystem
В зависимости от того, чего именно вы хотите достичь, вам, возможно, придется использовать комбинацию инструментов
Мануэль
Перезапуск Xcode устранил проблему с XML. Алс обнаружил, что при запуске сценария сборки, который изменяет pbxprojфайл, сборка отменяется. Боюсь, это не сработает.
г-н Zystem
Я обновил свой оригинальный вопрос с помощью вышеуказанной информации.
г-н Зистем
1
Например, мой вариант использования заключается в синхронизации версии и построении по нескольким целям - я хотел бы установить версию и сборку для первой цели, которая автоматически обновляется для всех остальных. Раньше это работало хорошо, потому что вы просто модифицировали ресурс. Теперь я не могу изменить проект на этапе сборки любой цели, потому что сборка отменяется.
KoCMoHaBTa