iPhone自动 打包 脚本

xcodebuild和xcrun实现自动打包iOS应用程序

2011-12-03 20:30:07 来源:百度搜索研发部 作者:

随着苹果手持设备用户的不断增加,ios应用也增长迅速,同时随着iphone被越狱越来越多的app 的渠道也不断增多,为各个渠道打包成了一件费时费力的工作,本文提供一种比较智能的打包方式来减少其带来的各种不便。

随着苹果手持设备用户的不断增加,ios应用也增长迅速,同时随着iphone被越狱越来越多的app 的渠道也不断增多,为各个渠道打包成了一件费时费力的工作,本文提供一种比较智能的打包方式来减少其带来的各种不便。

自动化打包背景介绍

1、背景

随着ios程序发布的渠道逐渐的增多,为每个渠道打包也成为特别耗费时间和体力的一项技术活了,而这一般大多数都是由rd来完成的。这样就占用了 rd很多的开发时间,何不把这些东西写成一个自动化的脚本,然后交给qa 或是 pm来完成这个打包过程了。经过一番调研发现网上这种脚本还是很少的,不过xcode 提供了shell编译工具 xcodebuild 和 ipa打包工具xcrun ,这就有理由让我们利用这两个工具写一个自动化的打包脚本来提高我们的工作效率和自动化程度。

2、ios程序包格式、渠道包格式

1) 产生多渠道的原因及多渠道带来的打包问题:随着iphone、ipad、itouch等手持设备火热销售,而它们上面的应用也随之火爆了起来,而随之而来 的就是以上设备被越狱后就可以在越狱的设备上直接运行ipa程序包 而不用通过appstore去下载,这样一来国内就产生了众多的专门为越狱手机而开设的渠道提供ipa程序包的下载。随着越来越多的渠道,推广时为各个渠 道打包就成了一项比较耗费时间和精力的技术活了,因此我们必须寻找一种自动化的方式 让打包变得高效简单。
2) Ios程序包分为appstore二进制文件跟渠道包两种格式
appstore二进制文件:通过xcode工具可以生成一个.app格式的二进制文件。
渠道包:格式为.ipa格式,在没有自动化打包工具之前都是利用xcode来生成相应的渠道包,而且每次只能生成一个渠道包,每次打包之前都得手动该渠道ID,带来的问题就是耗费时间、效率低下、容易出错、增加风险。

3、传统的ios打包方式

利用xcode 打包

1) appstore 二进制程序包
打开你的项目,进入“Edit Project Settings”,进入Configuration页面,选中Release点击下面的Duplicate,复制一个新的配置项出来,命名为 Distribution。然后进入Build页面,顶上的Configuration下拉框选中Distribution,下面的Code Signing Identity里面的Any iPhone OS Device后面对应的值选中你的那个Distribution的证书。然后点击“Build”–> “Build” 就可以编译程序了
编译成功后,你就可以在相应的build目录下看到一个.app的二进制文件。

2) 渠道ipa包
根据以上步骤同样配置好Distribution 证书 ,然后点击 “Build”–> “Build and Archive” 就可以编译程序了。接着打开“Window””Organizer” 左边栏中选择”ARCHIVED APPLICATIONS” 然后再右侧列表中选中刚才编译的程序包 再点击右侧右边顶部的”Share”按钮 保存到磁盘即可。就会生成一个.ipa的文件 即为渠道包。
注意:以上运行设备必须选择“Deveice“

4、传统的打包带来的问题

耗费时间、耗费体力、效率低下、只能依赖RD来完成、容易出错、发布风险比较高、QA回归确认比较困难、 不智能化。

自动化打包具体实现

C/C++ Code 复制内容到剪贴板
  1. xcodebuild[-project][-activetarget][-alltargets][-target]...[-parallelizeTargets][-activeconfiguration][-configuration][-sdk |][=]...[]...   
  2. xcodebuild[-version[-sdk |]]   
  3. xcodebuild[-showsdks]   
  4. xcodebuild[-find ][-sdk |]   
  5. xcodebuild[-list]  

 

1、xcodebuild 介绍:

也可以在终端输入:xcodebuild –help 或 –h查看具体的选项
显示xcodebuildversion:xcodebuild –version
显示当前系统安装的sdk:xcodebuild –showsdks
显示当前目录下project Information:xcodebuild –list
需要注意的是:执行以上命令时必须把位置定位在ios项目文件的根目录下 否则会提示找不相关命令的。

2、xcrun 介绍:

此工具主要用于将app文件打包成ipa格式的程序包。(主要用于已越狱手机)。
具体用法如下:

其中:-v 对应的是app文件的绝对相对路径 –o 对应ipa文件的路径跟文件名 –sign
对应的是 发布证书中对应的公司名或是个人名  –embed 对应的是发布证书文件
注意如果对应的Distribution 配置中已经配置好了相关证书信息的话 –sign 和 –embed可以忽略

3、具体方案

a) 从源程序一次性打出所有渠道的ipa包 跟appstore的二进制包
为了让自动化脚本执行一次把所有的渠道包都打好,所以必须有一个配置文件用来存储所有的渠道名跟渠道号,而项目文件中也应该有个对应存储当前渠道号的文件,每次程序都从这个存放渠道号的文件中读取渠道号即可,大概的思路就是利用脚本循环执行打包过程,而每次打包前都通过脚本修改项目中存放渠道号的文件为当前循环的最新渠道号,让后逐个打包。
注:具体事例见附录

b) 提供一个ipa格式的母包 从母包生成其它所有的渠道包跟 appstore 包
qa的一些疑问,如何确保所有的渠道包就是他们验证过的那份代码呢?
的确,以上代码每次都是重新对程序进行打包,可qa往往测试验证的只有一个包,如果个个去验证无意中之中又增加了qa的工作量哈!!而且风险也不可控。因此基于上面的问题我们想出了一下办法:qa只验证一个程序包(即母包)如果这个包通过验证 我们就通过母包去生成其它渠道的包,这样一来qa也不用确认那么多的渠道包了,风险也得到了有效的控制。
可能你会问:用一个包生成其他的包可行么??
原因是这样的:因为每个渠道只是渠道号发生变化,而其他的内容又不会发生变化,而我们的渠道号又是存储在sourceid.dat这个文件中的,所以只要改变母包中的sourceid.dat文件的内容即可,而ipa包又是同zip格式进行压缩,所以基本思路就是通过zip先对母包进行解压,然后改变sourceid.dat的内容 最后再用zip进行压缩成相应的渠道包即可。
Ipa包的目录:\
注:具体事例见附录

一些问题

当有些shell命令在mac的终端中运行不通过时,请确保你的shell脚本是在mac环境下编写的而不是同xp等其他环境中copy过来的。因为mac跟xp的编码是不一样所以会有问题。

总结:

通过从母包打出其他渠道的包这种方法:得到以下好处

i.   降低了rd的工作量,一起qa的工作量。

ii.  让测试发布程序时的风险得到了控制。

iii. 提高了打包发布工作效率。(几十个包 只需短短的几分钟)。

iv. 提高了自动化。

v. 不依赖mac 以及xcode环境 直接在linux 下即可完成 从母包生成其它包

附录

利用xcode环境一次生成所有包的shell 脚本代码:

C/C++ Code 复制内容到剪贴板
  1. #!/bin/sh   
  2.   
  3. xcodebuild clean -configuration Distribution      //clean项目   
  4.   
  5. distDir="/Users/xxxx/dist"  
  6. releaseDir="build/Distribution-iphoneos"  
  7. version="1_0_0"  
  8. rm -rdf "$distDir"  
  9. mkdir "$distDir"  
  10. for line in $(cat data.dat)        //读取所有渠道号data.dat文件   
  11. do  
  12. ipafilename=`echo $line|cut -f1 -d':'//渠道名   
  13. sourceid=`echo $line|cut -f2 -d':'`    //渠道号   
  14. echo "ipafilename=$ipaname"  
  15. echo "sourceid=$sourceid"  
  16. targetName="youtargename"   //项目名称(xcode左边列表中显示的项目名称)   
  17. echo "sourceid=$sourceid"  
  18. echo "ipafilename=$ipafilename"  
  19. echo "$sourceid" > sourceid.dat   
  20. echo "sourceid.dat: "  
  21. cat sourceid.dat   
  22. rm -rdf "$releaseDir"  
  23.   
  24. ipapath="${distDir}/${targetName}_${version}_from_${sourceid}.ipa"  
  25.   
  26. echo "***开始build app文件***"  
  27. xcodebuild -target "$targetName" -configuration Distribution  -sdk iphoneos build   
  28. appfile="${releaseDir}/${targetName}.app"  
  29. if [ $sourceid == "appstore" ]   
  30. then   
  31. cd $releaseDir   
  32. zip -r "${targetName}_${ipafilename}_${version}.zip" "${targetName}.app"  
  33. mv "${targetName}_${ipafilename}.zip" $distDir 2> /dev/null   
  34. cd ../..   
  35. else  
  36. echo "***开始打ipa渠道包****"  
  37. /usr/bin/xcrun -sdk iphoneos PackageApplication -v "$appfile" -o "$ipapath" --sign "iPhone Distribution:xxxxxx"  
  38. fi   
  39. done  

 

注:以上的data.dat文件为存放渠道号列表的文件 其格式为:3g:1001b 即 (渠道名:渠道号) sourceid.dat 为项目文件中存放渠道号的文件(内容只有一个渠道号)。当然了上面脚本只是说明了下如何利用xcodebuild 和 xcrun 进行打包 以及自动打包的一个逻辑,shell脚本好的同学可以自由发挥哈。。。

从ipa格式的母包生成其它渠道包的shell脚本实例:

复制内容到剪贴板
  1. #!/bin/sh   
  2. sourceipaname="母包名.ipa"  
  3. appname=”app文件名.app”  //加压后Pauload目录项.app文件名需要根据自己的项目修改   
  4. distDir="/Users/lxxx/Qa"   //打包后文件存储目录   
  5. version="1.0.0"  
  6. rm -rdf "$distDir "  
  7. mkdir "$distDir" unzip $sourceipaname     //解压母包文件   
  8. for line in $(cat data.dat)   //读取渠道号文件并进行循环   
  9. do  
  10. ipafilename=`echo $line|cut -f1 -d':'`   
  11. sourceid=`echo $line|cut -f2 -d':'`   
  12. echo "ipafilename=$ipaname"  
  13. echo "sourceid=$sourceid"  
  14. targetName="ipa包名"  
  15. echo "sourceid=$sourceid"  
  16. echo "ipafilename=$ipafilename"  
  17. cd Payload   
  18. cd $appname   
  19. echo "replace sourceid.dat before: "  
  20. cat sourceid.dat   
  21. echo "$sourceid" > sourceid.dat   
  22. echo "replace sourceid.dat after: "  
  23. cat sourceid.dat   
  24. if [ $sourceid == "appstroe" ]   
  25. then   
  26. cd ..   
  27. zip -r "${targetName}_${version}_from_${sourceid}.zip" $appname //appstore二进制文件   
  28.   
  29. mv "${targetName}_${version}_from_${sourceid}.zip" $distDir   
  30. cd ..   
  31. else  
  32. cd ../..   
  33. zip -r "${targetName}_${version}_from_${sourceid}.ipa" Payload   //打成其他渠道的包   
  34. mv "${targetName}_${version}_from_${sourceid}.ipa" $distDir   
  35. fi   
  36. done rm -rdf Payload  

 

注:以上data.dat也是用来存储所有渠道号的,sourceipaname就是通过qa验证的母包,appname为ipa包加压后Payload 目录下的app文件名并且以上所有文件必须与脚本文件保持在同一目录下以及在mac环境中执行。

原文:http://stblog.baidu-tech.com/?p=1295


转帖分析:

xcode4.3中,传统ios打包:

利用xcode 打包

渠道ipa包
配置好Distribution 证书 ,然后点击 “Build”–> “Archive” 就可以编译程序并且自动弹出Archive配置页面了。也可以打开”Organizer” 左边栏中选择”Archives” 然后再右侧列表中选中刚才编译的程序包 再点击右侧右边顶部的”Distribute”按钮,再选择Save for Enterprise or Ad-hoc Deployment选项,点击Next后,选择Code sign 的证书,再点击Next, 保存到磁盘即可。就会生成一个.ipa的文件 即为渠道包。如果希望能有供网络使用的plist文件生成,则勾选Save for Enterprise Distribution就行了。

注意:以上运行设备必须选择“Deveice“

 

˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜˜

 

IOS build脚本

 

generate_manifest.py

 

   
   
   
   
#!/usr/bin/python
 
from optparse import OptionParser
import shutil
import fileinput
import os
import sys
import glob
import subprocess
import plistlib
import urlparse
import string
import 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 = file
break
return 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 format
subprocess . 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 )

 

build_ipa.sh:

   
   
   
   
#!/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 project
security 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; do
APP_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 users
cp "$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.plist
python -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 across
PAYLOAD_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 up
rm "$IPA_FILENAME"
rm "$ARCHIVE_FILENAME"
rm "$MANIFEST_OUTPUT_HTML_FILENAME"
rm "$MANIFEST_OUTPUT_MANIFEST_FILENAME"
rm "$PAYLOAD_FILENAME"
done

转帖分析:

build_ipa.sh稍微修改一下,将该sh文件以及py文件全部放到文件目录下,直接在Terminal中运行./build_ipa.sh就 能生成所需要的ipa文件和manifest.plist文件,将这两个文件放入服务器,并在服务器的网页地址中加入<a href="itms-services://?action=download-manifest&url=http://服务器地址目录 /manifest.plist">,这个时候你就可以通过手机客户端进入服务器网址下载程序了。

 

参考资料:

https://github.com/baz/ios-build-scripts/blob/master/generate_manifest.py

https://github.com/baz/ios-build-scripts

 

 

 

80行脚本全自动批量编译打包iphone app

最近做了个有声电子书的应用,出于size的考虑,分成了很多个APP,这些APP大同小异。


只有一些小区别:名字不同,icon不同,界面主图片不同,源码稍微有点差异;


五六十个,如果手工做体力活实在太累...



如果能做到用脚本批量生成就好了,google到了xcode是支持命令行编译的,


MacOS支持bash等几乎全套的GNU工具,剩下的事情就比较好办了...



思路:


1.准备一个干净的xcode项目作为模板


2.复制一份模板,用脚本设置好正确的信息,及资源文件


3.自动编译打包



顺便做个广告啊...


♥♥♥在itunes里搜索“声声”或 "SoundBook",您会有意外惊喜!评书,讲坛,畅销小说有声版,尽在《声声入耳系列电子读物》♥♥♥



分享源码(可根据自己的需求灵活处理,总之这种方式是可行的,而且极大的提升了效率,呵呵):



auto.sh   主程序


========================


复制代码

  1. #!/bin/bash
    RES_PATH="/Users/xingzip/Desktop/MCSRC/"
    TARGET_PATH="/Users/xingzip/Desktop/MCZIP/"
    m=0
    s=0
    e=0
    for ((n=1; n<3; n++))
    do
            echo "从项目模板复制创建项目..."
            m=`expr $n + 45`
            s=`expr \( $n - 1 \) \* 20 + 1`
            e=`expr $s + 20`
            ./gen_project.sh S$m 声声入耳$n 20 SoundBook$m


            echo "拷贝图片音频等项目资源..."
            j=0
            for ((i=$s; i<$e; i++))
            do
                    j=`expr $j + 1`
                    cp $RES_PATH/$i.mp3 S$m/res/$j.mp3
            done
            cp $RES_PATH/gfx$m.png S$m/res/gfx.png
            cp $RES_PATH/icon$m.png S$m/res/icon.png


            echo "编译项目..."
            cd S$m/
            xcodebuild -configuration Distribution -sdk iphoneos2.2.1 clean build
            cd ..


            echo "压缩打包并把zip包拷贝到目标目录..."
            echo "zip的-y参数一定要加,跟踪符号链接用的,不加这个参数上传会失败(非法格式)"
            cd S$m/build/Distribution-iphoneos/
            rm -f SoundBook$m.zip
            zip SoundBook$m.zip -y -r SoundBook$m.app
            cp SoundBook$m.zip $TARGET_PATH
            cd ../../..
    done


gen_project.sh   从模板拷贝替换,生成新项目目录的脚本,由auto.sh调用


===============================================================


复制代码

if [ $# -eq 4 ];


then


    echo "    复制项目模板..."


    cp -r STP $1



    echo "    处理Info.plist,设置成需要的显示名和应用名..."


    cat $1/Info.plist | sed 's/$TMP_DISPNAME/'$2'/' | sed 's/$TMP_APPNAME/'$4'/' > tmp.plist


    mv tmp.plist $1/Info.plist



    echo "    处理源程序,替换需要改变的宏定义..."


    cat $1/Classes/GameStateSplash.h | sed 's/$TMP_MAXMP3COUNT/'$3'/' > tmp.cpp


    mv tmp.cpp $1/Classes/GameStateSplash.h



    echo "    处理xcodeproj,把三个xml文件中的应用名设置正确..."


    cat $1/Gamebox.xcodeproj/project.pbxproj | sed 's/$TMP_APPNAME/'$4'/' > tmp.pbxproj


    mv tmp.pbxproj $1/GameBox.xcodeproj/project.pbxproj


    cat $1/Gamebox.xcodeproj/xingzip.mode1v3 | sed 's/$TMP_APPNAME/'$4'/' > tmp.mode1v3


    mv tmp.mode1v3 $1/GameBox.xcodeproj/xingzip.mode1v3


    cat $1/Gamebox.xcodeproj/xingzip.pbxuser | sed 's/$TMP_APPNAME/'$4'/' > tmp.pbxuser


    mv tmp.pbxuser $1/GameBox.xcodeproj/xingzip.pbxuser


else


    echo "用法:gen_project.sh <DirName> <DispName> <MaxMP3Count> <AppName>"


fi

你可能感兴趣的:(iPhone,应用程序,百度搜索)