private void CompileMod(BuildingMod mod, List <LocalMod> refMods, bool forWindows, ref byte[] dll, ref byte[] pdb) { status.SetProgress(forWindows ? 0 : 1, 2); // use an assembly compiled by msbuild, instead of supplying our own if (Program.LaunchParameters.ContainsKey("-eac") && forWindows == windows) { var path = Program.LaunchParameters["-eac"]; status.SetStatus(Language.GetTextValue("tModLoader.LoadingPrecompiled", forWindows ? "Windows.dll" : "Mono.dll")); PostProcess(path, !forWindows, mod.properties.includePDB && !forWindows); //post-processing still required on mono dll = File.ReadAllBytes(path); if (mod.properties.includePDB) { pdb = File.ReadAllBytes(Path.ChangeExtension(path, forWindows ? "pdb" : "dll.mdb")); } return; } status.SetStatus(Language.GetTextValue("tModLoader.Compiling" + (forWindows ? "Windows" : "Mono"), mod)); if (!DeveloperModeReady(out string msg)) { status.LogError(msg); return; } //collect all dll references var tempDir = Path.Combine(ModPath, "compile_temp"); Directory.CreateDirectory(tempDir); var refs = new List <string>(); //everything used to compile the tModLoader for the target platform refs.AddRange(GetTerrariaReferences(tempDir, forWindows)); // add framework assemblies refs.AddRange(Directory.GetFiles(referenceAssembliesPath, "*.dll", SearchOption.AllDirectories) .Where(path => !path.EndsWith("Thunk.dll") && !path.EndsWith("Wrapper.dll"))); //libs added by the mod refs.AddRange(mod.properties.dllReferences.Select(refDll => Path.Combine(mod.path, "lib/" + refDll + ".dll"))); //all dlls included in all referenced mods foreach (var refMod in refMods) { using (refMod.modFile.EnsureOpen()) { var path = Path.Combine(tempDir, refMod + ".dll"); File.WriteAllBytes(path, refMod.modFile.GetMainAssembly(forWindows)); refs.Add(path); foreach (var refDll in refMod.properties.dllReferences) { path = Path.Combine(tempDir, refDll + ".dll"); File.WriteAllBytes(path, refMod.modFile.GetBytes("lib/" + refDll + ".dll")); refs.Add(path); } } } var compileOptions = new CompilerParameters { OutputAssembly = Path.Combine(tempDir, mod + ".dll"), GenerateExecutable = false, GenerateInMemory = false, TempFiles = new TempFileCollection(tempDir, true), IncludeDebugInformation = mod.properties.includePDB, CompilerOptions = "/optimize" }; compileOptions.ReferencedAssemblies.AddRange(refs.ToArray()); var files = Directory.GetFiles(mod.path, "*.cs", SearchOption.AllDirectories).Where(file => !mod.properties.ignoreFile(file.Substring(mod.path.Length + 1))).ToArray(); try { var results = RoslynCompile(compileOptions, files); if (results.Errors.HasErrors) { status.LogCompileErrors(mod.Name + (forWindows ? "/Windows.dll" : "/Mono.dll"), results.Errors, forWindows != windows ? Language.GetTextValue("tModLoader.BuildErrorModCompileFolderHint") : null); return; } PostProcess(compileOptions.OutputAssembly, !forWindows, mod.properties.includePDB); dll = File.ReadAllBytes(compileOptions.OutputAssembly); if (mod.properties.includePDB) { pdb = File.ReadAllBytes(Path.ChangeExtension(compileOptions.OutputAssembly, forWindows ? "pdb" : "dll.mdb")); } } finally { int numTries = 10; while (numTries > 0) { try { Directory.Delete(tempDir, true); numTries = 0; } catch { System.Threading.Thread.Sleep(1); numTries--; } } } }
private void CompileMod(BuildingMod mod, List <LocalMod> refMods, bool forWindows, ref byte[] dll, ref byte[] pdb) { if (!LoadCompilationReferences()) { return; } bool generatePDB = mod.properties.includePDB && forWindows; if (generatePDB && !windows) { Console.WriteLine(Language.GetTextValue("tModLoader.BuildErrorPDBWindowsOnly")); generatePDB = false; } //collect all dll references var tempDir = Path.Combine(ModPath, "compile_temp"); Directory.CreateDirectory(tempDir); var refs = new List <string>(); //everything used to compile the tModLoader for the target platform refs.AddRange(GetTerrariaReferences(tempDir, forWindows)); //libs added by the mod refs.AddRange(mod.properties.dllReferences.Select(refDll => Path.Combine(mod.path, "lib/" + refDll + ".dll"))); //all dlls included in all referenced mods foreach (var refMod in refMods) { using (refMod.modFile.EnsureOpen()) { var path = Path.Combine(tempDir, refMod + ".dll"); File.WriteAllBytes(path, refMod.modFile.GetMainAssembly(forWindows)); refs.Add(path); foreach (var refDll in refMod.properties.dllReferences) { path = Path.Combine(tempDir, refDll + ".dll"); File.WriteAllBytes(path, refMod.modFile.GetBytes("lib/" + refDll + ".dll")); refs.Add(path); } } } var compileOptions = new CompilerParameters { OutputAssembly = Path.Combine(tempDir, mod + ".dll"), GenerateExecutable = false, GenerateInMemory = false, TempFiles = new TempFileCollection(tempDir, true), IncludeDebugInformation = generatePDB, CompilerOptions = "/optimize" }; compileOptions.ReferencedAssemblies.AddRange(refs.ToArray()); var files = Directory.GetFiles(mod.path, "*.cs", SearchOption.AllDirectories).Where(file => !mod.properties.ignoreFile(file.Substring(mod.path.Length + 1))).ToArray(); try { var results = RoslynCompile(compileOptions, files); if (results.Errors.HasErrors) { status.LogCompileErrors(mod.Name + (forWindows ? "/Windows.dll" : "/Mono.dll"), results.Errors, forWindows != windows ? Language.GetTextValue("tModLoader.BuildErrorModCompileFolderHint") : null); return; } dll = File.ReadAllBytes(compileOptions.OutputAssembly); dll = PostProcess(dll, forWindows); if (generatePDB) { pdb = File.ReadAllBytes(Path.Combine(tempDir, mod + ".pdb")); } } finally { int numTries = 10; while (numTries > 0) { try { Directory.Delete(tempDir, true); numTries = 0; } catch { System.Threading.Thread.Sleep(1); numTries--; } } } }