446 votes

Xcode "Build and Archive" depuis la ligne de commande

Xcode 3.2 offre une nouvelle fonctionnalité impressionnante dans le menu Build, "Build and Archive", qui génère un fichier .ipa adapté à une distribution ad hoc. Vous pouvez également ouvrir l'Organiseur, aller dans "Applications archivées" et "Soumettre l'application à iTunesConnect".

Existe-t-il un moyen d'utiliser "Build and Archive" à partir de la ligne de commande (dans le cadre d'un build script) ? Je suppose que xcodebuild serait impliqué d'une manière ou d'une autre, mais le man La page ne semble pas dire quoi que ce soit à ce sujet.

UPDATE Michael Grinich a demandé une clarification ; voici ce que vous ne pouvez pas faire exactement avec les constructions en ligne de commande, les fonctions que vous pouvez SEULEMENT faire avec l'Organiseur de Xcode après avoir "construit et archivé".

  1. Vous pouvez cliquer sur "Partager l'application..." pour partager votre IPA avec les bêta-testeurs. Comme Guillaume le souligne ci-dessous, grâce à une certaine magie de Xcode, ce fichier IPA ne nécessite pas un fichier .mobileprovision distribué séparément que les bêta-testeurs doivent installer ; c'est magique. Aucune ligne de commande script ne peut le faire. Par exemple, le script d'Arrix (soumis le 1er mai) ne répond pas à cette exigence.
  2. Plus important encore, après avoir testé une version bêta, vous pouvez cliquer sur "Soumettre l'application à iTunes Connect" pour soumettre cette EXACTE même version à Apple, le même binaire que vous avez testé, sans le reconstruire. C'est impossible en ligne de commande, car la signature de l'application fait partie du processus de construction ; vous pouvez signer des bits pour le bêta-test ad hoc OU vous pouvez les signer pour les soumettre à l'App Store, mais pas les deux. Aucune IPA construite en ligne de commande ne peut être testée en bêta sur des téléphones et ensuite soumise directement à Apple.

J'aimerais que quelqu'un vienne me prouver que j'ai tort : ces deux fonctionnalités fonctionnent parfaitement dans l'interface graphique de Xcode et ne peuvent pas être reproduites à partir de la ligne de commande.

1 votes

Aw, crud. Cela semble être impossible. Si vous ne connaissez pas la réponse, veuillez au moins voter pour la question afin que ma prime ne disparaisse pas dans l'éther... :-(

3 votes

Ce n'est pas impossible, c'est juste que ça ne fait pas partie de l'ordre du jour. xcodebuild . Pour créer un fichier IPA, il suffit de placer l'application dans un répertoire appelé "Payload", de zipper ce répertoire et de le renommer en "MyAppName.ipa".

0 votes

@Michael, "Build and Archive" permet également d'utiliser les fonctions de l'Organizer, qui ne sont pas disponibles lorsque vous créez simplement un fichier IPA à la main.

329voto

vdaubry Points 6127

J'ai trouvé comment automatiser le processus de construction et d'archivage à partir de la ligne de commande. article de blog en expliquant comment vous pouvez y parvenir.

La commande que vous devez utiliser est xcrun :

/usr/bin/xcrun -sdk iphoneos PackageApplication \
-v "${RELEASE_BUILDDIR}/${APPLICATION_NAME}.app" \
-o "${BUILD_HISTORY_DIR}/${APPLICATION_NAME}.ipa" \
--sign "${DEVELOPER_NAME}" \
--embed "${PROVISONING_PROFILE}"

Vous trouverez tous les détails dans l'article . Si vous avez des questions, n'hésitez pas à les poser.

21 votes

Ce n'est pas évident pour moi depuis un certain temps, mais RELEASE_BUILDDIR doit être un chemin absolu.

5 votes

Notez également que vous n'avez pas besoin des options --sign ou --embed si vous souhaitez conserver le même profil de signature utilisé lors de la construction du fichier .app. Il s'agira de ce que vous avez défini dans les paramètres de construction de la signature de code pour votre configuration Release.

0 votes

En utilisant une phase Run script dans un Aggregate Target enveloppant, vous pouvez même automatiser cette commande et le téléchargement/emailing/... ultérieur du fichier ipa. (sans la cible agrégée, le script sera exécuté trop tôt).

294voto

Reid Points 2082

Avec Xcode 4.2, vous pouvez utiliser le drapeau -scheme pour faire cela :

xcodebuild -scheme <SchemeName> archive

Après cette commande, l'archive apparaîtra dans l'Organisateur Xcode.

3 votes

Oui, beaucoup mieux ! Pour le faire fonctionner, j'ai fait ce qui suit : cd dans le dossier de votre projet, puis lancez "xcodebuild -scheme MyProjectName archive" (parce que normalement, vous avez un schéma avec le même nom que votre projet).

22 votes

Notez que le archive action ne respecte aucun paramètre que vous fournissez par le biais de cette invocation, en dehors de l'espace de travail et du schéma - cela vient de me coûter heures !

0 votes

"l'action d'archivage n'honore pas les paramètres que vous fournissez par le biais de cette invocation" - veuillez soumettre un rapport de bogue à ce sujet si cela vous concerne ! Ce problème doit être corrigé.

191voto

Raj Points 1740

Mise à jour de ma réponse avec Xcode 9 et Swift

Archives

xcodebuild -workspace <ProjectName>/<ProjectName>.xcworkspace \
  -scheme <schemeName> clean archive -configuration release \
  -sdk iphoneos -archivePath <ProjectName>.xcarchive

IPA Export ( veuillez noter la plist des options d'exportation )

xcodebuild -exportArchive -archivePath  <ProjectName>.xcarchive \
  -exportOptionsPlist  <ProjectName>/exportOptions.plist \
  -exportPath  <ProjectName>.ipa

Pour ceux qui ne connaissent pas le fichier exportOptions.plist, https://blog.bitrise.io/post/new-export-options-plist-in-xcode-9


Ceux qui l'ont utilisé pour construire des projets dans des outils CI/CD comme teamcity/jenkins, veuillez vous assurer que vous utilisez le bon Xcode installé dans l'agent de construction pour l'archivage et l'exportation.

Vous pouvez utiliser l'une des deux options suivantes pour cela.

  1. Utilisez le chemin complet de xcodebuild,

    /Applications/Xcode 9.3.1.app/Contents/Developer/usr/bin/xcodebuild

  2. Utilisez xcode-select,

    xcode-select -switch /Applications/Xcode 9.3.1.app


Voici mon ancienne réponse

Voici la ligne de commande script pour créer l'archive et l'exemple IPA. J'ai un projet iPhone xcode, qui est situé dans le dossier Desktop/MyiOSApp.

Exécutez les commandes suivantes une par une :

cd /Users/username/Desktop/MyiOSApp/

xcodebuild -scheme MyiOSApp archive \
  -archivePath /Users/username/Desktop/MyiOSApp.xcarchive

xcodebuild -exportArchive -exportFormat ipa \
  -archivePath "/Users/username/Desktop/MyiOSApp.xcarchive" \
  -exportPath "/Users/username/Desktop/MyiOSApp.ipa" \
  -exportProvisioningProfile "MyCompany Distribution Profile"

Ceci est testé avec Xcode 5 et fonctionne bien pour moi.

2 votes

Il a fonctionné parfaitement sur Xcode6.1.1 . J'ai choisi de construire mes applications à partir du terminal car Xcode6 me donne une erreur "Your account already has a valid certificate" lorsque j'essaie de construire une distribution AdHoc à partir de l'organisateur.

0 votes

Si vous avez une application WatchKit, alors il y a un nouveau dossier dans l'ipa appelé WatchKitSupport ainsi qu'un dossier Symboles (peut être optionnel). Savez-vous s'il existe un moyen de faire en sorte que l'exportArcive exporte également ces dossiers ?

2 votes

xcodebuild -workspace <ProjectName>/<ProjectName>.xcworkspace -scheme <schemeName> clean archive -configuration release -sdk iphoneos -archivePath <ProjectName>.xcarchive envoie une erreur : requires a provisioning profile with the Associated Domains feature. Select a provisioning profile for the "Release" build configuration in the project editor.

32voto

Arrix Points 1659

J'ai utilisé mon propre build script pour générer le paquet ipa pour une distribution ad hoc.

die() {
    echo "$*" >&2
    exit 1
}

appname='AppName'
config='Ad Hoc Distribution'
sdk='iphoneos3.1.3'
project_dir=$(pwd)

echo using configuration $config

echo updating version number
agvtool bump -all
fullversion="$(agvtool mvers -terse1)($(agvtool vers -terse))"
echo building version $fullversion

xcodebuild -activetarget -configuration "$config" -sdk $sdk build || die "build failed"

echo making ipa...
# packaging
cd build/"$config"-iphoneos || die "no such directory"
rm -rf Payload
rm -f "$appname".*.ipa
mkdir Payload
cp -Rp "$appname.app" Payload/
if [ -f "$project_dir"/iTunesArtwork ] ; then
    cp -f "$project_dir"/iTunesArtwork Payload/iTunesArtwork
fi

ipaname="$appname.$fullversion.$(date -u +%Y%m%d%H%M%S).ipa"
zip -r $ipaname Payload

echo finished making $ipaname

Le script incrémente également le numéro de version. Vous pouvez supprimer cette partie si elle n'est pas nécessaire. J'espère que cela vous aidera.

3 votes

C'est une bonne solution, même si votre code est un peu difficile à lire sans commentaires. Pourriez-vous écrire un peu plus sur ce qui se passe ?

0 votes

Où xcode obtient-il le nom "APPNAME.ipa" ? De l'emballage-> Nom du produit ?

3 votes

Ce script ne suffit plus maintenant avec l'application WatchKit. Quelqu'un connaît-il les nouvelles spécifications du fichier ipa avec l'app watchkit ?

25voto

FuePi Points 541

Nous avons développé une application iPad avec XCode 4.2.1 et nous voulions intégrer le build dans notre intégration continue (Jenkins) pour une distribution OTA. Voici la solution que j'ai trouvée :

# Unlock keychain
security unlock-keychain -p jenkins /Users/jenkins/Library/Keychains/login.keychain

# Build and sign app
xcodebuild -configuration Distribution clean build

# Set variables
APP_PATH="$PWD/build/Distribution-iphoneos/iPadApp.app"
VERSION=`defaults read $APP_PATH/Info CFBundleShortVersionString`
REVISION=`defaults read $APP_PATH/Info CFBundleVersion`
DATE=`date +"%Y%m%d-%H%M%S"`
ITUNES_LINK="<a href=\"itms-services:\/\/?action=download-manifest\&url=https:\/\/xxx.xxx.xxx\/iPadApp-$VERSION.$REVISION-$DATE.plist\">Download iPad2-App v$VERSION.$REVISION-$DATE<\/a>"

# Package and verify app
xcrun -sdk iphoneos PackageApplication -v build/Distribution-iphoneos/iPadApp.app -o $PWD/iPadApp-$VERSION.$REVISION-$DATE.ipa

# Create plist
cat iPadApp.plist.template | sed -e "s/\${VERSION}/$VERSION/" -e "s/\${DATE}/$DATE/" -e "s/\${REVISION}/$REVISION/" > iPadApp-$VERSION.$REVISION-$DATE.plist

# Update index.html
curl https://xxx.xxx.xxx/index.html -o index.html.$DATE
cat index.html.$DATE | sed -n '1h;1!H;${;g;s/\(<h3>Aktuelle Version<\/h3>\)\(.*\)\(<h3>&Auml;ltere Versionen<\/h3>.<ul>.<li>\)/\1\
${ITUNES_LINK}\
\3\2<\/li>\
<li>/g;p;}' | sed -e "s/\${ITUNES_LINK}/$ITUNES_LINK/" > index.html

Ensuite, Jenkins télécharge les fichiers ipa, plist et html sur notre serveur web.

C'est le modèle plist :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>items</key>
    <array>
        <dict>
            <key>assets</key>
            <array>
                <dict>
                    <key>kind</key>
                    <string>software-package</string>
                    <key>url</key>
                    <string>https://xxx.xxx.xxx/iPadApp-${VERSION}.${REVISION}-${DATE}.ipa</string>
                </dict>
                <dict>
                    <key>kind</key>
                    <string>full-size-image</string>
                    <key>needs-shine</key>
                    <true/>
                    <key>url</key>
                    <string>https://xxx.xxx.xxx/iPadApp.png</string>
                </dict>
                <dict>
                    <key>kind</key>
                    <string>display-image</string>
                    <key>needs-shine</key>
                    <true/>
                    <key>url</key>
                    <string>https://xxx.xxx.xxx/iPadApp_sm.png</string>
                </dict>
            </array>
            <key>metadata</key>
            <dict>
                <key>bundle-identifier</key>
                <string>xxx.xxx.xxx.iPadApp</string>
                <key>bundle-version</key>
                <string>${VERSION}</string>
                <key>kind</key>
                <string>software</string>
                <key>subtitle</key>
                <string>iPad2-App</string>
                <key>title</key>
                <string>iPadApp</string>
            </dict>
        </dict>
    </array>
</dict>
</plist>

Pour ce faire, vous devez importer le certificat de distribution et le profil de provisionnement dans le trousseau de clés de l'utilisateur désigné.

3 votes

Vous pouvez également modifier un fichier plist avec la commande Plistbuddy d'Apple, par ex : /usr/libexec/PlistBuddy -c "Set :CFBundleVersion 1.2.3.4" /path/to/info.plist . Au lieu de jouer avec SED :)

0 votes

Merci pour l'information. Je suis plus expérimenté avec sed qu'avec plistbuddy, donc je choisis sed :)

1 votes

Je recommande $WORKSPACE au lieu de $PWD pour générer APP_PATH

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X