|
本文是个笔记,记录 2 个编辑器下编译程序集的逻辑。 一 . 编译 Runtime 用的程序集
Runtime 用的程序集:特征是会剔除 #if UNITY_EDITOR 注释的逻辑块)
public static void OnAssemblyBuildRequired() { // todo 目前是全部都编译,有木有方法只编译需要的 程序集呢? var buildDir = Application.temporaryCachePath; var files = new DirectoryInfo(buildDir).GetFiles(); foreach (var file in files) { FileUtil.DeleteFileOrDirectory(file.FullName); } var target = EditorUserBuildSettings.activeBuildTarget; var group = BuildPipeline.GetBuildTargetGroup(target); ScriptCompilationSettings scriptCompilationSettings = default; scriptCompilationSettings.group = group; scriptCompilationSettings.target = target; ScriptCompilationResult scriptCompilationResult = PlayerBuildInterface.CompilePlayerScripts(scriptCompilationSettings, buildDir); var lib_dir = Path.Combine(Application.dataPath, "..", "Library\\ScriptAssemblies"); foreach (var item in Instance.assemblies) { if (item.IsValid) // 如果配置正确则尝试转存储文件 { var file = new FileInfo(Path.Combine(lib_dir, item.Dll)); var lastWriteTime = file.LastWriteTime.Ticks; if (item.lastWriteTime < lastWriteTime) { item.lastWriteTime = lastWriteTime; FileUtil.ReplaceFile(Path.Combine(buildDir, item.Dll), item.OutputPath); item.UpdateInformation(); } } else { Debug.LogError($"{nameof(AssemblyHotfixManager)}: 请先完善 Hotfix Configuration 配置项!"); } } EditorUtility.SetDirty(Instance); }
Build App 使用的这个APIAddressable 也是这个API
二 . 编译指定 .asmdef 定义的程序集
public static void SyncAssemblyRawData(bool forceCompilie = false) { // 1. dll 编译存放处 var lib_dir = Path.Combine(Application.dataPath, "..", "Library\\ScriptAssemblies"); foreach (var item in Instance.assemblies) { // 如果配置正确则开始尝试编译 if (item.IsValid) { var data = JsonUtility.FromJson<SimplifiedAssemblyData>(item.assembly.text); var dll = Path.Combine(lib_dir, $"{data.name}.dll"); var temp = Path.Combine(Application.temporaryCachePath, $"{data.name}.bytes"); var file = new FileInfo(dll); if (file.Exists) { var lastWriteTime = file.LastWriteTime.Ticks; if (forceCompilie || item.lastWriteTime < lastWriteTime) { item.lastWriteTime = lastWriteTime; var assembly = CompilationPipeline.GetAssemblies(AssembliesType.Player).FirstOrDefault(v => v.name == item.assembly.name); if (null != assembly) { // Compiles scripts outside the Assets folder into a managed assembly that can be used inside the Assets folder. AssemblyBuilder builder = new AssemblyBuilder(temp, assembly.sourceFiles); builder.compilerOptions.AllowUnsafeCode = item.AllowUnsafeCode; BuildTargetGroup buildTargetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget); builder.compilerOptions.ApiCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup); builder.additionalReferences = assembly.allReferences; builder.flags = AssemblyBuilderFlags.None; // todo: 以下动作会导致程序集完成编译后IDE 报错,待确认:减少编译频率,变成 aa build 时编译,同时看能不能将 csproj 回到原点 builder.referencesOptions = ReferencesOptions.UseEngineModules; builder.buildTarget = EditorUserBuildSettings.activeBuildTarget; builder.buildTargetGroup = buildTargetGroup; builder.excludeReferences = new string[] { assembly.outputPath }; builder.additionalDefines = assembly.defines; builder.compilerOptions = assembly.compilerOptions; builder.buildFinished += (arg1, arg2) => { bool noErr = true; foreach (var msg in arg2) { if (msg.type == CompilerMessageType.Error) { Debug.LogError(msg.message); noErr = false; } else if (msg.type == CompilerMessageType.Warning) { Debug.LogWarning(msg.message); } else { Debug.Log(msg.message); } } if (noErr) { FileUtil.ReplaceFile(temp, item.OutputPath); item.UpdateInformation(); } }; if (!builder.Build()) { Debug.LogError($"{nameof(AssemblyHotfixManager)}: Assembly {item.Dll} Build Fail!"); } else { Debug.Log($"{nameof(AssemblyHotfixManager)} 热更程序集: <color=yellow>{item.Dll} </color> 完成构建!"); } } } } } else { Debug.LogError($"{nameof(AssemblyHotfixManager)}: 请先完善 Hotfix Configuration 配置项!"); } EditorUtility.SetDirty(Instance); AssetDatabase.Refresh(); } }
builder.referencesOptions = ReferencesOptions.UseEngineModules; 编译为 Runtime 程序集这个类主要用于将 Assets 文件夹以外的 Assembly 进行编译并放回到 Assets 中使用这个类使用的编译器不同于 PlayerBuildInterface.CompilePlayerScripts ,编译时会修改所有的 .sln 和 .csproj 文件上述代码并不完善,剩余部分在:这里
|
|