Beispiel #1
0
        private void MakeRunnable()
        {
            var runtimeContext = _rootProject.CreateRuntimeContext(_args.GetRuntimes());

            if (_args.PortableMode)
            {
                // HACK: Force the use of the portable target
                runtimeContext = _rootProject;
            }

            var outputPaths     = runtimeContext.GetOutputPaths(_args.ConfigValue, _args.BuildBasePathValue, _args.OutputValue);
            var libraryExporter = runtimeContext.CreateExporter(_args.ConfigValue, _args.BuildBasePathValue);

            // If we're building for a specific RID, we need to copy the RID-less compilation output into
            // the RID-specific output dir
            if (!string.IsNullOrEmpty(runtimeContext.RuntimeIdentifier))
            {
                CopyCompilationOutput(outputPaths);
            }

            var executable = new Executable(runtimeContext, outputPaths, libraryExporter, _args.ConfigValue);

            executable.MakeCompilationOutputRunnable();

            PatchMscorlibNextToCoreClr(runtimeContext, _args.ConfigValue);
        }
Beispiel #2
0
        private void MakeRunnable()
        {
            var runtimeContext  = _rootProject.CreateRuntimeContext(_args.GetRuntimes());
            var outputPaths     = runtimeContext.GetOutputPaths(_args.ConfigValue, _args.BuildBasePathValue, _args.OutputValue);
            var libraryExporter = runtimeContext.CreateExporter(_args.ConfigValue, _args.BuildBasePathValue);

            CopyCompilationOutput(outputPaths);

            var executable = new Executable(runtimeContext, outputPaths, libraryExporter, _args.ConfigValue);

            executable.MakeCompilationOutputRunnable();
        }
Beispiel #3
0
        // computes all the inputs and outputs that would be used in the compilation of a project
        // ensures that all paths are files
        // ensures no missing inputs
        public CompilerIO GetCompileIO(ProjectContext project, ProjectDependenciesFacade dependencies)
        {
            var buildConfiguration = _args.ConfigValue;
            var buildBasePath      = _args.BuildBasePathValue;
            var outputPath         = _args.OutputValue;
            var isRootProject      = project == _rootProject;

            var compilerIO         = new CompilerIO(new List <string>(), new List <string>());
            var calculator         = project.GetOutputPaths(buildConfiguration, buildBasePath, outputPath);
            var binariesOutputPath = calculator.CompilationOutputPath;

            // input: project.json
            compilerIO.Inputs.Add(project.ProjectFile.ProjectFilePath);

            // input: lock file; find when dependencies change
            AddLockFile(project, compilerIO);

            // input: source files
            compilerIO.Inputs.AddRange(CompilerUtil.GetCompilationSources(project));

            // todo: Factor out dependency resolution between Build and Compile. Ideally Build injects the dependencies into Compile
            // input: dependencies
            AddDependencies(dependencies, compilerIO);

            var allOutputPath = new HashSet <string>(calculator.CompilationFiles.All());

            if (isRootProject && project.ProjectFile.HasRuntimeOutput(buildConfiguration))
            {
                var runtimeContext = project.CreateRuntimeContext(_args.GetRuntimes());
                foreach (var path in runtimeContext.GetOutputPaths(buildConfiguration, buildBasePath, outputPath).RuntimeFiles.All())
                {
                    allOutputPath.Add(path);
                }
            }

            // output: compiler outputs
            foreach (var path in allOutputPath)
            {
                compilerIO.Outputs.Add(path);
            }

            // input compilation options files
            AddCompilationOptions(project, buildConfiguration, compilerIO);

            // input / output: resources with culture
            AddNonCultureResources(project, calculator.IntermediateOutputDirectoryPath, compilerIO);

            // input / output: resources without culture
            AddCultureResources(project, binariesOutputPath, compilerIO);

            return(compilerIO);
        }
Beispiel #4
0
        public override bool Compile(ProjectContext context, CompilerCommandApp 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 (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 = outputPaths.CompilationFiles.Assembly;

            // 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.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    = context.CreateRuntimeContext(args.GetRuntimes());
                var runtimeOutputPath = runtimeContext.GetOutputPaths(args.ConfigValue, args.BuildBasePathValue, args.OutputValue);

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

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

            var result = _commandFactory.Create($"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();
            _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, intermediateOutputPath, outputPath);
            }

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