Wie kann verhindert werden, dass Xcode 11 CFBundleVersion und CFBundleShortVersionString in $ (CURRENT_PROJECT_VERSION) und $ (MARKETING_VERSION) ändert?


14

Seit Version 11 setzt Xcode meinen CFBundleVersionWert auf $(CURRENT_PROJECT_VERSION)und meinen CFBundleShortVersionStringWert auf, $(MARKETING_VERSION)wenn ich in den Zieleinstellungen Versions- oder Build-Werte eingebe (Registerkarte "Allgemein").

Die von mir eingegebenen tatsächlichen Versions- und Buildwerte werden jetzt in der Datei project.pbxproj gespeichert. Ich möchte oder mag dieses Verhalten nicht, da ich Shell-Skripte verwende, um die Werte zur Erstellungszeit zu ändern.

Ich kann die korrekten Werte in der Datei Info.plist manuell festlegen. Sobald ich jedoch die Versions- oder Build-Nummern in den Zieleinstellungen ändere, wird die Datei Info.plist von Xcode erneut geändert.

Wie kann ich verhindern, dass Xcode 11 dies tut?

Wenn ich mein Build-Skript so ändere, dass die Projektdatei selbst geändert wird, bricht Xcode den Build sofort ab, sobald die Projektdatei geändert wird.


Warum sollte Xcode 11 dies nicht mehr tun, anstatt Ihr Shell-Skript so zu ändern, dass der Wert abgerufen wird?
Manuel

1
@Manuel Ich denke, das Ändern einer Liste mit plistbuddyist nett und sauber, während das Ändern der Projektdatei viel chaotischer, unzuverlässiger und anfällig für unerwartete Änderungen im Dateiformat ist.
Herr Zystem

1
Das Bearbeiten der Datei project.pbxproj ist nicht unübersichtlich, wenn Sie das Dateiformat verstehen. Es ist nur eine Plist im Next-Stil, die gut dokumentiert ist. Sie können die Datei sogar mit plistbuddy ändern, sie ist mit diesem Format kompatibel.
Manuel

Ich habe meine Antwort mit einem Vorschlag für Ihren Anwendungsfall aktualisiert.
Manuel

Antworten:


1

Der Weg bisher

Mein Anwendungsfall war:

  1. Ich synchronisiere die Version und baue Nummern über mehrere Ziele hinweg.
  2. Ich synchronisiere die Version und erstelle Nummern mit denen des Ziels Settigns.bundle
  3. Ich lese und ändere die Build-Nummer von einem CI-Server.

Ich habe Punkt 1 und 2 als Zielerstellungsskript und Punkt 3 als benutzerdefiniertes Skript auf dem CI selbst ausgeführt.

Die neue Art, die Version und den Build in den Xcode-Build-Einstellungen zu speichern, verursachte Probleme mit den Skripten, da die Werte nicht mehr effektiv geändert werden konnten. Zumindest war Lesen möglich.

Leider konnte ich keinen legitimen Weg finden, um zu verhindern, dass Xcode die Version speichert und Nummern in die Projekterstellungseinstellungen einbaut, aber ich habe es geschafft, eine Problemumgehung zu erstellen.

Es stellt sich heraus, dass beim Erstellen eines Builds oder Archivs der in geschriebene Wert Info.plistverwendet wird. Dies bedeutet, dass der Wert während der Erstellungszeit ersetzt wird, sodass wir ihn nicht während derselben Erstellungszeit ändern können.

Ich habe auch versucht, das Projekt mit xcodeprojcli zu ändern. Änderungen am Projekt führten jedoch dazu, dass Builds gestoppt wurden, sodass diese Lösung nicht funktionierte.

Nach vielen verschiedenen Ansätzen, die ich ausprobiert habe, habe ich es endlich geschafft, einen Kompromiss zu finden, der das neue Verhalten des Xcodes nicht verletzt.

Kurze Antwort:

Als Zielvoraktion wird ein Skript ausgeführt, das die entsprechenden Werte in CFBundleShortVersionStringund CFBundleVersionin die Ziele schreibtInfo.plist

Als Quelle der Wahrheit, verwende ich die Xcode Build - Einstellungen die Werte zu lesen MARKETING_VERSIONund CURRENT_PROJECT_VERSIONdes gewünschten Ziels.

Auf diese Weise werden beim Ändern der Werte aus den Projekteinstellungen - beim nächsten Erstellen / Archivieren - diese in das geschrieben Info.plist, sodass Ihre vorhandene Skriptlogik weiterhin funktioniert.

Detaillierte Antwort

Die einzige Möglichkeit, eine Ressource bei einer Build-Aktion zu ändern, ist die Verwendung eines pre-actionSkripts. Wenn Sie versuchen, dies über ein Build-Skript zu tun, werden die Änderungen nicht sofort wirksam und sind am Ende des Builds / Archivs nicht vorhanden.

Um eine vorgefertigte Aktion hinzuzufügen, gehen Sie zum Bearbeitungsschema.

Geben Sie hier die Bildbeschreibung ein

Erweitern Sie dann die Abschnitte Erstellen und Archivieren. Unter Pre-actionder klicken Provide build and settings fromDrop - Down und die Quelle der Wahrheit Ziel auszuwählen , von dem Sie die Werte lesen möchten.

Geben Sie hier die Bildbeschreibung ein

Fügen Sie das folgende Skript hinzu:

# 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

Die Skriptzeilen führen Folgendes aus:

  1. Wechseln Sie in das Verzeichnis, in dem sich das Synchronisierungsskript befindet, um es auszuführen
  2. Ermöglicht das Schreiben eines Protokolls während der Voraktion, andernfalls wird jede Ausgabe standardmäßig stummgeschaltet
  3. Führen Sie das Synchronisierungsskript aus, indem Sie das MARKETING_VERSIONund angebenCURRENT_PROJECT_VERSION

Der letzte Schritt besteht darin, ein eigenes Synchronisierungsskript zu schreiben, das die Werte der bereitgestellten MARKETING_VERSIONund CURRENT_PROJECT_VERSIONder jeweiligen Ziele liest und wann immer Sie möchten.

In meinem Fall lautet das Skript wie folgt:

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

Ich verwende Shared Info.plistund Settings.bundlezwischen meinen beiden App-Zielen, daher muss ich dies einmal aktualisieren.

Außerdem verwende ich eine Benachrichtigungsdiensterweiterung BadgeCounter, die genau dieselbe Version haben und als Ziel erstellt werden muss, in das sie eingebettet ist. Also aktualisiere ich das auch.


1

Tu es nicht.

Vermutlich gibt es einen Grund, warum sich dieses Verhalten geändert hat. Wenn spätere Xcode-Funktionen auf diesem Verhalten aufbauen, werden die Dinge auf der ganzen Linie immer mehr "konstruiert".

Anstatt zu versuchen, Xcode zu biegen, ändern Sie, wie das Build-Skript diese Werte abruft:

Lesen der aktuellen App-Version in Xcode 11 mit Skript

Wenn Sie die project.pbxprojDatei bearbeiten müssen, handelt es sich um eine gut dokumentierte Plist im nächsten Stil. Sie können verwenden, plistbuddywelches mit diesem alten Format kompatibel ist. Sie können auch awkmit mehr Skripten arbeiten, wenn Sie komplexere Manipulationen haben.

Wenn ich Ihren Anwendungsfall verstehe, können Sie ein Skript schreiben, mit dem die höchsten Versionsnummern abgerufen werden, awkund dann alle niedrigeren Versionsnummern aktualisieren, die in der Datei enthalten sind sed.


Das Drucken von Werten mit PlistBuddy scheint gut zu funktionieren, aber wenn ich den setBefehl verwende, wird die gesamte project.pbxproj in eine XML .plist-Datei konvertiert und kann von Xcode nicht mehr gelesen werden. Beispiel:PlistBuddy -c "Set :objects:$configurationId:buildSettings:CURRENT_PROJECT_VERSION $newProjectVersion" "$projectFile"
Herr Zystem

Je nachdem, was genau Sie erreichen möchten, müssen Sie möglicherweise eine Kombination von Werkzeugen verwenden
Manuel

Durch einen Neustart von Xcode wurde das XML-Problem behoben. Als festgestellt, dass beim Ausführen eines Build-Skripts, das die pbxprojDatei ändert , der Build abgebrochen wird. Ich fürchte, das wird nicht wirklich funktionieren.
Herr Zystem

Ich habe meine ursprüngliche Frage mit den obigen Informationen aktualisiert.
Herr Zystem

1
Zum Beispiel - mein Anwendungsfall ist das Synchronisieren der Version und das Erstellen über mehrere Ziele hinweg - möchte ich die Version festlegen und auf das erste Ziel erstellen, und das wird automatisch auf alle anderen aktualisiert. Es hat schon früher funktioniert, weil Sie nur eine Ressource ändern. Jetzt kann ich das Projekt während der Build-Phase eines Ziels nicht mehr ändern, da der Build abgebrochen wird.
KoCMoHaBTa
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.