public static void Merge(string asmLoc, string asmBacLoc, string sfmfLoc) { AssemblyDefinition asmDef = AssemblyDefinition.ReadAssembly(asmLoc); ModuleDefinition modDef = asmDef.MainModule; if (Util.Util.GetDefinition(modDef.Types, "SFMF.Core", true) == null) { File.Copy(asmLoc, asmBacLoc, true); } var options = new RepackOptions { OutputFile = asmLoc, InputAssemblies = new[] { asmBacLoc, sfmfLoc }, SearchDirectories = new List <string>().AsEnumerable(), TargetKind = ILRepack.Kind.Dll }; var repack = new ILRepack(options); repack.Repack(); }
private static byte[] GetOptimizedBytes(string path) { Environment.CurrentDirectory = Path.GetDirectoryName(path) ?? throw new ArgumentException("Path not found"); string asmNameExt = Path.GetFileName(path); string asmName = Path.GetFileNameWithoutExtension(asmNameExt); string asmNameMerged = $"{asmName}.merged{Path.GetExtension(asmNameExt)}"; string asmNameMinified = $"{asmName}.minified{Path.GetExtension(asmNameExt)}"; Assembly asm = Assembly.LoadFrom(path); ILRepack repack = new ILRepack(new RepackOptions(new[] { "/internalize", $"/out:{asmNameMerged}", asmNameExt }.Concat(GetDependentFilesPass(asm, Environment.CurrentDirectory)))); repack.Repack(); ILStrip optimizer = new ILStrip(asmNameMerged); optimizer.MakeInternal(); optimizer.ScanUsedClasses(); optimizer.ScanUnusedClasses(); optimizer.CleanupUnusedClasses(); optimizer.CleanupUnusedResources(); optimizer.CleanupUnusedReferences(); optimizer.Save(asmNameMinified); optimizer.Dispose(); File.Delete(asmNameMerged); byte[] result = File.ReadAllBytes(asmNameMinified); File.Delete(asmNameMinified); return(result); }
private void Merge(string asmLoc, string asmBacLoc, string sfmfLoc) { AssemblyDefinition asmDef = AssemblyDefinition.ReadAssembly(asmLoc); ModuleDefinition modDef = asmDef.MainModule; if (Util.Util.GetDefinition(modDef.Types, "SFMF.Core", true) == null) { File.Copy(asmLoc, asmBacLoc, true); } var options = new RepackOptions { OutputFile = asmLoc, InputAssemblies = new[] { asmBacLoc, sfmfLoc }, SearchDirectories = new List <string>().AsEnumerable(), TargetKind = ILRepack.Kind.Dll }; var repack = new ILRepack(options); repack.Repack(); Dispatcher.Invoke(new Action(delegate() { PgbLoad.Value = 75; RefreshButtonStates(); })); }
protected void InjectFarmhandCoreClasses(string output, params string[] inputs) { RepackOptions options = new RepackOptions(); ILogger logger = new RepackLogger(); try { options.InputAssemblies = inputs; options.OutputFile = output; options.DebugInfo = true; options.SearchDirectories = new[] { Directory.GetCurrentDirectory() }; var repack = new ILRepack(options, logger); repack.Repack(); } catch (Exception ex) { Console.WriteLine($"FATAL ERROR: ILRepack: {ex.Message}"); throw new Exception("ILRepack Error", ex); // ignored } finally { if (options.PauseBeforeExit) { Console.WriteLine("Press Any Key To Continue"); Console.ReadKey(true); } } }
static void Repack(string input, string[] extras, string output, string name = null) { Console.Error.WriteLine($"Repacking: {input} -> {output}"); if (name == null) { name = Path.GetFileName(output); } string outputTmp = Path.Combine(Path.GetDirectoryName(output), name); if (File.Exists(outputTmp)) { File.Delete(outputTmp); } List <string> args = new List <string>(); args.Add($"/out:{outputTmp}"); args.Add(input); foreach (string dep in extras) { if (!string.IsNullOrWhiteSpace(dep)) { args.Add(dep.Trim()); } } RepackOptions options = new RepackOptions(args); ILRepack repack = new ILRepack(options); repack.Repack(); if (output != outputTmp) { if (File.Exists(output)) { File.Delete(output); } File.Move(outputTmp, output); } }
/// <summary> /// Injects Farmhand assemblies into the game's executable /// </summary> /// <param name="output"> /// The output path /// </param> /// <param name="inputs"> /// The assemblies to merge /// </param> /// <exception cref="Exception"> /// Throws an exception if ILRepack fails. /// </exception> protected void InjectFarmhandCoreClasses(string output, params string[] inputs) { var options = new RepackOptions(); ILogger logger = new RepackLogger(); try { options.InputAssemblies = string.IsNullOrEmpty(this.Options.AssemblyDirectory) ? inputs : inputs.Select( n => Path.IsPathRooted(n) ? n : Path.Combine(this.Options.AssemblyDirectory, n)).ToArray(); options.OutputFile = output; options.DebugInfo = true; options.SearchDirectories = string.IsNullOrEmpty(this.Options.AssemblyDirectory) ? new[] { Directory.GetCurrentDirectory() } : new[] { this.Options.AssemblyDirectory }; var repack = new ILRepack(options, logger); repack.Repack(); } catch (Exception ex) { Console.WriteLine($"FATAL ERROR: ILRepack: {ex.Message}"); throw new Exception("ILRepack Error", ex); } finally { if (options.PauseBeforeExit) { Console.WriteLine("Press Any Key To Continue"); Console.ReadKey(true); } } }
/// <summary> /// Executes ILRepack with specified options. /// </summary> /// <returns>Returns true if its successful.</returns> public override bool Execute() { repackOptions = new RepackOptions { KeyFile = keyFile, KeyContainer = keyContainer, LogFile = logFile, Log = !string.IsNullOrEmpty(logFile), LogVerbose = Verbose, UnionMerge = Union, DebugInfo = DebugInfo, CopyAttributes = CopyAttributes, AttributeFile = AttributeFile, AllowMultipleAssemblyLevelAttributes = AllowMultiple, TargetKind = targetKind, TargetPlatformVersion = TargetPlatformVersion, TargetPlatformDirectory = TargetPlatformDirectory, XmlDocumentation = XmlDocumentation, Internalize = Internalize, RenameInternalized = RenameInternalized, DelaySign = DelaySign, AllowDuplicateResources = AllowDuplicateResources, AllowZeroPeKind = ZeroPeKind, Parallel = Parallel, PauseBeforeExit = PauseBeforeExit, OutputFile = outputFile, AllowWildCards = Wildcards }; ilMerger = new ILRepack(repackOptions); // attempt to create output directory if it does not exist var outputPath = Path.GetDirectoryName(OutputFile); if (outputPath != null && Directory.Exists(outputPath) == false) { try { Directory.CreateDirectory(outputPath); } catch (Exception ex) { Log.LogErrorFromException(ex); return(false); } } // assemblies to be merged var assemblies = new string[this.assemblies.Length]; for (var i = 0; i < this.assemblies.Length; i++) { assemblies[i] = this.assemblies[i].ItemSpec; if (string.IsNullOrEmpty(assemblies[i])) { throw new Exception($"Invalid assembly path on item index {i}"); } if (!File.Exists(assemblies[i]) && !File.Exists(BuildPath(assemblies[i]))) { throw new Exception($"Unable to resolve assembly '{assemblies[i]}'"); } Log.LogMessage(MessageImportance.High, "Added assembly '{0}'", assemblies[i]); } // List of regex to compare against FullName of types NOT to internalize if (InternalizeExclude != null) { var internalizeExclude = new string[InternalizeExclude.Length]; if (Internalize) { for (var i = 0; i < InternalizeExclude.Length; i++) { internalizeExclude[i] = InternalizeExclude[i].ItemSpec; if (string.IsNullOrEmpty(internalizeExclude[i])) { throw new Exception($"Invalid internalize exclude pattern at item index {i}. Pattern cannot be blank."); } Log.LogMessage(MessageImportance.High, "Excluding namespaces/types matching pattern '{0}' from being internalized", internalizeExclude[i]); } // Create a temporary file with a list of assemblies that should not be internalized. excludeFileTmpPath = Path.GetTempFileName(); File.WriteAllLines(excludeFileTmpPath, internalizeExclude); repackOptions.ExcludeFile = excludeFileTmpPath; } } repackOptions.InputAssemblies = assemblies; // Path that will be used when searching for assemblies to merge. var searchPath = new List <string> { "." }; searchPath.AddRange(LibraryPath.Select(iti => BuildPath(iti.ItemSpec))); repackOptions.SearchDirectories = searchPath.ToArray(); // Attempt to merge assemblies. try { Log.LogMessage(MessageImportance.High, "Merging {0} assemb{1} to '{2}'", this.assemblies.Length, this.assemblies.Length != 1 ? "ies" : "y", outputFile); // Measure performance var stopWatch = new Stopwatch(); stopWatch.Start(); ilMerger.Repack(); stopWatch.Stop(); Log.LogMessage(MessageImportance.High, "Merge succeeded in {0} s", stopWatch.Elapsed.TotalSeconds); } catch (Exception e) { Log.LogErrorFromException(e); return(false); } return(true); }
public void Merge(IEnumerable <string> assemblies, string outputPath) { var assembliesToMerge = assemblies?.ToList() ?? throw new ArgumentNullException(nameof(assemblies)); var assemblyResolver = new DefaultAssemblyResolver(); if (SearchDirectories != null) { foreach (var dir in SearchDirectories) { assemblyResolver.AddSearchDirectory(dir); } } if (Verbose) { Console.WriteLine("Merging:"); foreach (var include in assembliesToMerge) { Console.WriteLine($" - {include}"); } } var tempRoot = Path.Combine(Path.GetTempPath(), "Mono.ApiTools", "AssemblyMerger", Guid.NewGuid().ToString()); if (InjectAssemblyNames) { if (!string.IsNullOrWhiteSpace(tempRoot) && !Directory.Exists(tempRoot)) { Directory.CreateDirectory(tempRoot); } assembliesToMerge = assembliesToMerge.ToList(); for (int i = 0; i < assembliesToMerge.Count; i++) { var ass = assembliesToMerge[i]; var temp = Path.Combine(tempRoot, Guid.NewGuid().ToString() + ".dll"); InjectAssemblyName(assemblyResolver, ass, temp); assembliesToMerge[i] = temp; } if (Verbose) { Console.WriteLine("Temporary assemblies:"); foreach (var include in assembliesToMerge) { Console.WriteLine($" - {include}"); } } } var options = new RepackOptions { InputAssemblies = assembliesToMerge.ToArray(), OutputFile = outputPath, SearchDirectories = SearchDirectories.ToArray(), CopyAttributes = true, AllowMultipleAssemblyLevelAttributes = true, LogVerbose = Verbose }; options.AllowedDuplicateTypes.Add(InjectedAttributeFullName, InjectedAttributeFullName); var repacker = new ILRepack(options); repacker.Repack(); if (InjectAssemblyNames) { if (Directory.Exists(tempRoot)) { try { Directory.Delete(tempRoot, true); } catch { } } } }
public override Task Execute() { var(file, deps) = GetDeps(); var currentDir = Directory.GetCurrentDirectory(); string[] dlls = null; if (_options.MergeAll) { dlls = GetDllsFromDir(file, currentDir); } else { dlls = GetDllsFromDeps(deps); } if (dlls != null) { if (!string.IsNullOrWhiteSpace(_options.Exclude)) { //exclude special dlls dlls = dlls.Where(d => !IsMatch(_options.Exclude, d)).ToArray();//todo:will keep the order? } if (dlls.Length > 0) { foreach (var dll in dlls) { if (!File.Exists(Path.Combine(currentDir, dll))) { throw new Exception($"Can not find dll in current dir:{dll}"); } } MessageHelper.Info($"minify dlls:{string.Join(";", dlls)}"); var outDir = Path.Combine(currentDir, string.IsNullOrWhiteSpace(_options.Directory) ? "nustored" : _options.Directory); var outFile = Path.Combine(outDir, dlls.First()); var options = new RepackOptions() { DelaySign = _options.DelaySign, DebugInfo = _options.DebugInfo, SearchDirectories = _options.SearchDirectories ?? new string[0], LogVerbose = _options.Verbosity, OutputFile = outFile, InputAssemblies = dlls }; if (!string.IsNullOrWhiteSpace(_options.Kind)) { options.TargetKind = Enum.Parse <ILRepack.Kind>(_options.Kind, true); } var pack = new ILRepack(options, new PackLogger() { ShouldLogVerbose = _options.Verbosity }); pack.Repack(); //generate deps.json var hashDlls = new HashSet <string>(dlls.Skip(1).Select(d => Path.GetFileNameWithoutExtension(d)));// hold the main dll if (hashDlls.Any()) { if (deps.Targets != null) { foreach (var target in deps.Targets) { RemoveMergedDlls(target.Value, hashDlls); } } RemoveMergedDlls(deps.Libraries, hashDlls); } File.WriteAllText(Path.Combine(outDir, Path.GetFileName(file)), JsonConvert.SerializeObject(deps, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.Indented }), Encoding.UTF8); foreach (var filter in (_options.CopyFilters == null || _options.CopyFilters.Count() == 0 ? new[] { "appsettings.json" } : _options.CopyFilters)) { CopyFile(currentDir, filter, outDir); } //copy runtimeconfig CopyFile(currentDir, "*.runtimeconfig.*", outDir); MessageHelper.Successs($"minify completed. output:{outDir}"); } else { MessageHelper.Error("can not find/match dlls"); } } return(Task.CompletedTask); }
public void Merge(string outputPath) { var assemblies = Assemblies; if (Program.Verbose) { Console.WriteLine("Merging:"); foreach (var include in assemblies) { Console.WriteLine($" - {include}"); } } var tempRoot = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); if (InjectAssemblyNames) { assemblies = assemblies.ToList(); if (!Directory.Exists(tempRoot)) { Directory.CreateDirectory(tempRoot); } for (int i = 0; i < assemblies.Count; i++) { var ass = assemblies[i]; var temp = Path.Combine(tempRoot, Guid.NewGuid().ToString() + ".dll"); InjectAssemblyName(ass, temp); assemblies[i] = temp; } if (Program.Verbose) { Console.WriteLine("Temporary assemblies:"); foreach (var include in assemblies) { Console.WriteLine($" - {include}"); } } } var options = new RepackOptions { InputAssemblies = assemblies.ToArray(), OutputFile = outputPath, SearchDirectories = SearchDirectories.ToArray(), CopyAttributes = true, AllowMultipleAssemblyLevelAttributes = true, LogVerbose = Program.Verbose }; var repacker = new ILRepack(options); repacker.Repack(); if (InjectAssemblyNames) { MergeAssemblyNameAttributes(outputPath); if (Directory.Exists(tempRoot)) { Directory.Delete(tempRoot, true); } } }
/// <summary> /// Compiles this project to a DLL file. /// </summary> public void CompileToDLL(string generationPath) { //Set up compilation. string outputPath = Path.Combine(generationPath, ProjectName + ".dll"); string pdbPath = Path.Combine(generationPath, ProjectName + ".pdb"); //Generate syntax trees for all files. var trees = new List <SyntaxTree>(); foreach (var file in Files.Values) { try { trees.Add(CSharpSyntaxTree.ParseText(file)); } catch (Exception e) { Logger.Write("[ERR] - Internal compile error: '" + e.Message + "'.", 1); return; } } //Generate dependency references. var deps = new List <PortableExecutableReference>(); deps.Add(MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location)); //make sure to add system deps.Add(MetadataReference.CreateFromFile(typeof(Enumerable).GetTypeInfo().Assembly.Location)); //linq deps.Add(MetadataReference.CreateFromFile(typeof(BurritoCore.API).GetTypeInfo().Assembly.Location)); //api foreach (var dep in CompileDependencies) { deps.Add(MetadataReference.CreateFromFile(dep)); } //Compilation options. var compilationOpts = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary); //Set up compilation. CSharpCompilation compilation = CSharpCompilation.Create( ProjectName, trees.ToArray(), deps.ToArray(), compilationOpts); //Write to a DLL stream. using (var dllStream = new MemoryStream()) using (var pdbStream = new MemoryStream()) { var emitResult = compilation.Emit(dllStream, pdbStream); if (!emitResult.Success) { //Emit errors. foreach (var error in emitResult.Diagnostics) { Logger.Write("[ERR] - Internal compile error at '" + error.Location + "': " + error.GetMessage(), 1); } return; } //From the DLL stream, write to file. using (FileStream fs = new FileStream(outputPath, FileMode.OpenOrCreate)) { dllStream.WriteTo(fs); fs.Flush(); } //If debug information is enabled, flush PDB too. if (BurritoAPI.IncludeDebugInformation) { using (FileStream fs = new FileStream(pdbPath, FileMode.OpenOrCreate)) { pdbStream.WriteTo(fs); fs.Flush(); } } } //Set up options for merging DLL libraries (suppressing console input). RepackOptions opt = new RepackOptions(); opt.OutputFile = outputPath + ".packed"; opt.SearchDirectories = new string[] { Environment.CurrentDirectory, AppDomain.CurrentDomain.BaseDirectory }; //Setting input assemblies. opt.InputAssemblies = new string[] { outputPath }.Concat(CompileDependencies).ToArray(); //Redirecting console input temporarily. using (var writer = new ConsoleCatcher()) { //Set up writer. var originalOut = Console.Out; if (BurritoAPI.VerbosityLevel < 0) { Console.SetOut(writer); } //Merge. ILRepack pack = new ILRepack(opt); pack.Repack(); //Set input back. Console.SetOut(originalOut); } //Delete original assembly, rename packed. string packedName = outputPath + ".packed"; try { File.Delete(outputPath); File.Move(packedName, outputPath); } catch { Logger.Write("[WARN] - Failed renaming packed (.dll.packed) to normal (.dll), insufficient permissions. Job still completed.", 2); } }
//////////////////////////// /// MAIN COMPILE METHODS /// //////////////////////////// public static void Compile(string file) { //Print the compile header. PrintCompileHeader(); //Note the compile start time. CompileStartTime = DateTime.Now; //Does the file that is being compiled exist? if (!File.Exists(file)) { Error.FatalCompile("The file you wish to compile does not exist."); return; } //Get the FileInfo, set the name of the project. FileInfo fi = new FileInfo(file); if (fi.Name.Contains(".")) { ProjectName = fi.Name.Split('.')[0]; } else { ProjectName = fi.Name; } //Yes, read the file into memory and strip all the comments. Log("Linking base Algo file '" + file + "'."); string toCompile = ""; try { toCompile = File.ReadAllText(file); } catch (Exception e) { Error.FatalCompile("Could not read from base script file, error '" + e.Message + "'."); return; } //Attaching the "core" library to the start. Log("Attaching the 'core' library to the base script."); MainScript = "import \"core\";" + MainScript; //Strip all comment lines. var scriptLines = toCompile.Replace("\r", "").Split('\n'); foreach (var line in scriptLines) { if (!line.StartsWith("//")) { MainScript += line + "\n"; } } Log("Successfully linked main file, linking references..."); //Get all linked import reference files. LinkFile(MainScript, file); Log("Successfully linked base and all referenced Algo scripts.", ALECEvent.Success); //Replacing import references with their proper scripts. Log("Attempting to replace abstract import links..."); bool success = ReplaceImportReferences(); if (!success) { Error.FatalCompile("Failed to replace import links with script references. Do you have a circular import loop?"); return; } //Do a sanity check to make sure it compiles as normal Algo. Log("Sanity checking the syntax of the provided script..."); SyntaxCheck(MainScript, MainScript.Replace("\r", "").Split('\n').Length - scriptLines.Length); //That's done, now convert it to a literal string. Log("Converting script into literal form for compilation..."); MainScript = MainScript.Replace("\"", "\"\""); Log("Successfully converted into literal form."); //Create the compiler (with arguments). CSharpCodeProvider provider = new CSharpCodeProvider(); CompilerParameters cp = new CompilerParameters(); cp.GenerateExecutable = true; cp.OutputAssembly = ProjectName + ".exe"; cp.GenerateInMemory = false; //Reference the main Algo assembly (this one) when compiling. Assembly entryasm = Assembly.GetEntryAssembly(); if (AlgoPlatformInfo.IsWindows) { cp.ReferencedAssemblies.Add(entryasm.Location); } else { cp.ReferencedAssemblies.Add(CPFilePath.GetPlatformFilePath(new string[] { DefaultDirectories.AssemblyDirectory, "Algo.exe" })); } cp.ReferencedAssemblies.Add(CPFilePath.GetPlatformFilePath(new string[] { DefaultDirectories.AssemblyDirectory, "Antlr4.Runtime.dll" })); //Attempt to compile. string finalScript = ALECTemplates.ALECEntryPoint.Replace("[CUSTOM-CODE-HERE]", MainScript); CompilerResults results = provider.CompileAssemblyFromSource(cp, finalScript); if (results.Errors.HasErrors) { //Uh oh, failed. //Collect the errors. string final = "Attempting to compile returned some errors:\n"; List <string> errors = new List <string>(); foreach (CompilerError error in results.Errors) { errors.Add(error.ErrorText + " (Line " + error.Line + ", column " + error.Column + ")."); } for (int i = 0; i < errors.Count; i++) { final += "[" + (i + 1) + "] - " + errors[i] + "\n"; } //Log. Error.FatalCompile(final); return; } //Successfully compiled, try to output to file. Log("Successfully compiled the Algo script into assembly.", ALECEvent.Success); Log("Output has been saved in '" + ProjectName + ".exe'."); //If Linux, MKBundle. if (AlgoPlatformInfo.IsLinux) { //Attempt to run MKBundle. Log("Linux detected as the operating system, attempting to create a native binary..."); Log("MAKE SURE YOU HAVE MKBUNDLE INSTALLED, AND HAVE A MONO 'machine.config' AT /etc/mono/4.5/machine.config."); Process proc = new Process(); proc.StartInfo.FileName = "/bin/bash"; proc.StartInfo.Arguments = "-c \" mkbundle -o " + ProjectName + " --simple " + cp.OutputAssembly + " --machine-config /etc/mono/4.5/machine.config --no-config --nodeps " + CPFilePath.GetPlatformFilePath(new string[] { DefaultDirectories.AssemblyDirectory, "*.dll" }) + " " + CPFilePath.GetPlatformFilePath(new string[] { DefaultDirectories.AssemblyDirectory, "Algo.exe" }) + "\""; proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardOutput = true; proc.Start(); while (!proc.StandardOutput.EndOfStream) { Log(proc.StandardOutput.ReadLine()); } Log("MKBundle has finished executing."); //Delete the main executable. Log("Attempting to clean up..."); try { File.Delete(ProjectName + ".exe"); } catch (Exception e) { Error.WarningCompile("Failed to clean up Windows executable, given error '" + e.Message + "'."); } } else if (AlgoPlatformInfo.IsWindows) { //It's Windows, use ILRepack instead. Log("Windows detected as the operating system, attempting to create a native binary..."); Log("Attempting to bundle dependencies into packed executable..."); RepackOptions opt = new RepackOptions(); opt.OutputFile = ProjectName + "_packed.exe"; opt.SearchDirectories = new string[] { AppDomain.CurrentDomain.BaseDirectory, Environment.CurrentDirectory }; //Setting input assemblies. string[] files = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll"); opt.InputAssemblies = new string[] { ProjectName + ".exe", entryasm.Location }.Concat(files).ToArray(); try { //Merging. ILRepack pack = new ILRepack(opt); pack.Repack(); Log("Successfully merged all dependencies with the output executable.", ALECEvent.Success); //Replacing the depending executable with the new one. Log("Cleaning up build files..."); try { File.Delete(ProjectName + ".exe"); File.Move(ProjectName + "_packed.exe", ProjectName + ".exe"); } catch (Exception e) { Error.WarningCompile("File cleanup failed with error '" + e.Message + "'."); Error.WarningCompile("Failed to clean up build files, the executable to use is named '" + ProjectName + "_packed.exe' rather than '" + ProjectName + ".exe'."); } } catch (Exception e) { Error.WarningCompile("Packing the executable's dependencies failed, with error '" + e.Message + "'. You will need to include algo.exe and all it's dependencies along with the built executable for it to run."); } } else { Error.FatalCompile("Could not detect the operating system to compile native binary."); return; } //Print the compile footer. PrintCompileFooter(); return; }