BuildEditor.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  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. //生成exe之前,先生成最新的link.xml
  105. BuildModelAndHotfix(this.codeOptimization);
  106. CopyHotfixdllToHybridDir();
  107. LinkGeneratorCommand.GenerateLinkXml(EditorUserBuildSettings.activeBuildTarget);
  108. BuildHelper.Build(this.platformType, this.buildAssetBundleOptions, this.buildOptions, this.isBuildExe, this.isContainAB, this.clearFolder);
  109. }
  110. GUILayout.Label("");
  111. GUILayout.Label("Build & copy AOTMetadlls");
  112. if (GUILayout.Button("BuildAOTDlls & copy "))
  113. {
  114. BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
  115. CompileDllCommand.CompileDll(target);
  116. CopyHotfixdllToHybridDir();
  117. Il2CppDefGeneratorCommand.GenerateIl2CppDef();
  118. // 这几个生成依赖HotUpdateDlls
  119. //LinkGeneratorCommand.GenerateLinkXml(target);
  120. // 生成裁剪后的aot dll
  121. StripAOTDllCommand.GenerateStripedAOTDlls(target, EditorUserBuildSettings.selectedBuildTargetGroup);
  122. // 桥接函数生成依赖于AOT dll,必须保证已经build过,生成AOT dll
  123. MethodBridgeGeneratorCommand.GenerateMethodBridge(target);
  124. ReversePInvokeWrapperGeneratorCommand.GenerateReversePInvokeWrapper(target);
  125. AOTReferenceGeneratorCommand.GenerateAOTGenericReference(target);
  126. string aotDllDir = SettingsUtil.GetAssembliesPostIl2CppStripDir(target);
  127. HotUpdateAssemblyManifest manifest = AssetDatabase.LoadAssetAtPath("Assets/Res/Config/HotUpdateAssemblyManifest.asset", typeof(HotUpdateAssemblyManifest)) as HotUpdateAssemblyManifest;
  128. if (manifest == null)
  129. {
  130. throw new Exception($"resource asset:{nameof(HotUpdateAssemblyManifest)} 配置不存在,请在Resources目录下创建");
  131. }
  132. List<string> AOTMetaAssemblies = (manifest.AOTMetadataDlls ?? Array.Empty<string>()).ToList();
  133. foreach (var dll in AOTMetaAssemblies)
  134. {
  135. string dllPath = $"{aotDllDir}/{dll}";
  136. if (!File.Exists(dllPath))
  137. {
  138. Debug.LogError($"ab中添加AOT补充元数据dll:{dllPath} 时发生错误,文件不存在。裁剪后的AOT dll在BuildPlayer时才能生成,因此需要你先构建一次游戏App后再打包。");
  139. continue;
  140. }
  141. string dllBytesPath = $"{YooAssetCodeDll}/{dll}.bytes";
  142. File.Copy(dllPath, dllBytesPath, true);
  143. Debug.Log($"copy AOT dll {dllPath} -> {dllBytesPath}");
  144. }
  145. }
  146. GUILayout.Label("");
  147. GUILayout.Label("Build热更dll & ab:");
  148. this.globalConfig.CodeMode = CodeMode.Client;// (CodeMode)EditorGUILayout.EnumPopup("CodeMode: ", this.globalConfig.CodeMode);
  149. if (GUILayout.Button("BuildModelAndHotfix"))
  150. {
  151. BuildModelAndHotfix(this.codeOptimization);
  152. //用yooAsset打ab, 不用你了
  153. //AfterCompiling();
  154. ShowNotification("Build Model And Hotfix Success!");
  155. }
  156. if (GUILayout.Button("BuildAB by YooAsset"))
  157. {
  158. var target = EditorUserBuildSettings.activeBuildTarget;
  159. BuildHelper.BuildAB(target, null);
  160. }
  161. GUILayout.Label("");
  162. GUILayout.Label("Config Tools: =======================");
  163. if (GUILayout.Button("ExcelExporter"))
  164. {
  165. //Directory.Delete("Assets/Bundles/Config", true);
  166. ToolsEditor.ExcelExporter();
  167. // 设置ab包
  168. AssetImporter assetImporter = AssetImporter.GetAtPath($"Assets/Bundles/Config");
  169. assetImporter.assetBundleName = "Config.unity3d";
  170. AssetDatabase.SaveAssets();
  171. AssetDatabase.Refresh();
  172. }
  173. if (GUILayout.Button("Proto2CS"))
  174. {
  175. ToolsEditor.Proto2CS();
  176. }
  177. GUILayout.Space(5);
  178. }
  179. private static void CopyHotfixdllToHybridDir()
  180. {
  181. var target = EditorUserBuildSettings.activeBuildTarget; ;
  182. var dll = Path.Combine(YooAssetCodeDll, "Model.dll.bytes");
  183. if (!File.Exists(dll))
  184. {
  185. Debug.LogError($"not exists: {dll}");
  186. }
  187. else
  188. {
  189. File.Copy(dll, Path.Combine(SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target), "Model.dll"), true);
  190. }
  191. dll = Path.Combine(YooAssetCodeDll, "Hotfix.dll.bytes");
  192. if (!File.Exists(dll))
  193. {
  194. Debug.LogError($"not exists: {dll}");
  195. }
  196. else
  197. {
  198. File.Copy(dll, Path.Combine(SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target), "Hotfix.dll"), true);
  199. }
  200. }
  201. public static void BuildModelAndHotfix(CodeOptimization codeOptimization = CodeOptimization.Release)
  202. {
  203. if (Define.EnableCodes)
  204. {
  205. throw new Exception("Remove macro 'ENABLE_CODES' first!");
  206. }
  207. var globalConfig = Resources.Load<GlobalConfig>("GlobalConfig");
  208. if (globalConfig.CodeMode == CodeMode.Server)
  209. {
  210. throw new Exception("Don't compile server here, open 'ET.sln' to compile!");
  211. }
  212. BuildAssembliesHelper.BuildModel(codeOptimization, globalConfig);
  213. BuildAssembliesHelper.BuildHotfix(codeOptimization, globalConfig);
  214. }
  215. //将model.dll打包成ab
  216. /*private static void AfterCompiling()
  217. {
  218. Directory.CreateDirectory(BuildAssembliesHelper.CodeDir);
  219. // 设置ab包
  220. AssetImporter assetImporter = AssetImporter.GetAtPath("Assets/Bundles/Code");
  221. assetImporter.assetBundleName = "Code.unity3d";
  222. AssetDatabase.SaveAssets();
  223. AssetDatabase.Refresh();
  224. Debug.Log("build success!");
  225. }*/
  226. public static void ShowNotification(string tips)
  227. {
  228. EditorWindow game = EditorWindow.GetWindow(typeof(EditorWindow).Assembly.GetType("UnityEditor.GameView"));
  229. game?.ShowNotification(new GUIContent($"{tips}"));
  230. }
  231. }
  232. }