Comment empêcher Xcode 11 de changer CFBundleVersion et CFBundleShortVersionString en $ (CURRENT_PROJECT_VERSION) et $ (MARKETING_VERSION)?

14

Depuis la version 11, Xcode définit ma CFBundleVersionvaleur à $(CURRENT_PROJECT_VERSION)et ma CFBundleShortVersionStringvaleur à $(MARKETING_VERSION)chaque fois que j'entre des valeurs de version ou de build dans les paramètres cibles (onglet "Général").

La version réelle et les valeurs de build que j'entre sont désormais stockées dans le fichier project.pbxproj. Je ne veux pas ou n'aime pas ce comportement, car j'utilise des scripts shell pour modifier les valeurs au moment de la construction.

Je peux définir manuellement les valeurs correctes dans le fichier Info.plist, mais dès que je modifie les numéros de version ou de build dans les paramètres cibles, le fichier Info.plist est à nouveau modifié par Xcode.

Comment puis-je empêcher Xcode 11 de faire cela?

Lorsque je modifie mon script de génération pour modifier le fichier de projet lui-même, Xcode annule immédiatement la génération dès que le fichier de projet est modifié.

M. Zystem
la source
Pourquoi voudriez-vous que Xcode 11 arrête de faire cela, au lieu de modifier votre script shell pour récupérer la valeur?
Manuel
1
@Manuel Je pense que la modification d'un plist en utilisant plistbuddyest agréable et propre, tandis que la modification du fichier de projet est beaucoup plus compliquée, peu fiable et sujette à des changements inattendus dans le format de fichier.
M. Zystem
1
La manipulation du fichier project.pbxproj n'est pas compliquée lorsque vous comprenez le format de fichier. C'est juste une liste de styles Next qui est bien documentée. Vous pouvez même modifier le fichier avec plistbuddy, il est compatible avec ce format.
Manuel
J'ai mis à jour ma réponse avec une suggestion pour votre cas d'utilisation.
Manuel

Réponses:

1

La route jusqu'ici

Mon cas d'utilisation était que:

  1. Je synchronise la version et les numéros de build sur plusieurs cibles.
  2. Je synchronise la version et les numéros de build avec ceux de la cible Settigns.bundle
  3. Je lis et modifie le numéro de build d'un serveur CI.

J'avais l'habitude d'exécuter les points 1 et 2 en tant que script de build cible et le point 3 en tant que script personnalisé sur le CI lui-même.

La nouvelle façon de stocker la version et la génération dans les paramètres de génération Xcode posait des problèmes avec les scripts, car ils n'étaient plus en mesure de modifier efficacement les valeurs. Au moins, la lecture était possible.

Malheureusement, je n'ai pas pu découvrir un moyen légitime d'empêcher Xcode de stocker la version et les numéros de build dans les paramètres de construction du projet, mais j'ai réussi à créer une solution de contournement.

Il s'avère que lorsqu'une construction ou une archive est effectuée, la valeur écrite dans le Info.plistest utilisée. Cela signifie que la valeur est substituée pendant la construction, ce qui ne nous permet pas de la modifier pendant la même construction.

J'ai également essayé de modifier le projet à l'aide de xcodeprojcli, mais toute modification apportée au projet entraînait l'arrêt de toutes les versions, donc cette solution ne fonctionnait pas.

Finalement, après beaucoup d'approches différentes que j'ai essayées, j'ai finalement réussi à trouver un compromis qui ne violait pas le nouveau comportement du Xcode.

Réponse courte:

En tant que pré-action cible, un script est exécuté qui écrit les valeurs respectives dans CFBundleShortVersionStringet CFBundleVersionvers la cibleInfo.plist

Comme source de vérité, j'utilise les paramètres de construction de Xcode pour lire les valeurs de MARKETING_VERSIONet CURRENT_PROJECT_VERSIONde la cible souhaitée.

De cette façon, lorsque vous modifiez les valeurs des paramètres du projet - lors de la prochaine génération / archive - elles seront écrites dans le Info.plist, permettant à toute logique de script existante de continuer à fonctionner.

Réponse détaillée

La seule façon de modifier une ressource lors d'une action de génération est d'utiliser un pre-actionscript. Si vous essayez de le faire à partir d'un script de build - les modifications ne prendront pas effet immédiatement et ne seront pas présentes à la fin de la build / archive.

Pour ajouter une action de pré-construction - allez dans le schéma d'édition.

entrez la description de l'image ici

Développez ensuite les sections Build et Archive. Sous Pre-action, cliquez sur le Provide build and settings frommenu déroulant et sélectionnez la source de cible de vérité à partir de laquelle vous souhaitez lire les valeurs.

entrez la description de l'image ici

Ajoutez le script suivant:

# 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

Les lignes de script font ce qui suit:

  1. Accédez au répertoire où se trouve le script de synchronisation afin de l'exécuter
  2. Permet à un journal d'être écrit pendant la pré-action, sinon toute sortie est désactivée par défaut
  3. Exécutez le script de synchronisation en fournissant le MARKETING_VERSIONetCURRENT_PROJECT_VERSION

La dernière étape consiste à écrire votre propre script de synchronisation qui lit les valeurs du fourni MARKETING_VERSIONet CURRENT_PROJECT_VERSIONà la cible / s respectifs et chaque fois que vous le souhaitez.

Dans mon cas, le script est le suivant:

#!/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

J'utilise partagé Info.plistet Settings.bundleentre mes deux cibles d'application, donc je dois le mettre à jour une fois.

J'utilise également une extension de service de notification BadgeCounter, qui doit avoir exactement la même version et être la cible dans laquelle elle est intégrée. Je mets donc cela à jour également.

KoCMoHaBTa
la source
1

Non.

Vraisemblablement, il y a une raison pour laquelle ce comportement a changé. Si les fonctionnalités Xcode ultérieures s'appuient sur ce comportement, les choses deviennent de plus en plus "construites" sur toute la ligne.

Au lieu d'essayer de plier Xcode, modifiez la façon dont le script de génération récupère ces valeurs:

Comment lire la version actuelle de l'application dans Xcode 11 avec un script

Si vous devez manipuler le project.pbxprojfichier, c'est une liste de styles Next qui est bien documentée. Vous pouvez utiliser plistbuddyce qui est compatible avec cet ancien format. Vous pouvez également utiliser awkavec plus de scripts si vous avez des manipulations plus complexes.

Si je comprends votre cas d'utilisation, vous pouvez écrire un script qui obtient les numéros de version les plus élevés avec awkpuis met à jour tous les numéros de version inférieurs qu'il peut trouver dans le fichier sed.

Manuel
la source
l'impression de valeurs avec PlistBuddy semble fonctionner correctement, mais lorsque j'utilise la setcommande, l'ensemble du projet.pbxproj est converti en un fichier XML .plist et ne peut plus être lu par Xcode. exemple:PlistBuddy -c "Set :objects:$configurationId:buildSettings:CURRENT_PROJECT_VERSION $newProjectVersion" "$projectFile"
M. Zystem
Selon ce que vous voulez exactement réaliser, vous devrez peut-être utiliser une combinaison d'outils
Manuel
Le redémarrage de Xcode a résolu le problème XML. Als a constaté que lors de l'exécution d'un script de construction qui modifie le pbxprojfichier, la construction sera annulée. Donc ça ne va pas vraiment marcher, je le crains.
M. Zystem
J'ai mis à jour ma question d'origine avec les informations ci-dessus.
M. Zystem
1
Par exemple - mon cas d'utilisation est de synchroniser la version et la génération sur plusieurs cibles - je voudrais définir la version et la génération sur la première cible et qui est mise à jour automatiquement pour toutes les autres. Cela fonctionnait bien avant, car vous venez de modifier une ressource. Maintenant, je ne peux pas modifier le projet pendant la phase de construction d'une cible, car la construction est annulée.
KoCMoHaBTa