2025-03-31 14:55:24 +08:00
using HybridCLR.Editor.AOT ;
using HybridCLR.Editor.Meta ;
using System ;
using System.Collections.Generic ;
2025-06-12 18:00:06 +08:00
using System.IO ;
2025-03-31 14:55:24 +08:00
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 );
}
2025-06-12 18:00:06 +08:00
/// <summary>
/// 计算热更代码中的泛型引用
/// </summary>
/// <param name="target"></param>
2025-03-31 14:55:24 +08:00
public static void GenerateAOTGenericReference ( BuildTarget target )
{
var gs = SettingsUtil . HybridCLRSettings ;
List < string > hotUpdateDllNames = SettingsUtil . HotUpdateAssemblyNamesExcludePreserved ;
2025-06-12 18:00:06 +08:00
AssemblyReferenceDeepCollector collector = new AssemblyReferenceDeepCollector ( MetaUtil . CreateHotUpdateAndAOTAssemblyResolver ( target , hotUpdateDllNames ), hotUpdateDllNames );
var analyzer = new Analyzer ( new Analyzer . Options
2025-03-31 14:55:24 +08:00
{
2025-06-12 18:00:06 +08:00
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);
//}
/// <summary>
/// 计算热更新代码中的泛型引用,但排除AOT已经存在的泛型引用
/// </summary>
/// <param name="target"></param>
///
public static void GeneratedAOTGenericReferenceExcludeExistsAOTClassAndMethods ( BuildTarget target )
{
var gs = SettingsUtil . HybridCLRSettings ;
List < string > 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 ();
2025-03-31 14:55:24 +08:00
2025-06-12 18:00:06 +08:00
string aotDllDir = SettingsUtil . GetAssembliesPostIl2CppStripDir ( target );
List < string > aotAssemblyNames = Directory . Exists ( aotDllDir ) ?
Directory . GetFiles ( aotDllDir , "*.dll" , SearchOption . TopDirectoryOnly ). Select ( Path . GetFileNameWithoutExtension ). ToList ()
: new List < string >();
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 < GenericClass >, List < GenericMethod >) ExcludeExistAOTGenericTypeAndMethodss ( List < GenericClass > hotUpdateTypes , List < GenericMethod > hotUpdateMethods , List < GenericClass > aotTypes , List < GenericMethod > aotMethods )
{
var types = new List < GenericClass >();
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()} " );
}
}
2025-03-31 14:55:24 +08:00
2025-06-12 18:00:06 +08:00
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()} " );
}
2025-03-31 14:55:24 +08:00
}
2025-06-12 18:00:06 +08:00
return ( typeSig2Type . Values . ToList (), methodSig2Method . Values . ToList ());
2025-03-31 14:55:24 +08:00
}
}
}