最近研究了一下iOS的自動化編譯,目的是為了簡化測試和開發的同學溝通協調的次數,實現測試同學可以隨時從網頁操作編譯SVN最新源碼并打包ipa進行測試。
具體思路是通過從配置文件讀取需要編譯的項目配置列表展示在網頁上,測試同學選擇需要編譯的項目,確定后將選擇項目的相關參數傳入shell腳本運行,編譯完成自動跳轉至下載頁面。
主要流程包括:
自動編譯其實就是使用了xcodebuild
的相關命令來實現編譯功能,再使用xcrun
來將app打包成ipa。xcodebuild
的官方文檔見這里。
編譯workspace
xcodebuild -workspace workspacename -scheme schemename -configuration [-configuration configurationname] clean build SYMROOT=(SYMROOT)
編譯PRoject
xcodebuild -target targetname -configuration [-configuration configurationname] clean build SYMROOT=(SYMROOT)
查看配置信息
xcodebuild -list
xcrun打包ipa
xcrun -sdk iphoneos Packageapplication -v projectName.app -o ipaName.ipa
完整的shell腳本稍長放在文章的最后,該腳本改自BashShell。
需要注意,腳本中的路徑最好使用絕對路徑。
啟動:sudo apachectl start停止:sudo apachectl stop重啟:sudo apachectl restart
http://localhosts/
對應的文件目錄是:/Library/WebServer/Documents/
系統級根目錄默認沒有開啟目錄列表,開啟方法:
編輯 /etc/apache2/httpd.conf
文件
搜索找到 <Directory "/Library/WebServer/Documents">
將 Options Multiviews
修改為 Options Indexes Multiviews
另一個 Web 根目錄默認是 ~/Sites
,10.9 中你需要手動創建這個Sites目錄。
檢查這個目錄下是否有 username.conf
文件/etc/apache2/users/
如果沒有,則需要新建一個,username
需要是你的賬戶名字,建議使用終端創建這個文件:
cd /etc/apache2/userssudo vi username.conf
貼入以下內容,注意修改 username
為你的賬戶名字
<Directory "/Users/username/Sites/">Options Indexes MultiViews FollowSymLinksAllowOverride AllOrder allow,denyAllow from allRequire all granted</Directory>
這個文件的權限應該是:-rw-r--r-- 1 root wheel 298 Jun 28 16:47 username.conf
如果不是,請修改sudo chmod 644 username.conf
編輯 /etc/apache2/httpd.conf
文件,刪除下列這些代碼前的注釋符號: #
Include /private/etc/apache2/extra/httpd-userdir.confLoadModule authz_core_module libexec/apache2/mod_authz_core.soLoadModule authz_host_module libexec/apache2/mod_authz_host.soLoadModule userdir_module libexec/apache2/mod_userdir.so
編輯 /etc/apache2/extra/httpd-userdir.conf
文件,刪除下列這些代碼前的注釋符號: #
Include /private/etc/apache2/users/*.conf
重啟 Apache
sudo apachectl restart
這時,這個網址應該已經可以用了:http://localhost/~username/
這里主要用到了PHP的system命令:system($cmd)
PHP調用shell的權限是比較低的,我們的shell里會需要創建文件及文件夾的權限,解決辦法是通過命令行將PHP文件所在目錄及目錄下的所有文件都提升權限,否則腳本會報權限錯誤。具體步驟如下:
/private/etc/apache2
打開文件 httpd.conf
找到
User _www Group _www
修改_www為你的登錄用戶名
User <登錄用戶名>
從命令行重啟Apache
sudo apachectl restart
提升網站目錄權限。因為我的網站根目錄就是上文提到的用戶的Sites文件,因此執行以下命令
sudo chmod 775 ~/Sitessudo chmod 775 ~/Sites/*
好了,權限問題解決了。當滿懷信心看到從網頁調用腳本輸出信息的時候,結果又報了無法找到證書的錯誤,OMG,但從終端調用腳本就可以成功,起初以為權限不夠導致無法調用證書,繞了一大圈后發現這個問題只是因為鑰匙串
中的證書一般安裝在登錄
下,只需要移動到系統
下就行了。
關于從SVN倉庫獲取源碼的部分就不寫了,既然都可以調用腳本了,這部分就也很簡單了。
這個過程還是比較折騰的,希望這篇文章能夠save your time :)
最后奉上相關文件的源碼。
#!/bin/shexport LC_ALL=zh_CN.GB2312;export LANG=zh_CN.GB2312username=用戶名###############配置項目名稱和路徑等相關參數projectName=$1 #項目所在目錄的名稱isWorkSpace=$2 #判斷是用的workspace還是直接project,workspace設置為true,否則設置為falseprojectDir=/Users/${username}/workspace/projects/$3/ #項目所在目錄的絕對路徑buildConfig=$4 #編譯的方式,默認為Release,還有Debug等###############配置下載的文件名稱和路徑等相關參數wwwIPADir=/Users/${username}/Sites/$projectName #html,ipa,icon,plist最后所在的目錄絕對路徑url="http://localhost/${projectName}" #下載路徑########################################################################################################################以下部分為自動生產部分,不需要手動修改############################################################################################################################################# FUCTION START #######################replaceString(){ local inputString=$1 result=${inputString//(/} result=${result//)/} echo $result}date_Y_M_D_W_T(){ WEEKDAYS=(星期日 星期一 星期二 星期三 星期四 星期五 星期六) WEEKDAY=$(date +%w) DT="$(date +%Y年%m月%d日) ${WEEKDAYS[$WEEKDAY]} $(date "+%H:%M:%S")" echo "$DT"}####################### FUCTION END ##########################Log的路徑,如果發現log里又亂碼請在終端執行:export LC_ALL=zh_CN.GB2312;export LANG=zh_CN.GB2312logDir=/Users/${username}/workspace/xcodebuildmkdir -pv $logDirlogPath=$logDir/$projectName-$buildConfig.logecho "~~~~~~~~~~~~~~~~~~~開始編譯~~~~~~~~~~~~~~~~~~~" >>$logPathloginInfo=`who am i`loginUser=`echo $loginInfo |awk '{print $1}'`echo "登陸用戶:$loginUser" >>$logPathloginDate=`echo $loginInfo |awk '{print $3,$4,$5}'`echo "登陸時間:$loginDate" >>$logPathloginServer=`echo $loginInfo |awk '{print $6}'`if [ -n "$loginServer" ]; then echo "登陸用戶IP:$(replaceString $loginServer)" >>$logPathelse echo "登陸用戶IP:localhost(127.0.0.1)" >>$logPathfiif [ -d "$logDir" ]; then echo "${logDir}文件目錄存在"else echo "${logDir}文件目錄不存在,創建${logDir}目錄成功" echo "創建${logDir}目錄成功" >>$logPathfiecho "<br />"###############檢查html等文件放置目錄是否存在,不存在就創建echo "開始時間:$(date_Y_M_D_W_T)" >>$logPathecho "項目名稱:$projectName" >>$logPathecho "編譯模式:$buildConfig" >>$logPathecho "開始目錄檢查........" >>$logPathif [ -d "$wwwIPADir" ]; then echo "文件目錄存在" >>$logPathelse echo "文件目錄不存在" >>$logPath mkdir -pv $wwwIPADir echo "創建${wwwIPADir}目錄成功" >>$logPathfi###############進入項目目錄rm -rf ./buildbuildAPPToDir=/Users/${username}/workspace/build/$projectName #編譯打包完成后.archive .ipa文件存放的目錄###############獲取版本號,bundleIDinfoPlist="${projectDir}${projectName}/$projectName-Info.plist"bundleDisplayName=`/usr/libexec/PlistBuddy -c "Print CFBundleDisplayName" $infoPlist`bundleVersion=`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" $infoPlist`bundleIdentifier=`/usr/libexec/PlistBuddy -c "Print CFBundleIdentifier" $infoPlist`bundleBuildVersion=`/usr/libexec/PlistBuddy -c "Print CFBundleVersion" $infoPlist`###############在網頁上顯示的名字和bundleDisplayName一致appName=$bundleDisplayName echo "$bundleDisplayName"###############開始編譯appif $isWorkSpace ; then #判斷編譯方式 echo "開始編譯workspace...." >>$logPath echo "$projectDir$projectName.xcworkspace" xcodebuild -workspace ${projectDir}$projectName.xcworkspace -scheme $projectName -configuration $buildConfig clean build SYMROOT=$buildAppToDirelse echo "開始編譯target...." >>$logPath cd ${projectDir} xcodebuild -target $projectName -configuration $buildConfig clean build SYMROOT=$buildAppToDirfi#判斷編譯結果if test $? -eq 0thenecho "~~~~~~~~~~~~~~~~~~~編譯成功~~~~~~~~~~~~~~~~~~~"elseecho "~~~~~~~~~~~~~~~~~~~編譯失敗~~~~~~~~~~~~~~~~~~~" >>$logPathecho "/n" >>$logPathexit 1fi###############開始打包成.ipaipaName=`echo $projectName | tr "[:upper:]" "[:lower:]"` #將項目名轉小寫appDir=$buildAppToDir/$buildConfig-iphoneos #app所在路徑echo "開始打包$projectName.xcarchive成$projectName.ipa....." >>$logPathxcrun -sdk iphoneos PackageApplication -v $appDir/$projectName.app -o $appDir/$ipaName.ipa #將app打包成ipa###############開始拷貝到目標下載目錄iconName="icon.png" #icon名稱iconSize=100 #icon大小#unzipAppDir=$appDir/$projectName.appunzipAppDir=$projectDiriconImages=($(find $unzipAppDir -path "$buildAppToDir" -prune -o -type f -size +1k -name "*[iI]con*.png" |xargs ls -lSar| grep ^-)) #查找帶Icon或icon的圖標,取最大的圖片,忽略build目錄,按大小排序輸出#iconImages=($(find $unzipAppDir -size +1k -name "*[iI]con*.png")) #查找帶Icon或icon的圖標,取最大的圖片iconImagesLength=${#iconImages[@]} #獲取數組的countcp -f -p ${iconImages[iconImagesLength-1]} $wwwIPADir/$iconName #拷貝icon.png文件#檢查文件是否存在if [ -f "$appDir/$ipaName.ipa" ]thenecho "打包$ipaName.ipa成功." >>$logPathelseecho "打包$ipaName.ipa失敗." >>$logPathexit 1ficp -f -p $appDir/$ipaName.ipa $wwwIPADir/$ipaName.ipa #拷貝ipa文件echo "復制$ipaName.ipa到${wwwIPADir}成功" >>$logPath###############計算文件大小和最后更新時間fileSize=`stat $appDir/$ipaName.ipa |awk '{if($8!=4096){size=size+$8;}} END{print "文件大小:", size/1024/1024,"M"}'`lastUpdateDate=`stat $appDir/$ipaName.ipa | awk '{print "最后更新時間:",$13,$14,$15,$16}'`echo "$fileSize" >>$logPathecho "$lastUpdateDate" >>$logPath plistDir=${wwwIPADir}/$ipaName.plist #plist文件的路徑htmlDir=${wwwIPADir}/index.html #html文件的路徑###############生成PLIST文件cat << EOF > $plistDir <?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/$ipaName.ipa</string> </dict> </array> <key>metadata</key> <dict> <key>bundle-identifier</key> <string>$bundleIdentifier</string> <key>bundle-version</key> <string>$bundleVersion</string> <key>kind</key> <string>software</string> <key>title</key> <string>$appName</string> </dict> </dict> </array> </dict> </plist>EOFecho "生成plist文件到$plistDir成功" >>$logPath###############生成html下載頁面cat << EOF > $htmlDir <!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 id="viewport" name="viewport" content="width=device-width; height=device-height; initial-scale=1.0; "/> <title>安裝$appName</title> <style type="text/CSS"> </style> </head> <body> <h2>$appName</h2> <img src="./$iconName" width=$iconSize height = $iconSize> <ul> <li><h2><a href="itms-services://?action=download-manifest&url=$url/$ipaName.plist">手機安裝$appName(V$bundleVersion.$bundleBuildVersion)</a></h2></li> <li><h2><a href="$url/$ipaName.ipa">電腦下載IPA包</a></h2></li> </ul> <p> $fileSize <p> $lastUpdateDate </body> </html>EOFecho "生成html文件到$htmlDir成功" >>$logPathecho "結束時間:$(date_Y_M_D_W_T)" >>$logPathecho "~~~~~~~~~~~~~~~~~~~結束編譯~~~~~~~~~~~~~~~~~~~" >>$logPathecho "~~~~~~~~~~~~~~~~~~~結束編譯,處理成功~~~~~~~~~~~~~~~~~~~"echo "/n" >>$logPathecho "$url"
[ { "name":"項目展示的名稱1", "projectname":"項目名稱1", "isworkspace":"是否是workspace", "foldername":"項目文件夾名1", "buildconfig":"Release/Debug/其他自定義編譯名稱" }, { "name":"項目展示的名稱2", "projectname":"項目名稱2", "isworkspace":"是否是workspace", "foldername":"項目文件夾名2", "buildconfig":"Release/Debug/其他自定義編譯名稱" }]
<html> <head> <title>iOS應用打包</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> </head> <body style="text-align:center"> <h1>請選擇編譯項目</h1> <form name="form1" method="post" action=""> <?php $filename ='data.json'; $jsonstring = file_get_contents($filename); $jsondecode = json_decode($jsonstring, true); for ($i= 0;$i< count($jsondecode); $i++) { $name = $jsondecode[$i]["name"]; echo "<label> <input type='radio' name='radio' value='$i'> ${name} </label> <br />"; } if($_POST) { $value = $_POST['radio']; $name = $jsondecode[$value]["name"]; $projectname = $jsondecode[$value]["projectname"]; $isworkspace = $jsondecode[$value]["isworkspace"]; $foldername = $jsondecode[$value]["foldername"]; $buildconfig = $jsondecode[$value]["buildconfig"]; echo '<br />即將編譯:',$name; echo '<br />編譯完成自動跳轉至下載頁面<br /><br /><br />'; $cmd = "./buildtool.sh $projectname $isworkspace $foldername $buildconfig"; $url = system($cmd); echo "<script language=/"javascript/">"; echo "location.href=/"$url/""; echo "</script>"; } ?> <br /> <input type="submit" name="Submit" value="提交" /> </form> </body></html>
新聞熱點
疑難解答