using MongoDB.Libmongocrypt; using Sirenix.Utilities; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using UnityEditor; using UnityEditor.Compilation; using UnityEngine; namespace ET { public static class BuildAssembliesHelper { public const string CodeDir = "./Assets/Res/CodeDll/"; private const string BattleDllDir = "../../WSHCommon/Library/Debug/"; private static ListRefBattleDlls = new List(); public static void BuildModel(CodeOptimization codeOptimization, GlobalConfig globalConfig) { try { string[] logicFiles = Directory.GetFiles(Define.BuildOutputDir, "Model*"); foreach (string file in logicFiles) { File.Delete(file); } } catch { } //int random = RandomGenerator.RandomNumber(100000000, 999999999); string logicFile = $"Model"; List codes; switch (globalConfig.CodeMode) { case CodeMode.Client: codes = new List() { "Assets/Scripts/Codes/Model/", "Assets/Scripts/Codes/ModelView/Client/", }; break; default: throw new Exception("unknow 'CodeMode'"); } BuildMuteAssembly(logicFile, codes, GetBatlleDlls().ToArray(), codeOptimization, globalConfig.CodeMode); File.Copy(Path.Combine(Define.BuildOutputDir, $"{logicFile}.dll"), Path.Combine(CodeDir, $"Model.dll.bytes"), true); File.Copy(Path.Combine(Define.BuildOutputDir, $"{logicFile}.pdb"), Path.Combine(CodeDir, $"Model.pdb.bytes"), true); Debug.Log("copy Model.dll to Assets/Res/CodeDll success!"); } public static void BuildHotfix(CodeOptimization codeOptimization, GlobalConfig globalConfig) { try { string[] logicFiles = Directory.GetFiles(Define.BuildOutputDir, "Hotfix_*"); foreach (string file in logicFiles) { File.Delete(file); } } catch { } string modelfile; string[] modelFiles = Directory.GetFiles(Define.BuildOutputDir, "Model*.dll"); if (modelFiles.Length > 0) { modelfile = modelFiles[0]; } else { throw new Exception($"Not Found model_xx.dll @{Define.BuildOutputDir}"); } int random = RandomGenerator.RandomNumber(100000000, 999999999); string logicFile = $"Hotfix_{random}"; List codes; switch (globalConfig.CodeMode) { case CodeMode.Client: codes = new List() { "Assets/Scripts/Codes/Hotfix/", "Assets/Scripts/Codes/HotfixView/Client/", }; break; default: throw new Exception("unknow 'CodeMode'"); } var depends = new List(GetBatlleDlls()); depends.Add(modelfile); BuildMuteAssembly(logicFile, codes, depends.ToArray(), codeOptimization, globalConfig.CodeMode); File.Copy(Path.Combine(Define.BuildOutputDir, $"{logicFile}.dll"), Path.Combine(CodeDir, $"Hotfix.dll.bytes"), true); File.Copy(Path.Combine(Define.BuildOutputDir, $"{logicFile}.pdb"), Path.Combine(CodeDir, $"Hotfix.pdb.bytes"), true); Debug.Log("copy Hotfix.dll to Assets/Res/CodeDll success!"); } private static List GetBatlleDlls() { if(RefBattleDlls.Count == 0) { var manifest = AssetDatabase.LoadAssetAtPath("Assets/Res/Config/HotupdateBattleDlls.asset", typeof(ConfigStringList)) as ConfigStringList; if (manifest == null) { throw new Exception($"Assets/Res/Config/HotupdateBattleDlls 配置不存在"); } foreach (var dll in manifest.List) { RefBattleDlls.Add(Path.Combine(BattleDllDir, dll)); } } return RefBattleDlls; } public static void BuildMuteAssembly( string assemblyName, List CodeDirectorys, string[] additionalReferences, CodeOptimization codeOptimization, CodeMode codeMode = CodeMode.Client) { if (!Directory.Exists(Define.BuildOutputDir)) { Directory.CreateDirectory(Define.BuildOutputDir); } List scripts = new List(); for (int i = 0; i < CodeDirectorys.Count; i++) { DirectoryInfo dti = new DirectoryInfo(CodeDirectorys[i]); FileInfo[] fileInfos = dti.GetFiles("*.cs", System.IO.SearchOption.AllDirectories); for (int j = 0; j < fileInfos.Length; j++) { scripts.Add(fileInfos[j].FullName); } } string dllPath = Path.Combine(Define.BuildOutputDir, $"{assemblyName}.dll"); string pdbPath = Path.Combine(Define.BuildOutputDir, $"{assemblyName}.pdb"); File.Delete(dllPath); File.Delete(pdbPath); Directory.CreateDirectory(Define.BuildOutputDir); AssemblyBuilder assemblyBuilder = new AssemblyBuilder(dllPath, scripts.ToArray()); if (codeMode == CodeMode.Client) { assemblyBuilder.excludeReferences = new string[] { "DnsClient.dll", "MongoDB.Driver.Core.dll", "MongoDB.Driver.dll", "MongoDB.Driver.Legacy.dll", "MongoDB.Libmongocrypt.dll", "SharpCompress.dll", "System.Buffers.dll", "System.Runtime.CompilerServices.Unsafe.dll", "System.Text.Encoding.CodePages.dll" }; } //启用UnSafe assemblyBuilder.compilerOptions.AllowUnsafeCode = true; BuildTargetGroup buildTargetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget); assemblyBuilder.compilerOptions.CodeOptimization = codeOptimization; assemblyBuilder.compilerOptions.ApiCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup); // assemblyBuilder.compilerOptions.ApiCompatibilityLevel = ApiCompatibilityLevel.NET_4_6; assemblyBuilder.additionalReferences = additionalReferences; assemblyBuilder.flags = AssemblyBuilderFlags.None; //AssemblyBuilderFlags.None 正常发布 //AssemblyBuilderFlags.DevelopmentBuild 开发模式打包 //AssemblyBuilderFlags.EditorAssembly 编辑器状态 assemblyBuilder.referencesOptions = ReferencesOptions.UseEngineModules; assemblyBuilder.buildTarget = EditorUserBuildSettings.activeBuildTarget; assemblyBuilder.buildTargetGroup = buildTargetGroup; assemblyBuilder.buildStarted += assemblyPath => Debug.LogFormat("build start:" + assemblyPath); assemblyBuilder.buildFinished += (assemblyPath, compilerMessages) => { int errorCount = compilerMessages.Count(m => m.type == CompilerMessageType.Error); int warningCount = compilerMessages.Count(m => m.type == CompilerMessageType.Warning); Debug.LogFormat("Warnings: {0} - Errors: {1}", warningCount, errorCount); if (warningCount > 0) { Debug.LogFormat("有{0}个Warning!!!", warningCount); for (int i = 0; i < compilerMessages.Length; i++) { if (compilerMessages[i].type == CompilerMessageType.Warning) { Debug.LogWarning(compilerMessages[i].message); } } } if (errorCount > 0) { for (int i = 0; i < compilerMessages.Length; i++) { if (compilerMessages[i].type == CompilerMessageType.Error) { string filename = compilerMessages[i].file; if(filename.IsNullOrWhitespace()) { Debug.LogError( compilerMessages[i].message); } else { filename = Path.GetFullPath(filename); Debug.LogError( $"{compilerMessages[i].message} (at {Path.GetFileName(filename)})"); } } } } }; //开始构建 if (!assemblyBuilder.Build()) { Debug.LogErrorFormat("build fail:" + assemblyBuilder.assemblyPath); return; } while (EditorApplication.isCompiling) { // 主线程sleep并不影响编译线程 Thread.Sleep(1); } } } }