diff --git a/Editor/AOT/Analyzer.cs b/Editor/AOT/Analyzer.cs index 68253e3..dcd2a87 100644 --- a/Editor/AOT/Analyzer.cs +++ b/Editor/AOT/Analyzer.cs @@ -17,12 +17,16 @@ namespace HybridCLR.Editor.AOT public AssemblyReferenceDeepCollector Collector { get; set; } public int MaxIterationCount { get; set; } + + public bool ComputeAotAssembly { get; set; } } private readonly int _maxInterationCount; private readonly AssemblyReferenceDeepCollector _assemblyCollector; + private readonly bool _computeAotAssembly; + private readonly HashSet _genericTypes = new HashSet(); private readonly HashSet _genericMethods = new HashSet(); @@ -47,6 +51,7 @@ namespace HybridCLR.Editor.AOT { _assemblyCollector = options.Collector; _maxInterationCount = options.MaxIterationCount; + _computeAotAssembly = options.ComputeAotAssembly; _methodReferenceAnalyzer = new MethodReferenceAnalyzer(this.OnNewMethod); _hotUpdateAssemblyFiles = new HashSet(options.Collector.GetRootAssemblyNames().Select(assName => assName + ".dll")); } @@ -71,7 +76,7 @@ namespace HybridCLR.Editor.AOT private bool IsAotType(TypeDef type) { - return !_hotUpdateAssemblyFiles.Contains(type.Module.Name); + return _computeAotAssembly || !_hotUpdateAssemblyFiles.Contains(type.Module.Name); } private bool IsAotGenericMethod(MethodDef method) diff --git a/Editor/Commands/AOTReferenceGeneratorCommand.cs b/Editor/Commands/AOTReferenceGeneratorCommand.cs index c2d6340..b4dfb41 100644 --- a/Editor/Commands/AOTReferenceGeneratorCommand.cs +++ b/Editor/Commands/AOTReferenceGeneratorCommand.cs @@ -2,6 +2,7 @@ using HybridCLR.Editor.Meta; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -22,6 +23,10 @@ namespace HybridCLR.Editor.Commands GenerateAOTGenericReference(target); } + /// + /// 计算热更代码中的泛型引用 + /// + /// public static void GenerateAOTGenericReference(BuildTarget target) { var gs = SettingsUtil.HybridCLRSettings; @@ -40,5 +45,88 @@ namespace HybridCLR.Editor.Commands writer.Write(analyzer.AotGenericTypes.ToList(), analyzer.AotGenericMethods.ToList(), $"{Application.dataPath}/{gs.outputAOTGenericReferenceFile}"); AssetDatabase.Refresh(); } + + + + //[MenuItem("HybridCLR/Generate/AOTGenericReference2", priority = 103)] + //public static void GeneratedAOTGenericReferenceExcludeExists() + //{ + // GeneratedAOTGenericReferenceExcludeExists(EditorUserBuildSettings.activeBuildTarget); + //} + + /// + /// 计算热更新代码中的泛型引用,但排除AOT已经存在的泛型引用 + /// + /// + /// + public static void GeneratedAOTGenericReferenceExcludeExistsAOTClassAndMethods(BuildTarget target) + { + + var gs = SettingsUtil.HybridCLRSettings; + List hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved; + + AssemblyReferenceDeepCollector hotUpdateCollector = new AssemblyReferenceDeepCollector(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDllNames), hotUpdateDllNames); + var hotUpdateAnalyzer = new Analyzer(new Analyzer.Options + { + MaxIterationCount = Math.Min(10, gs.maxGenericReferenceIteration), + Collector = hotUpdateCollector, + }); + + hotUpdateAnalyzer.Run(); + + + string aotDllDir = SettingsUtil.GetAssembliesPostIl2CppStripDir(target); + List aotAssemblyNames = Directory.Exists(aotDllDir) ? + Directory.GetFiles(aotDllDir, "*.dll", SearchOption.TopDirectoryOnly).Select(Path.GetFileNameWithoutExtension).ToList() + : new List(); + if (aotAssemblyNames.Count == 0) + { + 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`"); + } + AssemblyReferenceDeepCollector aotCollector = new AssemblyReferenceDeepCollector(MetaUtil.CreateAOTAssemblyResolver(target), aotAssemblyNames); + var aotAnalyzer = new Analyzer(new Analyzer.Options + { + MaxIterationCount = Math.Min(10, gs.maxGenericReferenceIteration), + Collector = aotCollector, + ComputeAotAssembly = true, + }); + + aotAnalyzer.Run(); + + var (resultTypes, resultMethods) = ExcludeExistAOTGenericTypeAndMethodss(hotUpdateAnalyzer.AotGenericTypes.ToList(), hotUpdateAnalyzer.AotGenericMethods.ToList(), aotAnalyzer.AotGenericTypes.ToList(), aotAnalyzer.AotGenericMethods.ToList()); + var writer = new GenericReferenceWriter(); + writer.Write(resultTypes, resultMethods, $"{Application.dataPath}/{gs.outputAOTGenericReferenceFile}"); + AssetDatabase.Refresh(); + } + + + private static (List, List) ExcludeExistAOTGenericTypeAndMethodss(List hotUpdateTypes, List hotUpdateMethods, List aotTypes, List aotMethods) + { + var types = new List(); + + var typeSig2Type = hotUpdateTypes.ToDictionary(t => t.Type.DefinitionAssembly.Name + ":" + t.ToTypeSig(), t => t); + foreach (var t in aotTypes) + { + string key = t.Type.DefinitionAssembly.Name + ":" + t.ToTypeSig(); + if (typeSig2Type.TryGetValue(key, out var removedType)) + { + typeSig2Type.Remove(key); + Debug.Log($"remove AOT type:{removedType.ToTypeSig()} "); + } + } + + var methodSig2Method = hotUpdateMethods.ToDictionary(m => m.Method.DeclaringType.DefinitionAssembly.Name + ":" + m.ToMethodSpec().ToString(), m => m); + foreach (var m in aotMethods) + { + string key = m.Method.DeclaringType.DefinitionAssembly.Name + ":" + m.ToMethodSpec().ToString(); + if (methodSig2Method.TryGetValue(key, out var removedMethod)) + { + methodSig2Method.Remove(key); + Debug.Log($"remove AOT method:{removedMethod.ToMethodSpec()} "); + } + } + + return (typeSig2Type.Values.ToList(), methodSig2Method.Values.ToList()); + } } }