iOS自動化編譯

來源:互聯網
上載者:User

標籤:

最近研究了一下iOS的自動化編譯,目的是為了簡化測試和開發的同學溝通協調的次數,實現測試同學可以隨時從網頁操作編譯SVN最新源碼並打包ipa進行測試。

具體思路是通過從設定檔讀取需要編譯的項目配置列表展示在網頁上,測試同學選擇需要編譯的項目,確定後將選擇項目的相關參數傳入shell指令碼運行,編譯完成自動跳轉至下載頁面。
主要流程包括:

  1. Shell指令碼的編寫。通過xcodebuild和xcrun實現自動編譯並打包。
  2. PHP呼叫指令碼。開啟OS X內建的Apache伺服器,編寫PHP來調用shell。
編寫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。
需要注意,指令碼中的路徑最好使用絕對路徑。

配置Apache和PHP啟動Apache
啟動: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調用shell指令碼

這裡主要用到了PHP的system命令:system($cmd)
PHP調用shell的許可權是比較低的,我們的shell裡會需要建立檔案及檔案夾的許可權,解決辦法是通過命令列將PHP檔案所在目錄及目錄下的所有檔案都提升許可權,否則指令碼會報許可權錯誤。具體步驟如下:

  1. 開啟目錄 /private/etc/apache2
  2. 開啟檔案 httpd.conf
    找到

    User _www Group _www

    修改_www為你的登入使用者名稱

    User <登入使用者名稱>
  3. 從命令列重啟Apache

    sudo apachectl restart
  4. 提升網站目錄許可權。因為我的網站根目錄就是上文提到的使用者的Sites檔案,因此執行以下命令

    sudo chmod 775 ~/Sitessudo chmod 775 ~/Sites/*

好了,許可權問題解決了。當滿懷信心看到從網頁呼叫指令碼輸出資訊的時候,結果又報了無法找到認證的錯誤,OMG,但從終端呼叫指令碼就可以成功,起初以為許可權不夠導致無法調用認證,繞了一大圈後發現這個問題只是因為鑰匙串中的認證一般安裝在登入下,只需要移動到系統下就行了。

關於從SVN倉庫擷取源碼的部分就不寫了,既然都可以呼叫指令碼了,這部分就也很簡單了。這個過程還是比較折騰的,希望這篇文章能夠save your time :)

最後奉上相關檔案的源碼。

Shell指令檔(buildtool.sh)
#!/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=$1result=${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" ]; thenecho "登陸使用者IP:$(replaceString $loginServer)" >>$logPathelse    echo "登陸使用者IP:localhost(127.0.0.1)" >>$logPathfiif [ -d "$logDir" ]; thenecho "${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" ]; thenecho "檔案目錄存在" >>$logPathelse echo "檔案目錄不存在" >>$logPath    mkdir -pv $wwwIPADirecho "建立${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&amp;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"
設定檔格式(data.json)
[{"name":"項目展示的名稱1","projectname":"項目名稱1","isworkspace":"是否是workspace","foldername":"專案檔夾名1","buildconfig":"Release/Debug/其他自訂編譯名稱"},{"name":"項目展示的名稱2","projectname":"項目名稱2","isworkspace":"是否是workspace","foldername":"專案檔夾名2","buildconfig":"Release/Debug/其他自訂編譯名稱"}]
PHP檔案(index.php)
<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>

iOS自動化編譯

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.