Como impedir que o Xcode 11 altere CFBundleVersion e CFBundleShortVersionString para $ (CURRENT_PROJECT_VERSION) e $ (MARKETING_VERSION)?

14

Desde a versão 11, Xcode define o meu CFBundleVersionvalor para $(CURRENT_PROJECT_VERSION)e meu CFBundleShortVersionStringao valor $(MARKETING_VERSION)sempre que eu entrar Versão ou valores construir no configurações de destino (guia "Geral").

A versão real e os valores de compilação inseridos agora são armazenados no arquivo project.pbxproj. Não quero ou gosto desse comportamento, pois uso scripts de shell para modificar os valores no momento da construção.

Posso definir manualmente os valores corretos no arquivo Info.plist, mas assim que altero os números de Versão ou Compilação nas configurações de destino, o arquivo Info.plist é alterado novamente pelo Xcode.

Como faço para parar o Xcode 11 de fazer isso?

Quando modifico meu script de construção para alterar o próprio arquivo do projeto, o Xcode cancelará imediatamente a construção assim que o arquivo do projeto for alterado.

Mr. Zystem
fonte
Por que você deseja que o Xcode 11 pare de fazer isso, em vez de modificar seu script de shell para recuperar o valor?
Manuel
11
@Manuel Eu acho que modificar um plist usando plistbuddyé agradável e limpo, enquanto que modificar o arquivo do projeto é muito mais confuso, pouco confiável e propenso a alterações inesperadas no formato do arquivo.
Zystem
11
Manipular o arquivo project.pbxproj não é complicado quando você entende o formato do arquivo. É apenas uma lista do estilo Next que está bem documentada. Você pode até modificar o arquivo com plistbuddy, é compatível com este formato.
Manuel
Atualizei minha resposta com uma sugestão para o seu caso de uso.
Manuel

Respostas:

1

A estrada até agora

Meu caso de uso foi o seguinte:

  1. Estou sincronizando a versão e construindo números em vários destinos.
  2. Estou sincronizando a versão e construindo números com o alvo Settigns.bundle
  3. Estou lendo e modificando o número da compilação de um servidor de IC.

Eu costumava executar os pontos 1 e 2 como um script de construção de destino e o ponto 3 como um script personalizado no próprio IC.

A nova maneira de armazenar a versão e compilar nas configurações de compilação do Xcode estava causando problemas nos scripts, porque eles não eram mais capazes de modificar efetivamente os valores. Pelo menos a leitura era possível.

Infelizmente, não consegui descobrir uma maneira legítima de impedir o Xcode de armazenar a versão e criar números nas configurações de compilação do projeto, no entanto, consegui criar uma solução alternativa.

Acontece que, quando uma compilação ou arquivamento é feita, o valor escrito em Info.plisté usado. Isso significa que o valor é substituído durante o tempo de construção, o que não nos permite modificá-lo durante o mesmo tempo de construção.

Também tentei modificar o projeto usando o xcodeprojcli, no entanto, qualquer alteração no projeto estava causando a interrupção de qualquer compilação, portanto, esta solução não estava funcionando.

Eventualmente, depois de várias abordagens diferentes que tentei, finalmente consegui encontrar um compromisso que não estava violando o novo comportamento do Xcode.

Resposta curta:

Como uma ação prévia do alvo, é executado um script que grava os respectivos valores para CFBundleShortVersionStringe CFBundleVersionpara oInfo.plist

Como fonte da verdade, eu uso as configurações de compilação do Xcode para ler os valores de MARKETING_VERSIONe CURRENT_PROJECT_VERSIONdo destino desejado.

Dessa forma, quando você modificar os valores das configurações do projeto - na próxima compilação / arquivamento - eles serão gravados no Info.plist, permitindo que qualquer uma, se sua lógica de script existente, continue a funcionar.

Resposta detalhada

A única maneira de modificar um recurso em uma ação de construção é usando um pre-actionscript. Se você tentar fazer isso a partir de um script de construção - as alterações não entrarão em vigor imediatamente e não estarão presentes no final da construção / arquivamento.

Para adicionar uma ação de pré-construção - vá para o esquema de edição.

insira a descrição da imagem aqui

Expanda as seções Build e Archive. Em Pre-action, clique no Provide build and settings frommenu suspenso e selecione a fonte do destino da verdade a partir da qual você deseja ler os valores.

insira a descrição da imagem aqui

Adicione o seguinte script:

# 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

As linhas de script fazem o seguinte:

  1. Vá para o diretório em que o script de sincronização está localizado para executá-lo
  2. Permite que um log seja gravado durante a pré-ação, caso contrário, qualquer saída será silenciada por padrão
  3. Execute o script de sincronização, fornecendo a MARKETING_VERSIONeCURRENT_PROJECT_VERSION

A etapa final é escrever seu próprio script de sincronização que leia os valores do fornecido MARKETING_VERSIONe CURRENT_PROJECT_VERSIONpara o (s) destino (s) respectivo (s) e sempre que desejar.

No meu caso, o script é o seguinte:

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

Eu uso compartilhado Info.pliste Settings.bundleentre os dois destinos de aplicativos, por isso preciso atualizá-lo uma vez.

Também uso uma extensão de serviço de notificação BadgeCounter, que precisa ter exatamente a mesma versão e compilar como o destino no qual está incorporada. Então eu atualizo isso também.

KoCMoHaBTa
fonte
1

Não.

Presumivelmente, há uma razão pela qual esse comportamento mudou. Se os recursos posteriores do Xcode se basearem nesse comportamento, as coisas serão cada vez mais "construídas" na linha.

Em vez de tentar dobrar o Xcode, altere como o script de construção recupera esses valores:

Como ler a versão atual do aplicativo no Xcode 11 com script

Se você precisar manipular o project.pbxprojarquivo, é uma lista de estilo Próximo que está bem documentada. Você pode usar o plistbuddyque é compatível com este formato antigo. Você também pode usar awkcom mais scripts se tiver manipulações mais complexas.

Se eu entendo o seu caso de uso, você pode escrever um script que obtenha os números de versão mais altos awke, em seguida, atualize todos os números de versão inferiores que pode encontrar no arquivo sed.

Manuel
fonte
imprimir valores com PlistBuddy parece funcionar bem, mas quando eu uso o setcomando, todo o project.pbxproj é convertido em um arquivo .plist XML e não pode mais ser lido pelo Xcode. exemplo:PlistBuddy -c "Set :objects:$configurationId:buildSettings:CURRENT_PROJECT_VERSION $newProjectVersion" "$projectFile"
Sr. Zystem 16/10/19
Dependendo do que exatamente você deseja alcançar, você pode ter que usar uma combinação de ferramentas #
Manuel Manuel
A reinicialização do Xcode corrigiu o problema de XML. Als descobriu que, ao executar um script de construção que altera o pbxprojarquivo, a construção será cancelada. Receio que isso não vá realmente funcionar.
Zystem
Atualizei minha pergunta original com as informações acima.
Zystem
11
Por exemplo - meu caso de uso é sincronizar a versão e compilar em vários destinos - eu gostaria de definir a versão e compilar no primeiro destino e que seja atualizado automaticamente para todos os outros. Estava funcionando bem antes, porque você acabou de modificar um recurso. Agora não consigo modificar o projeto durante a fase de construção de nenhum destino, porque a compilação é cancelada.
51319 KoCMoHaBTa