随着苹果手持设备用户的不断增加,ios应用也增长迅速,同时随着iphone被越狱越来越多的app 的渠道也不断增多,为各个渠道打包成了一件费时费力的工作,本文提供一种比较智能的打包方式来减少其带来的各种不便。
自动化打包背景介绍
1、背景
2、ios程序包格式、渠道包格式
3、传统的ios打包方式
4、传统的打包带来的问题
自动化打包具体实现
C/C++ Code复制内容到剪贴板- xcodebuild[-project][-activetarget][-alltargets][-target]...[-parallelizeTargets][-activeconfiguration][-configuration][-sdk |][=]...[]...
- xcodebuild[-version[-sdk |]]
- xcodebuild[-showsdks]
- xcodebuild[-find ][-sdk |]
- xcodebuild[-list]
1、xcodebuild 介绍:
2、xcrun 介绍:
3、具体方案
一些问题
总结:
附录
利用xcode环境一次生成所有包的shell 脚本代码:
C/C++ Code复制内容到剪贴板- #!/bin/sh
- xcodebuild clean -configuration Distribution //clean项目
- distDir="/Users/xxxx/dist"
- releaseDir="build/Distribution-iphoneos"
- version="1_0_0"
- rm -rdf "$distDir"
- mkdir "$distDir"
- for line in $(cat data.dat) //读取所有渠道号data.dat文件
- do
- ipafilename=`echo $line|cut -f1 -d':'` //渠道名
- sourceid=`echo $line|cut -f2 -d':'` //渠道号
- echo "ipafilename=$ipaname"
- echo "sourceid=$sourceid"
- targetName="youtargename" //项目名称(xcode左边列表中显示的项目名称)
- echo "sourceid=$sourceid"
- echo "ipafilename=$ipafilename"
- echo "$sourceid" > sourceid.dat
- echo "sourceid.dat: "
- cat sourceid.dat
- rm -rdf "$releaseDir"
- ipapath="${distDir}/${targetName}_${version}_from_${sourceid}.ipa"
- echo "***开始build app文件***"
- xcodebuild -target "$targetName" -configuration Distribution -sdk iphoneos build
- appfile="${releaseDir}/${targetName}.app"
- if [ $sourceid == "appstore" ]
- then
- cd $releaseDir
- zip -r "${targetName}_${ipafilename}_${version}.zip" "${targetName}.app"
- mv "${targetName}_${ipafilename}.zip" $distDir 2> /dev/null
- cd ../..
- else
- echo "***开始打ipa渠道包****"
- /usr/bin/xcrun -sdk iphoneos PackageApplication -v "$appfile" -o "$ipapath" --sign "iPhone Distribution:xxxxxx"
- fi
- done
从ipa格式的母包生成其它渠道包的shell脚本实例:
复制内容到剪贴板- #!/bin/sh
- sourceipaname="母包名.ipa"
- appname=”app文件名.app” //加压后Pauload目录项.app文件名需要根据自己的项目修改
- distDir="/Users/lxxx/Qa" //打包后文件存储目录
- version="1.0.0"
- rm -rdf "$distDir "
- mkdir "$distDir" unzip $sourceipaname //解压母包文件
- for line in $(cat data.dat) //读取渠道号文件并进行循环
- do
- ipafilename=`echo $line|cut -f1 -d':'`
- sourceid=`echo $line|cut -f2 -d':'`
- echo "ipafilename=$ipaname"
- echo "sourceid=$sourceid"
- targetName="ipa包名"
- echo "sourceid=$sourceid"
- echo "ipafilename=$ipafilename"
- cd Payload
- cd $appname
- echo "replace sourceid.dat before: "
- cat sourceid.dat
- echo "$sourceid" > sourceid.dat
- echo "replace sourceid.dat after: "
- cat sourceid.dat
- if [ $sourceid == "appstroe" ]
- then
- cd ..
- zip -r "${targetName}_${version}_from_${sourceid}.zip" $appname //appstore二进制文件
- mv "${targetName}_${version}_from_${sourceid}.zip" $distDir
- cd ..
- else
- cd ../..
- zip -r "${targetName}_${version}_from_${sourceid}.ipa" Payload //打成其他渠道的包
- mv "${targetName}_${version}_from_${sourceid}.ipa" $distDir
- fi
- done rm -rdf Payload
IOS build脚本
#!/usr/bin/python from optparse import OptionParserimport shutilimport fileinputimport osimport sysimport globimport subprocessimport plistlibimport urlparseimport stringimport fnmatch parser = OptionParser()parser.add_option('-f', '--app-bundle', action='store', dest='app_bundle', help='Path to app bundle')parser.add_option('-a', '--archive-name', action='store', dest='archive_name', help='Legacy archive filename')parser.add_option('-d', '--deployment-address', action='store', dest='deployment_address', help='Remote deployment path, where the app will eventually be hosted')parser.add_option('-c', '--changes-page-url', action='store', dest='changes_page_url', help='URL describing the changes that went into this build') (options, args) = parser.parse_args() if options.app_bundle == None:parser.error("Please specify the file path to the app bundle.")elif options.deployment_address == None:parser.error("Please specify the deployment address.")elif options.archive_name == None:parser.error("Please specify the filename of the legacy archive.")elif options.changes_page_url == None:parser.error("Please specify a URL to a page listing the changes in this build.") class IPAGenerator(object):"Generate index.html"def generate_html(self, app_name):HTML_FILENAME = 'index.html'index_file = open(HTML_FILENAME, 'w')index_file.write(self.template(app_name))return HTML_FILENAME "Locates the app's Info.plist"def info_plist_filename(self):filename = 'Info.plist'for file in os.listdir(options.app_bundle):if fnmatch.fnmatch(file, '*Info.plist'):filename = filebreakreturn filename "Generate manifest by parsing values from the app's Info.plist"def generate_manifest(self, app_name):filename = self.info_plist_filename()info_plist_filepath = os.path.join(options.app_bundle, filename)info_plist_xml_filename = 'info_plist.xml'# Use plutil to ensure that we are dealing with XML rather than the binary formatsubprocess.Popen('plutil -convert xml1 -o ' + info_plist_xml_filename + ' ' + "'" + info_plist_filepath + "'", shell=True).wait()info_plist_xml_file = open(info_plist_xml_filename, 'r')app_plist = plistlib.readPlist(info_plist_xml_file)os.remove(info_plist_xml_filename)MANIFEST_FILENAME = 'manifest.plist'manifest_plist = {'items' : [{'assets' : [{'kind' : 'software-package','url' : urlparse.urljoin(options.deployment_address, app_name + '.ipa'),}],'metadata' : {'bundle-identifier' : app_plist['CFBundleIdentifier'],'bundle-version' : app_plist['CFBundleVersion'],'kind' : 'software','title' : app_plist['CFBundleName'],}}]}plistlib.writePlist(manifest_plist, MANIFEST_FILENAME)return MANIFEST_FILENAME "Template from http://github.com/HunterHillegas/iOS-BetaBuilder"def template(self, app_name):template_html = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"><title>[BETA_NAME] - Beta Release</title><style type="text/css">body {background:#fff;margin:0;padding:0;font-family:arial,helvetica,sans-serif;text-align:center;padding:10px;color:#333;font-size:16px;}#container {width:300px;margin:0 auto;}h1 {margin:0;padding:0;font-size:14px;}p {font-size:13px;}.link {background:#ecf5ff;border-top:1px solid #fff;border:1px solid #dfebf8;margin-top:.5em;padding:.3em;}.link a {text-decoration:none;font-size:15px;display:block;color:#069;}</style></head><body><div id="container"><h1>iOS 4.0 Users:</h1><div class="link"><a href="itms-services://?action=download-manifest&url=[DEPLOYMENT_PATH]">Tap here to install<br />[BETA_NAME]<br />On Your Device</a></div> <p><strong><em><a href="[BUILD_CHANGES_URL]">Tap here to view changes in this build</a></em></strong><br /></p><p><strong>Link didn't work?</strong><br />Make sure you're visiting this page on your device, not your computer.</p><p><strong>On a version of iOS before 4.0?</strong><br />Reload this page in your computer browser and download a zipped archive and provisioning profile here:</p><div class="link"><a href="[BETA_ARCHIVE_FILENAME]">[BETA_NAME]<br />Archive w/ Provisioning Profile</a></div></div></body></html>"""TEMPLATE_PLACEHOLDER_NAME = '[BETA_NAME]'TEMPLATE_PLACEHOLDER_DEPLOYMENT_PATH = '[DEPLOYMENT_PATH]'TEMPLATE_PLACEHOLDER_ARCHIVE_FILENAME = '[BETA_ARCHIVE_FILENAME]'TEMPLATE_PLACEHOLDER_BUILD_CHANGES_URL = '[BUILD_CHANGES_URL]'template_html = string.replace(template_html, TEMPLATE_PLACEHOLDER_NAME, app_name)template_html = string.replace(template_html, TEMPLATE_PLACEHOLDER_DEPLOYMENT_PATH, options.deployment_address)template_html = string.replace(template_html, TEMPLATE_PLACEHOLDER_ARCHIVE_FILENAME, options.archive_name)template_html = string.replace(template_html, TEMPLATE_PLACEHOLDER_BUILD_CHANGES_URL, options.changes_page_url)return template_html generator = IPAGenerator()app_name = os.path.splitext(options.app_bundle)[0]html_filename = generator.generate_html(app_name)manifest_filename = generator.generate_manifest(app_name)
#!/bin/bash# Below are required environment variables with some example content:# XCODE_BUILD_COMMAND='xcodebuild -sdk iphoneos4.1 -alltargets -configuration "Ad Hoc" clean build'# XCODE_BUILD_CONFIGURATION='Ad Hoc'# DISTRIBUTION_CERTIFICATE='iPhone Distribution: Your Company Pty Ltd'# PROVISIONING_PROFILE_PATH='/Users/tomcat/Library/MobileDevice/Provisioning Profiles/Your_Company_Ad_Hoc.mobileprovision'# GIT_BINARY='/usr/local/git/bin/git'# REMOTE_HOST='your.remote.host.com'# REMOTE_PARENT_PATH='/www/docs/ios_builds'# MANIFEST_SCRIPT_LOCATION='http://github.com/baz/ios-build-scripts/raw/master/generate_manifest.py'# ROOT_DEPLOYMENT_ADDRESS='http://your.remote.host.com/ios_builds'# ARCHIVE_FILENAME='beta_archive.zip'# KEYCHAIN_LOCATION='/Users/tomcat/Library/Keychains/Your Company.keychain'# KEYCHAIN_PASSWORD='Password' # Build projectsecurity default-keychain -s "$KEYCHAIN_LOCATION"security unlock-keychain -p $KEYCHAIN_PASSWORD "$KEYCHAIN_LOCATION"eval $XCODE_BUILD_COMMAND GIT_HASH="$($GIT_BINARY log --pretty=format:'' | wc -l)-$($GIT_BINARY rev-parse --short HEAD)"GIT_HASH=${GIT_HASH//[[:space:]]}BUILD_DIRECTORY="$(pwd)/build/${XCODE_BUILD_CONFIGURATION}-iphoneos"cd "$BUILD_DIRECTORY" || die "Build directory does not exist."MANIFEST_SCRIPT=$(curl -fsS $MANIFEST_SCRIPT_LOCATION)MANIFEST_OUTPUT_HTML_FILENAME='index.html'MANIFEST_OUTPUT_MANIFEST_FILENAME='manifest.plist'for APP_FILENAME in *.app; doAPP_NAME=$(echo "$APP_FILENAME" | sed -e 's/.app//')IPA_FILENAME="$APP_NAME.ipa"DSYM_FILEPATH="$APP_FILENAME.dSYM" /usr/bin/xcrun -sdk iphoneos PackageApplication -v "$APP_FILENAME" -o "$BUILD_DIRECTORY/$IPA_FILENAME" --sign "$DISTRIBUTION_CERTIFICATE" --embed "$PROVISIONING_PROFILE_PATH" # Create legacy archive for pre iOS4.0 userscp "$PROVISIONING_PROFILE_PATH" .PROVISIONING_PROFILE_FILENAME=$(basename "$PROVISIONING_PROFILE_PATH")zip "$ARCHIVE_FILENAME" "$IPA_FILENAME" "$PROVISIONING_PROFILE_FILENAME"rm "$PROVISIONING_PROFILE_FILENAME" # Output of this is index.html and manifest.plistpython -c "$MANIFEST_SCRIPT" -f "$APP_FILENAME" -d "$ROOT_DEPLOYMENT_ADDRESS/$APP_NAME/$GIT_HASH/$MANIFEST_OUTPUT_MANIFEST_FILENAME" -a "$ARCHIVE_FILENAME" -c "$JOB_URL/$BUILD_NUMBER" # Create tarball with .ipa, dSYM directory, legacy build and generated manifest files and scp them all acrossPAYLOAD_FILENAME='payload.tar'tar -cf $PAYLOAD_FILENAME "$IPA_FILENAME" "$DSYM_FILEPATH" "$ARCHIVE_FILENAME" "$MANIFEST_OUTPUT_HTML_FILENAME" "$MANIFEST_OUTPUT_MANIFEST_FILENAME" QUOTE='"'ssh $REMOTE_HOST "cd $REMOTE_PARENT_PATH; rm -rf ${QUOTE}$APP_NAME${QUOTE}/$GIT_HASH; mkdir -p ${QUOTE}$APP_NAME${QUOTE}/$GIT_HASH;"scp "$PAYLOAD_FILENAME" "$REMOTE_HOST:$REMOTE_PARENT_PATH/${QUOTE}$APP_NAME${QUOTE}/$GIT_HASH"ssh $REMOTE_HOST "cd $REMOTE_PARENT_PATH/${QUOTE}$APP_NAME${QUOTE}/$GIT_HASH; tar -xf $PAYLOAD_FILENAME; rm $PAYLOAD_FILENAME" # Clean uprm "$IPA_FILENAME"rm "$ARCHIVE_FILENAME"rm "$MANIFEST_OUTPUT_HTML_FILENAME"rm "$MANIFEST_OUTPUT_MANIFEST_FILENAME"rm "$PAYLOAD_FILENAME"done
80行脚本全自动批量编译打包iphone app
复制代码
|
复制代码