Auto build apk / xcode / ipa by unity3d

Auto build apk/xcode/ipa by unity3d

Unity Editor Scripts

AutoBuildProject.CS

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using UnityEngine.iOS;
public class AutoBuildProject : Editor {
    [MenuItem("Tool/AutoBuild_AndroidAPK")]
    public static void AutoBuildAndroidAPK()
    {
        BuildTargetGroup buildTargetGroup = BuildTargetGroup.Android;
        BuildTarget buildTarget = BuildTarget.Android;
        EditorUserBuildSettings.SwitchActiveBuildTarget(buildTargetGroup,buildTarget);
        //// keystore 路径, G:\keystore\one.keystore
        //PlayerSettings.Android.keystoreName = "G:\\keystore\\one.keystore";
        //// one.keystore 密码
        //PlayerSettings.Android.keystorePass = "123456";
        // one.keystore 别名
        //PlayerSettings.Android.keyaliasName = "bieming1";
        //// 别名密码
        //PlayerSettings.Android.keyaliasPass = "123456";

        string apkName = string.Format("./Android/Apks/{0}.apk", "Test");
        string res = BuildPipeline.BuildPlayer(GetBuildScenes(), apkName, buildTarget, BuildOptions.None);
        AssetDatabase.Refresh();
    }
    [MenuItem("Tool/AutoBuild_XCode")]
    public static void AutoBuildXCode()
    {
        //打包之前先设置一下 预定义标签, 我建议大家最好 做一些  91 同步推 快用 PP助手一类的标签。 这样在代码中可以灵活的开启 或者关闭 一些代码。
        //因为 这里我是承接 上一篇文章, 我就以sharesdk做例子 ,这样方便大家学习 ,
        //PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.iOS, "USE_SHARE");
        BuildTargetGroup buildTargetGroup = BuildTargetGroup.iOS;
        BuildTarget buildTarget = BuildTarget.iOS;
        EditorUserBuildSettings.SwitchActiveBuildTarget(buildTargetGroup, buildTarget);


        //PlayerSettings.bundleVersion = "";
        string pathName = string.Format("./XCodeProjects/{0}","Test"); 
        string res = BuildPipeline.BuildPlayer(GetBuildScenes(), pathName, buildTarget, BuildOptions.None);
        AssetDatabase.Refresh();
    }

    //在这里找出你当前工程所有的场景文件,假设你只想把部分的scene文件打包 那么这里可以写你的条件判断 总之返回一个字符串数组。
    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();
    }
    private static string[] s;
    static void BuildPackage()
    {
        s = System.Environment.GetCommandLineArgs();
        var target = s[s.Length - 3];
        if (target.Equals("0")) //windows
        {
            BuildForStandaloneWindows();
        }
        else if (target.Equals("1")) //android
        {
            //BuildForAndroid();
        }
        else if (target.Equals("2"))  //ios
        {
            //BuildForIOS();
        }
        //其他平台自己看着写就行 
        s = null;
    }

    static void BuildForStandaloneWindows()
    {
        string[] levels = { "Assets/Scenes/1.unity" };
        string path = GetExportPath(BuildTarget.StandaloneWindows);
        PlayerSettings.defaultIsFullScreen = false;
        PlayerSettings.companyName = companyName;
        PlayerSettings.productName = productName;
        PlayerSettings.resizableWindow = false;
        PlayerSettings.displayResolutionDialog = ResolutionDialogSetting.Disabled;

        var tx = Resources.Load<Texture2D>("icon");
        Texture2D[] txs = { tx, tx, tx, tx, tx, tx, tx, };
        var lengt = PlayerSettings.GetIconsForTargetGroup(BuildTargetGroup.Standalone);
        if (txs != null)
            PlayerSettings.SetIconsForTargetGroup(BuildTargetGroup.Standalone, txs);
        var st = BuildPipeline.BuildPlayer(levels, path, BuildTarget.StandaloneWindows, BuildOptions.None);
    }
    private static string GetExportPath(BuildTarget target)
    {
        //var s = System.Environment.GetCommandLineArgs();
        string path = s[s.Length - 2];
        string name = string.Empty;
        if (target == BuildTarget.Android)
        {
            name = "/" + s[s.Length - 1] + ".apk";
        }
        else if (target == BuildTarget.iOS)
        {
            name = "/" + s[s.Length - 1];
        }
        else if (target == BuildTarget.StandaloneWindows)
        {
            name = "/" + s[s.Length - 1] + ".exe";
        }
        UnityEngine.Debug.Log(path);
        UnityEngine.Debug.Log(name);
        string exepath = @path + name;
        UnityEngine.Debug.Log(exepath);
        return exepath;
    }
    private static string companyName
    {
        get
        {
            return s[s.Length - 5];
        }
    }
    private static string productName
    {
        get
        {
            return s[s.Length - 4];
        }
    }
}

XCodeAPI

XCodeProjectMod.CS

using UnityEngine;
//#if UNITY_STANDALONE_OSX
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
using System.Collections.Generic;
using System.IO;
//#endif

public class XCodeProjectMod : MonoBehaviour
{
//#if UNITY_STANDALONE_OSX
    private const string SETTING_DATA_PATH = "Assets/Editor/XCodeAPI/Setting/XcodeProjectSetting.asset";
    [PostProcessBuild]
    private static void OnPostprocessBuild(BuildTarget buildTarget, string buildPath)
    {
        if (buildTarget != BuildTarget.iOS)
            return;
        PBXProject pbxProject = null;
        XcodeProjectSetting setting = null;
        string pbxProjPath = PBXProject.GetPBXProjectPath(buildPath);
        string targetGuid = null;
        Debug.Log("开始设置.XCodeProj");

        setting = AssetDatabase.LoadAssetAtPath<XcodeProjectSetting>(SETTING_DATA_PATH);
        pbxProject = new PBXProject();
        pbxProject.ReadFromString(File.ReadAllText(pbxProjPath));
        targetGuid = pbxProject.TargetGuidByName(PBXProject.GetUnityTargetName());

        pbxProject.SetBuildProperty(targetGuid, XcodeProjectSetting.ENABLE_BITCODE_KEY, setting.EnableBitCode ? "YES" : "NO");
        pbxProject.SetBuildProperty(targetGuid, XcodeProjectSetting.DEVELOPMENT_TEAM, setting.DevelopmentTeam);
        pbxProject.SetBuildProperty(targetGuid, XcodeProjectSetting.GCC_ENABLE_CPP_EXCEPTIONS, setting.EnableCppEcceptions ? "YES" : "NO");
        pbxProject.SetBuildProperty(targetGuid, XcodeProjectSetting.GCC_ENABLE_CPP_RTTI, setting.EnableCppRtti ? "YES" : "NO");
        pbxProject.SetBuildProperty(targetGuid, XcodeProjectSetting.GCC_ENABLE_OBJC_EXCEPTIONS, setting.EnableObjcExceptions ? "YES" : "NO");

        if (!string.IsNullOrEmpty(setting.CopyDirectoryPath))
            DirectoryProcessor.CopyAndAddBuildToXcode(pbxProject, targetGuid, setting.CopyDirectoryPath, buildPath, "");

        //编译器标记(Compiler flags)
        foreach (XcodeProjectSetting.CompilerFlagsSet compilerFlagsSet in setting.CompilerFlagsSetList)
        {
            foreach (string targetPath in compilerFlagsSet.TargetPathList)
            {
                if (!pbxProject.ContainsFileByProjectPath(targetPath))
                    continue;
                string fileGuid = pbxProject.FindFileGuidByProjectPath(targetPath);
                List<string> flagsList = pbxProject.GetCompileFlagsForFile(targetGuid, fileGuid);
                flagsList.Add(compilerFlagsSet.Flags);
                pbxProject.SetCompileFlagsForFile(targetGuid, fileGuid, flagsList);
            }
        }

        //引用内部框架
        foreach (string framework in setting.FrameworkList)
        {
            pbxProject.AddFrameworkToProject(targetGuid, framework, false);
        }

        //引用.tbd文件
        foreach (string tbd in setting.TbdList)
        {
            pbxProject.AddFileToBuild(targetGuid, pbxProject.AddFile("usr/lib/" + tbd, "Frameworks/" + tbd, PBXSourceTree.Sdk));
        }

        //设置OTHER_LDFLAGS
        pbxProject.UpdateBuildProperty(targetGuid, XcodeProjectSetting.LINKER_FLAG_KEY, setting.LinkerFlagArray, null);
        //设置Framework Search Paths
        pbxProject.UpdateBuildProperty(targetGuid, XcodeProjectSetting.FRAMEWORK_SEARCH_PATHS_KEY, setting.FrameworkSearchPathArray, null);
        File.WriteAllText(pbxProjPath, pbxProject.WriteToString());

        //已经存在的文件,拷贝替换
        foreach (XcodeProjectSetting.CopeFiles file in setting.CopeFilesList)
        {
            File.Copy(Application.dataPath + file.sourcePath, buildPath + file.copyPath, true);
        }

        //File.Copy(Application.dataPath + "/Editor/XCodeAPI/UnityAppController.h", buildPath + "/Classes/UnityAppController.h", true);
        //File.Copy(Application.dataPath + "/Editor/XCodeAPI/UnityAppController.mm", buildPath + "/Classes/UnityAppController.mm", true);

        //设置Plist
        InfoPlistProcessor.SetInfoPlist(buildPath, setting);
    }
//#endif
}

DirectoryProcessor.CS


using UnityEditor.iOS.Xcode;
using System.IO;


public static class DirectoryProcessor
{
    // 拷贝并增加到项目
    public static void CopyAndAddBuildToXcode(PBXProject pbxProject, string targetGuid, string copyDirectoryPath, string buildPath, string currentDirectoryPath, bool needToAddBuild = true)
    {
        string unityDirectoryPath = copyDirectoryPath;
        string xcodeDirectoryPath = buildPath;

        if (!string.IsNullOrEmpty(currentDirectoryPath))
        {
            unityDirectoryPath = Path.Combine(unityDirectoryPath, currentDirectoryPath);
            xcodeDirectoryPath = Path.Combine(xcodeDirectoryPath, currentDirectoryPath);
            Delete(xcodeDirectoryPath);
            Directory.CreateDirectory(xcodeDirectoryPath);
        }

        foreach (string filePath in Directory.GetFiles(unityDirectoryPath))
        {
            //过滤.meta文件
            string extension = Path.GetExtension(filePath);
            if (extension == ExtensionName.META)
                continue;
            //
            if (extension == ExtensionName.ARCHIVE)
            {
                pbxProject.AddBuildProperty(targetGuid, XcodeProjectSetting.LIBRARY_SEARCH_PATHS_KEY, XcodeProjectSetting.PROJECT_ROOT + currentDirectoryPath);
            }

            string fileName = Path.GetFileName(filePath);
            string copyPath = Path.Combine(xcodeDirectoryPath, fileName);

            //有可能是.DS_Store文件,直接过滤
            if (fileName[0] == '.')
                continue;
            File.Delete(copyPath);
            File.Copy(filePath, copyPath);

            if (needToAddBuild)
            {
                string relativePath = Path.Combine(currentDirectoryPath, fileName);
                pbxProject.AddFileToBuild(targetGuid, pbxProject.AddFile(relativePath, relativePath, PBXSourceTree.Source));
            }
        }

        foreach (string directoryPath in Directory.GetDirectories(unityDirectoryPath))
        {
            string directoryName = Path.GetFileName(directoryPath);
            bool nextNeedToAddBuild = needToAddBuild;
            if (directoryName.Contains(ExtensionName.FRAMEWORK) || directoryName.Contains(ExtensionName.BUNDLE) || directoryName == XcodeProjectSetting.IMAGE_XCASSETS_DIRECTORY_NAME)
            {
                nextNeedToAddBuild = false;
            }
            CopyAndAddBuildToXcode(pbxProject, targetGuid, copyDirectoryPath, buildPath, Path.Combine(currentDirectoryPath, directoryName), nextNeedToAddBuild);
            if (directoryName.Contains(ExtensionName.FRAMEWORK) || directoryName.Contains(ExtensionName.BUNDLE))
            {
                string relativePath = Path.Combine(currentDirectoryPath, directoryName);
                pbxProject.AddFileToBuild(targetGuid, pbxProject.AddFile(relativePath, relativePath, PBXSourceTree.Source));
                pbxProject.AddBuildProperty(targetGuid, XcodeProjectSetting.FRAMEWORK_SEARCH_PATHS_KEY, XcodeProjectSetting.PROJECT_ROOT + currentDirectoryPath);
            }
        }
    }

    //拷贝文件夹或者文件
    public static void CopyAndReplace(string sourcePath, string copyPath)
    {
        Delete(copyPath);
        Directory.CreateDirectory(copyPath);
        foreach (var file in Directory.GetFiles(sourcePath))
        {
            if (Path.GetExtension(file) == ExtensionName.META)
                continue;
            File.Copy(file, Path.Combine(copyPath, Path.GetFileName(file)));
        }
        foreach (var dir in Directory.GetDirectories(sourcePath))
        {
            CopyAndReplace(dir, Path.Combine(copyPath, Path.GetFileName(dir)));
        }
    }

    //删除目标文件夹以及文件夹内的所有文件
    public static void Delete(string targetDirectoryPath)
    {
        if (!Directory.Exists(targetDirectoryPath))
            return;
        string[] filePaths = Directory.GetFiles(targetDirectoryPath);
        foreach (string filePath in filePaths)
        {
            File.SetAttributes(filePath, FileAttributes.Normal);
            File.Delete(filePath);
        }
        string[] directoryPaths = Directory.GetDirectories(targetDirectoryPath);
        foreach (string directoryPath in directoryPaths)
        {
            Delete(directoryPath);
        }
        Directory.Delete(targetDirectoryPath, false);
    }
}

ExtensionName.CS


using UnityEngine;
using System.Collections;

public static class ExtensionName
{
    public const string META = ".meta";
    public const string ARCHIVE = ".a";
    public const string FRAMEWORK = ".framework";
    public const string BUNDLE = ".bundle";
}

InfoPlistProcessor.CS


using System.Collections.Generic;
using UnityEditor.iOS.Xcode;
using System.IO;

//Info.Plist修改设置
public static class InfoPlistProcessor
{
    private static string GetInfoPlistPath(string buildPath)
    {
        return Path.Combine(buildPath, XcodeProjectSetting.INFO_PLIST_NAME);
    }

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

    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 void SetApplicationQueriesSchemes(PlistDocument plist, List<string> _applicationQueriesSchemes)
    {
        PlistElementArray queriesSchemes;
        int count = _applicationQueriesSchemes.Count;
        string queriesScheme = null;

        if (plist.root.values.ContainsKey(XcodeProjectSetting.APPLICATION_QUERIES_SCHEMES_KEY))
            queriesSchemes = plist.root[XcodeProjectSetting.APPLICATION_QUERIES_SCHEMES_KEY].AsArray();
        else
            queriesSchemes = plist.root.CreateArray(XcodeProjectSetting.APPLICATION_QUERIES_SCHEMES_KEY);

        for (int i = 0; i < count; i++)
        {
            queriesScheme = _applicationQueriesSchemes[i];
            if (!queriesSchemes.values.Contains(new PlistElementString(queriesScheme)))
                queriesSchemes.AddString(queriesScheme);
        }
    }

    private static void SetBackgroundModes(PlistDocument plist, List<string> modes)
    {
        PlistElementDict rootDict = plist.root;
        PlistElementArray bgModes = rootDict.CreateArray("UIBackgroundModes");
        int count = modes.Count;
        for (int i = 0; i < count; i++)
        {
            bgModes.AddString(modes[i]);
        }
    }

    private static void SetURLSchemes(PlistDocument plist, List<XcodeProjectSetting.BundleUrlType> urlList)
    {
        PlistElementArray urlTypes;
        PlistElementDict itmeDict;
        if (plist.root.values.ContainsKey(XcodeProjectSetting.URL_TYPES_KEY))
            urlTypes = plist.root[XcodeProjectSetting.URL_TYPES_KEY].AsArray();
        else
            urlTypes = plist.root.CreateArray(XcodeProjectSetting.URL_TYPES_KEY);

        for (int i = 0; i < urlList.Count; i++)
        {
            itmeDict = urlTypes.AddDict();
            itmeDict.SetString(XcodeProjectSetting.URL_TYPE_ROLE_KEY, "Editor");
            itmeDict.SetString(XcodeProjectSetting.URL_IDENTIFIER_KEY, urlList[i].identifier);
            PlistElementArray schemesArray = itmeDict.CreateArray(XcodeProjectSetting.URL_SCHEMES_KEY);
            if (itmeDict.values.ContainsKey(XcodeProjectSetting.URL_SCHEMES_KEY))
                schemesArray = itmeDict[XcodeProjectSetting.URL_SCHEMES_KEY].AsArray();
            else
                schemesArray = itmeDict.CreateArray(XcodeProjectSetting.URL_SCHEMES_KEY);
            //TODO:按理说要排除已经存在的,但由于我们是新生成,所以不做排除
            for (int j = 0; j < urlList[i].bundleSchmes.Count; j++)
            {
                schemesArray.AddString(urlList[i].bundleSchmes[j]);
            }
        }
    }

    public static void SetInfoPlist(string buildPath, XcodeProjectSetting setting)
    {
        PlistDocument plist = GetInfoPlist(buildPath);
        SetPrivacySensiticeData(plist, setting.privacySensiticeData, "privacySensiticeData");
        SetApplicationQueriesSchemes(plist, setting.ApplicationQueriesSchemes);
        SetBackgroundModes(plist, setting.BackgroundModes);
        SetURLSchemes(plist, setting.BundleUrlTypeList);
        plist.WriteToFile(GetInfoPlistPath(buildPath));
    }





  

}

XcodeProjectSetting.CS


using UnityEngine;
using System.Collections.Generic;

/// <summary>
/// Xcode项目的一些设定值
/// </summary>
public class XcodeProjectSetting : ScriptableObject
{
    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";

    #region XCodeproj
    public bool EnableBitCode = false;
    public bool EnableCppEcceptions = true;
    public bool EnableCppRtti = true;
    public bool EnableObjcExceptions = true;

    //要拷贝到XCode内的文件的路径
    public string CopyDirectoryPath = "Assets/Editor/XCodeAPI/Frameworks";
    //AppleDevelopment内AppID表示
    public string DevelopmentTeam = "";
    //引用的内部Framework
    public List<string> FrameworkList = new List<string>() { };
    //引用的内部.tbd
    public List<string> TbdList = new List<string>() { };
    //设置OtherLinkerFlag
    public string[] LinkerFlagArray = new string[] { };
    //设置FrameworkSearchPath
    public string[] FrameworkSearchPathArray = new string[] { "$(inherited)", "$(PROJECT_DIR)/Frameworks" };

    #region 针对单个文件进行flag标记
    [System.Serializable]
    public struct CompilerFlagsSet
    {
        public string Flags;
        public List<string> TargetPathList;

        public CompilerFlagsSet(string flags, List<string> targetPathList)
        {
            Flags = flags;
            TargetPathList = targetPathList;
        }
    }

    public List<CompilerFlagsSet> CompilerFlagsSetList = new List<CompilerFlagsSet>()
    {
        /*new CompilerFlagsSet ("-fno-objc-arc", new List<string> () {"Plugin/Plugin.mm"})*/ //实例,请勿删除
    };
    #endregion

    #endregion

    #region 拷贝文件
    [System.Serializable]
    public struct CopeFiles
    {
        public string sourcePath;
        public string copyPath;

        public CopeFiles(string sourcePath, string copyPath)
        {
            this.sourcePath = sourcePath;
            this.copyPath = copyPath;
        }
    }

    public List<CopeFiles> CopeFilesList = new List<CopeFiles>() { };
    #endregion

    #region info.Plist
    //白名单
    public List<string> ApplicationQueriesSchemes = new List<string>() { };

    //iOS10新的特性
    public List<string> privacySensiticeData = new List<string>() { };

    #region 第三方平台URL Scheme
    [System.Serializable]
    public struct BundleUrlType
    {
        public string identifier;
        public List<string> bundleSchmes;

        public BundleUrlType(string identifier, List<string> bundleSchmes)
        {
            this.identifier = identifier;
            this.bundleSchmes = bundleSchmes;
        }
    }

    public List<BundleUrlType> BundleUrlTypeList = new List<BundleUrlType>() { };
    #endregion

    //放置后台需要开启的功能
    public List<string> BackgroundModes = new List<string>() { };
    #endregion
}

XcodeProjectSettingCreator.CS


using UnityEngine;
using UnityEditor;


public class XcodeProjectSettingCreator : MonoBehaviour
{
    [MenuItem("Assets/Create/XcodeProjectSetting")]
    public static void CreateAsset()
    {
        string path = AssetDatabase.GenerateUniqueAssetPath("Assets/Editor/XCodeAPI/Setting/XcodeProjectSetting.asset");
        XcodeProjectSetting data = ScriptableObject.CreateInstance<XcodeProjectSetting>();
        AssetDatabase.CreateAsset(data, path);
        AssetDatabase.SaveAssets();
    }
}

Shell Scripts

autoBuildApk.sh


#!/bin/sh

# unity app path
UNITY_PATH=/Applications/Unity/Unity17.3.1p4.app/Contents/MacOS/Unity

# project path
PROJ_PATH=/Users/joey/UnityProjects/AutoBuildTestOne

echo "============== Unity Build APK Begin =============="

$UNITY_PATH -projectPath $PROJ_PATH -executeMethod AutoBuildProject.AutoBuildAndroidAPK -logFile $PROJ_PATH/Android/Android.log -batchMode -quit

echo "============== Unity Build APK Finish =============="

autoBuildXcode.sh


#!/bin/sh

# unity app path
UNITY_PATH=/Applications/Unity/Unity17.3.1p4.app/Contents/MacOS/Unity

# project path
PROJ_PATH=/Users/joey/UnityProjects/AutoBuildTestOne

echo "============== Unity Build APK Begin =============="

$UNITY_PATH -projectPath $PROJ_PATH -executeMethod AutoBuildProject.AutoBuildXCode -logFile $PROJ_PATH/XCodeProjects/XCode.log -batchMode -quit

echo "============== Unity Build APK Finish =============="

#IOS打包脚本路径#
BUILD_IOS_PATH=${PROJ_PATH}/XCodeProjects/autoBuild_ipa.sh
XCODE_TRUE_PATH=${PROJ_PATH}/XCodeProjects/Test
IPA_PATH=ipa

#开始生成ipa#
echo "============== Unity Build IPA Begin =============="
echo $XCODE_TRUE_PATH
echo $IPA_PATH
echo $BUILD_IOS_PATH

$BUILD_IOS_PATH $XCODE_TRUE_PATH $IPA_PATH
echo "============== Unity Build IPA Finish =============="

autoBuild_ipa.sh


#!/bin/sh

# 参数判断  
if [ $# != 2 ];then  
    echo "Need two params: 1.path of project 2.name of ipa file"  
    exit  
# elif [ ! -d $1 ];then  
#     echo "The first param is not a dictionary."  
#     exit      
fi  
echo "================ Start ipa ================="
# 工程路径  
xcode_project_path=$1  

# IPA名称  
ipa_name=$2  

# build文件夹路径  
build_path=${xcode_project_path}/build  

archive_path=${build_path}/Archive/AutoBuild.xcarchive

# 清理#
xcodebuild clean

# 编译工程  
cd $xcode_project_path  
xcodebuild || exit  

xcodebuild archive \
-project ${xcode_project_path}/Unity-iPhone.xcodeproj \
-scheme Unity-iPhone \
-configuration "Release" \
-archivePath ${archive_path}

xcodebuild -exportArchive \
-exportOptionsPlist ${xcode_project_path}/info.plist \
-archivePath ${archive_path} \
-exportPath ${xcode_project_path}
echo "================= End ipa ==================="


猜你喜欢

转载自blog.csdn.net/u014732824/article/details/80652054