三国卡牌客户端基础资源仓库
yyl
4 天以前 cec146fc3fe287928e075c79ece20a20a9b16b20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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);
        }
 
        /// <summary>
        /// 计算热更代码中的泛型引用
        /// </summary>
        /// <param name="target"></param>
        public static void GenerateAOTGenericReference(BuildTarget target)
        {
            var gs = SettingsUtil.HybridCLRSettings;
            List<string> 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);
        //}
 
        /// <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();
 
 
            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()} ");
                }
            }
 
            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());
        }
    }
}