Bagaimana cara menghentikan Xcode 11 dari mengubah CFBundleVersion dan CFBundleShortVersionString menjadi $ (CURRENT_PROJECT_VERSION) dan $ (MARKETING_VERSION)?

14

Sejak versi 11, Xcode menetapkan CFBundleVersionnilai saya ke $(CURRENT_PROJECT_VERSION)dan nilai saya CFBundleShortVersionStringke $(MARKETING_VERSION)setiap kali saya memasukkan Versi atau nilai Build di pengaturan target (tab "Umum").

Versi aktual dan nilai bangun yang saya masukkan sekarang disimpan dalam file project.pbxproj. Saya tidak ingin atau menyukai perilaku ini, karena saya menggunakan skrip shell untuk memodifikasi nilai saat buildtime.

Saya dapat secara manual mengatur nilai yang benar dalam file Info.plist, tetapi segera setelah saya mengubah Versi atau Build angka dalam pengaturan target, file Info.plist akan diubah lagi oleh Xcode.

Bagaimana cara menghentikan Xcode 11 dari melakukan ini?

Ketika saya memodifikasi skrip build saya untuk mengubah file proyek itu sendiri, Xcode akan segera membatalkan build segera setelah file proyek diubah.

Tuan Zystem
sumber
Mengapa Anda ingin Xcode 11 berhenti melakukan ini, alih-alih memodifikasi skrip shell Anda untuk mengambil nilainya?
Manuel
1
@Manuel Saya pikir memodifikasi plist menggunakan plistbuddybagus dan bersih, sedangkan memodifikasi file proyek jauh lebih berantakan, tidak dapat diandalkan dan rentan terhadap perubahan tak terduga dalam format file.
Tn. Zystem
1
Memanipulasi file project.pbxproj tidak berantakan ketika Anda memahami format file. Itu hanya daftar gaya Next yang didokumentasikan dengan baik. Anda bahkan dapat memodifikasi file dengan plistbuddy, ini kompatibel dengan format ini.
Manuel
Saya memperbarui jawaban saya dengan saran untuk kasus penggunaan Anda.
Manuel

Jawaban:

1

Jalan sejauh ini

Kasus penggunaan saya adalah:

  1. Saya menyinkronkan versi dan membangun angka di beberapa target.
  2. Saya menyinkronkan versi dan membuat angka dengan target Settigns.bundle
  3. Saya membaca dan memodifikasi nomor build dari server CI.

Saya biasa mengeksekusi poin 1 dan 2 sebagai skrip build target dan point 3 sebagai skrip khusus pada CI itu sendiri.

Cara baru menyimpan versi dan membangun dalam pengaturan build Xcode menyebabkan masalah dengan skrip, karena mereka tidak lagi dapat secara efektif mengubah nilai-nilai. Setidaknya membaca adalah mungkin.

Sayangnya saya tidak dapat menemukan cara yang sah untuk mencegah Xcode dari menyimpan versi dan membangun nomor ke pengaturan membangun proyek, namun saya telah berhasil membuat solusi.

Ternyata ketika membangun atau arsip dibuat, nilai yang tertulis dalam Info.plistdigunakan. Ini berarti bahwa nilai tersebut diganti selama waktu pembuatan, yang tidak memungkinkan kami untuk memodifikasinya selama waktu pembuatan yang sama.

Saya juga mencoba memodifikasi proyek menggunakan xcodeprojcli, namun setiap perubahan pada proyek menyebabkan pembangunan berhenti, jadi solusi ini tidak berfungsi.

Akhirnya, setelah banyak pendekatan berbeda yang saya coba, saya akhirnya berhasil menemukan kompromi yang tidak melanggar perilaku baru Xcode.

Jawaban singkat:

Sebagai tindakan awal sasaran, skrip dijalankan yang menulis nilai masing-masing ke CFBundleShortVersionStringdan CFBundleVersionke targetInfo.plist

Sebagai sumber kebenaran, saya menggunakan pengaturan build Xcode untuk membaca nilai MARKETING_VERSIONdan CURRENT_PROJECT_VERSIONtarget yang diinginkan.

Dengan cara ini, ketika Anda memodifikasi nilai-nilai dari pengaturan proyek - setelah membangun / arsip berikutnya - mereka akan ditulis ke Info.plist, memungkinkan jika logika skrip yang ada untuk terus bekerja.

Jawaban terperinci

Satu-satunya cara untuk mengubah sumber daya pada tindakan membangun adalah menggunakan pre-actionskrip. Jika Anda mencoba melakukannya dari skrip build - perubahan tidak akan langsung berlaku dan tidak akan ada di akhir build / arsip.

Untuk menambahkan tindakan pra-bangun - buka edit skema.

masukkan deskripsi gambar di sini

Kemudian perluas bagian Bangun dan Arsip. Di bawah Pre-action, klik Provide build and settings fromdropdown dan pilih sumber target kebenaran dari mana Anda ingin membaca nilainya.

masukkan deskripsi gambar di sini

Tambahkan skrip berikut:

# 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

Baris skrip melakukan hal berikut:

  1. Buka direktori tempat skrip sinkronisasi berada untuk menjalankannya
  2. Mengizinkan log ditulis selama pra-aksi, jika tidak, output apa pun akan dibungkam secara default
  3. Jalankan skrip sinkronisasi dengan memberikan MARKETING_VERSIONdanCURRENT_PROJECT_VERSION

Langkah terakhir adalah menulis skrip sinkronisasi Anda sendiri yang membaca nilai yang disediakan MARKETING_VERSIONdan CURRENT_PROJECT_VERSIONuntuk masing-masing target dan kapan pun Anda inginkan.

Dalam kasus saya, skripnya adalah sebagai berikut:

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

Saya menggunakan shared Info.plistdan di Settings.bundleantara kedua target aplikasi saya, jadi saya harus memperbarui ini sekali.

Saya juga menggunakan ekstensi layanan notifikasi BadgeCounter, yang harus memiliki versi yang sama persis dan membangun sebagai target di mana ia tertanam. Jadi saya memperbarui ini juga.

KoCMoHaBTa
sumber
1

Jangan.

Agaknya ada alasan mengapa perilaku ini berubah. Jika nanti fitur Xcode membangun perilaku ini, semakin banyak hal yang "dikonstruksi" di telepon.

Alih-alih mencoba menekuk Xcode, ubah cara skrip build mengambil nilai-nilai ini:

Cara membaca versi aplikasi saat ini di Xcode 11 dengan skrip

Jika Anda perlu memanipulasi project.pbxprojfile, itu adalah daftar gaya Next yang didokumentasikan dengan baik. Anda dapat menggunakan plistbuddyyang kompatibel dengan format lama ini. Anda juga dapat menggunakan awkskrip lebih banyak jika Anda memiliki manipulasi yang lebih kompleks.

Jika saya mengerti kasus penggunaan Anda, Anda bisa menulis skrip yang mendapatkan nomor versi tertinggi awkdan kemudian memperbarui semua nomor versi yang lebih rendah yang dapat ditemukan dalam file sed.

Manuel
sumber
nilai pencetakan dengan PlistBuddy tampaknya berfungsi dengan baik, tetapi ketika saya menggunakan setperintah seluruh project.pbxproj akan dikonversi ke file .plist XML dan tidak lagi dapat dibaca oleh Xcode. contoh:PlistBuddy -c "Set :objects:$configurationId:buildSettings:CURRENT_PROJECT_VERSION $newProjectVersion" "$projectFile"
Mr. Zystem
Bergantung pada apa yang ingin Anda capai, Anda mungkin harus menggunakan kombinasi alat
Manuel
Restart Xcode memperbaiki masalah XML. Juga ditemukan bahwa ketika menjalankan skrip build yang mengubah pbxprojfile akan membatalkan build. Jadi ini tidak benar-benar akan berhasil, saya takut.
Tn. Zystem
Saya memperbarui pertanyaan awal saya dengan info di atas.
Tn. Zystem
1
Sebagai contoh - kasus penggunaan saya adalah untuk menyinkronkan versi dan membangun di beberapa target - saya ingin mengatur versi dan membangun ke target pertama dan yang diperbarui secara otomatis ke semua lainnya. Itu berfungsi dengan baik sebelumnya, karena Anda hanya memodifikasi sumber daya. Sekarang saya tidak dapat memodifikasi proyek selama fase pembangunan target apa pun, karena pembangunan dibatalkan.
KoCMoHaBTa