Skip to content

Commit

Permalink
[refactor] 重构并且修复了Generate相关Assembly Resolve潜在的bug。
Browse files Browse the repository at this point in the history
[opt] 优化 PrebuildCommand.Build 中多次编译热更新dll的问题,大幅缩短了时间。
  • Loading branch information
walon committed Dec 14, 2022
1 parent 947b15e commit 00f9433
Show file tree
Hide file tree
Showing 20 changed files with 151 additions and 241 deletions.
19 changes: 10 additions & 9 deletions Editor/BuildProcessors/FilterHotFixAssemblies.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,32 +24,33 @@ public string[] OnFilterAssemblies(BuildOptions buildOptions, string[] assemblie
Debug.Log($"[FilterHotFixAssemblies] disabled");
return assemblies;
}
List<string> allHotUpdateDllFiles = SettingsUtil.HotUpdateAssemblyFiles;
List<string> allHotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNames;
List<string> allHotupdateDllFiles = SettingsUtil.HotUpdateAssemblyFiles;

// 检查是否重复填写
var hotUpdateDllSet = new HashSet<string>();
foreach(var hotUpdateDll in allHotUpdateDllFiles)
foreach(var hotUpdateDll in allHotUpdateDllNames)
{
if (!hotUpdateDllSet.Add(hotUpdateDll))
{
throw new Exception($"热更新 assembly:{hotUpdateDll} 在列表中重复,请除去重复条目");
}
}

var assResolver = MetaUtil.CreateHotUpdateAssemblyResolver(EditorUserBuildSettings.activeBuildTarget);
var assResolver = MetaUtil.CreateHotUpdateAssemblyResolver(EditorUserBuildSettings.activeBuildTarget, allHotUpdateDllNames);
// 检查是否填写了正确的dll名称
foreach (var hotUpdateDll in allHotUpdateDllFiles)
foreach (var hotUpdateDllName in allHotUpdateDllNames)
{
string hotUpdateAssName = hotUpdateDll.Substring(0, hotUpdateDll.Length - 4);
if (assemblies.All(ass => !ass.EndsWith(hotUpdateDll)) && string.IsNullOrEmpty(assResolver.ResolveAssembly(hotUpdateAssName, false)))
string hotUpdateDllFile = hotUpdateDllName + ".dll";
if (assemblies.All(ass => !ass.EndsWith(hotUpdateDllFile)) && string.IsNullOrEmpty(assResolver.ResolveAssembly(hotUpdateDllName, false)))
{
throw new Exception($"热更新 assembly:{hotUpdateDll} 不存在,请检查拼写错误");
throw new Exception($"热更新 assembly:{hotUpdateDllFile} 不存在,请检查拼写错误");
}
Debug.Log($"[FilterHotFixAssemblies] 过滤热更新assembly:{hotUpdateDll}");
Debug.Log($"[FilterHotFixAssemblies] 过滤热更新assembly:{hotUpdateDllFile}");
}

// 将热更dll从打包列表中移除
return assemblies.Where(ass => allHotUpdateDllFiles.All(dll => !ass.EndsWith(dll, StringComparison.OrdinalIgnoreCase))).ToArray();
return assemblies.Where(ass => allHotupdateDllFiles.All(dll => !ass.EndsWith(dll, StringComparison.OrdinalIgnoreCase))).ToArray();
}
}
}
18 changes: 7 additions & 11 deletions Editor/Commands/AOTReferenceGeneratorCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,19 @@ public static class AOTReferenceGeneratorCommand
{

[MenuItem("HybridCLR/Generate/AOTGenericReference", priority = 102)]
public static void GenerateAOTGenericReference()
public static void CompileAndGenerateAOTGenericReference()
{
GenerateAOTGenericReference(true);
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
CompileDllCommand.CompileDll(target);
GenerateAOTGenericReference(target);
}

public static void GenerateAOTGenericReference(bool compileDll)
public static void GenerateAOTGenericReference(BuildTarget target)
{
// 此处理论会有点问题,打每个平台的时候,都得针对当前平台生成桥接函数
// 但影响不大,先这样吧
if (compileDll)
{
CompileDllCommand.CompileDllActiveBuildTarget();
}

var gs = SettingsUtil.HybridCLRSettings;
List<string> hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNames;

using (AssemblyReferenceDeepCollector collector = new AssemblyReferenceDeepCollector(MetaUtil.CreateBuildTargetAssemblyResolver(EditorUserBuildSettings.activeBuildTarget), SettingsUtil.HotUpdateAssemblyNames))
using (AssemblyReferenceDeepCollector collector = new AssemblyReferenceDeepCollector(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDllNames), hotUpdateDllNames))
{
var analyzer = new Analyzer(new Analyzer.Options
{
Expand Down
2 changes: 1 addition & 1 deletion Editor/Commands/Il2CppDefGeneratorCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static void GenerateIl2CppDef()
{
var options = new Il2CppDef.Il2CppDefGenerator.Options()
{
UnityVersion = UnityEngine.Application.unityVersion,
UnityVersion = Application.unityVersion,
OutputFile = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/il2cpp-config.h",
};

Expand Down
14 changes: 6 additions & 8 deletions Editor/Commands/LinkGeneratorCommand.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using HybridCLR.Editor.Link;
using HybridCLR.Editor.Meta;
using System;
using System.Collections.Generic;
using System.Reflection;
Expand All @@ -14,21 +15,18 @@ public static class LinkGeneratorCommand
[MenuItem("HybridCLR/Generate/LinkXml", priority = 100)]
public static void GenerateLinkXml()
{
GenerateLinkXml(true);
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
CompileDllCommand.CompileDll(target);
GenerateLinkXml(target);
}

public static void GenerateLinkXml(bool compileDll)
public static void GenerateLinkXml(BuildTarget target)
{
if (compileDll)
{
CompileDllCommand.CompileDllActiveBuildTarget();
}

var ls = SettingsUtil.HybridCLRSettings;

List<string> hotfixAssemblies = SettingsUtil.HotUpdateAssemblyNames;

var analyzer = new Analyzer(Meta.MetaUtil.CreateBuildTargetAssemblyResolver(EditorUserBuildSettings.activeBuildTarget), HybridCLRSettings.Instance.collectAssetReferenceTypes);
var analyzer = new Analyzer(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotfixAssemblies), HybridCLRSettings.Instance.collectAssetReferenceTypes);
var refTypes = analyzer.CollectRefs(hotfixAssemblies);

Debug.Log($"[LinkGeneratorCommand] hotfix assembly count:{hotfixAssemblies.Count}, ref type count:{refTypes.Count} output:{Application.dataPath}/{ls.outputLinkFile}");
Expand Down
24 changes: 7 additions & 17 deletions Editor/Commands/MethodBridgeGeneratorCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,27 +45,17 @@ private static void GenerateMethodBridgeCppFile(Analyzer analyzer, PlatformABI p
}

[MenuItem("HybridCLR/Generate/MethodBridge", priority = 101)]
public static void GenerateMethodBridge()
public static void CompileAndGenerateMethodBridge()
{
GenerateMethodBridge(true);
}

static IAssemblyResolver CreateBuildTargetAssemblyResolver(BuildTarget target)
{
return new CombinedAssemblyResolver(
new PathAssemblyResolver(SettingsUtil.GetAssembliesPostIl2CppStripDir(target)),
MetaUtil.CreateHotUpdateAssemblyResolver(target)
);
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
CompileDllCommand.CompileDll(target);
GenerateMethodBridge(target);
}

public static void GenerateMethodBridge(bool compileDll)
public static void GenerateMethodBridge(BuildTarget target)
{
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
if (compileDll)
{
CompileDllCommand.CompileDllActiveBuildTarget();
}
using (AssemblyReferenceDeepCollector collector = new AssemblyReferenceDeepCollector(CreateBuildTargetAssemblyResolver(target), SettingsUtil.HotUpdateAssemblyNames))
List<string> hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNames;
using (AssemblyReferenceDeepCollector collector = new AssemblyReferenceDeepCollector(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDllNames), hotUpdateDllNames))
{
var analyzer = new Analyzer(new Analyzer.Options
{
Expand Down
16 changes: 9 additions & 7 deletions Editor/Commands/PrebuildCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,18 @@ public static class PrebuildCommand
[MenuItem("HybridCLR/Generate/All", priority = 200)]
public static void GenerateAll()
{
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
CompileDllCommand.CompileDll(target);

Il2CppDefGeneratorCommand.GenerateIl2CppDef();
// 顺序随意
ReversePInvokeWrapperGeneratorCommand.GenerateReversePInvokeWrapper();

// AOTReferenceGeneratorCommand 涉及到代码生成,必须在MethodBridgeGeneratorCommand之前
AOTReferenceGeneratorCommand.GenerateAOTGenericReference();
MethodBridgeGeneratorCommand.GenerateMethodBridge();
// 这几个生成依赖HotUpdateDlls
LinkGeneratorCommand.GenerateLinkXml(target);
ReversePInvokeWrapperGeneratorCommand.GenerateReversePInvokeWrapper(target);
AOTReferenceGeneratorCommand.GenerateAOTGenericReference(target);

// 顺序随意,只要保证 GenerateLinkXml之前有调用过CompileDll即可
LinkGeneratorCommand.GenerateLinkXml(false);
// 桥接函数生成依赖于AOT dll,必须保证已经build过,生成AOT dll
MethodBridgeGeneratorCommand.GenerateMethodBridge(target);
}
}
}
16 changes: 12 additions & 4 deletions Editor/Commands/ReversePInvokeWrapperGeneratorCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,20 @@ public static class ReversePInvokeWrapperGeneratorCommand
{

[MenuItem("HybridCLR/Generate/ReversePInvokeWrapper", priority = 103)]
public static void GenerateReversePInvokeWrapper()

public static void CompileAndGenerateReversePInvokeWrapper()
{
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
CompileDllCommand.CompileDll(target);
GenerateReversePInvokeWrapper(target);
}

public static void GenerateReversePInvokeWrapper(BuildTarget target)
{
CompileDllCommand.CompileDllActiveBuildTarget();
using (var cache = new AssemblyCache(MetaUtil.CreateBuildTargetAssemblyResolver(EditorUserBuildSettings.activeBuildTarget)))
List<string> hotUpdateDlls = SettingsUtil.HotUpdateAssemblyNames;
using (var cache = new AssemblyCache(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDlls)))
{
var analyzer = new ReversePInvokeWrap.Analyzer(cache, SettingsUtil.HotUpdateAssemblyNames);
var analyzer = new ReversePInvokeWrap.Analyzer(cache, hotUpdateDlls);
analyzer.Run();


Expand Down
13 changes: 3 additions & 10 deletions Editor/Link/Analyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,15 @@ public HashSet<TypeRef> CollectRefs(List<string> rootAssemblies)
{
using (var assCollector = new AssemblyCache(_resolver))
{
var rootAssemblyName = new HashSet<string>();
foreach (var ass in rootAssemblies)
{
if (!rootAssemblyName.Add(ass))
{
throw new Exception($"assembly:{ass} 重复");
}
}
var rootAssemblyNames = new HashSet<string>(rootAssemblies);

var typeRefs = new HashSet<TypeRef>(TypeEqualityComparer.Instance);
foreach (var rootAss in rootAssemblies)
{
var dnAss = assCollector.LoadModule(rootAss, _analyzeAssetType);
foreach (var type in dnAss.GetTypeRefs())
{
if (!rootAssemblyName.Contains(type.DefinitionAssembly.Name.ToString()))
if (!rootAssemblyNames.Contains(type.DefinitionAssembly.Name.ToString()))
{
typeRefs.Add(type);
}
Expand All @@ -51,7 +44,7 @@ public HashSet<TypeRef> CollectRefs(List<string> rootAssemblies)
if (_analyzeAssetType)
{
var modsExludeRoots = assCollector.LoadedModules
.Where(e => !rootAssemblyName.Contains(e.Key))
.Where(e => !rootAssemblyNames.Contains(e.Key))
.ToDictionary(e => e.Key, e => e.Value);
CollectObjectTypeInAssets(modsExludeRoots, typeRefs);
}
Expand Down
26 changes: 26 additions & 0 deletions Editor/Meta/AssemblyResolverBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HybridCLR.Editor.Meta
{
public abstract class AssemblyResolverBase : IAssemblyResolver
{
public string ResolveAssembly(string assemblyName, bool throwExIfNotFind)
{
if (TryResolveAssembly(assemblyName, out string assemblyPath))
{
return assemblyPath;
}
if (throwExIfNotFind)
{
throw new Exception($"resolve assembly:{assemblyName} 失败! 如果是热更新dll找不到,请先运行`HybridCLR/CompileDll/ActiveBuildTarget`编译生成热更新dll。如果是AOT dll找不到,请先运行`HybridCLR/Generate/LinkXml`,接着在`Build Settings`中打包或者导出工程来生成AOT dll");
}
return null;
}

protected abstract bool TryResolveAssembly(string assemblyName, out string assemblyPath);
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 6 additions & 8 deletions Editor/Meta/CombinedAssemblyResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace HybridCLR.Editor.Meta
{
public class CombinedAssemblyResolver : IAssemblyResolver
public class CombinedAssemblyResolver : AssemblyResolverBase
{
private readonly IAssemblyResolver[] _resolvers;

Expand All @@ -15,21 +15,19 @@ public CombinedAssemblyResolver(params IAssemblyResolver[] resolvers)
_resolvers = resolvers;
}

public string ResolveAssembly(string assemblyName, bool throwExIfNotFind)
protected override bool TryResolveAssembly(string assemblyName, out string assemblyPath)
{
foreach(var resolver in _resolvers)
{
var assembly = resolver.ResolveAssembly(assemblyName, false);
if (assembly != null)
{
return assembly;
assemblyPath = assembly;
return true;
}
}
if (throwExIfNotFind)
{
throw new Exception($"resolve assembly:{assemblyName} fail");
}
return null;
assemblyPath = null;
return false;
}
}
}
37 changes: 37 additions & 0 deletions Editor/Meta/FixedSetAssemblyResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;

namespace HybridCLR.Editor.Meta
{
public class FixedSetAssemblyResolver : AssemblyResolverBase
{
private readonly string _rootDir;
private readonly HashSet<string> _fileNames;

public FixedSetAssemblyResolver(string rootDir, IEnumerable<string> fileNameNotExts)
{
_rootDir = rootDir;
_fileNames = new HashSet<string>(fileNameNotExts);
}

protected override bool TryResolveAssembly(string assemblyName, out string assemblyPath)
{
if (_fileNames.Contains(assemblyName))
{
assemblyPath = $"{_rootDir}/{assemblyName}.dll";
if (File.Exists(assemblyPath))
{
Debug.Log($"[FixedSetAssemblyResolver] resolve:{assemblyName} path:{assemblyPath}");
return true;
}
}
assemblyPath = null;
return false;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 00f9433

Please sign in to comment.