从命令行“构建和归档”Xcode。

时间:2021-04-25 00:10:43

Xcode 3.2 provides an awesome new feature under the Build menu, "Build and Archive" which generates an .ipa file suitable for Ad Hoc distribution. You can also open the Organizer, go to "Archived Applications," and "Submit Application to iTunesConnect."

Xcode 3.2在Build菜单下提供了一个很棒的新功能,“Build and Archive”生成了一个适合于临时分发的.ipa文件。您也可以打开组织者,去“存档的应用程序”和“提交应用到iTunesConnect。”

Is there a way to use "Build and Archive" from the command line (as part of a build script)? I'd assume that xcodebuild would be involved somehow, but the man page doesn't seem to say anything about this.

是否有方法从命令行(作为构建脚本的一部分)使用“构建和存档”?我假设xcodebuild会参与其中,但是这个人页面似乎并没有提到这个。

UPDATE Michael Grinich requested clarification; here's what exactly you can't do with command-line builds, features you can ONLY do with Xcode's Organizer after you "Build and Archive."

更新Michael Grinich要求澄清;以下是您无法使用命令行构建的功能,您只能在“构建和归档”之后使用Xcode的组织者。

  1. You can click "Share Application..." to share your IPA with beta testers. As Guillaume points out below, due to some Xcode magic, this IPA file does not require a separately distributed .mobileprovision file that beta testers need to install; that's magical. No command-line script can do it. For example, Arrix's script (submitted May 1) does not meet that requirement.
  2. 您可以单击“共享应用程序”来与beta测试人员共享您的IPA。正如Guillaume所指出的,由于一些Xcode的魔力,这个IPA文件不需要一个单独的分布式的. mobile提供文件,测试人员需要安装;这是不可思议的。没有命令行脚本可以做到这一点。例如,Arrix的脚本(提交的5月1)不满足该要求。
  3. More importantly, after you've beta tested a build, you can click "Submit Application to iTunes Connect" to submit that EXACT same build to Apple, the very binary you tested, without rebuilding it. That's impossible from the command line, because signing the app is part of the build process; you can sign bits for Ad Hoc beta testing OR you can sign them for submission to the App Store, but not both. No IPA built on the command-line can be beta tested on phones and then submitted directly to Apple.
  4. 更重要的是,在测试了一个构建版本之后,您可以点击“提交应用程序到iTunes Connect”,提交与苹果完全相同的构建版本,而无需重新构建它。这在命令行中是不可能的,因为签名应用程序是构建过程的一部分;你可以在特定的beta测试中签名,或者你可以在App Store上签名,但不是两个都可以。没有在命令行上构建的IPA可以在手机上进行beta测试,然后直接提交给苹果。

I'd love for someone to come along and prove me wrong: both of these features work great in the Xcode GUI and cannot be replicated from the command line.

我希望有人能来证明我的错误:这两个特性在Xcode GUI中都很有用,不能从命令行复制。

18 个解决方案

#1


295  

I found how to automate the build and archive process from the comand line, I just wrote a blog article explaining how you can achieve that.

我发现了如何从comand line自动化构建和归档过程,我只是写了一篇博客文章来解释如何实现这一点。

The command you have to use is xcrun:

您需要使用的命令是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}"

You will find all the details in the article. If you have any questions dont hesitate to ask.

你会在文章中找到所有的细节。如果有什么问题,请尽管问。

#2


264  

With Xcode 4.2 you can use the -scheme flag to do this:

使用Xcode 4.2,您可以使用-scheme标志来执行以下操作:

xcodebuild -scheme <SchemeName> archive

After this command the Archive will show up in the Xcode Organizer.

在此命令之后,存档将显示在Xcode组织者中。

#3


104  

Here is command line script for creating archive and IPA example. I have an iPhone xcode project , which is located in Desktop/MyiOSApp folder.

下面是创建归档和IPA示例的命令行脚本。我有一个iPhone xcode项目,它位于桌面/MyiOSApp文件夹中。

Execute following commands one by one .

一个接一个执行下列命令。

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"

This is tested with Xcode 5 and working fine for me.

这是用Xcode 5测试的,对我来说没问题。

#4


27  

I've been using my own build script to generate the ipa package for ad hoc distribution.

我一直在使用我自己的构建脚本生成用于临时分发的ipa包。

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

The script also increment the version number. You can remove that part if it's not needed. Hope it helps.

脚本还会增加版本号。如果不需要,可以删除该部分。希望它可以帮助。

#5


24  

We developed an iPad app with XCode 4.2.1 and wanted to integrate the build into our continuous integration (Jenkins) for OTA distribution. Here's the solution I came up with:

我们开发了一个带有XCode 4.2.1的iPad应用程序,并希望将构建集成到我们的持续集成(Jenkins)中,以实现OTA的分发。下面是我提出的解决方案:

# 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

Then Jenkins uploads the ipa, plist and html files to our webserver.

然后Jenkins将ipa、plist和html文件上传至我们的webserver。

This is the plist template:

这是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>

To set this up, you have to import the distribution certificate and provisioning profile into the designated user's keychain.

要设置这个,您必须将分发证书和配置文件导入到指定的用户的密钥链中。

#6


21  

The xcodebuild tool can build and export archive products with the -exportArchive flag (as of Xcode 5). The export step was previously only possible via the Xcode Organizer UI.

xcodebuild工具可以使用-exportArchive标志(如Xcode 5)构建和导出存档产品。

First archive your app:

第一个存档你的应用:

xcodebuild -scheme <scheme name> archive

Given $ARCHIVE_PATH (the path to the .xcarchive file), export the app from the archive with one of the following:

给定$ARCHIVE_PATH(指向.xcarchive文件的路径),将应用程序从归档文件导出为以下内容之一:

iOS .ipa file:

iOS .ipa文件:

xcodebuild -exportArchive -exportFormat ipa -archivePath "$ARCHIVE_PATH" -exportPath "myApp.ipa" -exportProvisioningProfile "My App Provisioning profile"

Mac .app file:

Mac .app文件:

xcodebuild -exportArchive -exportFormat app -archivePath "$ARCHIVE_PATH" -exportPath "myApp.app" -exportSigningIdentity "Developer ID Application: My Software Company"

In both commands the -exportProvisioningProfile and -exportSigningIdentity arguments are optional. man xcodebuild for details on the semantics. In these examples, the provisioning profile for the iOS build specified an AdHoc distribution provisioning profile, and the signing identity for the Mac app specified a Developer ID for export as a 3rd party application (i.e. not distributed via the Mac App Store).

在这两个命令中,-exportProvisioningProfile和-exportSigningIdentity参数都是可选的。man xcodebuild了解语义的详细信息。在这些示例中,iOS构建的配置配置文件指定了一个临时分发配置文件,而Mac应用程序的签名标识则指定了作为第三方应用程序导出的开发人员ID(即不通过Mac应用程序商店分发)。

#7


16  

I found some of the other answers here hard to get going. This article did if for me. Some paths may need to be absolute, as mentioned in the other answers.

我发现有些其他的答案很难回答。这篇文章是为我写的。有些路径可能需要是绝对的,如其他答案所述。

The Command:

命令:

xcrun -sdk iphoneos PackageApplication \
    "/path/to/build/MyApp.app" \
    -o "output/path/to/MyApp.ipa" \
    --sign "iPhone Distribution: My Company" \
    --embed "/path/to/something.mobileprovision"

#8


15  

You CAN actually resign a build, just as XCode does, so that you can test and ship the same binary. For example in my script (similar to those above) I build my release version signed as an AdHoc build, then I archive that as an IPA for testing, then resign with my distribution cert and create a zip file, which is what I send to Apple. The relevant line is:

实际上,您可以像XCode那样放弃构建,这样您就可以测试和发送相同的二进制代码。例如,在我的脚本(类似于上面的脚本)中,我构建了作为一个临时构建签名的发布版本,然后我将其归档为测试的IPA,然后使用我的发行证书和创建zip文件,这就是我发送给Apple的文件。相关的线路是:

codesign -f -vv -s "$DistributionIdentity" "$APPDIR"

#9


13  

For Xcode 7, you have a much simpler solution. The only extra work is that you have to create a configuration plist file for exporting archive.

对于Xcode 7,您有一个更简单的解决方案。惟一的额外工作是,您必须为导出存档创建一个配置plist文件。

(Compared to Xcode 6, in the results of xcrun xcodebuild -help, -exportFormat and -exportProvisioningProfile options are not mentioned any more; the former is deleted, and the latter is superseded by -exportOptionsPlist.)

(与Xcode 6相比,在xcrun xcodebuild -help的结果中没有提到-exportFormat和- exportproviingprofile选项;前者被删除,后者被-exportOptionsPlist取代。

Step 1, change directory to the folder including .xcodeproject or .xcworkspace file.

步骤1,将目录更改为包含.xcodeproject或.xcworkspace文件的文件夹。

cd MyProjectFolder

Step 2, use Xcode or /usr/libexec/PlistBuddy exportOptions.plist to create export options plist file. By the way, xcrun xcodebuild -help will tell you what keys you have to insert to the plist file.

步骤2,使用Xcode或/usr/libexec/PlistBuddy exportOptions。plist创建导出选项plist文件。顺便说一下,xcrun xcodebuild -help将告诉您必须将哪些键插入到plist文件中。

Step 3, create .xcarchive file (folder, in fact) as follows(build/ directory will be automatically created by Xcode right now),

第3步,创建.xcarchive文件(实际上是文件夹)如下(现在将自动创建一个构建/目录),

xcrun xcodebuild -scheme MyApp -configuration Release archive -archivePath build/MyApp.xcarchive

Step 4, export as .ipa file like this, which differs from Xcode6

步骤4,导出为.ipa文件,与Xcode6不同。

xcrun xcodebuild -exportArchive -exportPath build/ -archivePath build/MyApp.xcarchive/ -exportOptionsPlist exportOptions.plist

Now, you get an ipa file in build/ directory. Just send it to apple App Store.

现在,在build/目录中获得一个ipa文件。把它发送到苹果应用商店。

By the way, the ipa file created by Xcode 7 is much larger than by Xcode 6.

顺便说一下,Xcode 7创建的ipa文件要比Xcode 6大得多。

#10


11  

I have given a brief description of steps to follow, and parameters to pass while generating an ipa using terrminal below:

我已经给出了下面步骤的简要说明,以及在生成ipa时要使用的参数:

  1. Go to the folder which contains the MyApp.xcodeproject file in terminal

    转到包含MyApp的文件夹。在终端xcodeproject文件

  2. By using the command given below you will get all the Targets of the application

    通过使用下面给出的命令,您将获得应用程序的所有目标。

    /usr/bin/xcodebuild -list 
    
  3. After the above command is executed, you will get a list of targets of which you should select a specific target you need to generate .ipa

    在执行上述命令之后,您将获得一个目标列表,其中您应该选择要生成的特定目标。

    /usr/bin/xcodebuild -target $TARGET -sdk iphoneos -configuration Release
    
  4. The above command builds the project and creates a .app file.The path to locate the .app file is ./build/Release-iphoneos/MyApp.app

    上面的命令构建项目并创建一个.app文件。找到.app文件的路径是。/build/Release-iphoneos/MyApp.app。

  5. After Build gets succeeded then execute the following command to generate .ipa of the application using Developer Name and Provisioning Profile using the syntax below:

    在构建成功之后,执行以下命令来生成.ipa,使用开发人员名称和配置概要文件,使用以下语法:

    /usr/bin/xcrun -sdk iphoneos PackageApplication -v “${TARGET}.app” -o “${OUTDIR}/${TARGET}.ipa” –sign “${IDENTITY}” –embed “${PROVISONING_PROFILE}”
    

Explanation of each Parameter in the above syntax:

以上句法参数说明:

${TARGET}.app                == Target path (ex :/Users/XXXXXX/desktop/Application/build/Release-iphoneos/MyApp.app)
${OUTDIR}                    == Select the output directory(Where you want to save .ipa file)
${IDENTITY}                   == iPhone Developer: XXXXXXX (XXXXXXXXXX)(which can be obtained from Keychain access)
${PROVISONING_PROFILE}   == Path to the provisioning profile(/Users/XXXXXX/Library/MobileDevice/Provisioning Profiles/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.mobileprovision”)
  1. ipa will be generated at selected output directory "${OUTDIR}"
  2. ipa将在选定的输出目录“${OUTDIR}”中生成。

#11


8  

Xcode 8:


IPA Format:

音标格式:

xcodebuild -exportArchive -exportFormat IPA -archivePath MyMobileApp.xcarchive -exportPath MyMobileApp.ipa -exportProvisioningProfile 'MyMobileApp Distribution Profile'

Exports the archive MyMobileApp.xcarchive as an IPA file to the path MyMobileApp.ipa using the provisioning profile MyMobileApp Distribution Profile.

存档MyMobileApp出口。xcarchive作为一个IPA文件到path MyMobileApp。ipa使用配置文件MyMobileApp分发配置文件。

APP Format:

应用格式:

xcodebuild -exportArchive -exportFormat APP -archivePath MyMacApp.xcarchive -exportPath MyMacApp.pkg -exportSigningIdentity 'Developer ID Application: My Team'

Exports the archive MyMacApp.xcarchive as a PKG file to the path MyMacApp.pkg using the appli-cation application cation signing identity Developer ID Application: My Team. The installer signing identity Developer ID Installer: My Team is implicitly used to sign the exported package.

存档MyMacApp出口。xcarchive作为PKG文件的路径MyMacApp。pkg使用申请阳离子签名的身份开发ID应用程序:我的团队。安装程序签名身份开发人员ID安装程序:我的团队被隐式地用于签署导出的包。

Xcodebuild man page

Xcodebuild手册页

#12


6  

Go to the folder where's your project root and:

到你的项目根目录,

xcodebuild -project projectname -activetarget -activeconfiguration archive

#13


4  

Going one step further, uploading to iTunesConnect via commandline with Xcode 7! (Assuming you are starting with an .ipa that has been signed with the correct release profile and signing identity.)

更进一步,通过命令行上传至iTunesConnect, Xcode 7!(假设您从一个已经签署了正确的发布配置文件和签名标识的.ipa开始。)

Enter altool, the CLI interface for the Application Loader (docs, page 38). Hidden deep within Xcode.app's structure, is a handy function to let us upload directly to ItunesConnect.

输入altool,应用程序加载程序的CLI接口(文档,第38页)。在Xcode深藏。app的结构,是一个方便的功能,让我们直接上传到ItunesConnect。

/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/altool

Simply run $ altool --upload-app -f file -u username [-p password] to upload your newly minted .ipa straight to Apple. The password is optional, and will prompt you for it if you leave it off the command.

简单运行$ altool——upload-app -f文件-u用户名[-p密码],上传你的新创建的.ipa直接到苹果。密码是可选的,如果您不使用它,将提示您输入密码。

If there are any issues with the app during the verification step, the console will print them out.

如果在验证步骤中应用程序有任何问题,控制台将打印出来。

You will likely have to export the path to altool if you don't want to save its location.

如果您不想保存它的位置,那么您很可能需要导出到altool的路径。

export PATH=$PATH:/Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/

Thats it! Simply login to iTunesConnect.com and select your new build for testing with testflight.

这就是它!只需登录到iTunesConnect.com,并选择您的新构建以进行testflight测试。

Final Note: If you get an error saying Exception while launching iTunesTransporter: Transporter not found at path: /usr/local/itms/bin/iTMSTransporter. You should reinstall the application, you can follow the suggestion on this SO answer, to run a symlink to the correct location:

最后注意:如果你在启动itunesporter时遇到一个错误,表示异常:在路径上没有发现:/ usr/local/itms/bin/itmsporter。您应该重新安装应用程序,您可以按照这个建议的建议,运行一个符号链接到正确的位置:

ln -s /Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/itms /usr/local/itms

#14


3  

Improving on Vincent's answer, I wrote a script to do that: xcodearchive
It allows you to archive (generate an ipa) your project via the command line. Think of it like the sister of the xcodebuild command, but for archiving.

改进Vincent的答案,我编写了一个脚本:xcodearchive,它允许您通过命令行存档(生成一个ipa)您的项目。可以把它看作是xcodebuild命令的姐妹,但是要存档。

Code is available on github: http://github.com/gcerquant/xcodearchive

代码可以在github上找到:http://github.com/gcerquant/xcodearchive。


One option of the script is to enable the archiving of the dSYM symbols in a timestamped archive. No excuse to not keep the symbols anymore, and not be able to symbolicate the crash log you might later receive.

该脚本的一个选项是在一个时间戳的存档中启用dSYM符号的归档。没有理由不再保留这些符号,也不能象征性地表示你以后可能会收到的崩溃日志。

#15


2  

try xctool, it is a replacement for Apple's xcodebuild that makes it easier to build and test iOS and Mac products. It's especially helpful for continuous integration. It has a few extra features:

尝试xctool,它是苹果的xcodebuild的替代品,可以更容易地构建和测试iOS和Mac产品。它特别有助于持续集成。它有一些额外的特点:

  1. Runs the same tests as Xcode.app.
  2. 运行与Xcode.app相同的测试。
  3. Structured output of build and test results.
  4. 构建和测试结果的结构化输出。
  5. Human-friendly, ANSI-colored output.
  6. 人性化,ANSI-colored输出。

No.3 is extremely useful. I don't if anyone can read the console output of xcodebuild, I can't, usually it gave me one line with 5000+ characters. Even harder to read than a thesis paper.

第三是非常有用的。我不知道是否有人能读取xcodebuild的控制台输出,我不能,通常它给了我一个5000+字符的线。甚至比论文还难读。

xctool: https://github.com/facebook/xctool

xctool:https://github.com/facebook/xctool

#16


2  

if you use next tool: https://github.com/nomad/shenzhen

如果您使用下一个工具:https://github.com/nomad/shenzhen。

then this task is very easy:

这个任务很简单:

which ipa 1>/dev/null 2>&1 || echo 'no shenzhen. to install use: sudo gem install shenzhen --no-ri --no-rdoc'
ipa build --verbose --scheme "${schemeName}"

source

#17


2  

After updating to Xcode 8, I found that enterprise ipa generate by

更新到Xcode 8后,我发现企业ipa生成。

/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}" 

Command cannot be launched because of some signature issue. The log indicates that "warning: PackageApplication is deprecated, use xcodebuild -exportArchive instead.

由于某些签名问题,命令不能启动。日志表示“警告:PackageApplication被弃用,使用xcodebuild -exportArchive代替。”

So I switch to xcodebuild -exportArchive and everything went back normal.

所以我切换到xcodebuild -exportArchive,一切恢复正常。

#18


1  

You mean the validate/share/submit options? I think those are specific to Xcode, and not suited for a command-line build tool.

您是指验证/共享/提交选项吗?我认为这些都是特定于Xcode的,不适合命令行构建工具。

With some cleverness, I bet you could make a script to do it for you. It looks like they're just stored in ~/Library/MobileDevice/Archived Applications/ with a UUDI and a plist. I can't imagine it would be that hard to reverse engineer the validator either.

有了一些聪明,我打赌你可以做一个脚本为你做。看起来它们只是存储在~/Library/MobileDevice/存档的应用程序/使用UUDI和plist。我无法想象,要逆向设计验证器会有多么困难。

The process I'm interested automating is sending builds to beta testers. (Since App Store submission happens infrequently, I don't mind doing it manually, especially since I often need to add new description text.) By doing a pseudo Build+Archive using Xcode's CLI, I can trigger automatic builds from every code commit, create IPA files with embedded provisioning profiles, and email it to testers.

我感兴趣的过程是将构建版本发送给beta测试人员。(因为App Store的提交很少发生,所以我不介意手动操作,特别是因为我经常需要添加新的描述文本。)通过使用Xcode的CLI做一个伪构建+归档,我可以触发每个代码提交的自动构建,创建带有嵌入式配置文件的IPA文件,并将其发送给测试人员。

#1


295  

I found how to automate the build and archive process from the comand line, I just wrote a blog article explaining how you can achieve that.

我发现了如何从comand line自动化构建和归档过程,我只是写了一篇博客文章来解释如何实现这一点。

The command you have to use is xcrun:

您需要使用的命令是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}"

You will find all the details in the article. If you have any questions dont hesitate to ask.

你会在文章中找到所有的细节。如果有什么问题,请尽管问。

#2


264  

With Xcode 4.2 you can use the -scheme flag to do this:

使用Xcode 4.2,您可以使用-scheme标志来执行以下操作:

xcodebuild -scheme <SchemeName> archive

After this command the Archive will show up in the Xcode Organizer.

在此命令之后,存档将显示在Xcode组织者中。

#3


104  

Here is command line script for creating archive and IPA example. I have an iPhone xcode project , which is located in Desktop/MyiOSApp folder.

下面是创建归档和IPA示例的命令行脚本。我有一个iPhone xcode项目,它位于桌面/MyiOSApp文件夹中。

Execute following commands one by one .

一个接一个执行下列命令。

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"

This is tested with Xcode 5 and working fine for me.

这是用Xcode 5测试的,对我来说没问题。

#4


27  

I've been using my own build script to generate the ipa package for ad hoc distribution.

我一直在使用我自己的构建脚本生成用于临时分发的ipa包。

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

The script also increment the version number. You can remove that part if it's not needed. Hope it helps.

脚本还会增加版本号。如果不需要,可以删除该部分。希望它可以帮助。

#5


24  

We developed an iPad app with XCode 4.2.1 and wanted to integrate the build into our continuous integration (Jenkins) for OTA distribution. Here's the solution I came up with:

我们开发了一个带有XCode 4.2.1的iPad应用程序,并希望将构建集成到我们的持续集成(Jenkins)中,以实现OTA的分发。下面是我提出的解决方案:

# 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

Then Jenkins uploads the ipa, plist and html files to our webserver.

然后Jenkins将ipa、plist和html文件上传至我们的webserver。

This is the plist template:

这是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>

To set this up, you have to import the distribution certificate and provisioning profile into the designated user's keychain.

要设置这个,您必须将分发证书和配置文件导入到指定的用户的密钥链中。

#6


21  

The xcodebuild tool can build and export archive products with the -exportArchive flag (as of Xcode 5). The export step was previously only possible via the Xcode Organizer UI.

xcodebuild工具可以使用-exportArchive标志(如Xcode 5)构建和导出存档产品。

First archive your app:

第一个存档你的应用:

xcodebuild -scheme <scheme name> archive

Given $ARCHIVE_PATH (the path to the .xcarchive file), export the app from the archive with one of the following:

给定$ARCHIVE_PATH(指向.xcarchive文件的路径),将应用程序从归档文件导出为以下内容之一:

iOS .ipa file:

iOS .ipa文件:

xcodebuild -exportArchive -exportFormat ipa -archivePath "$ARCHIVE_PATH" -exportPath "myApp.ipa" -exportProvisioningProfile "My App Provisioning profile"

Mac .app file:

Mac .app文件:

xcodebuild -exportArchive -exportFormat app -archivePath "$ARCHIVE_PATH" -exportPath "myApp.app" -exportSigningIdentity "Developer ID Application: My Software Company"

In both commands the -exportProvisioningProfile and -exportSigningIdentity arguments are optional. man xcodebuild for details on the semantics. In these examples, the provisioning profile for the iOS build specified an AdHoc distribution provisioning profile, and the signing identity for the Mac app specified a Developer ID for export as a 3rd party application (i.e. not distributed via the Mac App Store).

在这两个命令中,-exportProvisioningProfile和-exportSigningIdentity参数都是可选的。man xcodebuild了解语义的详细信息。在这些示例中,iOS构建的配置配置文件指定了一个临时分发配置文件,而Mac应用程序的签名标识则指定了作为第三方应用程序导出的开发人员ID(即不通过Mac应用程序商店分发)。

#7


16  

I found some of the other answers here hard to get going. This article did if for me. Some paths may need to be absolute, as mentioned in the other answers.

我发现有些其他的答案很难回答。这篇文章是为我写的。有些路径可能需要是绝对的,如其他答案所述。

The Command:

命令:

xcrun -sdk iphoneos PackageApplication \
    "/path/to/build/MyApp.app" \
    -o "output/path/to/MyApp.ipa" \
    --sign "iPhone Distribution: My Company" \
    --embed "/path/to/something.mobileprovision"

#8


15  

You CAN actually resign a build, just as XCode does, so that you can test and ship the same binary. For example in my script (similar to those above) I build my release version signed as an AdHoc build, then I archive that as an IPA for testing, then resign with my distribution cert and create a zip file, which is what I send to Apple. The relevant line is:

实际上,您可以像XCode那样放弃构建,这样您就可以测试和发送相同的二进制代码。例如,在我的脚本(类似于上面的脚本)中,我构建了作为一个临时构建签名的发布版本,然后我将其归档为测试的IPA,然后使用我的发行证书和创建zip文件,这就是我发送给Apple的文件。相关的线路是:

codesign -f -vv -s "$DistributionIdentity" "$APPDIR"

#9


13  

For Xcode 7, you have a much simpler solution. The only extra work is that you have to create a configuration plist file for exporting archive.

对于Xcode 7,您有一个更简单的解决方案。惟一的额外工作是,您必须为导出存档创建一个配置plist文件。

(Compared to Xcode 6, in the results of xcrun xcodebuild -help, -exportFormat and -exportProvisioningProfile options are not mentioned any more; the former is deleted, and the latter is superseded by -exportOptionsPlist.)

(与Xcode 6相比,在xcrun xcodebuild -help的结果中没有提到-exportFormat和- exportproviingprofile选项;前者被删除,后者被-exportOptionsPlist取代。

Step 1, change directory to the folder including .xcodeproject or .xcworkspace file.

步骤1,将目录更改为包含.xcodeproject或.xcworkspace文件的文件夹。

cd MyProjectFolder

Step 2, use Xcode or /usr/libexec/PlistBuddy exportOptions.plist to create export options plist file. By the way, xcrun xcodebuild -help will tell you what keys you have to insert to the plist file.

步骤2,使用Xcode或/usr/libexec/PlistBuddy exportOptions。plist创建导出选项plist文件。顺便说一下,xcrun xcodebuild -help将告诉您必须将哪些键插入到plist文件中。

Step 3, create .xcarchive file (folder, in fact) as follows(build/ directory will be automatically created by Xcode right now),

第3步,创建.xcarchive文件(实际上是文件夹)如下(现在将自动创建一个构建/目录),

xcrun xcodebuild -scheme MyApp -configuration Release archive -archivePath build/MyApp.xcarchive

Step 4, export as .ipa file like this, which differs from Xcode6

步骤4,导出为.ipa文件,与Xcode6不同。

xcrun xcodebuild -exportArchive -exportPath build/ -archivePath build/MyApp.xcarchive/ -exportOptionsPlist exportOptions.plist

Now, you get an ipa file in build/ directory. Just send it to apple App Store.

现在,在build/目录中获得一个ipa文件。把它发送到苹果应用商店。

By the way, the ipa file created by Xcode 7 is much larger than by Xcode 6.

顺便说一下,Xcode 7创建的ipa文件要比Xcode 6大得多。

#10


11  

I have given a brief description of steps to follow, and parameters to pass while generating an ipa using terrminal below:

我已经给出了下面步骤的简要说明,以及在生成ipa时要使用的参数:

  1. Go to the folder which contains the MyApp.xcodeproject file in terminal

    转到包含MyApp的文件夹。在终端xcodeproject文件

  2. By using the command given below you will get all the Targets of the application

    通过使用下面给出的命令,您将获得应用程序的所有目标。

    /usr/bin/xcodebuild -list 
    
  3. After the above command is executed, you will get a list of targets of which you should select a specific target you need to generate .ipa

    在执行上述命令之后,您将获得一个目标列表,其中您应该选择要生成的特定目标。

    /usr/bin/xcodebuild -target $TARGET -sdk iphoneos -configuration Release
    
  4. The above command builds the project and creates a .app file.The path to locate the .app file is ./build/Release-iphoneos/MyApp.app

    上面的命令构建项目并创建一个.app文件。找到.app文件的路径是。/build/Release-iphoneos/MyApp.app。

  5. After Build gets succeeded then execute the following command to generate .ipa of the application using Developer Name and Provisioning Profile using the syntax below:

    在构建成功之后,执行以下命令来生成.ipa,使用开发人员名称和配置概要文件,使用以下语法:

    /usr/bin/xcrun -sdk iphoneos PackageApplication -v “${TARGET}.app” -o “${OUTDIR}/${TARGET}.ipa” –sign “${IDENTITY}” –embed “${PROVISONING_PROFILE}”
    

Explanation of each Parameter in the above syntax:

以上句法参数说明:

${TARGET}.app                == Target path (ex :/Users/XXXXXX/desktop/Application/build/Release-iphoneos/MyApp.app)
${OUTDIR}                    == Select the output directory(Where you want to save .ipa file)
${IDENTITY}                   == iPhone Developer: XXXXXXX (XXXXXXXXXX)(which can be obtained from Keychain access)
${PROVISONING_PROFILE}   == Path to the provisioning profile(/Users/XXXXXX/Library/MobileDevice/Provisioning Profiles/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.mobileprovision”)
  1. ipa will be generated at selected output directory "${OUTDIR}"
  2. ipa将在选定的输出目录“${OUTDIR}”中生成。

#11


8  

Xcode 8:


IPA Format:

音标格式:

xcodebuild -exportArchive -exportFormat IPA -archivePath MyMobileApp.xcarchive -exportPath MyMobileApp.ipa -exportProvisioningProfile 'MyMobileApp Distribution Profile'

Exports the archive MyMobileApp.xcarchive as an IPA file to the path MyMobileApp.ipa using the provisioning profile MyMobileApp Distribution Profile.

存档MyMobileApp出口。xcarchive作为一个IPA文件到path MyMobileApp。ipa使用配置文件MyMobileApp分发配置文件。

APP Format:

应用格式:

xcodebuild -exportArchive -exportFormat APP -archivePath MyMacApp.xcarchive -exportPath MyMacApp.pkg -exportSigningIdentity 'Developer ID Application: My Team'

Exports the archive MyMacApp.xcarchive as a PKG file to the path MyMacApp.pkg using the appli-cation application cation signing identity Developer ID Application: My Team. The installer signing identity Developer ID Installer: My Team is implicitly used to sign the exported package.

存档MyMacApp出口。xcarchive作为PKG文件的路径MyMacApp。pkg使用申请阳离子签名的身份开发ID应用程序:我的团队。安装程序签名身份开发人员ID安装程序:我的团队被隐式地用于签署导出的包。

Xcodebuild man page

Xcodebuild手册页

#12


6  

Go to the folder where's your project root and:

到你的项目根目录,

xcodebuild -project projectname -activetarget -activeconfiguration archive

#13


4  

Going one step further, uploading to iTunesConnect via commandline with Xcode 7! (Assuming you are starting with an .ipa that has been signed with the correct release profile and signing identity.)

更进一步,通过命令行上传至iTunesConnect, Xcode 7!(假设您从一个已经签署了正确的发布配置文件和签名标识的.ipa开始。)

Enter altool, the CLI interface for the Application Loader (docs, page 38). Hidden deep within Xcode.app's structure, is a handy function to let us upload directly to ItunesConnect.

输入altool,应用程序加载程序的CLI接口(文档,第38页)。在Xcode深藏。app的结构,是一个方便的功能,让我们直接上传到ItunesConnect。

/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/altool

Simply run $ altool --upload-app -f file -u username [-p password] to upload your newly minted .ipa straight to Apple. The password is optional, and will prompt you for it if you leave it off the command.

简单运行$ altool——upload-app -f文件-u用户名[-p密码],上传你的新创建的.ipa直接到苹果。密码是可选的,如果您不使用它,将提示您输入密码。

If there are any issues with the app during the verification step, the console will print them out.

如果在验证步骤中应用程序有任何问题,控制台将打印出来。

You will likely have to export the path to altool if you don't want to save its location.

如果您不想保存它的位置,那么您很可能需要导出到altool的路径。

export PATH=$PATH:/Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/

Thats it! Simply login to iTunesConnect.com and select your new build for testing with testflight.

这就是它!只需登录到iTunesConnect.com,并选择您的新构建以进行testflight测试。

Final Note: If you get an error saying Exception while launching iTunesTransporter: Transporter not found at path: /usr/local/itms/bin/iTMSTransporter. You should reinstall the application, you can follow the suggestion on this SO answer, to run a symlink to the correct location:

最后注意:如果你在启动itunesporter时遇到一个错误,表示异常:在路径上没有发现:/ usr/local/itms/bin/itmsporter。您应该重新安装应用程序,您可以按照这个建议的建议,运行一个符号链接到正确的位置:

ln -s /Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/itms /usr/local/itms

#14


3  

Improving on Vincent's answer, I wrote a script to do that: xcodearchive
It allows you to archive (generate an ipa) your project via the command line. Think of it like the sister of the xcodebuild command, but for archiving.

改进Vincent的答案,我编写了一个脚本:xcodearchive,它允许您通过命令行存档(生成一个ipa)您的项目。可以把它看作是xcodebuild命令的姐妹,但是要存档。

Code is available on github: http://github.com/gcerquant/xcodearchive

代码可以在github上找到:http://github.com/gcerquant/xcodearchive。


One option of the script is to enable the archiving of the dSYM symbols in a timestamped archive. No excuse to not keep the symbols anymore, and not be able to symbolicate the crash log you might later receive.

该脚本的一个选项是在一个时间戳的存档中启用dSYM符号的归档。没有理由不再保留这些符号,也不能象征性地表示你以后可能会收到的崩溃日志。

#15


2  

try xctool, it is a replacement for Apple's xcodebuild that makes it easier to build and test iOS and Mac products. It's especially helpful for continuous integration. It has a few extra features:

尝试xctool,它是苹果的xcodebuild的替代品,可以更容易地构建和测试iOS和Mac产品。它特别有助于持续集成。它有一些额外的特点:

  1. Runs the same tests as Xcode.app.
  2. 运行与Xcode.app相同的测试。
  3. Structured output of build and test results.
  4. 构建和测试结果的结构化输出。
  5. Human-friendly, ANSI-colored output.
  6. 人性化,ANSI-colored输出。

No.3 is extremely useful. I don't if anyone can read the console output of xcodebuild, I can't, usually it gave me one line with 5000+ characters. Even harder to read than a thesis paper.

第三是非常有用的。我不知道是否有人能读取xcodebuild的控制台输出,我不能,通常它给了我一个5000+字符的线。甚至比论文还难读。

xctool: https://github.com/facebook/xctool

xctool:https://github.com/facebook/xctool

#16


2  

if you use next tool: https://github.com/nomad/shenzhen

如果您使用下一个工具:https://github.com/nomad/shenzhen。

then this task is very easy:

这个任务很简单:

which ipa 1>/dev/null 2>&1 || echo 'no shenzhen. to install use: sudo gem install shenzhen --no-ri --no-rdoc'
ipa build --verbose --scheme "${schemeName}"

source

#17


2  

After updating to Xcode 8, I found that enterprise ipa generate by

更新到Xcode 8后,我发现企业ipa生成。

/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}" 

Command cannot be launched because of some signature issue. The log indicates that "warning: PackageApplication is deprecated, use xcodebuild -exportArchive instead.

由于某些签名问题,命令不能启动。日志表示“警告:PackageApplication被弃用,使用xcodebuild -exportArchive代替。”

So I switch to xcodebuild -exportArchive and everything went back normal.

所以我切换到xcodebuild -exportArchive,一切恢复正常。

#18


1  

You mean the validate/share/submit options? I think those are specific to Xcode, and not suited for a command-line build tool.

您是指验证/共享/提交选项吗?我认为这些都是特定于Xcode的,不适合命令行构建工具。

With some cleverness, I bet you could make a script to do it for you. It looks like they're just stored in ~/Library/MobileDevice/Archived Applications/ with a UUDI and a plist. I can't imagine it would be that hard to reverse engineer the validator either.

有了一些聪明,我打赌你可以做一个脚本为你做。看起来它们只是存储在~/Library/MobileDevice/存档的应用程序/使用UUDI和plist。我无法想象,要逆向设计验证器会有多么困难。

The process I'm interested automating is sending builds to beta testers. (Since App Store submission happens infrequently, I don't mind doing it manually, especially since I often need to add new description text.) By doing a pseudo Build+Archive using Xcode's CLI, I can trigger automatic builds from every code commit, create IPA files with embedded provisioning profiles, and email it to testers.

我感兴趣的过程是将构建版本发送给beta测试人员。(因为App Store的提交很少发生,所以我不介意手动操作,特别是因为我经常需要添加新的描述文本。)通过使用Xcode的CLI做一个伪构建+归档,我可以触发每个代码提交的自动构建,创建带有嵌入式配置文件的IPA文件,并将其发送给测试人员。