39

CIの目的のために、ナイトリービルドでXCARCHIVEファイルとIPAファイルを生成できる必要があります。IPAは、テスターがアドホックキーで署名するためのものであり、XCARCHIVEはクライアントに送信して、Xcodeにインポートし、満足したときにアプリストアに送信できるようにします。

IPAの生成は少しグーグルするだけで十分簡単ですが、.XCARCHIVEファイルを生成する方法は私にはわかりません。私が見つけた最も近いものは次のとおりです。

xcodebuild -scheme myscheme archive

ただし、これにより、.xcarchiveが見つけにくいフォルダに保存されます。例:

/Users/me/Library/Developer/Xcode/Archives/2011-12-14/MyApp 14-12-11 11.42 AM.xcarchive

アーカイブが配置される場所、その名前、およびアーカイブを再コンパイルする必要がないようにする方法を制御する方法はありますか?最善の結果は、「xcodebuildビルド」を実行したときに生成されるDSYMとAPPからxcarchiveを生成することだと思います-これは可能ですか?

4

7 に答える 7

58

-archivePathXcode 5 はオプションをサポートするようになりました:

xcodebuild -scheme myscheme archive -archivePath /path/to/AppName.xcarchive

ビルドしたばかりのアーカイブから署名付き IPA をエクスポートすることもできます。

xcodebuild -exportArchive -exportFormat IPA -exportProvisioningProfile my_profile_name -archivePath /path/to/AppName.xcarchive -exportPath /path/to/AppName.ipa
于 2014-01-03T14:27:14.207 に答える
43

Xcode 4 Preview 5 以降では、スキーム アーカイブのポスト アクションでアクセスできる 3 つの環境変数があります。

ARCHIVE_PATH: The path to the archive.
ARCHIVE_PRODUCTS_PATH: The installation location for the archived product.
ARCHIVE_DSYMS_PATH: The path to the product’s dSYM files.

ここでアーカイブを移動/コピーできます。CI スクリプトでプロセスをもう少し制御したかったので、これらの値を含む CI スクリプトで簡単に取得できる一時ファイルを保存しました。

BUILD_DIR=$PROJECT_DIR/build
echo "ARCHIVE_PATH=\"$ARCHIVE_PATH\"" > $BUILD_DIR/archive_paths.sh
echo "ARCHIVE_PRODUCTS_PATH=\"$ARCHIVE_PRODUCTS_PATH\"" >> $BUILD_DIR/archive_paths.sh
echo "ARCHIVE_DSYMS_PATH=\"$ARCHIVE_DSYMS_PATH\"" >> $BUILD_DIR/archive_paths.sh
echo "INFOPLIST_PATH=\"$INFOPLIST_PATH\"" >> $BUILD_DIR/archive_paths.sh

次に、CI スクリプトで次を実行できます。

xcodebuild -alltargets -scheme [Scheme Name] -configuration [Config Name] clean archive
source build/archive_paths.sh
ARCHIVE_NAME=AppName-$APP_VERSION-$APP_BUILD.xcarchive
cp -r "$ARCHIVE_PATH" "$BUILD_DIR/$ARCHIVE_NAME"
于 2012-01-26T20:31:26.197 に答える
11

私はこれを解決しました--archivePath最初の質問が意味することを考えると、xcodeビルドコマンドラインに引数を追加するだけです:

xcodebuild -scheme myscheme archive

になる...

xcodebuild -scheme myscheme archive -archivePath Build/Archive

(注: パスは相対パスです。ビルドを に出力します$PWD/Build)

これにより、.app フォルダーが次の場所に配置されます。

Build/Archive.xarchive/Products/Application

ビルド ターゲットに署名証明書とプロビジョニング プロファイルが既に含まれている場合は、次のコマンドを使用して、再署名せずに IPA ファイルを作成できます。

xcrun -v -sdk iphoneos PackageApplication -v `pwd`'/Build/Archive.xarchive/Products/Application/my.app' -o `pwd`'/myapp.ipa'

(注: xcrun は相対パスを好まないため、pwd)

-v args は、多くの有用な情報をダンプします。このコマンドは、適切に署名できず、コード 0 で終了する可能性があります。

ビルドされた .ipa を実行できないことがわかっている場合は、おそらく署名の問題であり、次を使用して二重チェックを行うことができます。

codesign --verify -vvvv myapp.app

正しく署名され、改ざんされていない場合、出力には次のものが含まれます。

myapp.app: valid on disk
myapp.app: satisfies its Designated Requirement

そうでない場合は、次のようなものが表示されます。

Codesign check fails : /blahpath/myapp.app: a sealed resource is missing or invalid
file modified: /blahpath/ls-ios-develop.app/Assets.car

...これは通常、適切なアーカイブではなく中間出力ディレクトリを使用しようとしていることを意味します。

于 2014-06-19T15:29:27.973 に答える
2

私の現在の解決策は、ユーザーの既存のアーカイブフォルダーの名前を変更し、ビルドを実行し、「検索」を実行して必要な場所にアーカイブをコピーしてから、アーカイブフォルダーを削除し、古いフォルダーの名前を元に戻すことです。私のルビービルドスクリプト:

# Move the existing archives out of the way
system('mv ~/Library/Developer/Xcode/Archives ~/Library/Developer/Xcode/OldArchivesTemp')
# Build the .app, the .DSYM, and the .xcarchive
system("xcodebuild -scheme \"#{scheme}\" clean build archive CONFIGURATION_BUILD_DIR=\"#{build_destination_folder}\"")
# Find the xcarchive wherever it was placed and copy it where i want it
system("find ~/Library/Developer/Xcode/Archives -name *.xcarchive -exec cp -r {} \"#{build_destination_folder}\" \";\"")
# Delete the new archives folder with this new xcarchive
system('rm -rf ~/Library/Developer/Xcode/Archives')
# Put the old archives back
system('mv ~/Library/Developer/Xcode/OldArchivesTemp ~/Library/Developer/Xcode/Archives')

少しハックですが、現在、より良い解決策はありません。少なくとも、ユーザーの「アーカイブ」フォルダーと既存のすべてのアーカイブが保持されます。

- 重要な注意点! -

アーカイブを見つけて必要なフォルダーにコピーするコード行が、アーカイブ内のシンボリックリンクを正しくコピーしないため、アプリでのコード署名が壊れていることがわかりました。それを「mv」またはシンボリックリンクを維持するものに置き換えたいと思うでしょう。乾杯!

于 2012-01-05T03:32:45.400 に答える
0

他のものと似ていますが、.xcarchive ファイルの場所を記録しようとしているので、おそらく少し単純です。(また、アーカイブ フォルダーも移動しないので、複数のビルドを同時に実行している場合は、これがうまく機能します。)

私の呼び出し元ビルド スクリプトは、新しい一時ファイルを生成し、そのパスを という名前の環境変数に設定しますXCARCHIVE_PATH_TMPFILE。この環境変数は、私のスキームのアーカイブ アクション後のシェル スクリプトで使用できます。これにより、.xcarchive のパスがそのファイルに書き込まれます。を呼び出した後にそのファイルを読み取ることができるビルド スクリプトxcodebuild archive

アクション後のシェルスクリプト

echo $ARCHIVE_PATH > "$XCARCHIVE_PATH_TMPFILE"
于 2012-11-20T17:26:42.373 に答える
0

Xcode 4.6 では、スキームを xcarchive にコンパイルするビルド後のアクションを指定できます。

echo "ARCHIVE_PATH=\"$ARCHIVE_PATH\"" > $PROJECT_DIR/archive_paths.sh

ビルド スクリプトを使用して、xcodebuild の実行後に $ARCHIVE_PATH が定義されているかどうかを確認できます。定義されている場合は、出力 xcarchive を指定のフォルダーに移動できます。

プロジェクト内のターゲットが多数ある場合、この方法は保守性があまり高くありません。各ターゲットについて、対応するスキームを「共有」としてタグ付けし、ビルド後のアクションを追加する必要があるためです。

この問題に対処するために、当日のターゲット名に一致する最後のビルドを抽出することにより、アーカイブ パスをプログラムで生成するビルド スクリプトを作成しました。この方法は、同じターゲット名を持つ複数のビルドがマシン上で実行されていない限り、確実に機能します (これは、複数の同時ビルドが実行される運用環境では問題になる可能性があります)。

#!/bin/bash
#
# Script to archive an existing xcode project to a target location.
# The script checks for a post-build action that defines the $ARCHIVE_PATH as follows:
# echo "ARCHIVE_PATH=\"$ARCHIVE_PATH\"" > $PROJECT_DIR/archive_paths.sh
# If such post-build action does not exist or sourcing it doesn't define the $ARCHIVE_PATH   
# variable, the script tries to generate it programmatically by finding the latest build
# in the expected archiving folder
#

post_build_script=archive_paths.sh
build_errors_file=build_errors.log
OUTPUT=output/
XCODEBUILD_CMD='/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild'
TARGET_SDK=iphoneos

function archive()
{
    echo "Archiving target '$1'"

    # Delete $post_build_script if it already exists as it should be generated by a 
    # post-build action
    rm -f $post_build_script

    # Use custom provisioning profile and code sign identity if specified, otherwise
    # default to project settings
    # Note: xcodebuild always returns 0 even if the build failed. We look for failure in
    # the stderr output instead
    if [[ ! -z "$2" ]] && [[ ! -z "$3" ]]; then 
        ${XCODEBUILD_CMD} clean archive -scheme $1 -sdk "${TARGET_SDK}" \
        "CODE_SIGN_IDENTITY=$3" "PROVISIONING_PROFILE=$2" 2>$build_errors_file
    else
        ${XCODEBUILD_CMD} clean archive -scheme $1 -sdk "${TARGET_SDK}"
        2>$build_errors_file  
    fi

    errors=`grep -wc "The following build commands failed" $build_errors_file`
    if [ "$errors" != "0" ]
    then
        echo "BUILD FAILED. Error Log:"
        cat $build_errors_file
        rm $build_errors_file
        exit 1
    fi
    rm $build_errors_file

    # Check if archive_paths.sh exists
    if [ -f "$post_build_script" ]; then
        source "$post_build_script"
        if [ -z "$ARCHIVE_PATH" ]; then
            echo "'$post_build_script' exists but ARCHIVE_PATH was not set.
              Enabling auto-detection" 
        fi
    fi
    if [ -z "$ARCHIVE_PATH" ]; then
        # This is the format of the xcarchive path:
        # /Users/$USER/Library/Developer/Xcode/Archives/`date +%Y-%m-%d`/$1\ 
        # `date +%d-%m-%Y\ %H.%M`.xcarchive
        # In order to avoid mismatches with the hour/minute of creation of the archive and
        # the current time, we list all archives with the correct target that have been
        # built in the current day (this may fail if the build wraps around midnight) and
        # fetch the correct file with a combination of ls and grep.
        # This script can break only if there are multiple targets with exactly the same
        # name running at the same time.
        EXTRACTED_LINE=$(ls -lrt /Users/$USER/Library/Developer/Xcode/Archives/`date
          +%Y-%m-%d`/ | grep $1\ `date +%d-%m-%Y` | tail -n 1)
        if [ "$EXTRACTED_LINE" == "" ]; then
            echo "Error: couldn't fetch archive path"
            exit 1
        fi
        # ls -lrt prints lines with the following format
        # drwxr-xr-x  5 mario  1306712193  170 25 Jul 17:17 ArchiveTest 25-07-2013
        #   17.17.xcarchive
        # We can split this line with the " " separator and take the latest bit:
        #   17.17.xcarchive
        FILE_NAME_SUFFIX=$(echo $EXTRACTED_LINE | awk '{split($0,a," "); print a[11]}')
        if [ "$FILE_NAME_SUFFIX" == "" ]; then
            echo "Error: couldn't fetch archive path"
            exit 1
        fi
        # Finally, we can put everything together to generate the path to the xcarchive
        ARCHIVE_PATH="/Users/$USER/Library/Developer/Xcode/Archives/`date 
          +%Y-%m-%d`/$1 `date +%d-%m-%Y` $FILE_NAME_SUFFIX/"
    fi

    # Create output folder if it doesn't already exist
    mkdir -p "$OUTPUT"

    # Move archived xcarchive build to designated output folder
    mv -v "$ARCHIVE_PATH" "$OUTPUT"
}


# Check number of command line args
if [ $# -lt 1 ]; then
    echo "Syntax: `basename $0` <target name> [/path/to/provisioning-profile]
      [<code sign identity]"
    exit 1
fi

if [ ! -z "$2" ]; then
    PROVISIONING_PROFILE="$2"
fi

if [ ! -z "$3" ]; then
    SIGN_PROVISIONING_PROFILE="$3"
else
    if [ ! -z "$PROVISIONING_PROFILE" ]; then
        SIGN_PROVISIONING_PROFILE=$(cat "$PROVISIONING_PROFILE" | egrep -a -o
          '[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}')
    fi
fi


archive "$1" "$PROVISIONING_PROFILE" "$SIGN_PROVISIONING_PROFILE"

サンプル Xcode プロジェクトを含む完全なソース コードは、次の場所にあります。

https://github.com/bizz84/Xcode-xcarchive-command

于 2013-07-29T10:22:50.337 に答える