private static CSharpCompilationOptions GetCompilationOptions( IWebHostEnvironment hostingEnvironment, DependencyContextCompilationOptions dependencyContextOptions) { var csharpCompilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary); // Disable 1702 until roslyn turns this off by default csharpCompilationOptions = csharpCompilationOptions.WithSpecificDiagnosticOptions( new Dictionary <string, ReportDiagnostic> { { "CS1701", ReportDiagnostic.Suppress }, // Binding redirects { "CS1702", ReportDiagnostic.Suppress }, { "CS1705", ReportDiagnostic.Suppress } }); if (dependencyContextOptions.AllowUnsafe.HasValue) { csharpCompilationOptions = csharpCompilationOptions.WithAllowUnsafe( dependencyContextOptions.AllowUnsafe.Value); } OptimizationLevel optimizationLevel; if (dependencyContextOptions.Optimize.HasValue) { optimizationLevel = dependencyContextOptions.Optimize.Value ? OptimizationLevel.Release : OptimizationLevel.Debug; } else { optimizationLevel = hostingEnvironment.IsDevelopment() ? OptimizationLevel.Debug : OptimizationLevel.Release; } csharpCompilationOptions = csharpCompilationOptions.WithOptimizationLevel(optimizationLevel); if (dependencyContextOptions.WarningsAsErrors.HasValue) { var reportDiagnostic = dependencyContextOptions.WarningsAsErrors.Value ? ReportDiagnostic.Error : ReportDiagnostic.Default; csharpCompilationOptions = csharpCompilationOptions.WithGeneralDiagnosticOption(reportDiagnostic); } return(csharpCompilationOptions); }
public static CSharpCompilationOptions CreateCompilationOptions(this ProjectFileInfo projectFileInfo) { var compilationOptions = new CSharpCompilationOptions(projectFileInfo.OutputKind); compilationOptions = compilationOptions.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default) .WithSpecificDiagnosticOptions(projectFileInfo.GetDiagnosticOptions()) .WithOverflowChecks(projectFileInfo.CheckForOverflowUnderflow); if (projectFileInfo.AllowUnsafeCode) { compilationOptions = compilationOptions.WithAllowUnsafe(true); } if (projectFileInfo.TreatWarningsAsErrors) { compilationOptions = compilationOptions.WithGeneralDiagnosticOption(ReportDiagnostic.Error); } if (projectFileInfo.NullableContextOptions != compilationOptions.NullableContextOptions) { compilationOptions = compilationOptions.WithNullableContextOptions(projectFileInfo.NullableContextOptions); } if (projectFileInfo.SignAssembly && !string.IsNullOrEmpty(projectFileInfo.AssemblyOriginatorKeyFile)) { var keyFile = Path.Combine(projectFileInfo.Directory, projectFileInfo.AssemblyOriginatorKeyFile); compilationOptions = compilationOptions.WithStrongNameProvider(new DesktopStrongNameProvider()) .WithCryptoKeyFile(keyFile); } if (!string.IsNullOrWhiteSpace(projectFileInfo.DocumentationFile)) { compilationOptions = compilationOptions.WithXmlReferenceResolver(XmlFileResolver.Default); } return(compilationOptions); }
/// <summary> /// Compiles an embedded resource into an executable and writes it to disk in the same /// directory as the executing assembly. /// </summary> /// <param name="sourceResourcePath"> /// The relative resource path, as it must be formatted for a pack URI. /// </param> /// <param name="absOutputPath"> /// The absolute path /// </param> private string CompileExe(string sourceResourcePath, string absOutputPath) { m_logger.Info("Compiling internal service: {0} to output {1}.", sourceResourcePath, absOutputPath); string scriptContents = string.Empty; using (var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(sourceResourcePath)) { using (TextReader tsr = new StreamReader(resourceStream)) { scriptContents = tsr.ReadToEnd(); } } if (scriptContents == null || scriptContents.Length == 0) { m_logger.Warn("When compiling internal service {0}, failed to load source code.", sourceResourcePath); return(string.Empty); } // The sentinel service is special. It's the only that's going to watch us. // So, we need to code our process name into its source before compilation. if (sourceResourcePath.IndexOf("Sentinel", StringComparison.OrdinalIgnoreCase) != -1) { scriptContents = scriptContents.Replace("TARGET_APPLICATION_NAME", Process.GetCurrentProcess().ProcessName); } HashSet <string> allRefs = new HashSet <string>(); var dd = typeof(Enumerable).GetTypeInfo().Assembly.Location; var coreDir = Directory.GetParent(dd); List <MetadataReference> references = new List <MetadataReference> { // Here we get the path to the mscorlib and private mscorlib // libraries that are required for compilation to succeed. //MetadataReference.CreateFromFile(coreDir.FullName + Path.DirectorySeparatorChar + "mscorlib.dll"), MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location) }; var referencedAssemblies = RecursivelyGetReferencedAssemblies(Assembly.GetEntryAssembly()); foreach (var referencedAssembly in referencedAssemblies) { var mref = MetadataReference.CreateFromFile(referencedAssembly.Location); if (referencedAssembly.FullName.Contains("System.Runtime.Extension")) { // Have to do this to avoid collisions with duplicate type // definitions between private mscorlib and this assembly. // XXX TODO - Needs to be solved in a better way? mref = mref.WithAliases(new List <string>(new[] { "CorPrivate" })); } if (!allRefs.Contains(mref.Display)) { references.Add(mref); allRefs.Add(mref.Display); } } // Setup syntax parse options for C#. CSharpParseOptions parseOptions = CSharpParseOptions.Default; parseOptions = parseOptions.WithLanguageVersion(LanguageVersion.CSharp6); parseOptions = parseOptions.WithDocumentationMode(DocumentationMode.None); parseOptions = parseOptions.WithKind(SourceCodeKind.Regular); // Parse text into syntax tree. SyntaxTree jobSyntaxTree = CSharpSyntaxTree.ParseText(scriptContents, parseOptions); // Initialize compilation arguments for the build script we're about // to compile. var op = new CSharpCompilationOptions(OutputKind.ConsoleApplication); op = op.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default); op = op.WithGeneralDiagnosticOption(ReportDiagnostic.Warn); // Initialize the compilation with our options, references and the // already parsed syntax tree of the build script. CSharpCompilation compilation = CSharpCompilation.Create( Path.GetFileNameWithoutExtension(absOutputPath), syntaxTrees: new[] { jobSyntaxTree }, references: references, options: op); // Compile and emit new assembly into memory. using (var ms = new MemoryStream()) { EmitResult result = compilation.Emit(ms); if (result.Success) { File.WriteAllBytes(absOutputPath, ms.ToArray()); m_logger.Info("Generated service assembly {0} for service {1}.", absOutputPath, Path.GetFileNameWithoutExtension(absOutputPath)); return(absOutputPath); } else { // Compilation failed. m_logger.Error("Failed to generate service assembly for service {0}.", Path.GetFileNameWithoutExtension(absOutputPath)); foreach (var diag in result.Diagnostics) { m_logger.Error(diag.GetMessage()); } } } return(string.Empty); }
public HostBuildData Create(HostBuildOptions options) { var parseOptions = new CSharpParseOptions(languageVersion: LanguageVersion.CSharp6, documentationMode: DocumentationMode.Parse); var compilationOptions = new CSharpCompilationOptions( OutputKind.ConsoleApplication, xmlReferenceResolver: new XmlFileResolver(options.ProjectDirectory), sourceReferenceResolver: new SourceFileResolver(ImmutableArray<string>.Empty, options.ProjectDirectory), metadataReferenceResolver: new AssemblyReferenceResolver( new MetadataFileReferenceResolver(ImmutableArray<string>.Empty, options.ProjectDirectory), MetadataFileReferenceProvider.Default), strongNameProvider: new DesktopStrongNameProvider(ImmutableArray.Create(options.ProjectDirectory, options.OutputDirectory)), assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default); var warnings = new List<KeyValuePair<string, ReportDiagnostic>>(options.Warnings); if (options.OutputKind.HasValue) { var kind = options.OutputKind.Value; compilationOptions = compilationOptions.WithOutputKind(kind); if (compilationOptions.Platform == Platform.AnyCpu32BitPreferred && (kind == OutputKind.DynamicallyLinkedLibrary || kind == OutputKind.NetModule || kind == OutputKind.WindowsRuntimeMetadata)) { compilationOptions = compilationOptions.WithPlatform(Platform.AnyCpu); } } if (!string.IsNullOrEmpty(options.DefineConstants)) { IEnumerable<Diagnostic> diagnostics; parseOptions = parseOptions.WithPreprocessorSymbols(CSharpCommandLineParser.ParseConditionalCompilationSymbols(options.DefineConstants, out diagnostics)); } if (options.DocumentationFile != null) { parseOptions = parseOptions.WithDocumentationMode(!string.IsNullOrEmpty(options.DocumentationFile) ? DocumentationMode.Diagnose : DocumentationMode.Parse); } if (options.LanguageVersion != null) { var languageVersion = CompilationOptionsConversion.GetLanguageVersion(options.LanguageVersion); if (languageVersion.HasValue) { parseOptions = parseOptions.WithLanguageVersion(languageVersion.Value); } } if (!string.IsNullOrEmpty(options.PlatformWith32BitPreference)) { Platform platform; if (Enum.TryParse<Platform>(options.PlatformWith32BitPreference, true, out platform)) { if (platform == Platform.AnyCpu && compilationOptions.OutputKind != OutputKind.DynamicallyLinkedLibrary && compilationOptions.OutputKind != OutputKind.NetModule && compilationOptions.OutputKind != OutputKind.WindowsRuntimeMetadata) { platform = Platform.AnyCpu32BitPreferred; } compilationOptions = compilationOptions.WithPlatform(platform); } } if (options.AllowUnsafeBlocks.HasValue) { compilationOptions = compilationOptions.WithAllowUnsafe(options.AllowUnsafeBlocks.Value); } if (options.CheckForOverflowUnderflow.HasValue) { compilationOptions = compilationOptions.WithOverflowChecks(options.CheckForOverflowUnderflow.Value); } if (options.DelaySign != null) { bool delaySignExplicitlySet = options.DelaySign.Item1; bool delaySign = options.DelaySign.Item2; compilationOptions = compilationOptions.WithDelaySign(delaySignExplicitlySet ? delaySign : (bool?)null); } if (!string.IsNullOrEmpty(options.ApplicationConfiguration)) { var appConfigPath = FileUtilities.ResolveRelativePath(options.ApplicationConfiguration, options.ProjectDirectory); try { using (var appConfigStream = PortableShim.FileStream.Create(appConfigPath, PortableShim.FileMode.Open, PortableShim.FileAccess.Read)) { compilationOptions = compilationOptions.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.LoadFromXml(appConfigStream)); } } catch (Exception) { } } if (!string.IsNullOrEmpty(options.KeyContainer)) { compilationOptions = compilationOptions.WithCryptoKeyContainer(options.KeyContainer); } if (!string.IsNullOrEmpty(options.KeyFile)) { var fullPath = FileUtilities.ResolveRelativePath(options.KeyFile, options.ProjectDirectory); compilationOptions = compilationOptions.WithCryptoKeyFile(fullPath); } if (!string.IsNullOrEmpty(options.MainEntryPoint)) { compilationOptions = compilationOptions.WithMainTypeName(options.MainEntryPoint); } if (!string.IsNullOrEmpty(options.ModuleAssemblyName)) { compilationOptions = compilationOptions.WithModuleName(options.ModuleAssemblyName); } if (options.Optimize.HasValue) { compilationOptions = compilationOptions.WithOptimizationLevel(options.Optimize.Value ? OptimizationLevel.Release : OptimizationLevel.Debug); } if (!string.IsNullOrEmpty(options.Platform)) { Platform plat; if (Enum.TryParse<Platform>(options.Platform, ignoreCase: true, result: out plat)) { compilationOptions = compilationOptions.WithPlatform(plat); } } // Get options from the ruleset file, if any. if (!string.IsNullOrEmpty(options.RuleSetFile)) { var fullPath = FileUtilities.ResolveRelativePath(options.RuleSetFile, options.ProjectDirectory); Dictionary<string, ReportDiagnostic> specificDiagnosticOptions; var generalDiagnosticOption = RuleSet.GetDiagnosticOptionsFromRulesetFile(fullPath, out specificDiagnosticOptions); compilationOptions = compilationOptions.WithGeneralDiagnosticOption(generalDiagnosticOption); warnings.AddRange(specificDiagnosticOptions); } if (options.WarningsAsErrors.HasValue) { compilationOptions = compilationOptions.WithGeneralDiagnosticOption(options.WarningsAsErrors.Value ? ReportDiagnostic.Error : ReportDiagnostic.Default); } if (options.WarningLevel.HasValue) { compilationOptions = compilationOptions.WithWarningLevel(options.WarningLevel.Value); } compilationOptions = compilationOptions.WithSpecificDiagnosticOptions(warnings); return new HostBuildData( parseOptions, compilationOptions); }
/// <summary> /// This method attempts to load the build script at the given location, /// compile return the exported AbstractBuildTask from it. The script /// file must inherit from AbstractBuildTask. /// </summary> /// <param name="taskScriptPath"> /// The path to the build script to run. /// </param> /// <returns> /// In the event of successful discovery, read and compilation of the /// script at the given path, a list of all exported AbstractBuildTasks /// from the compiled assembly is returned. /// </returns> private static List <AbstractBuildTask> LoadTaskFromScript(string taskScriptPath) { WriteTitleToConsole("Loading & Parsing Build Script"); // Exhaustively verify that the file exists, is readable and is not // an empty file. Debug.Assert(!string.IsNullOrEmpty(taskScriptPath) && !string.IsNullOrWhiteSpace(taskScriptPath), "Build task script path is null, empty or whitespace."); if (string.IsNullOrEmpty(taskScriptPath) || string.IsNullOrWhiteSpace(taskScriptPath)) { throw new ArgumentException("Build task script path is null, empty or whitespace.", nameof(taskScriptPath)); } Debug.Assert(File.Exists(taskScriptPath), "Build task script path points to non-existent file."); if (!File.Exists(taskScriptPath)) { throw new ArgumentException("Build task script path points to non-existent file."); } Console.WriteLine(string.Format("Reading all text from file {0}", taskScriptPath)); var scriptContents = File.ReadAllText(taskScriptPath); Debug.Assert(!string.IsNullOrEmpty(scriptContents) && !string.IsNullOrWhiteSpace(scriptContents), "Build task script contents are null, empty or whitespace."); if (string.IsNullOrEmpty(scriptContents) || string.IsNullOrWhiteSpace(scriptContents)) { throw new ArgumentException("Build task script contents are null, empty or whitespace.", nameof(taskScriptPath)); } // Setup syntax parse options for C#. CSharpParseOptions parseOptions = CSharpParseOptions.Default; parseOptions = parseOptions.WithLanguageVersion(LanguageVersion.CSharp6); parseOptions = parseOptions.WithDocumentationMode(DocumentationMode.None); parseOptions = parseOptions.WithKind(SourceCodeKind.Regular); // Parse text into syntax tree. SyntaxTree jobSyntaxTree = CSharpSyntaxTree.ParseText(scriptContents, parseOptions); // Generate a random file name for the assembly we're about to produce. string generatedAssemblyName = Path.GetRandomFileName(); // Get the directory of a core assembly. We need this directory to // build out our platform specific reference to mscorlib. mscorlib // and the private mscorlib must be supplied as references for // compilation to succeed. Of these two assemblies, only the private // mscorlib is discovered via enumerataing assemblies referenced by // this executing binary. var dd = typeof(Enumerable).GetTypeInfo().Assembly.Location; var coreDir = Directory.GetParent(dd); HashSet <string> allRefs = new HashSet <string>(); List <MetadataReference> references = new List <MetadataReference> { // Here we get the path to the mscorlib and private mscorlib // libraries that are required for compilation to succeed. MetadataReference.CreateFromFile(coreDir.FullName + Path.DirectorySeparatorChar + "mscorlib.dll"), MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location) }; // Enumerate all assemblies referenced by this executing assembly // and provide them as references to the build script we're about to // compile. var referencedAssemblies = RecursivelyGetReferencedAssemblies(Assembly.GetEntryAssembly()); foreach (var referencedAssembly in referencedAssemblies) { var mref = MetadataReference.CreateFromFile(referencedAssembly.Location); if (referencedAssembly.FullName.Contains("System.Runtime.Extension")) { // Have to do this to avoid collisions with duplicate type // definitions between private mscorlib and this assembly. // XXX TODO - Needs to be solved in a better way? mref = mref.WithAliases(new List <string>(new[] { "CorPrivate" })); } if (!allRefs.Contains(mref.Display)) { references.Add(mref); allRefs.Add(mref.Display); } /* For debugging, to try to list explicit platform compat. Flaky. * try * { * var customAttributes = loadedAssembly.GetCustomAttributes(); * var attribute = customAttributes.OfType<TargetFrameworkAttribute>().First(); * * Console.WriteLine(attribute.FrameworkName); * Console.WriteLine(attribute.FrameworkDisplayName); * } * catch{} */ } // Initialize compilation arguments for the build script we're about // to compile. var op = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary); op = op.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default); op = op.WithGeneralDiagnosticOption(ReportDiagnostic.Warn); // Initialize the compilation with our options, references and the // already parsed syntax tree of the build script. CSharpCompilation compilation = CSharpCompilation.Create( generatedAssemblyName, syntaxTrees: new[] { jobSyntaxTree }, references: references, options: op); // Compile and emit new assembly into memory. var ms = new MemoryStream(); EmitResult result = compilation.Emit(ms); if (result.Success) { // Store the in-memory assembly until this program exits. GeneratedAssemblies.Add(ms); // Get an Assembly structure from the data in memory. ms.Seek(0, SeekOrigin.Begin); AssemblyLoadContext loadCtx = AssemblyLoadContext.Default; Assembly assembly = loadCtx.LoadFromStream(ms); // Enumerate types exported from the assembly. Presently not used. var exportedTypes = assembly.ExportedTypes; foreach (var xp in exportedTypes) { Console.WriteLine(string.Format("Build script exports type: {0}", xp.Name)); } // Filter exported types so we only pull types extending from AbstractBuildTask. var filteredExports = exportedTypes.Where(x => x.Name != typeof(AbstractBuildTask).Name); Console.WriteLine(string.Format("Number of exported build objects: {0}", filteredExports.Count())); // Ensure that we have at least one exported build task. Debug.Assert(filteredExports.Count() > 0, "Script either does not export any AbstractBuildTask objects. Build scripts should export one or more AbstractBuildTask objects."); if (filteredExports.Count() <= 0) { throw new ArgumentException("Script either does not export any AbstractBuildTask objects. Build scripts should export one or more AbstractBuildTask objects.", nameof(taskScriptPath)); } var filteredExportsList = filteredExports.ToList(); List <AbstractBuildTask> buildTasks = new List <AbstractBuildTask>(); foreach (var entry in filteredExportsList) { AbstractBuildTask typedExport = (AbstractBuildTask)Activator.CreateInstance(entry, new[] { taskScriptPath.ConvertToHostOsPath() }); buildTasks.Add(typedExport); } return(buildTasks); } else { ms.Dispose(); Console.WriteLine(string.Format("Failed to compile build script: {0}.", taskScriptPath)); IEnumerable <Diagnostic> failures = result.Diagnostics.Where(diagnostic => diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error); foreach (Diagnostic diagnostic in failures) { Console.Error.WriteLine("{0}: {1}", diagnostic.Id, diagnostic.GetMessage()); } CleanExit(ExitCodes.ScriptCompilationFailure); } Console.WriteLine("null"); return(null); }