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));
        }
Example #2
0
        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;
        }
 /// <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;
 }
        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);
        }