xcodebuild 不用多 target,打包不同 bundle identifier

2017-01-14 10:21:32来源:http://www.jianshu.com/p/14f5198bab10作者:Yang152412人点击

第七城市

xcode 8后,原来用企业证书 wildcard 打包,会因为没有 APNS 报错,所以只能指定 bundleIdentifier,但是指定之后,就不能和正常上线的 bundleIdentifier 一致了,每次打包就要重新设置一下 bundle identifier。解决方案 1、用两个 target,分开设置。2、makefile 打包的时候分别 设置 企业证书 和 上线证书。本文采用 第二种方案


一、配置参数:
version=$(shell /usr/libexec/PlistBuddy -c "print :CFBundleShortVersionString" ${infoPath})
tembundleDisplayName=$(shell /usr/libexec/PlistBuddy -c "print :CFBundleDisplayName" ${infoPath})
tembuildNumber=$(shell svn info |grep Revision)
buildNumberInfo=$(shell git log -a |wc -l | sed 's/^[ /t]*//g')
buildNumber=$(shell git log -1 --pretty=format:%h)_$(shell git log -a |wc -l | sed 's/^[ /t]*//g')
# 代码中的宏定义,定义 测试环境
serverEnvironment=BUILD_FOR_TEST
developmentTeam="NM9VP4YSNU"
productBundleIdentifier="com.***.***enterprise"
profileName=wildcard_can_push
profileID=aa64f6e9-4156-45b3-ae33-718ca2b24593
archivePath=build/DerivedData/neighborhood.xcarchive
bundleDisplayName="$(tembundleDisplayName)-e"
signKey=$(KEY_enterprise)

configWay=Adhoc

路径和文件名称 最好不要带空格,会把 shell 脚本 的参数 给 打乱。如果真有空格,就只能做转义了


# makefile 转义 infoPath 中的空格
infoPathFormat=$(subst / ,// ,./neighborhood/Support Files/neighborhood-Info.plist)

二、修改 企业证书打包的 build 号,显示名称

因为用了不同的 bundle identifier,会有两个 app,为了到设备上区分出来,displayName 也设置不同的名称区分。


/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $(buildNumberInfo)" "$(infoPathFormat)"
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $(bundleDisplayName)" "$(bundleDisplayName)"

key值可以把 info.plist 用文本文件打开查看。


三、打开钥匙串访问, 导入证书
security unlock-keychain "-p" 系统密码 "/Users/***/Library/Keychains/login.keychain" ;

我用的电脑 证书都已导入钥匙串,所以不用执行导入。


四、清理项目
xcodebuild -workspace ***.xcworkspace -scheme *** -configuration Adhoc clean

五、编译

因为 PackageApplication 已经弃用,改用 xcodebuild -exportArchive ,所以 编译 也改用 archive,xcodebuild archive


1、编译 pods


xcodebuild -workspace ***.xcworkspace -scheme Pods-*** -derivedDataPath build/DerivedData OBJROOT=$(PWD)/build SYMROOT=$(PWD)/build -configuration $(configWay)

2、编译 workspace


xcodebuild -workspace ***.xcworkspace -scheme *** -configuration $(configWay) -derivedDataPath build/DerivedData -archivePath "$(archivePath)" DEVELOPMENT_TEAM="$(developmentTeam)" PRODUCT_BUNDLE_IDENTIFIER="$(productBundleIdentifier)" CODE_SIGN_IDENTITY="$(signKey)" PROVISIONING_PROFILE="$(profileID)" PROVISIONING_PROFILE_SPECIFIER="$(profileName)" IPHONEOS_DEPLOYMENT_TARGET="7.0" archive

"***" 都替换成自己的。


因为 项目本身的设置都是 上线证书,这里要全部改成和 企业证书 用的配置 一模一样,所以 添加的参数比较多,少了一个编译就过不去。


参数和 正常在 xcode -> build setting 里面会有点不一样,可以把工程用文本编辑器打开,查找对应的名称:



project.png

图种的设置 应该都可以通过 xcodebuild 来设置。
参考 苹果官方文档 buildSettings


我们需要重新设置 证书和配置文件


需要设置的项目:
DEVELOPMENT_TEAM="$(developmentTeam)"
PRODUCT_BUNDLE_IDENTIFIER="$(productBundleIdentifier)"
CODE_SIGN_IDENTITY="$(signKey)"
PROVISIONING_PROFILE="$(profileID)"
PROVISIONING_PROFILE_SPECIFIER="$(profileName)"
IPHONEOS_DEPLOYMENT_TARGET="7.0"

profileID 可以通过 xcode-> account 里面查看。也可以通过脚本获取


获取 profile 的 ID
#!/bin/bash
if [ $# -ne 1 ]; then
echo "Usage: getmobileuuid the-mobileprovision-file-path"
exit 1
fi
# mobileprovision_uuid=`grep UUID -A1 -a $1 | grep -o "[-A-Z0-9]/{36/}"`
mobileprovision_uuid=`/usr/libexec/PlistBuddy -c "Print UUID" /dev/stdin <<< $(/usr/bin/security cms -D -i $1)`
echo "UUID is:"
echo ${mobileprovision_uuid}

添加 GCC_PREPROCESSOR_DEFINITIONS 环境变量

如果代码里面是用 宏定义来区分不同的网络 环境,比如 测试,预发,正式 环境,可以通过 传入 GCC_PREPROCESSOR_DEFINITIONS 来实现
例如代码中定义


//#define BUILD_FOR_DEVELOP
#define BUILD_FOR_TEST
//#define BUILD_FOR_PRERELEASE
//#define BUILD_FOR_RELEASE

if [ ${environment} == "test" ]; then
serverEnvironment=BUILD_FOR_TEST
elif [[ ${environment} == "prerelease" ]]; then
serverEnvironment=BUILD_FOR_PRERELEASE
elif [[ ${environment} == "release" ]]; then
serverEnvironment=BUILD_FOR_RELEASE
elif [[ ${environment} == "develop" ]]; then
serverEnvironment=BUILD_FOR_DEVELOP
else
echo "未知 环境,退出"
help_info
exit;
fi

那么 可以再 编译的时候,带上 GCC_PREPROCESSOR_DEFINITIONS参数


GCC_PREPROCESSOR_DEFINITIONS_Adhoc=(${serverEnvironmentDefine},${configInfo},"/$(inherited)")

例如:


xcodebuild -workspace neighborhood.xcworkspace -scheme neighborhood -configuration ${configWay} -derivedDataPath build/DerivedData -archivePath "${archivePath}" DEVELOPMENT_TEAM="${developmentTeam}" PRODUCT_BUNDLE_IDENTIFIER="${productBundleIdentifier}" CODE_SIGN_IDENTITY="${signKey}" PROVISIONING_PROFILE="${profileID}" PROVISIONING_PROFILE_SPECIFIER="${profileName}" IPHONEOS_DEPLOYMENT_TARGET="7.0" archive GCC_PREPROCESSOR_DEFINITIONS=${GCC_PREPROCESSOR_DEFINITIONS_Adhoc}

但是 如果直接就写


GCC_PREPROCESSOR_DEFINITIONS='$(GCC_PREPROCESSOR_DEFINITIONS) $(serverEnvironment) $(configInfo)'

则不会生效,不知道为什么。


可以参考:https://stackoverflow.com/questions/1402641/xcode-how-to-set-debug-environment-with-multiple-xcconfig-files/7907294


六、 打包

改用 xcodebuild -exportArchive


xcodebuild -exportArchive -exportFormat IPA -archivePath "$(archivePath)" -exportPath $(out_path)/$(ddxq_ipaName) -exportProvisioningProfile "$(profileName)"

这里 需要注意,最好带上 -exportProvisioningProfile,不然虽然能打包 ipa,但是 安装不到手机上。这里 设置为 配置文件名称就好,不是profile 的 UUID。
可以参考 这里,对各字段对应哪里 描述的比较清楚。
如果 设置不对,则会报错:"no provisioning profile matches:****"


报错
1、xcodebuild error: no provisioning profile matches

xcodebuild 后面跟的 配置文件,证书,team,要全部匹配。


2、archive 报:“ archive at path '/build/.xcarchive' is malformed”

这是因为刚开始 设置了


-derivedDataPath build/DerivedData 
OBJROOT=$(PWD)/build
SYMROOT=$(PWD)/build

最后发现 只需要 -derivedDataPath 就够了。


3、 安装时报 “A signed resource has been added modified or deleted”

是因为 最后 export archive 的时候没有带上 -exportProvisioningProfile
参考:这里


完整脚本

传送门


参考资料:


https://blog.reohou.com/how-to-export-ipa-from-archive-using-xcodebuild/
苹果官方xcodebuild 文档
http://liumh.com/2015/11/25/ios-auto-archive-ipa/
http://www.cocoachina.com/ios/20151104/14050.html



第七城市

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台