using HybridCLR.Editor.AOT;
using HybridCLR.Editor.Meta;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;
namespace HybridCLR.Editor.Commands
{
using Analyzer = HybridCLR.Editor.AOT.Analyzer;
public static class AOTReferenceGeneratorCommand
{
[MenuItem("HybridCLR/Generate/AOTGenericReference", priority = 102)]
public static void CompileAndGenerateAOTGenericReference()
{
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
CompileDllCommand.CompileDll(target);
GenerateAOTGenericReference(target);
}
///
/// 计算热更代码中的泛型引用
///
///
public static void GenerateAOTGenericReference(BuildTarget target)
{
var gs = SettingsUtil.HybridCLRSettings;
List hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
AssemblyReferenceDeepCollector collector = new AssemblyReferenceDeepCollector(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDllNames), hotUpdateDllNames);
var analyzer = new Analyzer(new Analyzer.Options
{
MaxIterationCount = Math.Min(20, gs.maxGenericReferenceIteration),
Collector = collector,
});
analyzer.Run();
var writer = new GenericReferenceWriter();
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());
}
}
}