AOTReferenceGeneratorCommand.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. using HybridCLR.Editor.AOT;
  2. using HybridCLR.Editor.Meta;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using UnityEditor;
  10. using UnityEngine;
  11. namespace HybridCLR.Editor.Commands
  12. {
  13. using Analyzer = HybridCLR.Editor.AOT.Analyzer;
  14. public static class AOTReferenceGeneratorCommand
  15. {
  16. [MenuItem("HybridCLR/Generate/AOTGenericReference", priority = 102)]
  17. public static void CompileAndGenerateAOTGenericReference()
  18. {
  19. BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
  20. CompileDllCommand.CompileDll(target);
  21. GenerateAOTGenericReference(target);
  22. }
  23. /// <summary>
  24. /// 计算热更代码中的泛型引用
  25. /// </summary>
  26. /// <param name="target"></param>
  27. public static void GenerateAOTGenericReference(BuildTarget target)
  28. {
  29. var gs = SettingsUtil.HybridCLRSettings;
  30. List<string> hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
  31. AssemblyReferenceDeepCollector collector = new AssemblyReferenceDeepCollector(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDllNames), hotUpdateDllNames);
  32. var analyzer = new Analyzer(new Analyzer.Options
  33. {
  34. MaxIterationCount = Math.Min(20, gs.maxGenericReferenceIteration),
  35. Collector = collector,
  36. });
  37. analyzer.Run();
  38. var writer = new GenericReferenceWriter();
  39. writer.Write(analyzer.AotGenericTypes.ToList(), analyzer.AotGenericMethods.ToList(), $"{Application.dataPath}/{gs.outputAOTGenericReferenceFile}");
  40. AssetDatabase.Refresh();
  41. }
  42. //[MenuItem("HybridCLR/Generate/AOTGenericReference2", priority = 103)]
  43. //public static void GeneratedAOTGenericReferenceExcludeExists()
  44. //{
  45. // GeneratedAOTGenericReferenceExcludeExists(EditorUserBuildSettings.activeBuildTarget);
  46. //}
  47. /// <summary>
  48. /// 计算热更新代码中的泛型引用,但排除AOT已经存在的泛型引用
  49. /// </summary>
  50. /// <param name="target"></param>
  51. ///
  52. public static void GeneratedAOTGenericReferenceExcludeExistsAOTClassAndMethods(BuildTarget target)
  53. {
  54. var gs = SettingsUtil.HybridCLRSettings;
  55. List<string> hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
  56. AssemblyReferenceDeepCollector hotUpdateCollector = new AssemblyReferenceDeepCollector(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDllNames), hotUpdateDllNames);
  57. var hotUpdateAnalyzer = new Analyzer(new Analyzer.Options
  58. {
  59. MaxIterationCount = Math.Min(10, gs.maxGenericReferenceIteration),
  60. Collector = hotUpdateCollector,
  61. });
  62. hotUpdateAnalyzer.Run();
  63. string aotDllDir = SettingsUtil.GetAssembliesPostIl2CppStripDir(target);
  64. List<string> aotAssemblyNames = Directory.Exists(aotDllDir) ?
  65. Directory.GetFiles(aotDllDir, "*.dll", SearchOption.TopDirectoryOnly).Select(Path.GetFileNameWithoutExtension).ToList()
  66. : new List<string>();
  67. if (aotAssemblyNames.Count == 0)
  68. {
  69. throw new Exception($"no aot assembly found. please run `HybridCLR/Generate/All` or `HybridCLR/Generate/AotDlls` to generate aot dlls before runing `HybridCLR/Generate/AOTGenericReference`");
  70. }
  71. AssemblyReferenceDeepCollector aotCollector = new AssemblyReferenceDeepCollector(MetaUtil.CreateAOTAssemblyResolver(target), aotAssemblyNames);
  72. var aotAnalyzer = new Analyzer(new Analyzer.Options
  73. {
  74. MaxIterationCount = Math.Min(10, gs.maxGenericReferenceIteration),
  75. Collector = aotCollector,
  76. ComputeAotAssembly = true,
  77. });
  78. aotAnalyzer.Run();
  79. var (resultTypes, resultMethods) = ExcludeExistAOTGenericTypeAndMethodss(hotUpdateAnalyzer.AotGenericTypes.ToList(), hotUpdateAnalyzer.AotGenericMethods.ToList(), aotAnalyzer.AotGenericTypes.ToList(), aotAnalyzer.AotGenericMethods.ToList());
  80. var writer = new GenericReferenceWriter();
  81. writer.Write(resultTypes, resultMethods, $"{Application.dataPath}/{gs.outputAOTGenericReferenceFile}");
  82. AssetDatabase.Refresh();
  83. }
  84. private static (List<GenericClass>, List<GenericMethod>) ExcludeExistAOTGenericTypeAndMethodss(List<GenericClass> hotUpdateTypes, List<GenericMethod> hotUpdateMethods, List<GenericClass> aotTypes, List<GenericMethod> aotMethods)
  85. {
  86. var types = new List<GenericClass>();
  87. var typeSig2Type = hotUpdateTypes.ToDictionary(t => t.Type.DefinitionAssembly.Name + ":" + t.ToTypeSig(), t => t);
  88. foreach (var t in aotTypes)
  89. {
  90. string key = t.Type.DefinitionAssembly.Name + ":" + t.ToTypeSig();
  91. if (typeSig2Type.TryGetValue(key, out var removedType))
  92. {
  93. typeSig2Type.Remove(key);
  94. Debug.Log($"remove AOT type:{removedType.ToTypeSig()} ");
  95. }
  96. }
  97. var methodSig2Method = hotUpdateMethods.ToDictionary(m => m.Method.DeclaringType.DefinitionAssembly.Name + ":" + m.ToMethodSpec().ToString(), m => m);
  98. foreach (var m in aotMethods)
  99. {
  100. string key = m.Method.DeclaringType.DefinitionAssembly.Name + ":" + m.ToMethodSpec().ToString();
  101. if (methodSig2Method.TryGetValue(key, out var removedMethod))
  102. {
  103. methodSig2Method.Remove(key);
  104. Debug.Log($"remove AOT method:{removedMethod.ToMethodSpec()} ");
  105. }
  106. }
  107. return (typeSig2Type.Values.ToList(), methodSig2Method.Values.ToList());
  108. }
  109. }
  110. }