Unity3d:使用Jenkins自動編譯打包IOS(只能打包Development)

系列傳送門

IOS:
IOS:使用shell命令打包并上傳Itunes
Unity3d:
Unity3d:Canvas適配屏幕分辨率與錨點(Anchors與Pivot)
Unity3d:在屏幕邊緣顯示其他玩家方位
Unity3d:命令行打包Android
Unity3d:命令行編譯IOS
Unity3d:使用Jenkins自動編譯打包IOS(只能打包Development)
Unity3d:使用Jenkins自動編譯打包IOS(打包Ad-hoc,上傳itunes)

安裝并配置Jenkns

1. 下載完后,安裝

官網(wǎng):https://jenkins.io/

2. 修改jenkins啟動用戶

參考:http://www.xuanyusong.com/archives/3349

安裝完之后jenkins會自動啟動,而且使用root用戶啟動的,這會在構建時造成一些麻煩,比如執(zhí)行權限,文件訪問權限等

所以需要把jenkins先關閉,然后修改jenkins的啟動用戶和當前登陸系統(tǒng)的用戶一致

  • 停止jenkins
sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plis
  • 修改org.jenkins-ci.plis文件
    • 修改GroupName和當前登陸系統(tǒng)的用戶的Group Name一致
    • 修改UserName和當前登陸系統(tǒng)的用戶的User Name一致
  • 啟動jenkins
不推薦:launchctl load /Library/LaunchDaemons/org.jenkins-ci.plist

推薦:  java -jar jenkins.war

3. 訪問http://127.0.0.1:8008

打開網(wǎng)頁后,會讓輸入安裝密碼,這個密碼在:

/User/當前系統(tǒng)登陸用戶/.jenkins/secrets/initialAdminPassword

然后下一步配置Jenkins網(wǎng)頁的登陸密碼,信息要全部填寫完成后,會提示安裝插件,直接選安裝推薦的插件

4. 安裝我們構建打包需要插件

安裝時,記得勾選自動重啟jenkins

5. 設置插件配置

配置Xcode Builder

進入jenkins主頁->左側系統(tǒng)管理->系統(tǒng)設置->Xcode Builder

Xcode路徑之類的,插件會自動補充,無需填寫

  • Development Team(可選,配置構建時可自己指定)
    • Team Name:***********(可以在開發(fā)者后臺查到)
    • Team ID:***********(可以在開發(fā)者后臺查到)
  • keychains
    • keychain Name:login.keychain(自己隨便定義)
    • keychain Path:/Users/當前系統(tǒng)登陸用戶/Library/Keychains/login.keychain(路徑中包括xxxx.keychain文件)
    • keychain Password:********(當前系統(tǒng)登陸用戶的密碼)

配置Unity3d

進入jenkins主頁->左側系統(tǒng)管理->全局工具配置->Unity3d

  • 別名:Unity3d(自己隨便定義)
  • 安裝目錄:/Applications/Unity/Unity.app(注意:該插件會自己在后面拼接“Contents/MacOS”或“Editor/Unity.exe”)

配置Keychains and Provisioning Profiles Management

進入jenkins主頁->左側系統(tǒng)管理->全局工具配置->Keychains and Provisioning Profiles Management

證書說明:

  • ios_development.cer:需要從開發(fā)者后臺下載(左側certificate欄目里)
  • xxxxxxx.mobileprovision(有development版(這里用開發(fā)版),ad-hoc的distribution版,正式distribution版):需要從開發(fā)者后臺下載(左側Provisioning Profiles欄目里)
  • xxxxxxx.developerprofile:需要從Xcode中導出(Xcode->Preferences->Accounts(需要在這里先登陸開發(fā)者賬號)->左下角齒輪按鈕->Export Apple ID And Code Signing Assets)
  • 上傳login.keychain
    • 配置Keychains
      • Filename:login.keychain(會自動填寫)
      • Password:當前系統(tǒng)登陸用戶的密碼
      • Description:(自己隨便定義)
      • Identities:
        • Code Sign Identity:iPhone Developer:XXXXXX(鑰匙串中,蘋果開發(fā)者證書簡介信息中的常用名稱,打開系統(tǒng)鑰匙串,把xxxxxxx.developerprofile復制進去即可)
  • 上傳xxxxxxx.mobileprovision
    • 配置Provisioning Profiles
      • Provisioning Profiles Directory Path:/Users/當前系統(tǒng)登陸用戶/Library/MobileDevice/Provisioning Profiiles
      • Filename:(會自動填寫)
      • UUID:(會自動填寫)

Jenkins配置結束

正式開工,創(chuàng)建構建

1. 創(chuàng)建構建

創(chuàng)建一個自由風格的軟件項目

  • 項目名:Unity3d_Build_IOS(自己隨便定義)

2. 構建配置

修改workspace

默認workspace:

/Users/當前系統(tǒng)登陸用戶/.jenkins/workspace/Unity3d_Build_IOS(項目名)

頂部選項卡->General->高級選項->選擇“使用自定義的工作空間”

  • 目錄:自定義的工作空間路徑
  • 顯示名稱:Unity3dBuildXXX(如果填寫了,會覆蓋上面的項目名:Unity3d_Build_IOS)

配置Unity3d編譯相關

頂部選項卡->構建->增加構建步驟->選擇Invoke Unity3d Editor

  • Unity3d installation name:Unity3d(會自動填寫,也就是在全局工具配置配置時寫的"Unity3d"別名)
  • Editor conmmand line arguments:
-quit -batchmode -executeMethod PerformBuild.CommandLineBuild -projectPath 要編譯的unity3d項目目錄
插件參考:https://wiki.jenkins.io/display/JENKINS/Unity3dBuilder+Plugin
腳本參考:http://www.cnblogs.com/yinghuochong/archive/2013/09/01/3294940.html
命令參考:https://docs.unity3d.com/Manual/CommandLineArguments.html
項目腳本 PerformBuild.cs,寫好后 ,放在Editor目錄下
    - 注意:腳本里寫的unity3d的IOS編譯輸出目錄一定要記得,后面會用得著
    - 此處unity3d的IOS編譯輸出目錄為:/Users/當前系統(tǒng)登陸用戶/Documents/Project/build/iPhone

配置完成后,可以點擊“立即構建”進行測試,看unity3d項目編譯是否正常
點擊左下角構建記錄,進入該記錄信息頁,再點擊左側“Console Output”即可查看構建日志輸出
注意:從日志里看到,編譯時,有無權限刪除IOS編譯輸出目錄的問題,此時需要做以下配置:

頂部選項卡->構建->增加構建步驟->選擇Execute shell

Commands輸入:

rm -rf /Users/當前系統(tǒng)登陸用戶/Documents/Project/build/iPhone(unity3d的IOS編譯輸出目錄)

命令配置好后,把Execute shell拖到Invoke Unity3d Editor的前面,此時在Unity3d指定編譯之前,會先執(zhí)行配置的shell命令

配置IOS編譯相關

上面配置好并測試完成后,繼續(xù)配置Xcode編譯相關

頂部選項卡->構建環(huán)境->勾選Keychains and Code signing Identities

勾選即可,保存后,刷新即可看到內容被自動填充(也就是之前配置的全局工具配置->Keychains and Provisioning Profiles Management)

頂部選項卡->構建環(huán)境->勾選Mobile Provisioning Profiles

勾選即可,保存后,刷新即可看到內容被自動填充(也就是之前配置的全局工具配置->Keychains and Provisioning Profiles Management)

頂部選項卡->構建->增加構建步驟->選擇Xcode

配置General build settings

  • Target:Unity-iPhone
    • 如果不知道應該寫,通過命令行工具,可以進入上一步生成的IOS項目目錄(unity3d的IOS編譯輸出目錄),執(zhí)行“xcodebuild -list”即可看到
  • Clear before build:Yes
  • Configuration:release( 或者 debug,看需要)
  • 勾選 Pack applicatin,build and sign ipa
    • Export method:develoment(看需要,如果Mobile Provisioning Profiles選擇的是develoment證書,則這里需要配置development,如果是ad-hoc的distribution證書,則這里需要配置ad-hoc,如果是正式上線的證書,則這里需要配置app-store)
    • .ipa filename pattern:${BUILD_DATE}(生成的ipa文件名字)
    • Output directory:/Users/當前系統(tǒng)登陸用戶/Desktop(這里是放在當前系統(tǒng)用戶的桌面,自己隨便定義)

配置Code signing & OS X keychain options

  • Development Team:*******(下拉選擇這個,也就是之前配置的系統(tǒng)設置->Xcode Builder->Development Team->Team Name)
    • Development Team ID:(當上面Development Team選擇None時,此處需要手動輸入TeamID,可以在開發(fā)者后臺查到)
  • 勾選Unlock keychain:
    • Keychain:login.keychain(下拉選擇這個,也就是之前配置的系統(tǒng)設置->Xcode Builder->keychains)
      • Keychain path:(當上面Keychain選擇None時,此處需要手動輸入xxxx.keychain所在路徑,路徑中包括xxxx.keychain文件)
      • Keychain password:(當上面Keychain選擇None時,此處需要手動輸入xxxx.keychain的解鎖密碼)

配置Advanced Xcode build options

  • Xcode Schem File:Unity-iPhone

    • 如果不知道應該寫,通過命令行工具,可以進入上一步生成的IOS項目目錄(unity3d的IOS編譯輸出目錄),執(zhí)行“xcodebuild -list”即可看到
  • SDK:iOS 11.2 - 如果不知道應該寫,通過命令行工具,可以進入上一步生成的IOS項目目錄(unity3d的IOS編譯輸出目錄),執(zhí)行“xcodebuild -list”即可看到

  • Custom xcodebuild arguments:-ENABLE_BITCODE=NO -allowProvisioningUpdates

    • 比如,編譯時不需要開啟 BITCODE,自此出填寫:-ENABLE_BITCODE=NO,這個配置如果在Unity中配置過了,此處可以寫
    • 比如,編譯時需要動態(tài)更新證書,自此出填寫:-allowProvisioningUpdates
  • Xcode Project Directory:/Users/當前系統(tǒng)登陸用戶/Documents/Project/build/iPhone(unity3d的IOS編譯輸出目錄)

創(chuàng)建構建并配置結束

注意事項#

  1. 如果出現(xiàn)“l(fā)d ... normal arm64”類的錯誤,就倒著分析log,可能有以下異常引起:
  • 看有沒有什么framework not found的異常
  1. 打包發(fā)布版本的時候,會出現(xiàn)找不到對應的證書:
  • 要鑰匙串中有開發(fā)證書

附:在Unity3d中動態(tài)添加IOS需要的Framework和plist參數(shù)方法

#if UNITY_IOS
using UnityEditor;
using UnityEditor.iOS.Xcode;
using System.Collections.Generic;
using System.IO;
#endif

public static class PBXHelper
{
    public const string PROJECT_ROOT = "$(PROJECT_DIR)/";
    public const string IMAGE_XCASSETS_DIRECTORY_NAME = "Unity-iPhone";
    public const string LINKER_FLAG_KEY = "OTHER_LDFLAGS";
    public const string FRAMEWORK_SEARCH_PATHS_KEY = "FRAMEWORK_SEARCH_PATHS";
    public const string LIBRARY_SEARCH_PATHS_KEY = "LIBRARY_SEARCH_PATHS";
    public const string ENABLE_BITCODE_KEY = "ENABLE_BITCODE";
    public const string DEVELOPMENT_TEAM = "DEVELOPMENT_TEAM";
    public const string GCC_ENABLE_CPP_EXCEPTIONS = "GCC_ENABLE_CPP_EXCEPTIONS";
    public const string GCC_ENABLE_CPP_RTTI = "GCC_ENABLE_CPP_RTTI";
    public const string GCC_ENABLE_OBJC_EXCEPTIONS = "GCC_ENABLE_OBJC_EXCEPTIONS";
    public const string INFO_PLIST_NAME = "Info.plist";

    public const string URL_TYPES_KEY = "CFBundleURLTypes";
    public const string URL_TYPE_ROLE_KEY = "CFBundleTypeRole";
    public const string URL_IDENTIFIER_KEY = "CFBundleURLName";
    public const string URL_SCHEMES_KEY = "CFBundleURLSchemes";
    public const string APPLICATION_QUERIES_SCHEMES_KEY = "LSApplicationQueriesSchemes";

#if UNITY_IOS
    /// <summary>
    /// </summary>
    /// <param name="buildTarget">Build target.</param>
    /// <param name="buildPath">Build path.</param>
    [PostProcessBuild]
    public static void OnPostprocessBuild (BuildTarget buildTarget, string buildPath)
    {
        if (buildTarget != BuildTarget.iOS)
            return;

        string pbxProjPath = PBXProject.GetPBXProjectPath (buildPath);
        pbxProject = new PBXProject ();
        pbxProject.ReadFromString (File.ReadAllText (pbxProjPath));
        string targetGuid = pbxProject.TargetGuidByName (PBXProject.GetUnityTargetName ());

        // 1、設置關閉Bitcode
        pbxProject.SetBuildProperty (targetGuid, ENABLE_BITCODE_KEY, "NO");

        // 2、添加Framework
        pbxProject.AddFrameworkToProject (targetGuid, "系統(tǒng)自帶的.framework", false);
        pbxProject.AddFrameworkToProject (targetGuid, "系統(tǒng)自帶的.framework", false);
        pbxProject.AddFrameworkToProject (targetGuid, "系統(tǒng)自帶的.framework", false);

        // 3、添加tbd
        pbxProject.AddFileToBuild(targetGuid, pbxProject.AddFile("usr/lib/" + "系統(tǒng)自帶的.tbd", "Frameworks/" + "系統(tǒng)自帶的.tbd", PBXSourceTree.Sdk));

        // 4、添加Privaty
        SetInfoPlist (buildPath);

        File.WriteAllText (pbxProjPath, pbxProject.WriteToString ());

        UnityEngine.Debug.Log ("PBXProject : ---->" + pbxProject.WriteToString ());
    }

    public static void SetInfoPlist (string buildPath)
    {
        List<string> privacySensiticeData = new List<string> ();
        
        // 添加權限
        privacySensiticeData.Add ("NSMicrophoneUsageDescription");
        privacySensiticeData.Add ("NSCameraUsageDescription");
        privacySensiticeData.Add ("NSLocationAlwaysAndWhenInUseUsageDescription");

        PlistDocument plist = GetInfoPlist (buildPath);
        SetPrivacySensiticeData (plist, privacySensiticeData, "Privacy");
        plist.WriteToFile (GetInfoPlistPath (buildPath));

        UnityEngine.Debug.Log ("PLIST : ---->" + plist.WriteToString ());
    }

    private static void SetPrivacySensiticeData (PlistDocument plist, List<string> permission, string description = "")
    {
        PlistElementDict rootDict = plist.root;
        int count = permission.Count;
        for (int i = 0; i < count; i++)
        {
            rootDict.SetString (permission[i], description);
        }
    }
    private static string GetInfoPlistPath (string buildPath)
    {
        return Path.Combine (buildPath, INFO_PLIST_NAME);
    }

    private static PlistDocument GetInfoPlist (string buildPath)
    {
        string plistPath = GetInfoPlistPath (buildPath);
        PlistDocument plist = new PlistDocument ();
        plist.ReadFromFile (plistPath);
        return plist;
    }
#endif
}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容