NLDClient-yudde/ProjectNLD/Assets/Editor/Common/BuildLauncher.cs

349 lines
13 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using UnityEngine;
using UnityEditor;
using HybridCLR.Editor.Commands;
using PhxhSDK.AOT.VersionUpdate;
using Debug = UnityEngine.Debug;
using System.Collections.Generic;
using AutoBuild.Helper;
using BuildTarget = UnityEditor.BuildTarget;
using HybridCLR.Editor.HotUpdate;
using HybridCLR.Editor;
using System.IO;
/// <summary>
/// Jenkins打包
/// </summary>
internal class BatchBuild
{
/// <summary>
/// 批处理更新设置
/// jenkins打包新包时使用该方法
/// </summary>
public static void ApplyPlayerSetting()
{
YooAssetBuildBase.Init();
}
public static string _oldDefines;
/// <summary>
/// 只在DEBUG下有
/// </summary>
private const string DEBUG = "DEBUG";
private const string DefineListKey = "Define_list:";
private const string PackageNameKey = "PackageName:";
private const string CRASH_SIGHT_KEY_ANDROID = "CrashSight_Android:";
private const string CRASH_SIGHT_KEY_IOS = "CrashSight_iOS:";
private const string ChannelSetting = "/../ChannelSetting.txt";
//[MenuItem("Tools/Modify Settings from Text File")]
private static void _InitScriptDefines()
{
var hasYooAsset = false;
// 判断本地是否有define_list.txt文件
string filePath = Application.dataPath + ChannelSetting;
List<string> appendDefineList = new();
if (EditorUserBuildSettings.development)
{
appendDefineList.Add(DEBUG);
Debug.Log("追加宏定义:" + DEBUG);
}
string newPackageName = "";
if (System.IO.File.Exists(filePath))
{
string fileContents = System.IO.File.ReadAllText(filePath);
string[] lines = fileContents.Split('\n');
foreach (string line in lines)
{
if (line.StartsWith(DefineListKey))
{
// 解析宏定义
string definePart = line[DefineListKey.Length..].Trim(); // 去掉 "definde:" 后的部分
string[] defines = definePart.Split(',');
foreach (string define in defines)
{
string cleanDefine = define.Trim(new char[]
{
'"', ' ',
'\r', '\n'
});
if (!string.IsNullOrEmpty(cleanDefine))
{
appendDefineList.Add(cleanDefine);
Debug.Log("追加宏定义:" + cleanDefine);
}
}
}
else if (line.StartsWith(PackageNameKey))
{
// 解析包名
int prefixLength = PackageNameKey.Length;
newPackageName = line[prefixLength..].Trim();
Debug.Log("设置新包名:" + newPackageName);
}
else if (line.StartsWith(CRASH_SIGHT_KEY_ANDROID))
{
Debug.Log("检测到CrashSight配置:" + line);
// 判断当前打包平台
if (EditorUserBuildSettings.activeBuildTarget != BuildTarget.Android)
{
Debug.LogError("当前打包平台不是Android无法设置CrashSight配置");
continue;
}
// CrashSight: id, key
string crashSightPart = line[CRASH_SIGHT_KEY_ANDROID.Length..].Trim();
string[] crashSight = crashSightPart.Split(',');
var crashSightData = new PhxhSDK.Data.CrashSightData
{
id = crashSight[0].Trim(),
key = crashSight[1].Trim()
};
// 保存到Resources
var crashSightPath = "Assets/Resources/CrashSightData.json";
var json = JsonUtility.ToJson(crashSightData);
System.IO.File.WriteAllText(crashSightPath, json);
Debug.Log("CrashSight配置已保存:" + crashSightData.id + "|" + crashSightData.key);
}
else if (line.StartsWith(CRASH_SIGHT_KEY_IOS))
{
Debug.Log("检测到CrashSight配置:" + line);
// 判断当前打包平台
if (EditorUserBuildSettings.activeBuildTarget != BuildTarget.iOS)
{
Debug.LogError("当前打包平台不是iOS无法设置CrashSight配置");
continue;
}
// CrashSight: id, key
string crashSightPart = line[CRASH_SIGHT_KEY_IOS.Length..].Trim();
string[] crashSight = crashSightPart.Split(',');
var crashSightData = new PhxhSDK.Data.CrashSightData
{
id = crashSight[0].Trim(),
key = crashSight[1].Trim()
};
// 保存到Resources
var crashSightPath = "Assets/Resources/CrashSightData.json";
var json = JsonUtility.ToJson(crashSightData);
System.IO.File.WriteAllText(crashSightPath, json);
Debug.Log("CrashSight配置已保存:" + crashSightData.id + "|" + crashSightData.key);
}
}
}
var currentTargetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);
var oldDefines = PlayerSettings.GetScriptingDefineSymbolsForGroup(currentTargetGroup);
_oldDefines = oldDefines;
// 判断是否有需要追加的宏
if (appendDefineList.Count > 0)
{
var newDefineList = new List<string>();
newDefineList.AddRange(oldDefines.Split(';'));
for (var i = 0; i < newDefineList.Count; i++)
{
var define = newDefineList[i];
if (string.IsNullOrEmpty(define))
continue;
if (define == "USE_YOO")
{
hasYooAsset = true;
}
if (appendDefineList.Contains(define))
appendDefineList.Remove(define);
}
newDefineList.AddRange(appendDefineList);
PlayerSettings.SetScriptingDefineSymbolsForGroup(currentTargetGroup, string.Join(";", newDefineList));
}
//只有安卓平台下修改
if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android && !string.IsNullOrEmpty(newPackageName))
{
PlayerSettings.applicationIdentifier = newPackageName;
//PlayerSettings.SetApplicationIdentifier(BuildTargetGroup.Android, newPackageName);
}
// 现已修改为使用YooAsset
// 关闭Unity闪屏
PlayerSettings.SplashScreen.showUnityLogo = false;
}
public static void _RevertScriptDefines()
{
var currentTargetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);
PlayerSettings.SetScriptingDefineSymbolsForGroup(currentTargetGroup, _oldDefines);
}
/// <summary>
/// 批处理构建Resources和Player
/// jenkins打包新包时使用该方法
/// </summary>
public static void BuildContentAndPlayer()
{
try
{
_InitScriptDefines();
var enableHotUpdate = YooAssetBuildBase.Init();
// 写入版本信息到Resources/LocalInfo.json
UpdateLocalInfo info = new()
{
workSpace = YooAssetBuildBase.workSpace,
accessKeyId = YooAssetBuildBase.accessKeyId,
accessKeySecret = YooAssetBuildBase.accessKeySecret,
bucketName = YooAssetBuildBase.bucketName,
endPoint = YooAssetBuildBase.endPoint,
version = YooAssetBuildBase.appVersion,
isDev = YooAssetBuildBase.isDev,
buildTicks = DateTime.Now.Ticks
};
PackDataInst.CreateResourceJson(info);
BuildTargetGroup currentTargetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);
string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(currentTargetGroup);
// 写入打包信息到Yoo_Build_Cache
#if DEVELOPMENT_BUILD || DEBUG
ExtBuildInfoHelper.CreateFirstExtBuildInfo(info.buildTicks, info.workSpace, info.version, true, defines);
#else
ExtBuildInfoHelper.CreateFirstExtBuildInfo(info.buildTicks, info.workSpace, info.version, false, defines);
#endif
BuildLauncher.SetEnableHotUpdate(enableHotUpdate);
if (enableHotUpdate)
BuildLauncher.BuildHotUpdateDlls();
YooAssetBuildBase.BuildContentAndPlayer();
// 写入打包信息到Yoo_Build_Cache
ExtBuildInfoHelper.CreateVertifyBuildInfo(info.workSpace, info.version);
// 还原宏
_RevertScriptDefines();
#region 打整包时缓存当前版本的AotDll
string aotDllStorePath = GetAotDllStorePath(info.workSpace, info.version);
string aotDllPath = SettingsUtil.GetAssembliesPostIl2CppStripDir(EditorUserBuildSettings.activeBuildTarget);
DirectoryInfo dir = new(aotDllPath);
if (Directory.Exists(aotDllStorePath))
Directory.Delete(aotDllStorePath, true);
Directory.CreateDirectory(aotDllStorePath);
FileInfo[] files = dir.GetFiles();
foreach (FileInfo file in files)
{
file.CopyTo(Path.Combine(aotDllStorePath, file.Name), false);
}
#endregion
}
catch (Exception e)
{
//Build Exception用于在日志文件中定位此次打包的异常
Debug.LogError($"[Build Exception]:{e.Message} \r\n {e.StackTrace}");
throw;
}
}
/// <summary>
/// 批处理增量更新资源
/// jenkins打包增量更新时使用该方法
/// </summary>
public static void UpdatePreviousBuild()
{
try
{
_InitScriptDefines();
var enableHotUpdate = YooAssetBuildBase.Init();
ExtBuildInfoHelper.VertifyExitBuildInfo(YooAssetBuildBase.workSpace, YooAssetBuildBase.appVersion);
if (enableHotUpdate)
{
Debug.Log("开始检查AOT版本");
if (CheckAotOutDate(YooAssetBuildBase.workSpace, YooAssetBuildBase.appVersion))
{
Debug.Log("AOT版本检查通过");
BuildLauncher.BuildHotUpdateDlls();
}
else
{
Debug.LogError("AOT版本不匹配请重新打AOT包");
}
}
else
{
Debug.Log("未开启热更");
}
BuildTargetGroup currentTargetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);
string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(currentTargetGroup);
// 写入打包信息到Yoo_Build_Cache
#if DEVELOPMENT_BUILD || DEBUG
ExtBuildInfoHelper.UpdateExtBuildInfo(YooAssetBuildBase.workSpace, YooAssetBuildBase.appVersion, true, defines);
#else
ExtBuildInfoHelper.UpdateExtBuildInfo(YooAssetBuildBase.workSpace, YooAssetBuildBase.appVersion, false, defines);
#endif
YooAssetBuildBase.BuildOnlyResUpdate();
ExtBuildInfoHelper.CreateVertifyBuildInfo(YooAssetBuildBase.workSpace, YooAssetBuildBase.appVersion);
_RevertScriptDefines();
}
catch (Exception e)
{
//Build Exception用于在日志文件中定位此次打包的异常
Debug.LogError($"[Build Exception]:{e.Message} \r\n {e.StackTrace}");
throw;
}
}
/// <summary>
/// jenkins检查AOT裁剪代码
/// </summary>
/// <param name="version"></param>
/// <returns></returns>
public static bool CheckAotOutDate(string workSpace, string version)
{
Debug.Log($"开始检查aot版本:{version}");
string stripedDllPath = GetAotDllStorePath(workSpace, version);
// 先编译dll
CompileDllCommand.CompileDllActiveBuildTarget();
// 再检查编译出来的dll是否满足以前的Aotdll
MissingMetadataChecker checker = new(stripedDllPath, new List<string>());
string hotUpdateDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(EditorUserBuildSettings.activeBuildTarget);
foreach (string dll in SettingsUtil.HotUpdateAssemblyFilesExcludePreserved)
{
string dllPath = $"{hotUpdateDir}/{dll}";
bool notAnyMissing = checker.Check(dllPath);
if (!notAnyMissing)
throw new Exception("AOT缺失Dll请重新打AOT包");
}
return true;
}
/// <summary>
/// 获取缓存的AOT Dll路径
/// </summary>
/// <param name="version"></param>
public static string GetAotDllStorePath(string workSpace, string version)
{
return Application.dataPath + $"/../Yoo_Build_Cache/{workSpace}/{version}/CacheAOTDll";
}
}