BuildAssembliesHelper.cs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. using MongoDB.Libmongocrypt;
  2. using Sirenix.Utilities;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Threading;
  8. using UnityEditor;
  9. using UnityEditor.Compilation;
  10. using UnityEngine;
  11. namespace ET
  12. {
  13. public static class BuildAssembliesHelper
  14. {
  15. public const string CodeDir = "./Assets/Res/CodeDll/";
  16. private const string BattleDllDir = "../../WSHCommon/Library/Debug/";
  17. private static List<string>RefBattleDlls = new List<string>();
  18. public static void BuildModel(CodeOptimization codeOptimization, GlobalConfig globalConfig)
  19. {
  20. try
  21. {
  22. string[] logicFiles = Directory.GetFiles(Define.BuildOutputDir, "Model*");
  23. foreach (string file in logicFiles)
  24. {
  25. File.Delete(file);
  26. }
  27. }
  28. catch { }
  29. //int random = RandomGenerator.RandomNumber(100000000, 999999999);
  30. string logicFile = $"Model";
  31. List<string> codes;
  32. switch (globalConfig.CodeMode)
  33. {
  34. case CodeMode.Client:
  35. codes = new List<string>()
  36. {
  37. "Assets/Scripts/Codes/Model/",
  38. "Assets/Scripts/Codes/ModelView/Client/",
  39. };
  40. break;
  41. default:
  42. throw new Exception("unknow 'CodeMode'");
  43. }
  44. BuildMuteAssembly(logicFile, codes, GetBatlleDlls().ToArray(), codeOptimization, globalConfig.CodeMode);
  45. File.Copy(Path.Combine(Define.BuildOutputDir, $"{logicFile}.dll"), Path.Combine(CodeDir, $"Model.dll.bytes"), true);
  46. File.Copy(Path.Combine(Define.BuildOutputDir, $"{logicFile}.pdb"), Path.Combine(CodeDir, $"Model.pdb.bytes"), true);
  47. Debug.Log("copy Model.dll to Assets/Res/CodeDll success!");
  48. }
  49. public static void BuildHotfix(CodeOptimization codeOptimization, GlobalConfig globalConfig)
  50. {
  51. try
  52. {
  53. string[] logicFiles = Directory.GetFiles(Define.BuildOutputDir, "Hotfix_*");
  54. foreach (string file in logicFiles)
  55. {
  56. File.Delete(file);
  57. }
  58. }
  59. catch { }
  60. string modelfile;
  61. string[] modelFiles = Directory.GetFiles(Define.BuildOutputDir, "Model*.dll");
  62. if (modelFiles.Length > 0)
  63. {
  64. modelfile = modelFiles[0];
  65. }
  66. else
  67. {
  68. throw new Exception($"Not Found model_xx.dll @{Define.BuildOutputDir}");
  69. }
  70. int random = RandomGenerator.RandomNumber(100000000, 999999999);
  71. string logicFile = $"Hotfix_{random}";
  72. List<string> codes;
  73. switch (globalConfig.CodeMode)
  74. {
  75. case CodeMode.Client:
  76. codes = new List<string>()
  77. {
  78. "Assets/Scripts/Codes/Hotfix/",
  79. "Assets/Scripts/Codes/HotfixView/Client/",
  80. };
  81. break;
  82. default:
  83. throw new Exception("unknow 'CodeMode'");
  84. }
  85. var depends = new List<string>(GetBatlleDlls());
  86. depends.Add(modelfile);
  87. BuildMuteAssembly(logicFile, codes, depends.ToArray(), codeOptimization, globalConfig.CodeMode);
  88. File.Copy(Path.Combine(Define.BuildOutputDir, $"{logicFile}.dll"), Path.Combine(CodeDir, $"Hotfix.dll.bytes"), true);
  89. File.Copy(Path.Combine(Define.BuildOutputDir, $"{logicFile}.pdb"), Path.Combine(CodeDir, $"Hotfix.pdb.bytes"), true);
  90. Debug.Log("copy Hotfix.dll to Assets/Res/CodeDll success!");
  91. }
  92. private static List<string> GetBatlleDlls()
  93. {
  94. if(RefBattleDlls.Count == 0)
  95. {
  96. var manifest = AssetDatabase.LoadAssetAtPath("Assets/Res/Config/HotupdateBattleDlls.asset", typeof(ConfigStringList)) as ConfigStringList;
  97. if (manifest == null)
  98. {
  99. throw new Exception($"Assets/Res/Config/HotupdateBattleDlls 配置不存在");
  100. }
  101. foreach (var dll in manifest.List)
  102. {
  103. RefBattleDlls.Add(Path.Combine(BattleDllDir, dll));
  104. }
  105. }
  106. return RefBattleDlls;
  107. }
  108. public static void BuildMuteAssembly(
  109. string assemblyName, List<string> CodeDirectorys,
  110. string[] additionalReferences, CodeOptimization codeOptimization, CodeMode codeMode = CodeMode.Client)
  111. {
  112. if (!Directory.Exists(Define.BuildOutputDir))
  113. {
  114. Directory.CreateDirectory(Define.BuildOutputDir);
  115. }
  116. List<string> scripts = new List<string>();
  117. for (int i = 0; i < CodeDirectorys.Count; i++)
  118. {
  119. DirectoryInfo dti = new DirectoryInfo(CodeDirectorys[i]);
  120. FileInfo[] fileInfos = dti.GetFiles("*.cs", System.IO.SearchOption.AllDirectories);
  121. for (int j = 0; j < fileInfos.Length; j++)
  122. {
  123. scripts.Add(fileInfos[j].FullName);
  124. }
  125. }
  126. string dllPath = Path.Combine(Define.BuildOutputDir, $"{assemblyName}.dll");
  127. string pdbPath = Path.Combine(Define.BuildOutputDir, $"{assemblyName}.pdb");
  128. File.Delete(dllPath);
  129. File.Delete(pdbPath);
  130. Directory.CreateDirectory(Define.BuildOutputDir);
  131. AssemblyBuilder assemblyBuilder = new AssemblyBuilder(dllPath, scripts.ToArray());
  132. if (codeMode == CodeMode.Client)
  133. {
  134. assemblyBuilder.excludeReferences = new string[]
  135. {
  136. "DnsClient.dll",
  137. "MongoDB.Driver.Core.dll",
  138. "MongoDB.Driver.dll",
  139. "MongoDB.Driver.Legacy.dll",
  140. "MongoDB.Libmongocrypt.dll",
  141. "SharpCompress.dll",
  142. "System.Buffers.dll",
  143. "System.Runtime.CompilerServices.Unsafe.dll",
  144. "System.Text.Encoding.CodePages.dll"
  145. };
  146. }
  147. //启用UnSafe
  148. assemblyBuilder.compilerOptions.AllowUnsafeCode = true;
  149. BuildTargetGroup buildTargetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);
  150. assemblyBuilder.compilerOptions.CodeOptimization = codeOptimization;
  151. assemblyBuilder.compilerOptions.ApiCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup);
  152. // assemblyBuilder.compilerOptions.ApiCompatibilityLevel = ApiCompatibilityLevel.NET_4_6;
  153. assemblyBuilder.additionalReferences = additionalReferences;
  154. assemblyBuilder.flags = AssemblyBuilderFlags.None;
  155. //AssemblyBuilderFlags.None 正常发布
  156. //AssemblyBuilderFlags.DevelopmentBuild 开发模式打包
  157. //AssemblyBuilderFlags.EditorAssembly 编辑器状态
  158. assemblyBuilder.referencesOptions = ReferencesOptions.UseEngineModules;
  159. assemblyBuilder.buildTarget = EditorUserBuildSettings.activeBuildTarget;
  160. assemblyBuilder.buildTargetGroup = buildTargetGroup;
  161. assemblyBuilder.buildStarted += assemblyPath => Debug.LogFormat("build start:" + assemblyPath);
  162. assemblyBuilder.buildFinished += (assemblyPath, compilerMessages) =>
  163. {
  164. int errorCount = compilerMessages.Count(m => m.type == CompilerMessageType.Error);
  165. int warningCount = compilerMessages.Count(m => m.type == CompilerMessageType.Warning);
  166. Debug.LogFormat("Warnings: {0} - Errors: {1}", warningCount, errorCount);
  167. if (warningCount > 0)
  168. {
  169. Debug.LogFormat("有{0}个Warning!!!", warningCount);
  170. for (int i = 0; i < compilerMessages.Length; i++)
  171. {
  172. if (compilerMessages[i].type == CompilerMessageType.Warning)
  173. {
  174. Debug.LogWarning(compilerMessages[i].message);
  175. }
  176. }
  177. }
  178. if (errorCount > 0)
  179. {
  180. for (int i = 0; i < compilerMessages.Length; i++)
  181. {
  182. if (compilerMessages[i].type == CompilerMessageType.Error)
  183. {
  184. string filename = compilerMessages[i].file;
  185. if(filename.IsNullOrWhitespace())
  186. {
  187. Debug.LogError( compilerMessages[i].message);
  188. }
  189. else
  190. {
  191. filename = Path.GetFullPath(filename);
  192. Debug.LogError(
  193. $"{compilerMessages[i].message} (at <a href=\"file:///{filename}/\" line=\"{compilerMessages[i].line}\">{Path.GetFileName(filename)}</a>)");
  194. }
  195. }
  196. }
  197. }
  198. };
  199. //开始构建
  200. if (!assemblyBuilder.Build())
  201. {
  202. Debug.LogErrorFormat("build fail:" + assemblyBuilder.assemblyPath);
  203. return;
  204. }
  205. while (EditorApplication.isCompiling)
  206. {
  207. // 主线程sleep并不影响编译线程
  208. Thread.Sleep(1);
  209. }
  210. }
  211. }
  212. }