340 lines
13 KiB
C#
340 lines
13 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Reflection;
|
||
using AutoBuild.Helper;
|
||
using HybridCLR.Editor;
|
||
using HybridCLR.Editor.Commands;
|
||
using HybridCLR.Editor.Installer;
|
||
using HybridCLR.Editor.Link;
|
||
using HybridCLR.Editor.Meta;
|
||
using Obfuz;
|
||
using Obfuz.Settings;
|
||
using Obfuz.Unity;
|
||
using Obfuz4HybridCLR;
|
||
using PhxhSDK.AOT.VersionUpdate;
|
||
using UnityEditor;
|
||
using UnityEditor.SceneManagement;
|
||
using UnityEngine;
|
||
|
||
/// <summary>
|
||
/// 编辑器下打包
|
||
/// </summary>
|
||
class BuildLauncher
|
||
{
|
||
private const string HybirdCLRGenerateDir = "/HybridCLRGenerate";
|
||
private const string HybirdCLRGenerateLinkPath = "Assets/HybridCLRGenerate/link.xml";
|
||
private const string GameLauncherSceneName = "Assets/Scenes/GameLauncher.unity";
|
||
|
||
private static bool enableHotUpdate;
|
||
|
||
/// <summary>
|
||
/// 开启热更
|
||
/// </summary>
|
||
public static void SetEnableHotUpdate(bool isEnable)
|
||
{
|
||
Debug.Log($"是否开启热更新:{isEnable}");
|
||
var gameLauncherScene = EditorSceneManager.OpenScene(GameLauncherSceneName, OpenSceneMode.Additive);
|
||
if (!gameLauncherScene.IsValid())
|
||
{
|
||
Debug.LogError($"无法加载场景{GameLauncherSceneName}");
|
||
return;
|
||
}
|
||
|
||
var gameLauncher = UnityEngine.Object.FindObjectOfType<GameLauncher>();
|
||
if (gameLauncher == null)
|
||
{
|
||
Debug.LogError("找不到GameLauncher");
|
||
return;
|
||
}
|
||
|
||
gameLauncher.enableHotUpdate = isEnable;
|
||
EditorSceneManager.MarkSceneDirty(gameLauncherScene);
|
||
EditorSceneManager.SaveScene(gameLauncherScene);
|
||
EditorSceneManager.CloseScene(gameLauncherScene, false);
|
||
HybridCLR.Editor.SettingsUtil.Enable = isEnable;
|
||
if (!isEnable)
|
||
{
|
||
//删除HybirdCLR生成的link文件
|
||
AssetDatabase.DeleteAsset(HybirdCLRGenerateLinkPath);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 构建热更
|
||
/// </summary>
|
||
public static void BuildHotUpdateDlls()
|
||
{
|
||
var controller = new InstallerController();
|
||
if (!controller.HasInstalledHybridCLR())
|
||
controller.InstallDefaultHybridCLR();
|
||
|
||
BuildUtils.SetFileReadable(Application.dataPath + HybirdCLRGenerateDir);
|
||
|
||
if (ObfuzSettings.Instance.buildPipelineSettings.enable)
|
||
{
|
||
ObfuzMenu.GenerateEncryptionVM();
|
||
ObfuzMenu.SaveSecretFile();
|
||
|
||
var kedrType = Type.GetType("KedrExtensionMenu, Assembly-CSharp-Editor");
|
||
if (kedrType != null)
|
||
{
|
||
var method = kedrType.GetMethod("GenerateAll",
|
||
BindingFlags.Public | BindingFlags.Static);
|
||
method?.Invoke(null, null);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning("[Obfuz] KedrExtensionMenu not found, falling back to PrebuildCommandExt");
|
||
PrebuildCommandExt.GenerateAll();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
PrebuildCommand.GenerateAll();
|
||
}
|
||
|
||
HotUpadeEditorHelper.CopyHotUpdateDll();
|
||
HotUpadeEditorHelper.CopyMetaDataDll();
|
||
|
||
if (ObfuzSettings.Instance.polymorphicDllSettings.enable)
|
||
{
|
||
// 使用多态dll
|
||
HotUpadeEditorHelper.ConvertOriginalDllToPolymorphicDll();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 打包面板初始化
|
||
/// </summary>
|
||
public static void Init(BuildTarget buildTarget,
|
||
string workSpace,
|
||
string appVersion,
|
||
string profileName,
|
||
bool developmentBuild,
|
||
bool hotUpdate)
|
||
{
|
||
EditorUserBuildSettings.development = developmentBuild;
|
||
YooAssetBuildBase.BuildTargetPlatform = buildTarget;
|
||
YooAssetBuildBase.profileName = profileName;
|
||
YooAssetBuildBase.JudgmentPlatform(buildTarget.ToString());
|
||
YooAssetBuildBase.workSpace = string.IsNullOrEmpty(workSpace) ? "WorkSpace" : workSpace;
|
||
PlayerSettings.bundleVersion = appVersion;
|
||
YooAssetBuildBase.appVersion = appVersion;
|
||
enableHotUpdate = hotUpdate;
|
||
|
||
if (profileName.Equals("AllLocal"))
|
||
{
|
||
List<string> appendDefineList = new() { "AllLocal" };
|
||
var currentTargetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);
|
||
var oldDefines = PlayerSettings.GetScriptingDefineSymbolsForGroup(currentTargetGroup);
|
||
BatchBuild._oldDefines = oldDefines;
|
||
|
||
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 (appendDefineList.Contains(define))
|
||
appendDefineList.Remove(define);
|
||
}
|
||
|
||
newDefineList.AddRange(appendDefineList);
|
||
PlayerSettings.SetScriptingDefineSymbolsForGroup(currentTargetGroup, string.Join(";", newDefineList));
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 编辑器下构建资源
|
||
/// </summary>
|
||
public static void BuildResource()
|
||
{
|
||
UpdateLocalInfo info = new()
|
||
{
|
||
workSpace = YooAssetBuildBase.workSpace,
|
||
accessKeyId = YooAssetBuildBase.appConfigAccessKeyId,
|
||
accessKeySecret = YooAssetBuildBase.appConfigAccessKeySecret,
|
||
bucketName = YooAssetBuildBase.appConfigBucketName,
|
||
configOriginalUrl = YooAssetBuildBase.appConfigURL,
|
||
//httpUrl = YooAssetBuildBase.httpURL,
|
||
httpAccessKey = YooAssetBuildBase.httpAccessKey,
|
||
httpKey = YooAssetBuildBase.httpKey,
|
||
version = YooAssetBuildBase.appVersion,
|
||
isDev = YooAssetBuildBase.isDev,
|
||
isOversea = YooAssetBuildBase.isOversea,
|
||
buildTicks = DateTime.Now.Ticks,
|
||
buildCode = BatchBuild.GetBundleVersionCode(),
|
||
};
|
||
PackDataInst.CreateResourceJson(info);
|
||
|
||
BuildTargetGroup currentTargetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);
|
||
string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(currentTargetGroup);
|
||
|
||
#if DEVELOPMENT_BUILD || DEBUG
|
||
ExtBuildInfoHelper.CreateFirstExtBuildInfo(info.buildTicks, info.workSpace, info.version, info.buildCode, true, defines);
|
||
#else
|
||
ExtBuildInfoHelper.CreateFirstExtBuildInfo(info.buildTicks, info.workSpace, info.version, false, defines);
|
||
#endif
|
||
|
||
SetEnableHotUpdate(enableHotUpdate);
|
||
if (enableHotUpdate)
|
||
{
|
||
BuildHotUpdateDlls();
|
||
}
|
||
|
||
YooAssetBuildBase.BuildResourceInEditor();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 编辑器下构建资源和Player
|
||
/// </summary>
|
||
public static void BuildResourceAndPlayer()
|
||
{
|
||
UpdateLocalInfo info = new()
|
||
{
|
||
workSpace = YooAssetBuildBase.workSpace,
|
||
accessKeyId = YooAssetBuildBase.appConfigAccessKeyId,
|
||
accessKeySecret = YooAssetBuildBase.appConfigAccessKeySecret,
|
||
bucketName = YooAssetBuildBase.appConfigBucketName,
|
||
configOriginalUrl = YooAssetBuildBase.appConfigURL,
|
||
//httpUrl = YooAssetBuildBase.httpURL,
|
||
httpAccessKey = YooAssetBuildBase.httpAccessKey,
|
||
httpKey = YooAssetBuildBase.httpKey,
|
||
version = YooAssetBuildBase.appVersion,
|
||
isDev = YooAssetBuildBase.isDev,
|
||
isOversea = YooAssetBuildBase.isOversea,
|
||
buildTicks = DateTime.Now.Ticks,
|
||
buildCode = BatchBuild.GetBundleVersionCode(),
|
||
};
|
||
PackDataInst.CreateResourceJson(info);
|
||
|
||
BuildTargetGroup currentTargetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);
|
||
string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(currentTargetGroup);
|
||
|
||
#if DEVELOPMENT_BUILD || DEBUG
|
||
ExtBuildInfoHelper.CreateFirstExtBuildInfo(info.buildTicks, info.workSpace, info.version, info.buildCode, true, defines);
|
||
#else
|
||
ExtBuildInfoHelper.CreateFirstExtBuildInfo(info.buildTicks, info.workSpace, info.version, false, defines);
|
||
#endif
|
||
|
||
SetEnableHotUpdate(enableHotUpdate);
|
||
if (enableHotUpdate)
|
||
{
|
||
BuildHotUpdateDlls();
|
||
}
|
||
|
||
YooAssetBuildBase.BuildContentAndPlayerInEditor();
|
||
|
||
ExtBuildInfoHelper.CreateVertifyBuildInfo(info.workSpace, info.version);
|
||
|
||
|
||
if (!string.IsNullOrEmpty(BatchBuild._oldDefines))
|
||
BatchBuild._RevertScriptDefines();
|
||
|
||
var aotDllStorePath = BatchBuild.GetAotDllStorePath(info.workSpace, info.version);
|
||
var 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);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 只构建Player
|
||
/// </summary>
|
||
public static void BuildPlayer()
|
||
{
|
||
YooAssetBuildBase.BuildPlayerInEditor();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 编辑器下热更
|
||
/// </summary>
|
||
public static void UpdatePreviousBuild(string workSpace, string version, BuildTarget buildTarget)
|
||
{
|
||
ExtBuildInfoHelper.VertifyExitBuildInfo(YooAssetBuildBase.workSpace, YooAssetBuildBase.appVersion);
|
||
|
||
Debug.Log("开始检查AOT版本");
|
||
if (BatchBuild.CheckAotOutDate(YooAssetBuildBase.workSpace, YooAssetBuildBase.appVersion))
|
||
{
|
||
Debug.Log("AOT版本检查通过");
|
||
BuildHotUpdateDlls();
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("AOT版本不匹配,请重新打AOT包");
|
||
}
|
||
|
||
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);
|
||
|
||
YooAssetBuildBase.UploadToServerYooAsset(workSpace, version, buildTarget);
|
||
/*try
|
||
{
|
||
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
DebugUtil.LogError($"[Build Exception]:{e.Message} \r\n {e.StackTrace}");
|
||
throw;
|
||
}*/
|
||
}
|
||
|
||
public static void UploadToServer(string workSpace, string version, BuildTarget buildTarget)
|
||
{
|
||
YooAssetBuildBase.UploadToServerYooAsset(workSpace, version, buildTarget);
|
||
}
|
||
|
||
public static void GenerateObfuzLinkXml()
|
||
{
|
||
//CompileDllCommand.CompileDllActiveBuildTarget();
|
||
PrebuildCommandExt.CompileAndObfuscateDll();
|
||
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
|
||
ObfuzSettings obfuzSettings = ObfuzSettings.Instance;
|
||
|
||
List<string> assemblySearchDirs = new()
|
||
{
|
||
SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target),
|
||
};
|
||
ObfuscatorBuilder builder = ObfuscatorBuilder.FromObfuzSettings(obfuzSettings, target, true);
|
||
builder.InsertTopPriorityAssemblySearchPaths(assemblySearchDirs);
|
||
|
||
Obfuscator obfuz = builder.Build();
|
||
obfuz.Run();
|
||
|
||
|
||
List<string> hotfixAssemblies = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
|
||
|
||
var analyzer = new Analyzer(new PathAssemblyResolver(builder.CoreSettingsFacade.obfuscatedAssemblyOutputPath));
|
||
var refTypes = analyzer.CollectRefs(hotfixAssemblies);
|
||
|
||
// HyridCLR中 LinkXmlWritter不是public的,在其他程序集无法访问,只能通过反射操作
|
||
var linkXmlWriter = typeof(SettingsUtil).Assembly.GetType("HybridCLR.Editor.Link.LinkXmlWriter");
|
||
var writeMethod = linkXmlWriter.GetMethod("Write", BindingFlags.Public | BindingFlags.Instance);
|
||
var instance = Activator.CreateInstance(linkXmlWriter);
|
||
string linkXmlOutputPath = $"{Application.dataPath}/Obfuz/link.xml";
|
||
writeMethod.Invoke(instance, new object[] { linkXmlOutputPath, refTypes });
|
||
Debug.Log($"[GenerateLinkXmlForObfuscatedAssembly] output:{linkXmlOutputPath}");
|
||
AssetDatabase.Refresh();
|
||
}
|
||
} |