示例#1
0
        public int Execute()
        {
            var inputResourceFiles = Args.Select(ParseInputFile).ToArray();
            var outputResourceFile = ResourceFile.Create(OutputFileName);

            switch (outputResourceFile.Type)
            {
            case ResourceFileType.Dll:
                using (var outputStream = outputResourceFile.File.Create())
                {
                    var metadata = new AssemblyInfoOptions
                    {
                        Culture         = AssemblyCulture,
                        AssemblyVersion = AssemblyVersion,
                    };

                    ResourceAssemblyGenerator.Generate(inputResourceFiles,
                                                       outputStream,
                                                       metadata,
                                                       Path.GetFileNameWithoutExtension(outputResourceFile.File.Name),
                                                       CompilationReferences.ToArray()
                                                       );
                }
                break;

            case ResourceFileType.Resources:
                using (var outputStream = outputResourceFile.File.Create())
                {
                    if (inputResourceFiles.Length > 1)
                    {
                        Reporter.Error.WriteLine("Only one input file required when generating .resource output");
                        return(1);
                    }
                    ResourcesFileGenerator.Generate(inputResourceFiles.Single().Resource, outputStream);
                }
                break;

            default:
                Reporter.Error.WriteLine("Resx output type not supported");
                return(1);
            }

            return(0);
        }
示例#2
0
        public static bool GenerateCultureResourceAssemblies(Project project, List <CompilerUtility.CultureResgenIO> cultureResgenFiles, List <string> referencePaths, IList <string> diagnostics)
        {
            foreach (var resgenFile in cultureResgenFiles)
            {
                var resourceOutputPath = Path.GetDirectoryName(resgenFile.OutputFile);
                Directory.CreateDirectory(resourceOutputPath);

                var inputResourceFiles = resgenFile.InputFileToMetadata
                                         .Select(fileToMetadata => new ResourceSource(ResourceFile.Create(fileToMetadata.Key), fileToMetadata.Value))
                                         .ToArray();

                var outputResourceFile = ResourceFile.Create(resgenFile.OutputFile);

                if (outputResourceFile.Type != ResourceFileType.Dll)
                {
                    diagnostics.Add("Resource output type not supported");
                    return(false);
                }

                using (var outputStream = outputResourceFile.File.Create())
                {
                    var metadata = new AssemblyInfoOptions
                    {
                        Culture         = resgenFile.Culture,
                        AssemblyVersion = project.Version.Version.ToString(),
                    };

                    ResourceAssemblyGenerator.Generate(inputResourceFiles,
                                                       outputStream,
                                                       metadata,
                                                       Path.GetFileNameWithoutExtension(outputResourceFile.File.Name),
                                                       referencePaths.ToArray(),
                                                       diagnostics);
                }
            }

            return(true);
        }
示例#3
0
        public static int Run(string[] args)
        {
            DebugHelper.HandleDebugSwitch(ref args);

            CommandLineApplication app = new CommandLineApplication();

            app.Name        = "dotnet compile-csc-linq-rewrite";
            app.FullName    = ".NET C# Compiler with LINQ rewrite";
            app.Description = "C# Compiler for the .NET Platform with LINQ rewrite optimizations";

            app.HandleResponseFiles = true;
            app.HelpOption("-h|--help");

            CommonCompilerOptionsCommandLine commonCompilerCommandLine = CommonCompilerOptionsCommandLine.AddOptions(app);
            AssemblyInfoOptionsCommandLine   assemblyInfoCommandLine   = AssemblyInfoOptionsCommandLine.AddOptions(app);

            CommandOption   tempOutput = app.Option("--temp-output <arg>", "Compilation temporary directory", CommandOptionType.SingleValue);
            CommandOption   outputName = app.Option("--out <arg>", "Name of the output assembly", CommandOptionType.SingleValue);
            CommandOption   references = app.Option("--reference <arg>...", "Path to a compiler metadata reference", CommandOptionType.MultipleValue);
            CommandOption   analyzers  = app.Option("--analyzer <arg>...", "Path to an analyzer assembly", CommandOptionType.MultipleValue);
            CommandOption   resources  = app.Option("--resource <arg>...", "Resources to embed", CommandOptionType.MultipleValue);
            CommandArgument sources    = app.Argument("<source-files>...", "Compilation sources", multipleValues: true);

            app.OnExecute(() =>
            {
                if (!tempOutput.HasValue())
                {
                    Reporter.Error.WriteLine("Option '--temp-output' is required");
                    return(ExitFailed);
                }

                CommonCompilerOptions commonOptions = commonCompilerCommandLine.GetOptionValues();

                AssemblyInfoOptions assemblyInfoOptions = assemblyInfoCommandLine.GetOptionValues();

                var translated = TranslateCommonOptions(commonOptions, outputName.Value());

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

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

                File.WriteAllText(assemblyInfo, AssemblyInfoFileGenerator.GenerateCSharp(assemblyInfoOptions, sources.Values));

                allArgs.Add($"\"{assemblyInfo}\"");

                if (outputName.HasValue())
                {
                    allArgs.Add($"-out:\"{outputName.Value()}\"");
                }

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

                // Resource has two parts separated by a comma
                // Only the first should be quoted. This is handled
                // in dotnet-compile where the information is present.
                allArgs.AddRange(resources.Values.Select(resource => $"-resource:{resource}"));

                allArgs.AddRange(sources.Values.Select(s => $"\"{s}\""));

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

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

                // Execute CSC!

                return(Microsoft.CodeAnalysis.CSharp.CommandLine.ProgramLinqRewrite.MainInternal(new string[] { $"-noconfig", "@" + $"{rsp}" }));
            });

            try
            {
                return(app.Execute(args));
            }
            catch (Exception ex)
            {
//#if DEBUG
                Reporter.Error.WriteLine(ex.ToString());
//#else
//                Reporter.Error.WriteLine(ex.Message);
///#endif
                return(ExitFailed);
            }
        }
示例#4
0
        public override bool Compile(ProjectContext context, BuildCommandApp args)
        {
            // Set up Output Paths
            var outputPaths            = context.GetOutputPaths(args.ConfigValue, args.BuildBasePathValue);
            var outputPath             = outputPaths.CompilationOutputPath;
            var intermediateOutputPath = outputPaths.IntermediateOutputDirectoryPath;

            Directory.CreateDirectory(outputPath);
            Directory.CreateDirectory(intermediateOutputPath);

            // Create the library exporter
            var exporter = context.CreateExporter(args.ConfigValue, args.BuildBasePathValue);

            // Gather exports for the project
            var dependencies = exporter.GetDependencies().ToList();

            Reporter.Output.WriteLine($"Compiling {context.RootProject.Identity.Name.Yellow()} for {context.TargetFramework.DotNetFrameworkName.Yellow()}");
            var sw = Stopwatch.StartNew();

            var diagnostics = new List <DiagnosticMessage>();
            var missingFrameworkDiagnostics = new List <DiagnosticMessage>();

            // Collect dependency diagnostics
            foreach (var diag in context.LibraryManager.GetAllDiagnostics())
            {
                if (diag.ErrorCode == ErrorCodes.DOTNET1011 ||
                    diag.ErrorCode == ErrorCodes.DOTNET1012)
                {
                    missingFrameworkDiagnostics.Add(diag);
                }

                diagnostics.Add(diag);
            }

            if (diagnostics.Any(d => d.Severity == DiagnosticMessageSeverity.Error))
            {
                // We got an unresolved dependency or missing framework. Don't continue the compilation.
                PrintSummary(diagnostics, sw);
                return(false);
            }

            // Get compilation options
            var outputName = outputPaths.CompilationFiles.Assembly;

            // Assemble args
            var compilerArgs = new List <string>()
            {
                $"--temp-output:{intermediateOutputPath}",
                $"--out:{outputName}"
            };

            var compilationOptions = context.ResolveCompilationOptions(args.ConfigValue);

            // Set default platform if it isn't already set and we're on desktop
            if (compilationOptions.EmitEntryPoint == true && string.IsNullOrEmpty(compilationOptions.Platform) && context.TargetFramework.IsDesktop())
            {
                // See https://github.com/dotnet/cli/issues/2428 for more details.
                compilationOptions.Platform = RuntimeInformation.ProcessArchitecture == Architecture.X64 ?
                                              "x64" : "anycpu32bitpreferred";
            }

            var languageId = CompilerUtil.ResolveLanguageId(context);

            var references = new List <string>();

            // Add compilation options to the args
            compilerArgs.AddRange(compilationOptions.SerializeToArgs());

            // Add metadata options
            compilerArgs.AddRange(AssemblyInfoOptions.SerializeToArgs(AssemblyInfoOptions.CreateForProject(context)));

            foreach (var dependency in dependencies)
            {
                references.AddRange(dependency.CompilationAssemblies.Select(r => r.ResolvedPath));

                compilerArgs.AddRange(dependency.SourceReferences.Select(s => s.GetTransformedFile(intermediateOutputPath)));

                foreach (var resourceFile in dependency.EmbeddedResources)
                {
                    var transformedResource = resourceFile.GetTransformedFile(intermediateOutputPath);
                    var resourceName        = ResourceManifestName.CreateManifestName(
                        Path.GetFileName(resourceFile.ResolvedPath), compilationOptions.OutputName);
                    compilerArgs.Add($"--resource:\"{transformedResource}\",{resourceName}");
                }

                // Add analyzer references
                compilerArgs.AddRange(dependency.AnalyzerReferences
                                      .Where(a => a.AnalyzerLanguage == languageId)
                                      .Select(a => $"--analyzer:{a.AssemblyPath}"));
            }

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

            if (compilationOptions.PreserveCompilationContext == true)
            {
                var allExports        = exporter.GetAllExports().ToList();
                var dependencyContext = new DependencyContextBuilder().Build(compilationOptions,
                                                                             allExports,
                                                                             allExports,
                                                                             false, // For now, just assume non-portable mode in the legacy deps file (this is going away soon anyway)
                                                                             context.TargetFramework,
                                                                             context.RuntimeIdentifier ?? string.Empty);

                var writer       = new DependencyContextWriter();
                var depsJsonFile = Path.Combine(intermediateOutputPath, compilationOptions.OutputName + "dotnet-compile.deps.json");
                using (var fileStream = File.Create(depsJsonFile))
                {
                    writer.Write(dependencyContext, fileStream);
                }

                compilerArgs.Add($"--resource:\"{depsJsonFile}\",{compilationOptions.OutputName}.deps.json");
            }

            if (!AddNonCultureResources(context.ProjectFile, compilerArgs, intermediateOutputPath, compilationOptions))
            {
                return(false);
            }
            // Add project source files
            var sourceFiles = CompilerUtil.GetCompilationSources(context, compilationOptions);

            compilerArgs.AddRange(sourceFiles);

            var compilerName = compilationOptions.CompilerName;

            // Write RSP file
            var rsp = Path.Combine(intermediateOutputPath, $"dotnet-compile.rsp");

            File.WriteAllLines(rsp, compilerArgs);

            // Run pre-compile event
            var contextVariables = new Dictionary <string, string>()
            {
                { "compile:TargetFramework", context.TargetFramework.GetShortFolderName() },
                { "compile:FullTargetFramework", context.TargetFramework.DotNetFrameworkName },
                { "compile:Configuration", args.ConfigValue },
                { "compile:OutputFile", outputName },
                { "compile:OutputDir", outputPath.TrimEnd('\\', '/') },
                { "compile:ResponseFile", rsp }
            };

            if (context.ProjectFile.HasRuntimeOutput(args.ConfigValue))
            {
                var runtimeContext    = args.Workspace.GetRuntimeContext(context, args.GetRuntimes());
                var runtimeOutputPath = runtimeContext.GetOutputPaths(args.ConfigValue, args.BuildBasePathValue, args.OutputValue);

                contextVariables.Add(
                    "compile:RuntimeOutputDir",
                    runtimeOutputPath.RuntimeOutputPath.TrimEnd('\\', '/'));

                contextVariables.Add(
                    "compile:RuntimeIdentifier",
                    runtimeContext.RuntimeIdentifier);
            }

            _scriptRunner.RunScripts(context, ScriptNames.PreCompile, contextVariables);

            // Cache the reporters before invoking the command in case it is a built-in command, which replaces
            // the static Reporter instances.
            Reporter errorReporter  = Reporter.Error;
            Reporter outputReporter = Reporter.Output;

            CommandResult result = _commandFactory.Create($"compile-{compilerName}", new[] { $"@{rsp}" })
                                   .WorkingDirectory(context.ProjectDirectory)
                                   .OnErrorLine(line => HandleCompilerOutputLine(line, context, diagnostics, errorReporter))
                                   .OnOutputLine(line => HandleCompilerOutputLine(line, context, diagnostics, outputReporter))
                                   .Execute();

            // Run post-compile event
            contextVariables["compile:CompilerExitCode"] = result.ExitCode.ToString();
            _scriptRunner.RunScripts(context, ScriptNames.PostCompile, contextVariables);

            var success = result.ExitCode == 0;

            if (!success)
            {
                Reporter.Error.WriteLine($"{result.StartInfo.FileName} {result.StartInfo.Arguments} returned Exit Code {result.ExitCode}");
            }

            if (success)
            {
                success &= GenerateCultureResourceAssemblies(context.ProjectFile, dependencies, outputPath, compilationOptions);
            }

            return(PrintSummary(diagnostics, sw, success));
        }
示例#5
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;

            try
            {
                ArgumentSyntax.Parse(args, syntax =>
                {
                    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.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());

            // 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);
        }
        internal bool CompileInternal(ProjectContext context, string config, string probingFolderPath)
        {
            // Check if ambient library
            if (AmbientLibraries.Contains(context.ProjectName()))
            {
                return(true);
            }

            bool compilationResult;

            // Check if already compiled
            if (_compiledLibraries.TryGetValue(context.ProjectName(), out compilationResult))
            {
                return(compilationResult);
            }

            // Get compilation options and source files
            var compilationOptions = context.ResolveCompilationOptions(config);
            var projectSourceFiles = CompilerUtility.GetCompilationSources(context, compilationOptions);

            // Check if precompiled
            if (!projectSourceFiles.Any())
            {
                return(_compiledLibraries[context.ProjectName()] = true);
            }

            // Set up Output Paths
            var outputPaths            = context.GetOutputPaths(config);
            var outputPath             = outputPaths.CompilationOutputPath;
            var intermediateOutputPath = outputPaths.IntermediateOutputDirectoryPath;

            Directory.CreateDirectory(outputPath);
            Directory.CreateDirectory(intermediateOutputPath);

            // Create the library exporter
            var exporter = context.CreateExporter(config);

            // Gather exports for the project
            var dependencies = exporter.GetDependencies().ToList();

            // Get compilation options
            var outputName = outputPaths.CompilationFiles.Assembly;

            // Set default platform if it isn't already set and we're on desktop
            if (compilationOptions.EmitEntryPoint == true && String.IsNullOrEmpty(compilationOptions.Platform) && context.TargetFramework.IsDesktop())
            {
                // See https://github.com/dotnet/cli/issues/2428 for more details.
                compilationOptions.Platform = RuntimeInformation.ProcessArchitecture == Architecture.X64 ?
                                              "x64" : "anycpu32bitpreferred";
            }

            var references  = new List <string>();
            var sourceFiles = new List <string>();
            var resources   = new List <string>();

            // Get the runtime directory
            var runtimeDirectory = Paths.GetParentFolderPath(EntryAssembly.Location);

            foreach (var dependency in dependencies)
            {
                sourceFiles.AddRange(dependency.SourceReferences.Select(s => s.GetTransformedFile(intermediateOutputPath)));

                foreach (var resourceFile in dependency.EmbeddedResources)
                {
                    var transformedResource = resourceFile.GetTransformedFile(intermediateOutputPath);
                    var resourceName        = ResourceManifestName.CreateManifestName(
                        Path.GetFileName(resourceFile.ResolvedPath), compilationOptions.OutputName);
                    resources.Add($"\"{transformedResource}\",{resourceName}");
                }

                var library = dependency.Library as ProjectDescription;
                var package = dependency.Library as PackageDescription;

                // Compile other referenced libraries
                if (library != null && !AmbientLibraries.Contains(library.Identity.Name) && dependency.CompilationAssemblies.Any())
                {
                    if (!_compiledLibraries.ContainsKey(library.Identity.Name))
                    {
                        var projectContext = GetProjectContextFromPath(library.Project.ProjectDirectory);

                        if (projectContext != null)
                        {
                            // Right now, if !success we try to use the last build
                            var success = Compile(projectContext, config, probingFolderPath);
                        }
                    }
                }

                // Check for an unresolved library
                if (library != null && !library.Resolved)
                {
                    var assetFileName = CompilerUtility.GetAssemblyFileName(library.Identity.Name);

                    // Search in the runtime directory
                    var assetResolvedPath = Path.Combine(runtimeDirectory, assetFileName);

                    if (!File.Exists(assetResolvedPath))
                    {
                        // Fallback to the project output path or probing folder
                        assetResolvedPath = ResolveAssetPath(outputPath, probingFolderPath, assetFileName);

                        if (String.IsNullOrEmpty(assetResolvedPath))
                        {
                            // Fallback to this (possible) precompiled module bin folder
                            var path = Path.Combine(Paths.GetParentFolderPath(library.Path), Constants.BinDirectoryName, assetFileName);
                            assetResolvedPath = File.Exists(path) ? path : null;
                        }
                    }

                    if (!String.IsNullOrEmpty(assetResolvedPath))
                    {
                        references.Add(assetResolvedPath);
                    }
                }
                // Check for an unresolved package
                else if (package != null && !package.Resolved)
                {
                    var    runtimeAssets   = new HashSet <string>(package.RuntimeAssemblies.Select(x => x.Path), StringComparer.OrdinalIgnoreCase);
                    string fallbackBinPath = null;

                    foreach (var asset in package.CompileTimeAssemblies)
                    {
                        var assetFileName  = Path.GetFileName(asset.Path);
                        var isRuntimeAsset = runtimeAssets.Contains(asset.Path);

                        // Search in the runtime directory
                        var relativeFolderPath = isRuntimeAsset ? String.Empty : CompilerUtility.RefsDirectoryName;
                        var assetResolvedPath  = Path.Combine(runtimeDirectory, relativeFolderPath, assetFileName);

                        if (!File.Exists(assetResolvedPath))
                        {
                            // Fallback to the project output path or probing folder
                            assetResolvedPath = ResolveAssetPath(outputPath, probingFolderPath, assetFileName, relativeFolderPath);
                        }

                        if (String.IsNullOrEmpty(assetResolvedPath))
                        {
                            if (fallbackBinPath == null)
                            {
                                fallbackBinPath = String.Empty;

                                // Fallback to a (possible) parent precompiled module bin folder
                                var parentBinPaths = CompilerUtility.GetOtherParentProjectsLocations(context, package)
                                                     .Select(x => Path.Combine(x, Constants.BinDirectoryName));

                                foreach (var binaryPath in parentBinPaths)
                                {
                                    var path = Path.Combine(binaryPath, relativeFolderPath, assetFileName);

                                    if (File.Exists(path))
                                    {
                                        assetResolvedPath = path;
                                        fallbackBinPath   = binaryPath;
                                        break;
                                    }
                                }
                            }
                            else if (!String.IsNullOrEmpty(fallbackBinPath))
                            {
                                var path = Path.Combine(fallbackBinPath, relativeFolderPath, assetFileName);
                                assetResolvedPath = File.Exists(path) ? path : null;
                            }
                        }

                        if (!String.IsNullOrEmpty(assetResolvedPath))
                        {
                            references.Add(assetResolvedPath);
                        }
                    }
                }
                // Check for a precompiled library
                else if (library != null && !dependency.CompilationAssemblies.Any())
                {
                    // Search in the project output path or probing folder
                    var assetFileName     = CompilerUtility.GetAssemblyFileName(library.Identity.Name);
                    var assetResolvedPath = ResolveAssetPath(outputPath, probingFolderPath, assetFileName);

                    if (String.IsNullOrEmpty(assetResolvedPath))
                    {
                        // Fallback to this precompiled project output path
                        var path = Path.Combine(CompilerUtility.GetAssemblyFolderPath(library.Project.ProjectDirectory,
                                                                                      config, context.TargetFramework.DotNetFrameworkName), assetFileName);
                        assetResolvedPath = File.Exists(path) ? path : null;
                    }

                    if (!String.IsNullOrEmpty(assetResolvedPath))
                    {
                        references.Add(assetResolvedPath);
                    }
                }
                // Check for a resolved but ambient library (compiled e.g by VS)
                else if (library != null && AmbientLibraries.Contains(library.Identity.Name))
                {
                    // Search in the regular project output path, fallback to the runtime directory
                    references.AddRange(dependency.CompilationAssemblies.Select(r => File.Exists(r.ResolvedPath)
                        ? r.ResolvedPath : Path.Combine(runtimeDirectory, r.FileName)));
                }
                else
                {
                    references.AddRange(dependency.CompilationAssemblies.Select(r => r.ResolvedPath));
                }
            }

            // Check again if already compiled, here through the dependency graph
            if (_compiledLibraries.TryGetValue(context.ProjectName(), out compilationResult))
            {
                return(compilationResult);
            }

            var sw = Stopwatch.StartNew();

            string            depsJsonFile      = null;
            DependencyContext dependencyContext = null;

            // Add dependency context as a resource
            if (compilationOptions.PreserveCompilationContext == true)
            {
                var allExports         = exporter.GetAllExports().ToList();
                var exportsLookup      = allExports.ToDictionary(e => e.Library.Identity.Name);
                var buildExclusionList = context.GetTypeBuildExclusionList(exportsLookup);
                var filteredExports    = allExports
                                         .Where(e => e.Library.Identity.Type.Equals(LibraryType.ReferenceAssembly) ||
                                                !buildExclusionList.Contains(e.Library.Identity.Name));

                dependencyContext = new DependencyContextBuilder().Build(compilationOptions,
                                                                         filteredExports,
                                                                         filteredExports,
                                                                         false, // For now, just assume non-portable mode in the legacy deps file (this is going away soon anyway)
                                                                         context.TargetFramework,
                                                                         context.RuntimeIdentifier ?? string.Empty);

                depsJsonFile = Path.Combine(intermediateOutputPath, compilationOptions.OutputName + "dotnet-compile.deps.json");
                resources.Add($"\"{depsJsonFile}\",{compilationOptions.OutputName}.deps.json");
            }

            // Add project source files
            sourceFiles.AddRange(projectSourceFiles);

            // Add non culture resources
            var resgenFiles = CompilerUtility.GetNonCultureResources(context.ProjectFile, intermediateOutputPath, compilationOptions);

            AddNonCultureResources(resources, resgenFiles);

            var translated = TranslateCommonOptions(compilationOptions, outputName);

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

            allArgs.AddRange(GetDefaultOptions());

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

            allArgs.Add($"\"{assemblyInfo}\"");

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

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

            // Gather all compile IO
            var inputs  = new List <string>();
            var outputs = new List <string>();

            inputs.Add(context.ProjectFile.ProjectFilePath);

            if (context.LockFile != null)
            {
                inputs.Add(context.LockFile.LockFilePath);
            }

            if (context.LockFile.ExportFile != null)
            {
                inputs.Add(context.LockFile.ExportFile.ExportFilePath);
            }

            inputs.AddRange(sourceFiles);
            inputs.AddRange(references);

            inputs.AddRange(resgenFiles.Select(x => x.InputFile));

            var cultureResgenFiles = CompilerUtility.GetCultureResources(context.ProjectFile, outputPath, compilationOptions);

            inputs.AddRange(cultureResgenFiles.SelectMany(x => x.InputFileToMetadata.Keys));

            outputs.AddRange(outputPaths.CompilationFiles.All());
            outputs.AddRange(resgenFiles.Where(x => x.OutputFile != null).Select(x => x.OutputFile));
            //outputs.AddRange(cultureResgenFiles.Where(x => x.OutputFile != null).Select(x => x.OutputFile));

            // Locate RSP file
            var rsp = Path.Combine(intermediateOutputPath, $"dotnet-compile-csc.rsp");

            // Check if there is no need to compile
            if (!CheckMissingIO(inputs, outputs) && !TimestampsChanged(inputs, outputs))
            {
                if (File.Exists(rsp))
                {
                    // Check if the compilation context has been changed
                    var prevInputs = new HashSet <string>(File.ReadAllLines(rsp));
                    var newInputs  = new HashSet <string>(allArgs);

                    if (!prevInputs.Except(newInputs).Any() && !newInputs.Except(prevInputs).Any())
                    {
                        PrintMessage($"{context.ProjectName()}: Previously compiled, skipping dynamic compilation.");
                        return(_compiledLibraries[context.ProjectName()] = true);
                    }
                }
                else
                {
                    // Write RSP file for the next time
                    File.WriteAllLines(rsp, allArgs);

                    PrintMessage($"{context.ProjectName()}:  Previously compiled, skipping dynamic compilation.");
                    return(_compiledLibraries[context.ProjectName()] = true);
                }
            }

            if (!CompilerUtility.GenerateNonCultureResources(context.ProjectFile, resgenFiles, Diagnostics))
            {
                return(_compiledLibraries[context.ProjectName()] = false);
            }

            PrintMessage(String.Format($"{context.ProjectName()}: Dynamic compiling for {context.TargetFramework.DotNetFrameworkName}"));

            // Write the dependencies file
            if (dependencyContext != null)
            {
                var writer = new DependencyContextWriter();
                using (var fileStream = File.Create(depsJsonFile))
                {
                    writer.Write(dependencyContext, fileStream);
                }
            }

            // Write assembly info and RSP files
            var assemblyInfoOptions = AssemblyInfoOptions.CreateForProject(context);

            File.WriteAllText(assemblyInfo, AssemblyInfoFileGenerator.GenerateCSharp(assemblyInfoOptions, sourceFiles));
            File.WriteAllLines(rsp, allArgs);

            // Locate runtime config files
            var runtimeConfigPath    = Path.Combine(runtimeDirectory, EntryAssembly.GetName().Name + FileNameSuffixes.RuntimeConfigJson);
            var cscRuntimeConfigPath = Path.Combine(runtimeDirectory, "csc" + FileNameSuffixes.RuntimeConfigJson);

            // Automatically create the csc runtime config file
            if (Files.IsNewer(runtimeConfigPath, cscRuntimeConfigPath))
            {
                lock (_syncLock)
                {
                    if (Files.IsNewer(runtimeConfigPath, cscRuntimeConfigPath))
                    {
                        File.Copy(runtimeConfigPath, cscRuntimeConfigPath, true);
                    }
                }
            }

            // Locate csc.dll and the csc.exe asset
            var cscDllPath = Path.Combine(runtimeDirectory, CompilerUtility.GetAssemblyFileName("csc"));

            // Search in the runtime directory
            var cscRelativePath = Path.Combine("runtimes", "any", "native", "csc.exe");
            var cscExePath      = Path.Combine(runtimeDirectory, cscRelativePath);

            // Fallback to the packages storage
            if (!File.Exists(cscExePath) && !String.IsNullOrEmpty(context.PackagesDirectory))
            {
                cscExePath = Path.Combine(context.PackagesDirectory, CscLibrary?.Name ?? String.Empty,
                                          CscLibrary?.Version ?? String.Empty, cscRelativePath);
            }

            // Automatically create csc.dll
            if (Files.IsNewer(cscExePath, cscDllPath))
            {
                lock (_syncLock)
                {
                    if (Files.IsNewer(cscExePath, cscDllPath))
                    {
                        File.Copy(cscExePath, cscDllPath, true);
                    }
                }
            }

            // Locate the csc dependencies file
            var cscDepsPath = Path.Combine(runtimeDirectory, "csc.deps.json");

            // Automatically create csc.deps.json
            if (NativePDBWriter != null && Files.IsNewer(cscDllPath, cscDepsPath))
            {
                lock (_syncLock)
                {
                    if (Files.IsNewer(cscDllPath, cscDepsPath))
                    {
                        // Only reference windows native pdb writers
                        var runtimeLibraries = new List <RuntimeLibrary>();
                        runtimeLibraries.Add(NativePDBWriter);

                        DependencyContext cscDependencyContext = new DependencyContext(
                            DependencyContext.Default.Target, CompilationOptions.Default,
                            new List <CompilationLibrary>(), runtimeLibraries,
                            new List <RuntimeFallbacks>());

                        // Write the csc.deps.json file
                        if (cscDependencyContext != null)
                        {
                            var writer = new DependencyContextWriter();
                            using (var fileStream = File.Create(cscDepsPath))
                            {
                                writer.Write(cscDependencyContext, fileStream);
                            }
                        }

                        // Windows native pdb writers are outputed on dotnet publish.
                        // But not on dotnet build during development, we do it here.

                        // Check if there is a packages storage
                        if (!String.IsNullOrEmpty(context.PackagesDirectory))
                        {
                            var assetPaths = NativePDBWriter.NativeLibraryGroups.SelectMany(l => l.AssetPaths);

                            foreach (var assetPath in assetPaths)
                            {
                                // Resolve the pdb writer from the packages storage
                                var pdbResolvedPath = Path.Combine(context.PackagesDirectory,
                                                                   NativePDBWriter.Name, NativePDBWriter.Version, assetPath);

                                var pdbOutputPath = Path.Combine(runtimeDirectory, assetPath);

                                // Store the pdb writer in the runtime directory
                                if (Files.IsNewer(pdbResolvedPath, pdbOutputPath))
                                {
                                    Directory.CreateDirectory(Paths.GetParentFolderPath(pdbOutputPath));
                                    File.Copy(pdbResolvedPath, pdbOutputPath, true);
                                }
                            }
                        }
                    }
                }
            }

            // Execute CSC!
            var result = Command.Create("csc.dll", new string[] { $"-noconfig", "@" + $"{rsp}" })
                         .WorkingDirectory(runtimeDirectory)
                         .OnErrorLine(line => Diagnostics.Add(line))
                         .OnOutputLine(line => Diagnostics.Add(line))
                         .Execute();

            compilationResult = result.ExitCode == 0;

            if (compilationResult)
            {
                compilationResult &= CompilerUtility.GenerateCultureResourceAssemblies(context.ProjectFile, cultureResgenFiles, references, Diagnostics);
            }

            PrintMessage(String.Empty);

            if (compilationResult && Diagnostics.Count == 0)
            {
                PrintMessage($"{context.ProjectName()}: Dynamic compilation succeeded.");
                PrintMessage($"0 Warning(s)");
                PrintMessage($"0 Error(s)");
            }
            else if (compilationResult && Diagnostics.Count > 0)
            {
                PrintMessage($"{context.ProjectName()}: Dynamic compilation succeeded but has warnings.");
                PrintMessage($"0 Error(s)");
            }
            else
            {
                PrintMessage($"{context.ProjectName()}: Dynamic compilation failed.");
            }

            foreach (var diagnostic in Diagnostics)
            {
                PrintMessage(diagnostic);
            }

            PrintMessage($"Time elapsed {sw.Elapsed}");
            PrintMessage(String.Empty);

            return(_compiledLibraries[context.ProjectName()] = compilationResult);
        }
示例#7
0
文件: Program.cs 项目: sethjuarez/cli
        public static int Main(string[] args)
        {
            DebugHelper.HandleDebugSwitch(ref args);

            var app = new CommandLineApplication(false);

            app.Name        = "resgen";
            app.FullName    = "Resource compiler";
            app.Description = "Microsoft (R) .NET Resource Generator";
            app.HelpOption("-h|--help");

            var ouputFile  = app.Option("-o", "Output file name", CommandOptionType.SingleValue);
            var culture    = app.Option("-c", "Ouput assembly culture", CommandOptionType.SingleValue);
            var version    = app.Option("-v", "Ouput assembly version", CommandOptionType.SingleValue);
            var references = app.Option("-r", "Compilation references", CommandOptionType.MultipleValue);
            var inputFiles = app.Argument("<input>", "Input files", true);

            app.OnExecute(() =>
            {
                if (!inputFiles.Values.Any())
                {
                    Reporter.Error.WriteLine("No input files specified");
                    return(1);
                }

                var intputResourceFiles = inputFiles.Values.Select(ParseInputFile).ToArray();
                var outputResourceFile  = ResourceFile.Create(ouputFile.Value());

                switch (outputResourceFile.Type)
                {
                case ResourceFileType.Dll:
                    using (var outputStream = outputResourceFile.File.Create())
                    {
                        var metadata             = new AssemblyInfoOptions();
                        metadata.Culture         = culture.Value();
                        metadata.AssemblyVersion = version.Value();

                        ResourceAssemblyGenerator.Generate(intputResourceFiles,
                                                           outputStream,
                                                           metadata,
                                                           Path.GetFileNameWithoutExtension(outputResourceFile.File.Name),
                                                           references.Values.ToArray()
                                                           );
                    }
                    break;

                case ResourceFileType.Resources:
                    using (var outputStream = outputResourceFile.File.Create())
                    {
                        if (intputResourceFiles.Length > 1)
                        {
                            Reporter.Error.WriteLine("Only one input file required when generating .resource output");
                            return(1);
                        }
                        ResourcesFileGenerator.Generate(intputResourceFiles.Single().Resource, outputStream);
                    }
                    break;

                default:
                    Reporter.Error.WriteLine("Resx output type not supported");
                    return(1);
                }

                return(0);
            });

            try
            {
                return(app.Execute(args));
            }
            catch (Exception ex)
            {
#if DEBUG
                Reporter.Error.WriteLine(ex.ToString());
#else
                Reporter.Error.WriteLine(ex.Message);
#endif
                return(1);
            }
        }
示例#8
0
文件: Program.cs 项目: NabidAlam/cli
        private static bool CompileProject(ProjectContext context, string configuration, string outputPath, string intermediateOutputPath, List <LibraryExport> dependencies, bool noHost)
        {
            Reporter.Output.WriteLine($"Compiling {context.RootProject.Identity.Name.Yellow()} for {context.TargetFramework.DotNetFrameworkName.Yellow()}");
            var sw = Stopwatch.StartNew();

            var diagnostics = new List <DiagnosticMessage>();
            var missingFrameworkDiagnostics = new List <DiagnosticMessage>();

            // Collect dependency diagnostics
            foreach (var diag in context.LibraryManager.GetAllDiagnostics())
            {
                if (diag.ErrorCode == ErrorCodes.DOTNET1011 ||
                    diag.ErrorCode == ErrorCodes.DOTNET1012)
                {
                    missingFrameworkDiagnostics.Add(diag);
                }

                diagnostics.Add(diag);
            }

            if (missingFrameworkDiagnostics.Count > 0)
            {
                // The framework isn't installed so we should short circuit the rest of the compilation
                // so we don't get flooded with errors
                PrintSummary(missingFrameworkDiagnostics, sw);
                return(false);
            }

            // Dump dependency data
            ShowDependencyInfo(dependencies);

            // Get compilation options
            var outputName = GetProjectOutput(context.ProjectFile, context.TargetFramework, configuration, outputPath);

            // Assemble args
            var compilerArgs = new List <string>()
            {
                $"--temp-output:{intermediateOutputPath}",
                $"--out:{outputName}"
            };

            var compilationOptions = context.ProjectFile.GetCompilerOptions(context.TargetFramework, configuration);

            // Path to strong naming key in environment variable overrides path in project.json
            var environmentKeyFile = Environment.GetEnvironmentVariable(EnvironmentNames.StrongNameKeyFile);

            if (!string.IsNullOrWhiteSpace(environmentKeyFile))
            {
                compilationOptions.KeyFile = environmentKeyFile;
            }
            else if (!string.IsNullOrWhiteSpace(compilationOptions.KeyFile))
            {
                // Resolve full path to key file
                compilationOptions.KeyFile = Path.GetFullPath(Path.Combine(context.ProjectFile.ProjectDirectory, compilationOptions.KeyFile));
            }

            // Add compilation options to the args
            compilerArgs.AddRange(compilationOptions.SerializeToArgs());

            // Add metadata options
            compilerArgs.AddRange(AssemblyInfoOptions.SerializeToArgs(AssemblyInfoOptions.CreateForProject(context)));

            foreach (var dependency in dependencies)
            {
                var projectDependency = dependency.Library as ProjectDescription;

                if (projectDependency != null)
                {
                    if (projectDependency.Project.Files.SourceFiles.Any())
                    {
                        var projectOutputPath = GetProjectOutput(projectDependency.Project, projectDependency.Framework, configuration, outputPath);
                        compilerArgs.Add($"--reference:{projectOutputPath}");
                    }
                }
                else
                {
                    compilerArgs.AddRange(dependency.CompilationAssemblies.Select(r => $"--reference:{r.ResolvedPath}"));
                }
                compilerArgs.AddRange(dependency.SourceReferences);
            }

            if (!AddResources(context.ProjectFile, compilerArgs, intermediateOutputPath))
            {
                return(false);
            }
            // Add project source files
            var sourceFiles = context.ProjectFile.Files.SourceFiles;

            compilerArgs.AddRange(sourceFiles);

            var compilerName = context.ProjectFile.CompilerName;

            compilerName = compilerName ?? "csc";

            // Write RSP file
            var rsp = Path.Combine(intermediateOutputPath, $"dotnet-compile.{context.ProjectFile.Name}.rsp");

            File.WriteAllLines(rsp, compilerArgs);

            // Run pre-compile event
            var contextVariables = new Dictionary <string, string>()
            {
                { "compile:TargetFramework", context.TargetFramework.DotNetFrameworkName },
                { "compile:Configuration", configuration },
                { "compile:OutputFile", outputName },
                { "compile:OutputDir", outputPath },
                { "compile:ResponseFile", rsp }
            };

            RunScripts(context, ScriptNames.PreCompile, contextVariables);

            var result = Command.Create($"dotnet-compile-{compilerName}", $"@\"{rsp}\"")
                         .OnErrorLine(line =>
            {
                var diagnostic = ParseDiagnostic(context.ProjectDirectory, line);
                if (diagnostic != null)
                {
                    diagnostics.Add(diagnostic);
                }
                else
                {
                    Reporter.Error.WriteLine(line);
                }
            })
                         .OnOutputLine(line =>
            {
                var diagnostic = ParseDiagnostic(context.ProjectDirectory, line);
                if (diagnostic != null)
                {
                    diagnostics.Add(diagnostic);
                }
                else
                {
                    Reporter.Output.WriteLine(line);
                }
            }).Execute();

            // Run post-compile event
            contextVariables["compile:CompilerExitCode"] = result.ExitCode.ToString();
            RunScripts(context, ScriptNames.PostCompile, contextVariables);

            var success = result.ExitCode == 0;

            if (success)
            {
                success &= GenerateResourceAssemblies(context.ProjectFile, dependencies, outputPath, configuration);
            }

            if (success && !noHost && compilationOptions.EmitEntryPoint.GetValueOrDefault())
            {
                var runtimeContext = ProjectContext.Create(context.ProjectDirectory, context.TargetFramework, new[] { RuntimeIdentifier.Current });
                MakeRunnable(runtimeContext,
                             outputPath,
                             runtimeContext.CreateExporter(configuration));
            }

            return(PrintSummary(diagnostics, sw, success));
        }
        public static void Generate(ResourceSource[] sourceFiles, Stream outputStream, AssemblyInfoOptions metadata, string assemblyName, string[] references)
        {
            if (sourceFiles == null)
            {
                throw new ArgumentNullException(nameof(sourceFiles));
            }

            if (outputStream == null)
            {
                throw new ArgumentNullException(nameof(outputStream));
            }

            if (!sourceFiles.Any())
            {
                throw new InvalidOperationException("No source files specified");
            }

            var resourceDescriptions = new List <ResourceDescription>();

            foreach (var resourceInputFile in sourceFiles)
            {
                if (resourceInputFile.Resource.Type == ResourceFileType.Resx)
                {
                    resourceDescriptions.Add(new ResourceDescription(
                                                 resourceInputFile.MetadataName,
                                                 () => GenerateResources(resourceInputFile.Resource), true));
                }
                else if (resourceInputFile.Resource.Type == ResourceFileType.Resources)
                {
                    resourceDescriptions.Add(new ResourceDescription(resourceInputFile.Resource.File.Name, () => resourceInputFile.Resource.File.OpenRead(), true));
                }
                else
                {
                    throw new InvalidOperationException("Generation of resource assemblies from dll not supported");
                }
            }

            var compilationOptions = new CSharpCompilationOptions(outputKind: OutputKind.DynamicallyLinkedLibrary);
            var compilation        = CSharpCompilation.Create(assemblyName,
                                                              references: references.Select(reference => MetadataReference.CreateFromFile(reference)),
                                                              options: compilationOptions);

            compilation = compilation.AddSyntaxTrees(new[]
            {
                CSharpSyntaxTree.ParseText(AssemblyInfoFileGenerator.Generate(metadata, Enumerable.Empty <string>()))
            });

            var result = compilation.Emit(outputStream, manifestResources: resourceDescriptions);

            if (!result.Success)
            {
                foreach (var diagnostic in result.Diagnostics)
                {
                    Reporter.Error.WriteLine(diagnostic.ToString());
                }
                throw new InvalidOperationException("Error occured while emiting assembly");
            }
        }
示例#10
0
        private static bool CompileProject(ProjectContext context, CompilerCommandApp args)
        {
            // Set up Output Paths
            string outputPath             = context.GetOutputPath(args.ConfigValue, args.OutputValue);
            string intermediateOutputPath = context.GetIntermediateOutputPath(args.ConfigValue, args.IntermediateValue, outputPath);

            Directory.CreateDirectory(outputPath);
            Directory.CreateDirectory(intermediateOutputPath);

            // Create the library exporter
            var exporter = context.CreateExporter(args.ConfigValue);

            // Gather exports for the project
            var dependencies = exporter.GetDependencies().ToList();

            Reporter.Output.WriteLine($"Compiling {context.RootProject.Identity.Name.Yellow()} for {context.TargetFramework.DotNetFrameworkName.Yellow()}");
            var sw = Stopwatch.StartNew();

            var diagnostics = new List <DiagnosticMessage>();
            var missingFrameworkDiagnostics = new List <DiagnosticMessage>();

            // Collect dependency diagnostics
            foreach (var diag in context.LibraryManager.GetAllDiagnostics())
            {
                if (diag.ErrorCode == ErrorCodes.DOTNET1011 ||
                    diag.ErrorCode == ErrorCodes.DOTNET1012)
                {
                    missingFrameworkDiagnostics.Add(diag);
                }

                diagnostics.Add(diag);
            }

            if (missingFrameworkDiagnostics.Count > 0)
            {
                // The framework isn't installed so we should short circuit the rest of the compilation
                // so we don't get flooded with errors
                PrintSummary(missingFrameworkDiagnostics, sw);
                return(false);
            }

            // Get compilation options
            var outputName = GetProjectOutput(context.ProjectFile, context.TargetFramework, args.ConfigValue, outputPath);

            // Assemble args
            var compilerArgs = new List <string>()
            {
                $"--temp-output:{intermediateOutputPath}",
                $"--out:{outputName}"
            };

            var compilationOptions = context.ProjectFile.GetCompilerOptions(context.TargetFramework, args.ConfigValue);

            // Path to strong naming key in environment variable overrides path in project.json
            var environmentKeyFile = Environment.GetEnvironmentVariable(EnvironmentNames.StrongNameKeyFile);

            if (!string.IsNullOrWhiteSpace(environmentKeyFile))
            {
                compilationOptions.KeyFile = environmentKeyFile;
            }
            else if (!string.IsNullOrWhiteSpace(compilationOptions.KeyFile))
            {
                // Resolve full path to key file
                compilationOptions.KeyFile = Path.GetFullPath(Path.Combine(context.ProjectFile.ProjectDirectory, compilationOptions.KeyFile));
            }

            var references = new List <string>();

            // Add compilation options to the args
            compilerArgs.AddRange(compilationOptions.SerializeToArgs());

            // Add metadata options
            compilerArgs.AddRange(AssemblyInfoOptions.SerializeToArgs(AssemblyInfoOptions.CreateForProject(context)));

            foreach (var dependency in dependencies)
            {
                var projectDependency = dependency.Library as ProjectDescription;

                if (projectDependency != null)
                {
                    if (projectDependency.Project.Files.SourceFiles.Any())
                    {
                        var projectOutputPath = GetProjectOutput(projectDependency.Project, projectDependency.Framework, args.ConfigValue, outputPath);
                        references.Add(projectOutputPath);
                    }
                }
                else
                {
                    references.AddRange(dependency.CompilationAssemblies.Select(r => r.ResolvedPath));
                }

                compilerArgs.AddRange(dependency.SourceReferences);
            }

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

            if (compilationOptions.PreserveCompilationContext == true)
            {
                var dependencyContext = DependencyContextBuilder.Build(compilationOptions,
                                                                       exporter,
                                                                       args.ConfigValue,
                                                                       context.TargetFramework,
                                                                       context.RuntimeIdentifier);

                var writer       = new DependencyContextWriter();
                var depsJsonFile = Path.Combine(intermediateOutputPath, context.ProjectFile.Name + "dotnet-compile.deps.json");
                using (var fileStream = File.Create(depsJsonFile))
                {
                    writer.Write(dependencyContext, fileStream);
                }

                compilerArgs.Add($"--resource:\"{depsJsonFile}\",{context.ProjectFile.Name}.deps.json");

                var refsFolder = Path.Combine(outputPath, "refs");
                if (Directory.Exists(refsFolder))
                {
                    Directory.Delete(refsFolder, true);
                }

                Directory.CreateDirectory(refsFolder);
                foreach (var reference in references)
                {
                    File.Copy(reference, Path.Combine(refsFolder, Path.GetFileName(reference)));
                }
            }

            if (!AddNonCultureResources(context.ProjectFile, compilerArgs, intermediateOutputPath))
            {
                return(false);
            }
            // Add project source files
            var sourceFiles = context.ProjectFile.Files.SourceFiles;

            compilerArgs.AddRange(sourceFiles);

            var compilerName = CompilerUtil.ResolveCompilerName(context);

            // Write RSP file
            var rsp = Path.Combine(intermediateOutputPath, $"dotnet-compile.{context.ProjectFile.Name}.rsp");

            File.WriteAllLines(rsp, compilerArgs);

            // Run pre-compile event
            var contextVariables = new Dictionary <string, string>()
            {
                { "compile:TargetFramework", context.TargetFramework.DotNetFrameworkName },
                { "compile:Configuration", args.ConfigValue },
                { "compile:OutputFile", outputName },
                { "compile:OutputDir", outputPath },
                { "compile:ResponseFile", rsp }
            };

            RunScripts(context, ScriptNames.PreCompile, contextVariables);

            var result = Command.Create($"dotnet-compile-{compilerName}", $"@\"{rsp}\"")
                         .OnErrorLine(line =>
            {
                var diagnostic = ParseDiagnostic(context.ProjectDirectory, line);
                if (diagnostic != null)
                {
                    diagnostics.Add(diagnostic);
                }
                else
                {
                    Reporter.Error.WriteLine(line);
                }
            })
                         .OnOutputLine(line =>
            {
                var diagnostic = ParseDiagnostic(context.ProjectDirectory, line);
                if (diagnostic != null)
                {
                    diagnostics.Add(diagnostic);
                }
                else
                {
                    Reporter.Output.WriteLine(line);
                }
            }).Execute();

            // Run post-compile event
            contextVariables["compile:CompilerExitCode"] = result.ExitCode.ToString();
            RunScripts(context, ScriptNames.PostCompile, contextVariables);

            var success = result.ExitCode == 0;

            if (success)
            {
                success &= GenerateCultureResourceAssemblies(context.ProjectFile, dependencies, outputPath);
            }

            if (success && !args.NoHostValue && compilationOptions.EmitEntryPoint.GetValueOrDefault())
            {
                var rids           = PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers();
                var runtimeContext = ProjectContext.Create(context.ProjectDirectory, context.TargetFramework, rids);
                runtimeContext
                .MakeCompilationOutputRunnable(outputPath, args.ConfigValue);
            }

            return(PrintSummary(diagnostics, sw, success));
        }
示例#11
0
文件: Program.cs 项目: nattress/cli
        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);
        }
示例#12
0
文件: Program.cs 项目: singhsarab/cli
        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>();
            IReadOnlyList <string> analyzers  = 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("analyzer", ref analyzers, "Path to an analyzer assembly");

                    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.GenerateCSharp(assemblyInfoOptions, sources));

            allArgs.Add($"\"{assemblyInfo}\"");

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

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

            // Resource has two parts separated by a comma
            // Only the first should be quoted. This is handled
            // in dotnet-compile where the information is present.
            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(new string[] { $"-noconfig", "@" + $"{rsp}" })
                         .ForwardStdErr()
                         .ForwardStdOut()
                         .Execute();

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

            CommandLineApplication app = new CommandLineApplication();

            app.Name                = "dotnet compile-vbc";
            app.FullName            = ".NET VB Compiler";
            app.Description         = "VB Compiler for the .NET Platform";
            app.HandleResponseFiles = true;
            app.HelpOption("-h|--help");

            CommonCompilerOptionsCommandLine commonCompilerCommandLine = CommonCompilerOptionsCommandLine.AddOptions(app);
            AssemblyInfoOptionsCommandLine   assemblyInfoCommandLine   = AssemblyInfoOptionsCommandLine.AddOptions(app);

            CommandOption   tempOutput = app.Option("--temp-output <arg>", "Compilation temporary directory", CommandOptionType.SingleValue);
            CommandOption   outputName = app.Option("--out <arg>", "Name of the output assembly", CommandOptionType.SingleValue);
            CommandOption   references = app.Option("--reference <arg>...", "Path to a compiler metadata reference", CommandOptionType.MultipleValue);
            CommandOption   analyzers  = app.Option("--analyzer <arg>...", "Path to an analyzer assembly", CommandOptionType.MultipleValue);
            CommandOption   resources  = app.Option("--resource <arg>...", "Resources to embed", CommandOptionType.MultipleValue);
            CommandArgument sources    = app.Argument("<source-files>...", "Compilation sources", multipleValues: true);

            app.OnExecute(() =>
            {
                if (!tempOutput.HasValue())
                {
                    Reporter.Error.WriteLine("Option '--temp-output' is required");
                    return(ExitFailed);
                }

                CommonCompilerOptions commonOptions = commonCompilerCommandLine.GetOptionValues();

                AssemblyInfoOptions assemblyInfoOptions = assemblyInfoCommandLine.GetOptionValues();

                var translated = TranslateCommonOptions(commonOptions, outputName.Value());

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

                // Generate assembly info

                /*DISABLED BECAUSE AssemblyInfoGenerator doesnt undertstand vb
                 * just add something like https://github.com/dotnet/cli/blob/04f40f906dce2678d80fb9787e68de76ee6bf57e/src/Microsoft.DotNet.Compiler.Common/AssemblyInfoFileGenerator.cs#L19
                 *
                 * var assemblyInfo = Path.Combine(tempOutput.Value(), $"dotnet-compile.assemblyinfo.vb");
                 *
                 * File.WriteAllText(assemblyInfo, AssemblyInfoFileGenerator.GenerateCSharp(assemblyInfoOptions, sources.Values));
                 *
                 * allArgs.Add($"\"{assemblyInfo}\"");
                 *
                 */

                if (outputName.HasValue())
                {
                    allArgs.Add($"-out:\"{outputName.Value()}\"");
                }

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

                // Resource has two parts separated by a comma
                // Only the first should be quoted. This is handled
                // in dotnet-compile where the information is present.
                allArgs.AddRange(resources.Values.Select(resource => $"-resource:{resource}"));

                allArgs.AddRange(sources.Values.Select(s => $"\"{s}\""));

                var rsp = Path.Combine(tempOutput.Value(), "dotnet-compile-vbc.rsp");

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

                // Execute VBC!
                var result = RunVbc(new string[] { $"-noconfig", "@" + $"{rsp}" })
                             .WorkingDirectory(Directory.GetCurrentDirectory())
                             .ForwardStdErr()
                             .ForwardStdOut()
                             .Execute();

                // RENAME things
                // This is currently necessary as the BUILD task of the dotnet executable expects (at this stage) a .DLL (not an EXE).
                var outExe = outputName.Value();
                outExe     = outExe + ".exe";
                if (!string.IsNullOrEmpty(outExe) && File.Exists(outExe))
                {
                    string outDll = outExe.Replace(".dll.exe", ".dll");
                    if (File.Exists(outDll))
                    {
                        File.Delete(outDll);
                    }
                    System.IO.File.Move(outExe, outDll);

                    string outPdbOrig = outExe.Replace(".dll.exe", ".dll.pdb");
                    string outPdb     = outPdbOrig.Replace(".dll.pdb", ".pdb");
                    if (File.Exists(outPdb))
                    {
                        File.Delete(outPdb);
                    }
                    System.IO.File.Move(outPdbOrig, outPdb);
                }

                return(result.ExitCode);
            });

            try
            {
                return(app.Execute(args));
            }
            catch (Exception ex)
            {
#if DEBUG
                Reporter.Error.WriteLine(ex.ToString());
#else
                Reporter.Error.WriteLine(ex.Message);
#endif
                return(ExitFailed);
            }
        }
示例#14
0
文件: Program.cs 项目: wtgodbe/cli
        public static int Main(string[] args)
        {
            DebugHelper.HandleDebugSwitch(ref args);

            CommandLineApplication app = new CommandLineApplication();

            app.Name                = "dotnet compile-fsc";
            app.FullName            = ".NET F# Compiler";
            app.Description         = "F# Compiler for the .NET Platform";
            app.HandleResponseFiles = true;
            app.HelpOption("-h|--help");

            CommonCompilerOptionsCommandLine commonCompilerCommandLine = CommonCompilerOptionsCommandLine.AddOptions(app);
            AssemblyInfoOptionsCommandLine   assemblyInfoCommandLine   = AssemblyInfoOptionsCommandLine.AddOptions(app);

            CommandOption   tempOutputOption = app.Option("--temp-output <arg>", "Compilation temporary directory", CommandOptionType.SingleValue);
            CommandOption   outputNameOption = app.Option("--out <arg>", "Name of the output assembly", CommandOptionType.SingleValue);
            CommandOption   referencesOption = app.Option("--reference <arg>...", "Path to a compiler metadata reference", CommandOptionType.MultipleValue);
            CommandOption   resourcesOption  = app.Option("--resource <arg>...", "Resources to embed", CommandOptionType.MultipleValue);
            CommandArgument sourcesArgument  = app.Argument("<source-files>...", "Compilation sources", multipleValues: true);

            app.OnExecute(() =>
            {
                if (!tempOutputOption.HasValue())
                {
                    Reporter.Error.WriteLine("Option '--temp-output' is required");
                    return(ExitFailed);
                }

                CommonCompilerOptions commonOptions = commonCompilerCommandLine.GetOptionValues();

                AssemblyInfoOptions assemblyInfoOptions = assemblyInfoCommandLine.GetOptionValues();

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

                // Get FSC Path upfront to use it for win32manifest path
                string tempOutDir  = tempOutputOption.Value();
                var fscCommandSpec = ResolveFsc(null, tempOutDir);
                var fscExeFile     = fscCommandSpec.FscExeFile;
                var fscExeDir      = fscCommandSpec.FscExeDir;

                // 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 outputName      = outputNameOption.Value();
                var 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(resourcesOption.Values.Select(resource => $"--resource:{resource.Replace("\"", "")}"));

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

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

                    //HACK we need default.win32manifest for exe
                    var win32manifestPath = Path.Combine(fscExeDir, "..", "..", "runtimes", "any", "native", "default.win32manifest");
                    allArgs.Add($"--win32manifest:{win32manifestPath}");
                }

                if (commonOptions.SuppressWarnings != null && commonOptions.SuppressWarnings.Any())
                {
                    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(sourcesArgument.Values, 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}"
                }, tempOutDir)
                             .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);
            });

            try
            {
                return(app.Execute(args));
            }
            catch (Exception ex)
            {
#if DEBUG
                Reporter.Error.WriteLine(ex.ToString());
#else
                Reporter.Error.WriteLine(ex.Message);
#endif
                return(ExitFailed);
            }
        }
示例#15
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.fs");

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

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

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

                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-fsc.rsp");

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

            // Execute FSC!
            var result = RunFsc(string.Join(" ", allArgs))
                         .ForwardStdErr()
                         .ForwardStdOut()
                         .Execute();

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

            return(result.ExitCode);
        }
示例#16
0
        public bool Compile(ProjectContext context, string config, string buildBasePath)
        {
            // Set up Output Paths
            var outputPaths            = context.GetOutputPaths(config, buildBasePath);
            var outputPath             = outputPaths.CompilationOutputPath;
            var intermediateOutputPath = outputPaths.IntermediateOutputDirectoryPath;

            Directory.CreateDirectory(outputPath);
            Directory.CreateDirectory(intermediateOutputPath);

            // Create the library exporter
            var exporter = context.CreateExporter(config, buildBasePath);

            // Gather exports for the project
            var dependencies = exporter.GetDependencies().ToList();

            var diagnostics = new List <DiagnosticMessage>();
            var missingFrameworkDiagnostics = new List <DiagnosticMessage>();

            // Collect dependency diagnostics
            foreach (var diag in context.LibraryManager.GetAllDiagnostics())
            {
                if (diag.ErrorCode == ErrorCodes.DOTNET1011 ||
                    diag.ErrorCode == ErrorCodes.DOTNET1012)
                {
                    missingFrameworkDiagnostics.Add(diag);
                }

                diagnostics.Add(diag);
            }

            if (diagnostics.Any(d => d.Severity == DiagnosticMessageSeverity.Error))
            {
                // We got an unresolved dependency or missing framework. Don't continue the compilation.
                return(false);
            }

            // Get compilation options
            var outputName         = outputPaths.CompilationFiles.Assembly;
            var compilationOptions = context.ResolveCompilationOptions(config);

            // Set default platform if it isn't already set and we're on desktop
            if (compilationOptions.EmitEntryPoint == true && string.IsNullOrEmpty(compilationOptions.Platform) && context.TargetFramework.IsDesktop())
            {
                // See https://github.com/dotnet/cli/issues/2428 for more details.
                compilationOptions.Platform = RuntimeInformation.ProcessArchitecture == Architecture.X64 ?
                                              "x64" : "anycpu32bitpreferred";
            }

            var references  = new List <string>();
            var sourceFiles = new List <string>();

            // Add metadata options
            var assemblyInfoOptions = AssemblyInfoOptions.CreateForProject(context);

            foreach (var dependency in dependencies)
            {
                references.AddRange(dependency.CompilationAssemblies.Select(r => r.ResolvedPath));
                sourceFiles.AddRange(dependency.SourceReferences.Select(s => s.GetTransformedFile(intermediateOutputPath)));
            }

            var resources = new List <string>();

            if (compilationOptions.PreserveCompilationContext == true)
            {
                var allExports        = exporter.GetAllExports().ToList();
                var dependencyContext = new DependencyContextBuilder().Build(compilationOptions,
                                                                             allExports,
                                                                             allExports,
                                                                             false, // For now, just assume non-portable mode in the legacy deps file (this is going away soon anyway)
                                                                             context.TargetFramework,
                                                                             context.RuntimeIdentifier ?? string.Empty);

                var writer       = new DependencyContextWriter();
                var depsJsonFile = Path.Combine(intermediateOutputPath, compilationOptions.OutputName + "dotnet-compile.deps.json");
                using (var fileStream = File.Create(depsJsonFile))
                {
                    writer.Write(dependencyContext, fileStream);
                }

                resources.Add($"\"{depsJsonFile}\",{compilationOptions.OutputName}.deps.json");
            }

            // Add project source files
            if (compilationOptions.CompileInclude == null)
            {
                sourceFiles.AddRange(context.ProjectFile.Files.SourceFiles);
            }
            else
            {
                var includeFiles = IncludeFilesResolver.GetIncludeFiles(compilationOptions.CompileInclude, "/", diagnostics: null);
                sourceFiles.AddRange(includeFiles.Select(f => f.SourcePath));
            }

            if (String.IsNullOrEmpty(intermediateOutputPath))
            {
                return(false);
            }

            var translated = TranslateCommonOptions(compilationOptions, outputName);

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

            allArgs.AddRange(GetDefaultOptions());

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

            File.WriteAllText(assemblyInfo, AssemblyInfoFileGenerator.GenerateCSharp(assemblyInfoOptions, sourceFiles));

            allArgs.Add($"\"{assemblyInfo}\"");

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

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

            // Execute CSC!
            var result = RunCsc(allArgs.ToArray())
                         .WorkingDirectory(Directory.GetCurrentDirectory())
                         .ForwardStdErr()
                         .ForwardStdOut()
                         .Execute();

            return(result.ExitCode == 0);
        }
示例#17
0
        private static bool CompileProject(ProjectContext context, CompilerCommandApp args)
        {
            // Set up Output Paths
            var outputPathCalculator   = context.GetOutputPathCalculator(args.OutputValue);
            var outputPath             = outputPathCalculator.GetOutputDirectoryPath(args.ConfigValue);
            var intermediateOutputPath =
                outputPathCalculator.GetIntermediateOutputDirectoryPath(args.ConfigValue, args.IntermediateValue);

            Directory.CreateDirectory(outputPath);
            Directory.CreateDirectory(intermediateOutputPath);

            // Create the library exporter
            var exporter = context.CreateExporter(args.ConfigValue);

            // Gather exports for the project
            var dependencies = exporter.GetDependencies().ToList();

            Reporter.Output.WriteLine($"Compiling {context.RootProject.Identity.Name.Yellow()} for {context.TargetFramework.DotNetFrameworkName.Yellow()}");
            var sw = Stopwatch.StartNew();

            var diagnostics = new List <DiagnosticMessage>();
            var missingFrameworkDiagnostics = new List <DiagnosticMessage>();

            // Collect dependency diagnostics
            foreach (var diag in context.LibraryManager.GetAllDiagnostics())
            {
                if (diag.ErrorCode == ErrorCodes.DOTNET1011 ||
                    diag.ErrorCode == ErrorCodes.DOTNET1012)
                {
                    missingFrameworkDiagnostics.Add(diag);
                }

                diagnostics.Add(diag);
            }

            if (missingFrameworkDiagnostics.Count > 0)
            {
                // The framework isn't installed so we should short circuit the rest of the compilation
                // so we don't get flooded with errors
                PrintSummary(missingFrameworkDiagnostics, sw);
                return(false);
            }

            // Get compilation options
            var outputName = outputPathCalculator.GetAssemblyPath(args.ConfigValue);

            // Assemble args
            var compilerArgs = new List <string>()
            {
                $"--temp-output:\"{intermediateOutputPath}\"",
                $"--out:\"{outputName}\""
            };

            var compilationOptions = CompilerUtil.ResolveCompilationOptions(context, args.ConfigValue);
            var languageId         = CompilerUtil.ResolveLanguageId(context);

            var references = new List <string>();

            // Add compilation options to the args
            compilerArgs.AddRange(compilationOptions.SerializeToArgs());

            // Add metadata options
            compilerArgs.AddRange(AssemblyInfoOptions.SerializeToArgs(AssemblyInfoOptions.CreateForProject(context)));

            foreach (var dependency in dependencies)
            {
                references.AddRange(dependency.CompilationAssemblies.Select(r => r.ResolvedPath));
                compilerArgs.AddRange(dependency.SourceReferences.Select(s => $"\"{s}\""));

                // Add analyzer references
                compilerArgs.AddRange(dependency.AnalyzerReferences
                                      .Where(a => a.AnalyzerLanguage == languageId)
                                      .Select(a => $"--analyzer:\"{a.AssemblyPath}\""));
            }

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

            if (compilationOptions.PreserveCompilationContext == true)
            {
                var dependencyContext = DependencyContextBuilder.Build(compilationOptions,
                                                                       exporter,
                                                                       args.ConfigValue,
                                                                       context.TargetFramework,
                                                                       context.RuntimeIdentifier);

                var writer       = new DependencyContextWriter();
                var depsJsonFile = Path.Combine(intermediateOutputPath, context.ProjectFile.Name + "dotnet-compile.deps.json");
                using (var fileStream = File.Create(depsJsonFile))
                {
                    writer.Write(dependencyContext, fileStream);
                }

                compilerArgs.Add($"--resource:\"{depsJsonFile},{context.ProjectFile.Name}.deps.json\"");
            }

            if (!AddNonCultureResources(context.ProjectFile, compilerArgs, intermediateOutputPath))
            {
                return(false);
            }
            // Add project source files
            var sourceFiles = CompilerUtil.GetCompilationSources(context);

            compilerArgs.AddRange(sourceFiles);

            var compilerName = CompilerUtil.ResolveCompilerName(context);

            // Write RSP file
            var rsp = Path.Combine(intermediateOutputPath, $"dotnet-compile.rsp");

            File.WriteAllLines(rsp, compilerArgs);

            // Run pre-compile event
            var contextVariables = new Dictionary <string, string>()
            {
                { "compile:TargetFramework", context.TargetFramework.DotNetFrameworkName },
                { "compile:Configuration", args.ConfigValue },
                { "compile:OutputFile", outputName },
                { "compile:OutputDir", outputPath },
                { "compile:ResponseFile", rsp }
            };

            RunScripts(context, ScriptNames.PreCompile, contextVariables);

            var result = Command.CreateDotNet($"compile-{compilerName}", new[] { "@" + $"{rsp}" })
                         .OnErrorLine(line =>
            {
                var diagnostic = ParseDiagnostic(context.ProjectDirectory, line);
                if (diagnostic != null)
                {
                    diagnostics.Add(diagnostic);
                }
                else
                {
                    Reporter.Error.WriteLine(line);
                }
            })
                         .OnOutputLine(line =>
            {
                var diagnostic = ParseDiagnostic(context.ProjectDirectory, line);
                if (diagnostic != null)
                {
                    diagnostics.Add(diagnostic);
                }
                else
                {
                    Reporter.Output.WriteLine(line);
                }
            }).Execute();

            // Run post-compile event
            contextVariables["compile:CompilerExitCode"] = result.ExitCode.ToString();
            RunScripts(context, ScriptNames.PostCompile, contextVariables);

            var success = result.ExitCode == 0;

            if (!success)
            {
                Reporter.Error.WriteLine($"{result.StartInfo.FileName} {result.StartInfo.Arguments} returned Exit Code {result.ExitCode}");
            }

            if (success)
            {
                success &= GenerateCultureResourceAssemblies(context.ProjectFile, dependencies, intermediateOutputPath, outputPath);
            }

            return(PrintSummary(diagnostics, sw, success));
        }