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

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 里面会有点不一样,可以把工程用文本编辑器打开,查找对应的名称:

xcodebuild 不用多 target,打包不同 bundle identifier_第1张图片
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

你可能感兴趣的:(xcodebuild 不用多 target,打包不同 bundle identifier)