Unity3d+Jenkins 自动编译iOS、Android版本
1、在Unity3d中, 创建导出 iOS、Android 项目脚本 PerformBuild.cs ,放在Editor目录下(必须),如下:
using UnityEditor; using System.IO; using System.Collections; using UnityEngine; using System.Collections.Generic; class PerformBuild { static string[] GetBuildScenes() { List<string> names = new List<string>(); foreach(EditorBuildSettingsScene e in EditorBuildSettings.scenes) { if(e==null) continue; if(e.enabled) names.Add(e.path); } return names.ToArray(); } static string GetBuildPath() { string dirPath = Application.dataPath +"/../../../build/iPhone"; if(!System.IO.Directory.Exists(dirPath)){ System.IO.Directory.CreateDirectory(dirPath); } return dirPath; } [UnityEditor.MenuItem("Tools/PerformBuild/Test Command Line Build iPhone Step")] static void CommandLineBuild () { Debug.Log("Command line build\n------------------\n------------------"); string[] scenes = GetBuildScenes(); string path = GetBuildPath(); if(scenes == null || scenes.Length==0 || path == null) return; Debug.Log(string.Format("Path: \"{0}\"", path)); for(int i=0; i<scenes.Length; ++i) { Debug.Log(string.Format("Scene[{0}]: \"{1}\"", i, scenes[i])); } Debug.Log("Starting Build!"); BuildPipeline.BuildPlayer(scenes, path, BuildTarget.iPhone, BuildOptions.None); } static string GetBuildPathAndroid() { string dirPath = Application.dataPath +"/../../../build/android"; if(!System.IO.Directory.Exists(dirPath)){ System.IO.Directory.CreateDirectory(dirPath); } return dirPath; } [UnityEditor.MenuItem("Tools/PerformBuild/Test Command Line Build Step Android")] static void CommandLineBuildAndroid () { Debug.Log("Command line build android version\n------------------\n------------------"); string[] scenes = GetBuildScenes(); string path = GetBuildPathAndroid(); if(scenes == null || scenes.Length==0 || path == null) return; Debug.Log(string.Format("Path: \"{0}\"", path)); for(int i=0; i<scenes.Length; ++i) { Debug.Log(string.Format("Scene[{0}]: \"{1}\"", i, scenes[i])); } Debug.Log("Starting Android Build!"); BuildPipeline.BuildPlayer(scenes, path, BuildTarget.Android, BuildOptions.None); } }
完成之后在Tools菜单下 会有 测试菜单 ,可以试一下是否可以成功导出项目。
2、创建Jenkins配置文件 build.xml 和 参数文件 settings.properties
build.xml 如下:(有其他需求,编辑此文件即可)
<?xml version="1.0" encoding="UTF-8"?> <project name="wx_client" default="main" basedir="."> <property environment="env"/> <property name="RAW_BUILD_NUMBER" value="${env.BUILD_NUMBER}"/> <script language="javascript"><![CDATA[ var buildNum = parseInt(project.getProperty("RAW_BUILD_NUMBER")) var minorBuildNumber = buildNum % 100; var majorBuildNumber = (Math.floor(buildNum / 100)) % 100; var uberBuildNumber = (Math.floor(buildNum / 10000)) % 100; project.setProperty("minorBuildNumber", minorBuildNumber); project.setProperty("majorBuildNumber", majorBuildNumber); project.setProperty("uberBuildNumber", uberBuildNumber); ]]></script> <property name="VERSION_STRING" value="${uberBuildNumber}.${majorBuildNumber}.${minorBuildNumber}"/> <property file="settings.properties"/> <property name="dev.dir.absolute" location="${dev.dir}"/> <tstamp> <format property="TODAY_STAMP" pattern="yyyy_MM_dd" locale="en,US"/> </tstamp> <tstamp> <format property="MONTH_STAMP" pattern="M" locale="en,US"/> </tstamp> <property name="VERSION_NUM" value="${uberBuildNumber}.${majorBuildNumber}.${minorBuildNumber}"/> <property name="VERSION_STRING" value="honorbound_${VERSION_NUM}"/> <target name="main" depends="ios, android, zipDsym" /> <target name="android" depends="compile-android" /> <target name="ios" depends="compile-ios" /> <target name="clean"> <echo message="Cleaning Build Space"/> <delete dir="${build.dir}"/> <mkdir dir="${build.dir}"/> </target> <target name="compile-ios" depends="clean"> <echo message="Compiling unity project for version ${VERSION_STRING}"/> <echo message="${unity.bin} -projectPath ${dev.dir.absolute} -executeMethod PerformBuild.CommandLineBuild -batchmode -quit"/> <exec executable="${unity.bin}" failonerror="true"> <arg line="-projectPath ${dev.dir.absolute}"/> <arg line="-executeMethod PerformBuild.CommandLineBuild"/> <arg line="-batchmode"/> <arg line="-quit"/> </exec> <replace file="${build.dir}/iPhone/Info.plist" preservelastmodified="true"> <replacefilter token="999.999.999" value="${VERSION_NUM}" /> </replace> <exec executable="${security.bin}" failonerror="true"> <arg value="unlock-keychain"/> <arg line="-p ${keychain.password}"/> </exec> <echo message="Building ${build.dir}/iPhone/Unity-iPhone.xcodeproj/ Sym Root ${build.dir}/iPhone/"/> <exec executable="${xcode.bin}" failonerror="true"> <arg line="-project ${build.dir}/iPhone/Unity-iPhone.xcodeproj/"/> <arg line="PROVISIONING_PROFILE=${provisioning.guid}"/> <arg line="-sdk iphoneos"/> <arg line='CODE_SIGN_IDENTITY="${codesign.identity}"'/> <arg line='GCC_GENERATE_DEBUGGING_SYMBOLS=YES'/> <arg line='DEBUG_INFORMATION_FORMAT=dwarf-with-dsym'/> <arg line='DWARF_DSYM_FILE_SHOULD_ACCOMPANY_PRODUCT=YES'/> <arg line='DEBUGGING_SYMBOLS=YES'/> <arg line="-configuration Release"/> </exec> <exec executable="${xcrun.bin}" failonerror="true"> <arg line="-sdk iphoneos"/> <arg line="PackageApplication"/> <arg line="-v ${build.dir}/iPhone/build/${APP_NAME}.app"/> <arg line="-o ${build.dir}/iPhone/build/${APP_NAME}.ipa"/> </exec> <copy file="${build.dir}/iPhone/build/${APP_NAME}.ipa" tofile="${ios.build.deploy.folder}/${VERSION_STRING}.ipa"/> </target> <target name="compile-android" depends="clean"> <echo message="Compiling unity project for android version ${VERSION_STRING}"/> <echo message="${unity.bin} -projectPath ${dev.dir.absolute} -executeMethod PerformBuild.CommandLineBuildAndroid -batchmode -quit"/> <exec executable="${unity.bin}" failonerror="true"> <arg line="-projectPath ${dev.dir.absolute}"/> <arg line="-executeMethod PerformBuild.CommandLineBuildAndroid"/> <arg line="-batchmode"/> <arg line="-quit"/> </exec> <copy file="${build.dir}/android" tofile="${android.build.deploy.folder}/${VERSION_STRING}.apk"/> <exec executable="curl" dir="${android.build.deploy.folder}"> <arg line="--form file=@${VERSION_STRING}.apk '${BUILD_URL}/save_file.php?appname=${APP_NAME}'" /> </exec> </target> <target name="zipDsym"> <echo message="Zipping dSym"/> <exec executable="zip" dir="${build.dir}/iPhone/build" failonerror="true"> <arg value="-r"/> <arg value="${APP_NAME}.app.dSYM.zip"/> <arg value="${APP_NAME}.app.dSYM"/> </exec> </target> </project>
settings.properties 如下: (注意把下面该改成自己项目的改一下)
注:xcode5 去 /Users/<home>/Library/MobileDevice/Provisioning Profiles 目录找证书GUID
unity.bin = /Applications/Unity/Unity.app/Contents/MacOS/Unity
xcode.bin = /usr/bin/xcodebuild
xcrun.bin = /usr/bin/xcrun
security.bin = /usr/bin/security
provisioning.guid = SOME-GUID-GOES-HERE(证书GUID)
codesign.identity = iPhone Distribution: Joe Developer
build.dir = ../UnityClient/build (PerformBuild到的目录)
dev.dir = ../UnityClient/ (Unity3d项目目录)
keychain.password = Woohoo
APP_NAME=honorbound
ios.build.deploy.folder = /Users/Shared/Jenkins/builds/ios
android.build.deploy.folder = /Users/Shared/Jenkins/builds/android
(最后两个是打包好的ipa 和 apk 要放到的地方)
3、打开Jenkins,按如下步骤新建一个Job:
3.1、
3.2、找到 构建 -> 增加构建步骤 -> Invoke Ant
3.3、选择高级
3.4、输入 build File 路径 和 Properties 路径,然后保存job
4、现在就可以点击 立即构建 开始编译你的项目了,开始前请先退出Unity3d,否则会报错。
此外 iOS 需要MAC相关环境
参考资料:
1、http://blog.juiceboxmobile.com/2013/03/08/unity3d-ios-android-jenkins-autobuild/
2、https://gist.github.com/jmcguirk/5113641
3、http://docs.unity3d.com/Documentation/Manual/CommandLineArguments.html