public static CmdLineCompilerContext Create(string sourcePath, CompilationFlags flags) { string outputFile; IEmitter emitter; if (flags.HasFlag(CompilationFlags.Assembly)) { outputFile = Path.ChangeExtension(sourcePath, "il"); emitter = new TextEmitter(outputFile); } else if (flags.HasFlag(CompilationFlags.WriteDll)) { outputFile = Path.ChangeExtension(sourcePath, "dll"); emitter = new PeEmitter(outputFile, flags); } else { outputFile = Path.ChangeExtension(sourcePath, "exe"); emitter = new PeEmitter(outputFile, flags); } Stream inputFile = File.Open(sourcePath, FileMode.Open, FileAccess.Read); StreamReader reader = new StreamReader(inputFile); return(new CmdLineCompilerContext(sourcePath, inputFile, reader, emitter, flags)); }
public void Flush() { if (_textEmitter != null) { _textEmitter.Flush(); _textEmitter.Dispose(); _textEmitter = null; string platform = _flags.HasFlag(CompilationFlags.Platform32) ? " /32BITPREFERRED" : " /X64"; string debug = _flags.HasFlag(CompilationFlags.NoDebug) ? string.Empty : " /DEBUG"; string dll = _flags.HasFlag(CompilationFlags.WriteDll) ? " /DLL" : string.Empty; // Find the path to ilasm.exe string mscorlibPath = typeof(object).Assembly.Location; string frameworkDir = Path.GetDirectoryName(mscorlibPath); string ilasmPath = Path.Combine(frameworkDir, "ilasm.exe"); // Invoke ilasm to convert the textual CIL into a PE file. Process process = new Process(); process.StartInfo.FileName = ilasmPath; process.StartInfo.WorkingDirectory = Path.GetDirectoryName(_outputFile); process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; process.StartInfo.Arguments = string.Format( @"{0}{1}{2}{3} /OUTPUT={4}", _ilFile, platform, debug, dll, _outputFile); process.Start(); process.WaitForExit(); } }
public static CmdLineCompilerContext Create(string sourcePath, CompilationFlags flags) { string outputFile; IEmitter emitter; if (flags.HasFlag(CompilationFlags.Assembly)) { outputFile = Path.ChangeExtension(sourcePath, "il"); emitter = new TextEmitter(outputFile); } else { outputFile = Path.ChangeExtension(sourcePath, "exe"); emitter = new PeEmitter(outputFile, flags); } Stream inputFile = File.Open(sourcePath, FileMode.Open, FileAccess.Read); StreamReader reader = new StreamReader(inputFile); return new CmdLineCompilerContext(sourcePath, inputFile, reader, emitter, flags); }
private static bool TryParseArgs(string[] args, out string sourceFile, out CompilationFlags flags) { sourceFile = null; flags = 0; if (args.Length < 1) { return(false); } foreach (string arg in args) { string normalizedArg = arg.ToUpper(); switch (normalizedArg) { case "/32": flags |= CompilationFlags.Platform32; break; case "/64": flags |= CompilationFlags.Platform64; break; case "/NODEBUG": flags |= CompilationFlags.NoDebug; break; case "/ASM": flags |= CompilationFlags.Assembly; break; default: if (normalizedArg.StartsWith("/")) { Console.WriteLine("Unrecognized option {0}", normalizedArg); return(false); } if (!File.Exists(arg)) { Console.WriteLine("Source file '{0}' not found", arg); return(false); } if (sourceFile != null) { Console.WriteLine("Multiple source files specified. Only one file is supported"); return(false); } sourceFile = arg; break; } } if (flags.HasFlag(CompilationFlags.Platform32) && flags.HasFlag(CompilationFlags.Platform64)) { Console.WriteLine("Both 32-bit and 64-bit platforms specified. Only one platform is supported"); return(false); } if (!flags.HasFlag(CompilationFlags.Platform32) && !flags.HasFlag(CompilationFlags.Platform64)) { flags |= CompilationFlags.Platform32; } if (sourceFile == null) { return(false); } // NOTE: Currently this project is always compiled for .NET Core, so this #if will always be true. But leaving // in case one wants to modify the project to run on desktop. Note that currently this compiler uses the assemblies // that it is running on as reference assemblies. So to produce .NET Framework assemblies it needs to be running // on the .NET Framework. #if NETCOREAPP flags |= CompilationFlags.NetCore; flags |= CompilationFlags.WriteDll; // force running application through dotnet #endif return(true); }
/// <summary> /// Initializes a new instance of the PeEmitter class. /// Use this constructor to when generating an in-memory PE file /// </summary> /// <param name="flags">Compiler flags</param> public PeEmitter(CompilationFlags flags) : this(GetPathToTempFile(flags.HasFlag(CompilationFlags.WriteDll) ? "dll" : "exe"), flags) { _deleteOutputOnClose = true; }
public void Flush() { if (_textEmitter != null) { _textEmitter.Flush(); _textEmitter.Dispose(); _textEmitter = null; string platform = _flags.HasFlag(CompilationFlags.Platform32) ? " -32BITPREFERRED" : " -X64"; string debug = _flags.HasFlag(CompilationFlags.NoDebug) ? string.Empty : " -DEBUG"; string dll = _flags.HasFlag(CompilationFlags.WriteDll) ? " -DLL" : string.Empty; string mscorlibPath; string frameworkDir; string ilasmPath = null; bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); // If we are on Windows, and we aren't targetting .NET Core, look next to our CoreLib's ilasm.exe. If we are running on desktop framework this will work. if (!_flags.HasFlag(CompilationFlags.NetCore) && isWindows) { mscorlibPath = typeof(object).Assembly.Location; frameworkDir = Path.GetDirectoryName(mscorlibPath); ilasmPath = Path.Combine(frameworkDir, "ilasm.exe"); } if (ilasmPath == null || !File.Exists(ilasmPath)) { string thisDir = Path.GetDirectoryName(GetType().Assembly.Location); string ilasmFileName = isWindows ? "ilasm.exe" : "ilasm"; ilasmPath = Path.Combine(thisDir, ilasmFileName); if (!File.Exists(ilasmPath)) throw new FileNotFoundException("ilasm cannot be found, make sure netcore ilasm is present in the same directory as IrisCompiler.dll"); if (!string.IsNullOrEmpty(debug)) // netcore ilasm requires explicitly specifying pdb format debug += " -PDBFMT=PORTABLE"; } // Invoke ilasm to convert the textual CIL into a PE file. using (Process process = new Process()) { process.StartInfo.FileName = ilasmPath; process.StartInfo.WorkingDirectory = Path.GetDirectoryName(_outputFile); process.StartInfo.RedirectStandardError = true; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.CreateNoWindow = true; process.StartInfo.Arguments = string.Format( @"{0} -QUIET{1}{2}{3} -OUTPUT={4}", _ilFile, platform, debug, dll, _outputFile); process.StartInfo.UseShellExecute = false; process.OutputDataReceived += (object sender, DataReceivedEventArgs e) => { // Ignore output. This ensures that the output stream doesn't fill up. }; process.Start(); process.WaitForExit(); if (process.ExitCode != 0) { throw new InvalidOperationException("ilasm failed.\nError text: " + process.StandardError.ReadToEnd()); } } } }
private static bool TryParseArgs(string[] args, out string sourceFile, out CompilationFlags flags) { sourceFile = null; flags = 0; if (args.Length < 1) return false; foreach (string arg in args) { string normalizedArg = arg.ToUpper(); switch (normalizedArg) { case "/32": flags |= CompilationFlags.Platform32; break; case "/64": flags |= CompilationFlags.Platform64; break; case "/NODEBUG": flags |= CompilationFlags.NoDebug; break; case "/ASM": flags |= CompilationFlags.Assembly; break; default: if (normalizedArg.StartsWith("/")) { Console.WriteLine("Unrecognized option {0}", normalizedArg); return false; } if (!File.Exists(arg)) { Console.WriteLine("Source file '{0}' not found", arg); return false; } if (sourceFile != null) { Console.WriteLine("Multiple source files specified. Only one file is supported"); return false; } sourceFile = arg; break; } } if (flags.HasFlag(CompilationFlags.Platform32) && flags.HasFlag(CompilationFlags.Platform64)) { Console.WriteLine("Both 32-bit and 64-bit platforms specified. Only one platform is supported"); return false; } if (!flags.HasFlag(CompilationFlags.Platform32) && !flags.HasFlag(CompilationFlags.Platform64)) flags |= CompilationFlags.Platform32; if (sourceFile == null) return false; return true; }
private static bool TryParseArgs(string[] args, out string sourceFile, out CompilationFlags flags) { sourceFile = null; flags = 0; if (args.Length < 1) { return(false); } foreach (string arg in args) { string normalizedArg = arg.ToUpper(); switch (normalizedArg) { case "/32": flags |= CompilationFlags.Platform32; break; case "/64": flags |= CompilationFlags.Platform64; break; case "/NODEBUG": flags |= CompilationFlags.NoDebug; break; case "/ASM": flags |= CompilationFlags.Assembly; break; default: if (normalizedArg.StartsWith("/")) { Console.WriteLine("Unrecognized option {0}", normalizedArg); return(false); } if (!File.Exists(arg)) { Console.WriteLine("Source file '{0}' not found", arg); return(false); } if (sourceFile != null) { Console.WriteLine("Multiple source files specified. Only one file is supported"); return(false); } sourceFile = arg; break; } } if (flags.HasFlag(CompilationFlags.Platform32) && flags.HasFlag(CompilationFlags.Platform64)) { Console.WriteLine("Both 32-bit and 64-bit platforms specified. Only one platform is supported"); return(false); } if (!flags.HasFlag(CompilationFlags.Platform32) && !flags.HasFlag(CompilationFlags.Platform64)) { flags |= CompilationFlags.Platform32; } if (sourceFile == null) { return(false); } return(true); }