BuildEditor.cs 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. using HybridCLR.Editor;
  2. using HybridCLR.Editor.Commands;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Linq;
  7. using UnityEditor;
  8. using UnityEditor.Compilation;
  9. using UnityEngine;
  10. using Debug = UnityEngine.Debug;
  11. namespace ET
  12. {
  13. public enum PlatformType
  14. {
  15. None,
  16. Android,
  17. IOS,
  18. Windows,
  19. MacOS,
  20. Linux
  21. }
  22. public enum BuildType
  23. {
  24. Development,
  25. Release,
  26. }
  27. public class BuildEditor : EditorWindow
  28. {
  29. private PlatformType activePlatform;
  30. private PlatformType platformType;
  31. private bool clearFolder = true;
  32. private bool isBuildExe = true;
  33. private bool isContainAB = false;
  34. private CodeOptimization codeOptimization = CodeOptimization.Debug;
  35. private BuildOptions buildOptions;
  36. private BuildAssetBundleOptions buildAssetBundleOptions = BuildAssetBundleOptions.None;
  37. public static string YooAssetCodeDll;
  38. private GlobalConfig globalConfig;
  39. [MenuItem("ET/Build Tool")]
  40. public static void ShowWindow()
  41. {
  42. GetWindow<BuildEditor>(DockDefine.Types);
  43. }
  44. private void OnEnable()
  45. {
  46. YooAssetCodeDll = Application.dataPath + "/Res/CodeDll/";
  47. globalConfig = Resources.Load<GlobalConfig>("GlobalConfig");
  48. #if UNITY_ANDROID
  49. activePlatform = PlatformType.Android;
  50. #elif UNITY_IOS
  51. activePlatform = PlatformType.IOS;
  52. #elif UNITY_STANDALONE_WIN
  53. activePlatform = PlatformType.Windows;
  54. #elif UNITY_STANDALONE_OSX
  55. activePlatform = PlatformType.MacOS;
  56. #elif UNITY_STANDALONE_LINUX
  57. activePlatform = PlatformType.Linux;
  58. #else
  59. activePlatform = PlatformType.None;
  60. #endif
  61. platformType = activePlatform;
  62. }
  63. private void OnGUI()
  64. {
  65. this.platformType = (PlatformType)EditorGUILayout.EnumPopup(platformType);
  66. this.clearFolder = EditorGUILayout.Toggle("clean folder? ", clearFolder);
  67. this.isBuildExe = EditorGUILayout.Toggle("build exe?", this.isBuildExe);
  68. this.isContainAB = false;
  69. this.codeOptimization = (CodeOptimization)EditorGUILayout.EnumPopup("CodeOptimization ", this.codeOptimization);
  70. //EditorGUILayout.LabelField("BuildAssetBundleOptions ");
  71. //this.buildAssetBundleOptions = (BuildAssetBundleOptions)EditorGUILayout.EnumFlagsField(this.buildAssetBundleOptions);
  72. switch (this.codeOptimization)
  73. {
  74. case CodeOptimization.None:
  75. case CodeOptimization.Debug:
  76. this.buildOptions = BuildOptions.Development | BuildOptions.ConnectWithProfiler;
  77. break;
  78. case CodeOptimization.Release:
  79. this.buildOptions = BuildOptions.None;
  80. break;
  81. }
  82. GUILayout.Space(5);
  83. if (GUILayout.Button("BuildPackage"))
  84. {
  85. if (this.platformType == PlatformType.None)
  86. {
  87. ShowNotification(new GUIContent("please select platform!"));
  88. return;
  89. }
  90. if (platformType != activePlatform)
  91. {
  92. switch (EditorUtility.DisplayDialogComplex("Warning!", $"current platform is {activePlatform}, if change to {platformType}, may be take a long time", "change", "cancel", "no change"))
  93. {
  94. case 0:
  95. activePlatform = platformType;
  96. break;
  97. case 1:
  98. return;
  99. case 2:
  100. platformType = activePlatform;
  101. break;
  102. }
  103. }
  104. BuildHelper.Build(this.platformType, this.buildAssetBundleOptions, this.buildOptions, this.isBuildExe, this.isContainAB, this.clearFolder);
  105. }
  106. GUILayout.Label("");
  107. GUILayout.Label("Build & copy AOTMetadlls");
  108. if (GUILayout.Button("Hybrid-GenerateAll & copy2CodeDll"))
  109. {
  110. //CompileDll时,HotUpdateDll目录的model.dll会被清理掉,生成link.xml会报错
  111. //所以在compileDll后,增加了BuildModel & copy动作
  112. //PrebuildCommand.GenerateAll();
  113. BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
  114. CompileDllCommand.CompileDll(target);
  115. //生成最新的mode.dll & hotfix.dll,然后copy到hotupdate目录,供linkxml用
  116. BuildModelAndHotfix(this.codeOptimization);
  117. CopyHotfixdllToHybridDir();
  118. Il2CppDefGeneratorCommand.GenerateIl2CppDef();
  119. // 这几个生成依赖HotUpdateDlls
  120. LinkGeneratorCommand.GenerateLinkXml(target);
  121. // 生成裁剪后的aot dll
  122. StripAOTDllCommand.GenerateStripedAOTDlls(target, EditorUserBuildSettings.selectedBuildTargetGroup);
  123. // 桥接函数生成依赖于AOT dll,必须保证已经build过,生成AOT dll
  124. MethodBridgeGeneratorCommand.GenerateMethodBridge(target);
  125. ReversePInvokeWrapperGeneratorCommand.GenerateReversePInvokeWrapper(target);
  126. AOTReferenceGeneratorCommand.GenerateAOTGenericReference(target);
  127. string aotDllDir = SettingsUtil.GetAssembliesPostIl2CppStripDir(target);
  128. HotUpdateAssemblyManifest manifest = AssetDatabase.LoadAssetAtPath("Assets/Res/Config/HotUpdateAssemblyManifest.asset", typeof(HotUpdateAssemblyManifest)) as HotUpdateAssemblyManifest;
  129. if (manifest == null)
  130. {
  131. throw new Exception($"resource asset:{nameof(HotUpdateAssemblyManifest)} 配置不存在,请在Resources目录下创建");
  132. }
  133. List<string> AOTMetaAssemblies = (manifest.AOTMetadataDlls ?? Array.Empty<string>()).ToList();
  134. foreach (var dll in AOTMetaAssemblies)
  135. {
  136. string dllPath = $"{aotDllDir}/{dll}";
  137. if (!File.Exists(dllPath))
  138. {
  139. Debug.LogError($"ab中添加AOT补充元数据dll:{dllPath} 时发生错误,文件不存在。裁剪后的AOT dll在BuildPlayer时才能生成,因此需要你先构建一次游戏App后再打包。");
  140. continue;
  141. }
  142. string dllBytesPath = $"{YooAssetCodeDll}/{dll}.bytes";
  143. File.Copy(dllPath, dllBytesPath, true);
  144. Debug.Log($"copy AOT dll {dllPath} -> {dllBytesPath}");
  145. }
  146. }
  147. GUILayout.Label("");
  148. GUILayout.Label("Build热更dll & ab:");
  149. this.globalConfig.CodeMode = CodeMode.Client;// (CodeMode)EditorGUILayout.EnumPopup("CodeMode: ", this.globalConfig.CodeMode);
  150. if (GUILayout.Button("BuildModelAndHotfix"))
  151. {
  152. BuildModelAndHotfix(this.codeOptimization);
  153. //用yooAsset打ab, 不用你了
  154. //AfterCompiling();
  155. ShowNotification("Build Model And Hotfix Success!");
  156. }
  157. if (GUILayout.Button("BuildAB by YooAsset"))
  158. {
  159. var target = EditorUserBuildSettings.activeBuildTarget;
  160. BuildHelper.BuildAB(target, null);
  161. }
  162. GUILayout.Label("");
  163. GUILayout.Label("Config Tools: =======================");
  164. if (GUILayout.Button("ExcelExporter"))
  165. {
  166. //Directory.Delete("Assets/Bundles/Config", true);
  167. ToolsEditor.ExcelExporter();
  168. }
  169. if (GUILayout.Button("Proto2CS"))
  170. {
  171. ToolsEditor.Proto2CS();
  172. }
  173. GUILayout.Space(5);
  174. }
  175. private static void CopyHotfixdllToHybridDir()
  176. {
  177. var target = EditorUserBuildSettings.activeBuildTarget; ;
  178. var dll = Path.Combine(YooAssetCodeDll, "Model.dll.bytes");
  179. if (!File.Exists(dll))
  180. {
  181. Debug.LogError($"not exists: {dll}");
  182. }
  183. else
  184. {
  185. File.Copy(dll, Path.Combine(SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target), "Model.dll"), true);
  186. }
  187. dll = Path.Combine(YooAssetCodeDll, "Hotfix.dll.bytes");
  188. if (!File.Exists(dll))
  189. {
  190. Debug.LogError($"not exists: {dll}");
  191. }
  192. else
  193. {
  194. File.Copy(dll, Path.Combine(SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target), "Hotfix.dll"), true);
  195. }
  196. }
  197. public static void BuildModelAndHotfix(CodeOptimization codeOptimization = CodeOptimization.Release)
  198. {
  199. if (Define.EnableCodes)
  200. {
  201. throw new Exception("Remove macro 'ENABLE_CODES' first!");
  202. }
  203. var globalConfig = Resources.Load<GlobalConfig>("GlobalConfig");
  204. if (globalConfig.CodeMode == CodeMode.Server)
  205. {
  206. throw new Exception("Don't compile server here, open 'ET.sln' to compile!");
  207. }
  208. BuildAssembliesHelper.BuildModel(codeOptimization, globalConfig);
  209. BuildAssembliesHelper.BuildHotfix(codeOptimization, globalConfig);
  210. }
  211. //将model.dll打包成ab
  212. /*private static void AfterCompiling()
  213. {
  214. Directory.CreateDirectory(BuildAssembliesHelper.CodeDir);
  215. // 设置ab包
  216. AssetImporter assetImporter = AssetImporter.GetAtPath("Assets/Bundles/Code");
  217. assetImporter.assetBundleName = "Code.unity3d";
  218. AssetDatabase.SaveAssets();
  219. AssetDatabase.Refresh();
  220. Debug.Log("build success!");
  221. }*/
  222. public static void ShowNotification(string tips)
  223. {
  224. EditorWindow game = EditorWindow.GetWindow(typeof(EditorWindow).Assembly.GetType("UnityEditor.GameView"));
  225. game?.ShowNotification(new GUIContent($"{tips}"));
  226. }
  227. }
  228. }