BuildAssembliesHelper.cs 10 KB

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