Beispiel #1
0
        public static int Main(string[] args)
        {
            DebugHelper.HandleDebugSwitch(ref args);

            CommonCompilerOptions commonOptions = null;
            string tempOutDir = null;
            IReadOnlyList <string> references = Array.Empty <string>();
            IReadOnlyList <string> resources  = Array.Empty <string>();
            IReadOnlyList <string> sources    = Array.Empty <string>();
            string outputName = null;

            try
            {
                ArgumentSyntax.Parse(args, syntax =>
                {
                    commonOptions = CommonCompilerOptionsExtensions.Parse(syntax);

                    syntax.DefineOption("temp-output", ref tempOutDir, "Compilation temporary directory");

                    syntax.DefineOption("out", ref outputName, "Name of the output assembly");

                    syntax.DefineOptionList("reference", ref references, "Path to a compiler metadata reference");

                    syntax.DefineOptionList("resource", ref resources, "Resources to embed");

                    syntax.DefineParameterList("source-files", ref sources, "Compilation sources");

                    if (tempOutDir == null)
                    {
                        syntax.ReportError("Option '--temp-output' is required");
                    }
                });
            }
            catch (ArgumentSyntaxException)
            {
                return(ExitFailed);
            }

            var translated = TranslateCommonOptions(commonOptions);

            var allArgs = new List <string>(translated);

            allArgs.AddRange(GetDefaultOptions());

            if (outputName != null)
            {
                allArgs.Add($"-out:\"{outputName}\"");
            }

            allArgs.AddRange(references.Select(r => $"-r:\"{r}\""));
            allArgs.AddRange(resources.Select(resource => $"-resource:{resource}"));
            allArgs.AddRange(sources.Select(s => $"\"{s}\""));

            var rsp = Path.Combine(tempOutDir, "dotnet-compile-csc.rsp");

            File.WriteAllLines(rsp, allArgs, Encoding.UTF8);

            // Execute CSC!
            var result = RunCsc($"-noconfig @\"{rsp}\"")
                         .ForwardStdErr()
                         .ForwardStdOut()
                         .Execute();

            return(result.ExitCode);
        }
Beispiel #2
0
        public static int Run(string[] args)
        {
            DebugHelper.HandleDebugSwitch(ref args);

            CommonCompilerOptions commonOptions       = null;
            AssemblyInfoOptions   assemblyInfoOptions = null;
            string tempOutDir = null;
            IReadOnlyList <string> references = Array.Empty <string>();
            IReadOnlyList <string> resources  = Array.Empty <string>();
            IReadOnlyList <string> sources    = Array.Empty <string>();
            string outputName = null;
            var    help       = false;
            var    returnCode = 0;
            string helpText   = null;

            try
            {
                ArgumentSyntax.Parse(args, syntax =>
                {
                    syntax.HandleHelp   = false;
                    syntax.HandleErrors = false;

                    commonOptions = CommonCompilerOptionsExtensions.Parse(syntax);

                    assemblyInfoOptions = AssemblyInfoOptions.Parse(syntax);

                    syntax.DefineOption("temp-output", ref tempOutDir, "Compilation temporary directory");

                    syntax.DefineOption("out", ref outputName, "Name of the output assembly");

                    syntax.DefineOptionList("reference", ref references, "Path to a compiler metadata reference");

                    syntax.DefineOptionList("resource", ref resources, "Resources to embed");

                    syntax.DefineOption("h|help", ref help, "Help for compile native.");

                    syntax.DefineParameterList("source-files", ref sources, "Compilation sources");

                    helpText = syntax.GetHelpText();

                    if (tempOutDir == null)
                    {
                        syntax.ReportError("Option '--temp-output' is required");
                    }
                });
            }
            catch (ArgumentSyntaxException exception)
            {
                Console.Error.WriteLine(exception.Message);
                help       = true;
                returnCode = ExitFailed;
            }

            if (help)
            {
                Console.WriteLine(helpText);

                return(returnCode);
            }


            // TODO less hacky
            bool targetNetCore =
                commonOptions.Defines.Contains("DNXCORE50") ||
                commonOptions.Defines.Where(d => d.StartsWith("NETSTANDARDAPP1_")).Any() ||
                commonOptions.Defines.Where(d => d.StartsWith("NETSTANDARD1_")).Any();

            // FSC arguments
            var allArgs = new List <string>();

            //HACK fsc raise error FS0208 if target exe doesnt have extension .exe
            bool   hackFS0208         = targetNetCore && commonOptions.EmitEntryPoint == true;
            string originalOutputName = outputName;

            if (outputName != null)
            {
                if (hackFS0208)
                {
                    outputName = Path.ChangeExtension(outputName, ".exe");
                }

                allArgs.Add($"--out:{outputName}");
            }

            //let's pass debugging type only if options.DebugType is specified, until
            //portablepdb are confirmed to work.
            //so it's possibile to test portable pdb without breaking existing build
            if (string.IsNullOrEmpty(commonOptions.DebugType))
            {
                //debug info (only windows pdb supported, not portablepdb)
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    allArgs.Add("--debug");
                    //TODO check if full or pdbonly
                    allArgs.Add("--debug:pdbonly");
                }
                else
                {
                    allArgs.Add("--debug-");
                }
            }
            else
            {
                allArgs.Add("--debug");
                allArgs.Add($"--debug:{commonOptions.DebugType}");
            }

            // Default options
            allArgs.Add("--noframework");
            allArgs.Add("--nologo");
            allArgs.Add("--simpleresolution");
            allArgs.Add("--nocopyfsharpcore");

            // project.json compilationOptions
            if (commonOptions.Defines != null)
            {
                allArgs.AddRange(commonOptions.Defines.Select(def => $"--define:{def}"));
            }

            if (commonOptions.GenerateXmlDocumentation == true)
            {
                allArgs.Add($"--doc:{Path.ChangeExtension(outputName, "xml")}");
            }

            if (commonOptions.KeyFile != null)
            {
                allArgs.Add($"--keyfile:{commonOptions.KeyFile}");
            }

            if (commonOptions.Optimize == true)
            {
                allArgs.Add("--optimize+");
            }

            //--resource doesnt expect "
            //bad: --resource:"path/to/file",name
            //ok:  --resource:path/to/file,name
            allArgs.AddRange(resources.Select(resource => $"--resource:{resource.Replace("\"", "")}"));

            allArgs.AddRange(references.Select(r => $"-r:{r}"));

            if (commonOptions.EmitEntryPoint != true)
            {
                allArgs.Add("--target:library");
            }
            else
            {
                allArgs.Add("--target:exe");

                //HACK we need default.win32manifest for exe
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    var win32manifestPath = Path.Combine(AppContext.BaseDirectory, "default.win32manifest");
                    allArgs.Add($"--win32manifest:{win32manifestPath}");
                }
            }

            if (commonOptions.SuppressWarnings != null)
            {
                allArgs.Add("--nowarn:" + string.Join(",", commonOptions.SuppressWarnings.ToArray()));
            }

            if (commonOptions.LanguageVersion != null)
            {
                // Not used in fsc
            }

            if (commonOptions.Platform != null)
            {
                allArgs.Add($"--platform:{commonOptions.Platform}");
            }

            if (commonOptions.AllowUnsafe == true)
            {
            }

            if (commonOptions.WarningsAsErrors == true)
            {
                allArgs.Add("--warnaserror");
            }

            //set target framework
            if (targetNetCore)
            {
                allArgs.Add("--targetprofile:netcore");
            }

            if (commonOptions.DelaySign == true)
            {
                allArgs.Add("--delaysign+");
            }

            if (commonOptions.PublicSign == true)
            {
            }

            if (commonOptions.AdditionalArguments != null)
            {
                // Additional arguments are added verbatim
                allArgs.AddRange(commonOptions.AdditionalArguments);
            }

            // Generate assembly info
            var assemblyInfo = Path.Combine(tempOutDir, $"dotnet-compile.assemblyinfo.fs");

            File.WriteAllText(assemblyInfo, AssemblyInfoFileGenerator.GenerateFSharp(assemblyInfoOptions));

            //source files + assemblyInfo
            allArgs.AddRange(GetSourceFiles(sources, assemblyInfo).ToArray());

            //TODO check the switch enabled in fsproj in RELEASE and DEBUG configuration

            var rsp = Path.Combine(tempOutDir, "dotnet-compile-fsc.rsp");

            File.WriteAllLines(rsp, allArgs, Encoding.UTF8);

            // Execute FSC!
            var result = RunFsc(new List <string> {
                $"@{rsp}"
            })
                         .ForwardStdErr()
                         .ForwardStdOut()
                         .Execute();

            bool successFsc = result.ExitCode == 0;

            if (hackFS0208 && File.Exists(outputName))
            {
                if (File.Exists(originalOutputName))
                {
                    File.Delete(originalOutputName);
                }
                File.Move(outputName, originalOutputName);
            }

            //HACK dotnet build require a pdb (crash without), fsc atm cant generate a portable pdb, so an empty pdb is created
            string pdbPath = Path.ChangeExtension(outputName, ".pdb");

            if (successFsc && !File.Exists(pdbPath))
            {
                File.WriteAllBytes(pdbPath, Array.Empty <byte>());
            }

            return(result.ExitCode);
        }
Beispiel #3
0
        public static int Main(string[] args)
        {
            DebugHelper.HandleDebugSwitch(ref args);

            CommonCompilerOptions commonOptions       = null;
            AssemblyInfoOptions   assemblyInfoOptions = null;
            string tempOutDir = null;
            IReadOnlyList <string> references = Array.Empty <string>();
            IReadOnlyList <string> resources  = Array.Empty <string>();
            IReadOnlyList <string> sources    = Array.Empty <string>();
            string outputName = null;
            var    help       = false;
            var    returnCode = 0;
            string helpText   = null;

            try
            {
                ArgumentSyntax.Parse(args, syntax =>
                {
                    syntax.HandleHelp   = false;
                    syntax.HandleErrors = false;

                    commonOptions = CommonCompilerOptionsExtensions.Parse(syntax);

                    assemblyInfoOptions = AssemblyInfoOptions.Parse(syntax);

                    syntax.DefineOption("temp-output", ref tempOutDir, "Compilation temporary directory");

                    syntax.DefineOption("out", ref outputName, "Name of the output assembly");

                    syntax.DefineOptionList("reference", ref references, "Path to a compiler metadata reference");

                    syntax.DefineOptionList("resource", ref resources, "Resources to embed");

                    syntax.DefineOption("h|help", ref help, "Help for compile native.");

                    syntax.DefineParameterList("source-files", ref sources, "Compilation sources");

                    helpText = syntax.GetHelpText();

                    if (tempOutDir == null)
                    {
                        syntax.ReportError("Option '--temp-output' is required");
                    }
                });
            }
            catch (ArgumentSyntaxException exception)
            {
                Console.Error.WriteLine(exception.Message);
                help       = true;
                returnCode = ExitFailed;
            }

            if (help)
            {
                Console.WriteLine(helpText);

                return(returnCode);
            }

            var translated = TranslateCommonOptions(commonOptions, outputName);

            var allArgs = new List <string>(translated);

            allArgs.AddRange(GetDefaultOptions());

            // Generate assembly info
            var assemblyInfo = Path.Combine(tempOutDir, $"dotnet-compile.assemblyinfo.cs");

            File.WriteAllText(assemblyInfo, AssemblyInfoFileGenerator.Generate(assemblyInfoOptions, sources));
            allArgs.Add($"\"{assemblyInfo}\"");

            if (outputName != null)
            {
                allArgs.Add($"-out:\"{outputName}\"");
            }

            allArgs.AddRange(references.Select(r => $"-r:\"{r}\""));
            allArgs.AddRange(resources.Select(resource => $"-resource:{resource}"));
            allArgs.AddRange(sources.Select(s => $"\"{s}\""));

            var rsp = Path.Combine(tempOutDir, "dotnet-compile-csc.rsp");

            File.WriteAllLines(rsp, allArgs, Encoding.UTF8);

            // Execute CSC!
            var result = RunCsc($"-noconfig @\"{rsp}\"")
                         .ForwardStdErr()
                         .ForwardStdOut()
                         .Execute();

            return(result.ExitCode);
        }
Beispiel #4
0
        public static int Run(string[] args)
        {
            DebugHelper.HandleDebugSwitch(ref args);

            CommonCompilerOptions commonOptions       = null;
            AssemblyInfoOptions   assemblyInfoOptions = null;
            string tempOutDir = null;
            IReadOnlyList <string> references = Array.Empty <string>();
            IReadOnlyList <string> resources  = Array.Empty <string>();
            IReadOnlyList <string> sources    = Array.Empty <string>();
            string outputName = null;
            var    help       = false;
            var    returnCode = 0;
            string helpText   = null;

            try
            {
                ArgumentSyntax.Parse(args, syntax =>
                {
                    syntax.HandleHelp   = false;
                    syntax.HandleErrors = false;

                    commonOptions = CommonCompilerOptionsExtensions.Parse(syntax);

                    assemblyInfoOptions = AssemblyInfoOptions.Parse(syntax);

                    syntax.DefineOption("temp-output", ref tempOutDir, "Compilation temporary directory");

                    syntax.DefineOption("out", ref outputName, "Name of the output assembly");

                    syntax.DefineOptionList("reference", ref references, "Path to a compiler metadata reference");

                    syntax.DefineOptionList("resource", ref resources, "Resources to embed");

                    syntax.DefineOption("h|help", ref help, "Help for compile native.");

                    syntax.DefineParameterList("source-files", ref sources, "Compilation sources");

                    helpText = syntax.GetHelpText();

                    if (tempOutDir == null)
                    {
                        syntax.ReportError("Option '--temp-output' is required");
                    }
                });
            }
            catch (ArgumentSyntaxException exception)
            {
                Console.Error.WriteLine(exception.Message);
                help       = true;
                returnCode = ExitFailed;
            }

            if (help)
            {
                Console.WriteLine(helpText);

                return(returnCode);
            }

            var translated = TranslateCommonOptions(commonOptions, outputName);

            var allArgs = new List <string>(translated);

            allArgs.AddRange(GetDefaultOptions());

            // Generate assembly info
            var assemblyInfo = Path.Combine(tempOutDir, $"dotnet-compile.assemblyinfo.fs");

            File.WriteAllText(assemblyInfo, AssemblyInfoFileGenerator.GenerateFSharp(assemblyInfoOptions));
            allArgs.Add($"{assemblyInfo}");

            bool targetNetCore = commonOptions.Defines.Contains("DNXCORE50");

            //HACK fsc raise error FS0208 if target exe doesnt have extension .exe
            bool   hackFS0208         = targetNetCore && commonOptions.EmitEntryPoint == true;
            string originalOutputName = outputName;

            if (outputName != null)
            {
                if (hackFS0208)
                {
                    outputName = Path.ChangeExtension(outputName, ".exe");
                }

                allArgs.Add($"--out:{outputName}");
            }

            //set target framework
            if (targetNetCore)
            {
                allArgs.Add("--targetprofile:netcore");
            }

            allArgs.AddRange(references.Select(r => $"-r:{r}"));
            allArgs.AddRange(resources.Select(resource => $"--resource:{resource}"));
            allArgs.AddRange(sources.Select(s => $"{s}"));

            var rsp = Path.Combine(tempOutDir, "dotnet-compile-fsc.rsp");

            File.WriteAllLines(rsp, allArgs, Encoding.UTF8);

            // Execute FSC!
            var result = RunFsc(allArgs)
                         .ForwardStdErr()
                         .ForwardStdOut()
                         .Execute();

            bool successFsc = result.ExitCode == 0;

            if (hackFS0208 && File.Exists(outputName))
            {
                if (File.Exists(originalOutputName))
                {
                    File.Delete(originalOutputName);
                }
                File.Move(outputName, originalOutputName);
            }

            //HACK dotnet build require a pdb (crash without), fsc atm cant generate a portable pdb, so an empty pdb is created
            string pdbPath = Path.ChangeExtension(outputName, ".pdb");

            if (successFsc && !File.Exists(pdbPath))
            {
                File.WriteAllBytes(pdbPath, Array.Empty <byte>());
            }

            return(result.ExitCode);
        }