為什么要用xcodebuild 命令行打包?因?yàn)椴粫?huì)受到 Jenkins xcode 插件的影響。最近就是因?yàn)樯?jí)了Jenkins xcode插件,導(dǎo)致所有xcode項(xiàng)目無(wú)法打包。
先來(lái)看看 xcodebuild 命令是怎樣打包和發(fā)布 ios 項(xiàng)目的
一 、xcodebuild 打包解析
1、xcodebuild 常用命令
xcodebuild -showsdks: 列出 Xcode 所有可用的 SDKs-
xcodebuild -showBuildSettings
xcodebuild -showBuildSettings [-project name.xcodeproj | [-workspace name.xcworkspace -scheme schemename]]查看當(dāng)前工程 build setting 的配置參數(shù),Xcode 詳細(xì)的 build setting 參數(shù)參考官方文檔 Xcode Build Setting Reference, 已有的配置參數(shù)可以在終端中以 buildsetting=value 的形式進(jìn)行覆蓋重新設(shè)置
-
xcodebuild -list
xcodebuild -list [-project name.xcodeproj | -workspace name.xcworkspace]查看 project 中的 targets 和 configurations,或者 workspace 中 schemes
2、打開(kāi)鑰匙串訪問(wèn), 導(dǎo)入證書
security unlock-keychain "-p" password "/Users/***/Library/Keychains/login.keychain-db"
3、清理項(xiàng)目
xcodebuild -workspace ***.xcworkspace -scheme *** -configuration Release clean
4、編譯 archive
xcodebuild archive -workspace $project_workspace \
-scheme $project_scheme \
-configuration $Configuration \
PLATFORM_NAME=iphoneos \
-archivePath $archive_path \
BUILD_DIR="$build_dir" \
CODE_SIGN_IDENTITY="$CODE_SIGN_IDENTITY" \
PROVISIONING_PROFILE_SPECIFIER="$CPROVISIONING_PROFILE_NAME" \
PROVISIONING_PROFILE="${PROFILE_UUID}" \
PRODUCT_BUNDLE_IDENTIFIER="${BUILD_ID}" \
-quiet
參數(shù)解析
-workspace 項(xiàng)目的workspace,以 .xcworkspace 命名的文件
-scheme 可通過(guò) xcodebuild -list 查詢
BUILD_DIR 編譯輸出路徑
-archivePath acrhive的目標(biāo)路徑,在BUIDL_DIR下
-
CODE_SIGN_IDENTITY 證書名稱, 注意可能會(huì)包證書錯(cuò)誤
CODE_SIGN_IDENTITY獲取方法:
打開(kāi)你的鑰匙串訪問(wèn)->選中目標(biāo)證書->右鍵->顯示簡(jiǎn)介,把標(biāo)題復(fù)制出來(lái)就可以了。
-
PROVISIONING_PROFILE_SPECIFIER
描述文件名
xxx.moileprovision -
PROVISIONING_PROFILE
描述文件UUID , 打開(kāi)
xxx.moileprovision文件,搜索UUID PRODUCT_BUNDLE_IDENTIFIER BUILD_ID
com.xxxx.mall-quiet 只輸出警告、錯(cuò)誤消息
5、以版本號(hào)命名 .ipa文件
/usr/libexec/PlistBuddy -c "Print :ApplicationProperties:CFBundleVersion" ${archivePath}/Info.plist
/usr/libexec/PlistBuddy -c "Print :ApplicationProperties:CFBundleShortVersionString" ${archivePath}/Info.plist
6、輸出 IPA 包文件
xcodebuild -exportArchive -archivePath $archive_path -exportOptionsPlist $exportOptionsPlist -exportPath $export_path
-
-exportOptionsPlist
這是必須項(xiàng),是一個(gè)配置文件,里面配置了證書信息什么的。
XCode9以后如果使用命令打包,就需要有這個(gè)配置文件。
創(chuàng)建ExportOptions.plist的方式有兩種:
1 、XCode執(zhí)行發(fā)布,生產(chǎn)ipa同時(shí)會(huì)同時(shí)生成這個(gè)文件。
2、 也可以手動(dòng)創(chuàng)建ExportOptions.plist,然后加入相關(guān)鍵值對(duì)。OptionExport.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>signingStyle</key> <string>manual</string> <key>method</key> <string>development</string> <key>signingCertificate</key> <string>iOS Developer</string> <key>provisioningProfiles</key> <dict> <key>'${BundleID}'</key> <string>'${PROFILE_UUID}'</string> </dict> <key>iCloudContainerEnvironment</key> <string>Development</string> <key>stripSwiftSymbols</key> <key>teamID</key> <string>XXXXXXXXX</string> <true/> <key>compileBitcode</key> <true/> </dict> </plist>OptionExport.plist各字段說(shuō)明
method: 字符串,為打包的類型,分為app-store,ad-hoc,enterprise和development,根據(jù)自己實(shí)際打包情況填寫。
provisioningProfiles: 字典,Xcode9需要,鍵值對(duì)為{bundleid:證書標(biāo)識(shí) Identifiers },{PROFILE_UUID:描述文件名對(duì)應(yīng)的UUID。}
signingCertificate: 證書類型,開(kāi)發(fā)環(huán)境為iPhone Developer,生產(chǎn)環(huán)境為iPhone Distribution。
signingStyle: 自動(dòng)還是手動(dòng)(manual與automatic),填寫manual即可。
stripSwiftSymbols: 填寫為YES。
teamID: 為開(kāi)團(tuán)隊(duì)ID,在鑰匙串中點(diǎn)擊證書詳情可以查看到。
uploadBitcode: 為YES即可。
uploadSymbols: 為YES即可。
!錯(cuò)誤解決
error: Missing private key for signing certificate. Failed to locate the private key matching certificate "Apple Development: *********" in the keychain. To sign with this signing certificate, install its private key in your keychain. If you don't have the private key, select a different signing certificate for CODE_SIGN_IDENTITY in the build settings editor. (in target 'ALWMallGuideDevelop' from project 'ALWMallGuide')
刪除 CODE_SIGN_IDENTITY="$CODE_SIGN_IDENTITY" 參數(shù)即可
二、 jenkins配置范例
需要的插件
git,emall, Inject environment variables(環(huán)境變量注入)
1、倉(cāng)庫(kù)配置

2、構(gòu)建腳本
先添加 shell 將變量寫入文件
# 打包的環(huán)境,正式環(huán)境為空,可選 {'Develop'; 'Release'; ''}
APP_ENV="Develop"
#工程名字(Target名字)
Project_Name="ALWMallGuide"
# build 路徑
project_workspace="${Project_Name}.xcworkspace"
project_scheme="${Project_Name}${APP_ENV}"
# 獲取app版本號(hào)
APP_VERSION=`/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "${WORKSPACE}/ALWMallGuide/Resources/${project_scheme}-Info.plist"`
export_path="/Users/admin/project/build/${Project_Name}"
export_name="${export_path}/${project_scheme}_${APP_VERSION}.ipa"
# archive 目標(biāo)路徑
build_dir="${WORKSPACE}/build"
archive_path="${build_dir}/${project_scheme}.xcarchive"
#plist文件
exportOptionsPlist="${build_dir}/${project_scheme}.plist"
# 構(gòu)建變量寫入文件
echo "APP_VERSION=${APP_VERSION}
project_workspace=${project_workspace}
project_scheme=${project_scheme}
export_path=${export_path}
export_name=${export_name}
build_dir=${build_dir}
archive_path=${archive_path}
exportOptionsPlist=${exportOptionsPlist}" > BuildVariable
添加環(huán)境變量注入

# 打包的環(huán)境,正式環(huán)境為空,可選 {'Develop'; 'Release'; ''}
APP_ENV=Develop
#配置環(huán)境,Release或者Debug
Configuration=Release
#AdHoc版本的Bundle ID
BundleID=com.xxxx.mall
#證書名#描述文件
CODE_SIGN_IDENTITY=Apple Development: **************
CPROVISIONING_PROFILE_NAME=***********Mall_dep
PROFILE_UUID=9f4b27dc-f3f7-45e3-bb0c-816c7586560f
添加打包腳本(Execute shell)
#!/bin/bash
#author Jony
func_export_plist(){
echo '<?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>signingStyle</key>
<string>manual</string>
<key>method</key>
<string>development</string>
<key>signingCertificate</key>
<string>iOS Developer</string>
<key>provisioningProfiles</key>
<dict>
<key>'${BundleID}'</key>
<string>'${PROFILE_UUID}'</string>
</dict>
<key>iCloudContainerEnvironment</key>
<string>Development</string>
<key>stripSwiftSymbols</key>
<true/>
<key>compileBitcode</key>
<true/>
</dict>
</plist>' > ${exportOptionsPlist}
}
func_build(){
# 證書解鎖
security unlock-keychain -p 123456 ~/Library/Keychains/login.keychain-db
# 清理
xcodebuild clean -workspace $project_workspace -scheme $project_scheme -configuration $Configuration
# 構(gòu)建 archive 包
xcodebuild archive -workspace $project_workspace \
-scheme $project_scheme \
-configuration $Configuration \
PLATFORM_NAME=iphoneos \
-archivePath $archive_path \
BUILD_DIR="$build_dir" \
PROVISIONING_PROFILE_SPECIFIER="$CPROVISIONING_PROFILE_NAME" \
PROVISIONING_PROFILE="${PROFILE_UUID}" \
PRODUCT_BUNDLE_IDENTIFIER="${BundleID}" -quiet
# 輸出版本號(hào)
/usr/libexec/PlistBuddy -c "Print :ApplicationProperties:CFBundleVersion" ${archivePath}/Info.plist
/usr/libexec/PlistBuddy -c "Print :ApplicationProperties:CFBundleShortVersionString" ${archivePath}/Info.plist
#輸出ipa包
xcodebuild -exportArchive -archivePath $archive_path -exportOptionsPlist $exportOptionsPlist -exportPath $export_path
}
cd ${WORKSPACE}
mkdir -p build
# 編譯
func_export_plist
func_build
添加發(fā)布腳本
# 生成download.plist文件
echo '<?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>${url}/mallguide/'${project_scheme}'_'${APP_VERSION}'.ipa</string>
</dict>
<dict>
<key>kind</key>
<string>display-image</string>
<key>url</key>
<string>${url}/mallguide/image.57x57.png</string>
</dict>
<dict>
<key>kind</key>
<string>full-size-image</string>
<key>url</key>
<string>${url}/mallguide/image.512x512.jpg</string>
</dict>
</array>
<key>metadata</key>
<dict>
<key>bundle-identifier</key>
<string>com.xxxx.mall</string>
<key>bundle-version</key>
<string>'${APP_VERSION}'</string>
<key>kind</key>
<string>software</string>
<key>title</key>
<string>App名稱</string>
</dict>
</dict>
</array>
</dict>
</plist>' > ${export_path}/${project_scheme}_${APP_VERSION}_Download.plist
mv ${export_path}/${project_scheme}.ipa ${export_name}
最后添加郵件發(fā)送