public IMetadataProjectReference CompileProject( CompilationProjectContext projectContext, Func<LibraryExport> referenceResolver, Func<IList<ResourceDescriptor>> resourcesResolver) { var export = referenceResolver(); if (export == null) { return null; } var incomingReferences = export.MetadataReferences; var incomingSourceReferences = export.SourceReferences; var compilationContext = _compiler.CompileProject( projectContext, incomingReferences, incomingSourceReferences, resourcesResolver); if (compilationContext == null) { return null; } // Project reference return new FSharpProjectReference(compilationContext); }
public CompiledProjectMetadataReference(CompilationProjectContext project, string assemblyPath, string pdbPath) { Name = project.Target.Name; ProjectPath = project.ProjectFilePath; Path = assemblyPath; _project = project; _assemblyPath = assemblyPath; _pdbPath = pdbPath; }
internal CompilationContext( CompilationProjectContext project, FSharpProjectInfo projectInfo, bool success, IEnumerable<FSharpDiagnosticMessage> messages, byte[] assembly, byte[] pdb, byte[] xml) { _project = project; ProjectInfo = projectInfo; Success = success; Diagnostics = messages.ToList(); Assembly = assembly; Pdb = pdb; Xml = xml; }
public DesignTimeProjectReference(CompilationProjectContext project, CompileResponse response) { _project = project; _response = response; }
public CompilationContext CompileProject( CompilationProjectContext projectContext, IEnumerable<IMetadataReference> incomingReferences, IEnumerable<ISourceReference> incomingSourceReferences, Func<IList<ResourceDescriptor>> resourcesResolver) { var path = projectContext.ProjectDirectory; var name = projectContext.Target.Name; var projectInfo = GetProjectInfo(projectContext.ProjectFilePath); if (_cacheContextAccessor.Current != null) { _cacheContextAccessor.Current.Monitor(new FileWriteTimeCacheDependency(projectContext.ProjectFilePath)); // Monitor the trigger {projectName}_BuildOutputs var buildOutputsName = name + "_BuildOutputs"; _cacheContextAccessor.Current.Monitor(_namedDependencyProvider.GetNamedDependency(buildOutputsName)); _cacheContextAccessor.Current.Monitor(_namedDependencyProvider.GetNamedDependency(name + "_Dependencies")); } Logger.TraceInformation("[{0}]: Compiling '{1}'", GetType().Name, name); var sw = Stopwatch.StartNew(); CompilationContext context; using (new ResolveHooker()) using (var files = new TempFiles()) { var outFileName = $"{name}.dll"; var outDir = files.CreateDir(); var outFile = Path.Combine(outDir, outFileName); var args = new List<string>(); args.Add("fsc.exe"); args.Add($"--out:{outFile}"); args.Add("--target:library"); args.Add("--noframework"); args.Add("--optimize-"); args.Add("--debug"); if (SupportsPdbGeneration) args.Add($"--pdb:{Path.ChangeExtension(outFile, ".pdb")}"); args.Add($"--doc:{Path.ChangeExtension(outFile, ".xml")}"); args.AddRange(projectInfo.Files); // These are the metadata references being used by your project. // Everything in your project.json is resolved and normailzed here: // - Project references // - Package references are turned into the appropriate assemblies // Each IMetadaReference maps to an assembly foreach (var reference in incomingReferences) { string fileName = null; var projectRef = reference as IMetadataProjectReference; if (projectRef != null) { var dir = files.CreateDir(); projectRef.EmitAssembly(dir); fileName = Path.Combine(dir, $"{projectRef.Name}.dll"); } var fileRef = reference as IMetadataFileReference; if (fileRef != null) fileName = fileRef.Path; else if (fileName == null) throw new Exception($"Unknown reference type {reference.GetType()}"); args.Add($"-r:{fileName}"); } //Console.WriteLine(string.Join(Environment.NewLine, args)); var scs = new SimpleSourceCodeServices(); var result = scs.Compile(args.ToArray()); var errors = result.Item1.Select(FSharpDiagnosticMessage.CompilationMessage); var resultCode = result.Item2; //System.Diagnostics.Debugger.Launch(); MemoryStream assembly = null; MemoryStream pdb = null; MemoryStream xml = null; if (resultCode == 0) { assembly = new MemoryStream(); xml = new MemoryStream(); using (var fs = File.OpenRead(outFile)) fs.CopyTo(assembly); var pdbFile = Path.ChangeExtension(outFile, ".pdb"); if (File.Exists(pdbFile)) { pdb = new MemoryStream(); using (var fs = File.OpenRead(pdbFile)) fs.CopyTo(pdb); } var xmlFile = Path.ChangeExtension(outFile, ".xml"); if (File.Exists(xmlFile)) { xml = new MemoryStream(); using (var fs = File.OpenRead(xmlFile)) fs.CopyTo(xml); } } context = new CompilationContext( projectContext, projectInfo, resultCode == 0, errors, assembly?.ToArray(), pdb?.ToArray(), xml?.ToArray()); assembly?.Dispose(); pdb?.Dispose(); xml?.Dispose(); } sw.Stop(); Logger.TraceInformation("[{0}]: Compiled '{1}' in {2}ms", GetType().Name, name, sw.ElapsedMilliseconds); return context; }
public CompilationContext CompileProject( CompilationProjectContext projectContext, IEnumerable<IMetadataReference> incomingReferences, IEnumerable<ISourceReference> incomingSourceReferences, Func<IList<ResourceDescriptor>> resourcesResolver) { var path = projectContext.ProjectDirectory; var name = projectContext.Target.Name.TrimStart('/'); var isMainAspect = string.IsNullOrEmpty(projectContext.Target.Aspect); var isPreprocessAspect = string.Equals(projectContext.Target.Aspect, "preprocess", StringComparison.OrdinalIgnoreCase); if (!string.IsNullOrEmpty(projectContext.Target.Aspect)) { name += "!" + projectContext.Target.Aspect; } _watcher.WatchProject(path); _watcher.WatchFile(projectContext.ProjectFilePath); if (_cacheContextAccessor.Current != null) { _cacheContextAccessor.Current.Monitor(new FileWriteTimeCacheDependency(projectContext.ProjectFilePath)); if (isMainAspect) { // Monitor the trigger {projectName}_BuildOutputs var buildOutputsName = projectContext.Target.Name + "_BuildOutputs"; _cacheContextAccessor.Current.Monitor(_namedDependencyProvider.GetNamedDependency(buildOutputsName)); } _cacheContextAccessor.Current.Monitor(_namedDependencyProvider.GetNamedDependency(projectContext.Target.Name + "_Dependencies")); } var exportedReferences = incomingReferences.Select(ConvertMetadataReference); Logger.TraceInformation("[{0}]: Compiling '{1}'", GetType().Name, name); var sw = Stopwatch.StartNew(); var compilationSettings = projectContext.CompilerOptions.ToCompilationSettings( projectContext.Target.TargetFramework); var sourceFiles = Enumerable.Empty<String>(); if (isMainAspect) { sourceFiles = projectContext.Files.SourceFiles; } else if (isPreprocessAspect) { sourceFiles = projectContext.Files.PreprocessSourceFiles; } var parseOptions = new CSharpParseOptions(languageVersion: compilationSettings.LanguageVersion, preprocessorSymbols: compilationSettings.Defines); IList<SyntaxTree> trees = GetSyntaxTrees( projectContext, sourceFiles, incomingSourceReferences, parseOptions, isMainAspect); var embeddedReferences = incomingReferences.OfType<IMetadataEmbeddedReference>() .ToDictionary(a => a.Name, ConvertMetadataReference); var references = new List<MetadataReference>(); references.AddRange(exportedReferences); var compilation = CSharpCompilation.Create( name, trees, references, compilationSettings.CompilationOptions); compilation = ApplyVersionInfo(compilation, projectContext, parseOptions); var compilationContext = new CompilationContext( compilation, projectContext, incomingReferences, () => resourcesResolver() .Select(res => new ResourceDescription( res.Name, res.StreamFactory, isPublic: true)) .ToList()); // Apply strong-name settings ApplyStrongNameSettings(compilationContext); if (isMainAspect && projectContext.Files.PreprocessSourceFiles.Any()) { try { var modules = GetCompileModules(projectContext.Target).Modules; foreach (var m in modules) { compilationContext.Modules.Add(m); } } catch (Exception ex) { var compilationException = ex.InnerException as RoslynCompilationException; if (compilationException != null) { // Add diagnostics from the precompile step foreach (var diag in compilationException.Diagnostics) { compilationContext.Diagnostics.Add(diag); } Logger.TraceError("[{0}]: Failed loading meta assembly '{1}'", GetType().Name, name); } else { Logger.TraceError("[{0}]: Failed loading meta assembly '{1}':\n {2}", GetType().Name, name, ex); } } } if (compilationContext.Modules.Count > 0) { var precompSw = Stopwatch.StartNew(); foreach (var module in compilationContext.Modules) { module.BeforeCompile(compilationContext.BeforeCompileContext); } precompSw.Stop(); Logger.TraceInformation("[{0}]: Compile modules ran in in {1}ms", GetType().Name, precompSw.ElapsedMilliseconds); } sw.Stop(); Logger.TraceInformation("[{0}]: Compiled '{1}' in {2}ms", GetType().Name, name, sw.ElapsedMilliseconds); return compilationContext; }
private IList<SyntaxTree> GetSyntaxTrees(CompilationProjectContext project, IEnumerable<string> sourceFiles, IEnumerable<ISourceReference> sourceReferences, CSharpParseOptions parseOptions, bool isMainAspect) { var trees = new List<SyntaxTree>(); var dirs = new HashSet<string>(); if (isMainAspect) { dirs.Add(project.ProjectDirectory); } foreach (var sourcePath in sourceFiles) { _watcher.WatchFile(sourcePath); var syntaxTree = CreateSyntaxTree(sourcePath, parseOptions); trees.Add(syntaxTree); } foreach (var sourceFileReference in sourceReferences.OfType<ISourceFileReference>()) { var sourcePath = sourceFileReference.Path; _watcher.WatchFile(sourcePath); var syntaxTree = CreateSyntaxTree(sourcePath, parseOptions); trees.Add(syntaxTree); } // Watch all directories var ctx = _cacheContextAccessor.Current; foreach (var d in dirs) { ctx?.Monitor(new FileWriteTimeCacheDependency(d)); // TODO: Make the file watcher hand out cache dependencies as well _watcher.WatchDirectory(d, ".cs"); } return trees; }
private static CSharpCompilation ApplyVersionInfo(CSharpCompilation compilation, CompilationProjectContext project, CSharpParseOptions parseOptions) { const string assemblyFileVersionName = "System.Reflection.AssemblyFileVersionAttribute"; const string assemblyVersionName = "System.Reflection.AssemblyVersionAttribute"; const string assemblyInformationalVersion = "System.Reflection.AssemblyInformationalVersionAttribute"; var assemblyAttributes = compilation.Assembly.GetAttributes(); var foundAssemblyFileVersion = false; var foundAssemblyVersion = false; var foundAssemblyInformationalVersion = false; foreach (var assembly in assemblyAttributes) { string attributeName = assembly.AttributeClass.ToString(); if (string.Equals(attributeName, assemblyFileVersionName, StringComparison.Ordinal)) { foundAssemblyFileVersion = true; } else if (string.Equals(attributeName, assemblyVersionName, StringComparison.Ordinal)) { foundAssemblyVersion = true; } else if (string.Equals(attributeName, assemblyInformationalVersion, StringComparison.Ordinal)) { foundAssemblyInformationalVersion = true; } } var versionAttributes = new StringBuilder(); if (!foundAssemblyFileVersion) { versionAttributes.AppendLine($"[assembly:{assemblyFileVersionName}(\"{project.AssemblyFileVersion}\")]"); } if (!foundAssemblyVersion) { versionAttributes.AppendLine($"[assembly:{assemblyVersionName}(\"{RemovePrereleaseTag(project.Version)}\")]"); } if (!foundAssemblyInformationalVersion) { versionAttributes.AppendLine($"[assembly:{assemblyInformationalVersion}(\"{project.Version}\")]"); } if (versionAttributes.Length != 0) { compilation = compilation.AddSyntaxTrees(new[] { CSharpSyntaxTree.ParseText(versionAttributes.ToString(), parseOptions) }); } return compilation; }
public IMetadataProjectReference CompileProject( CompilationProjectContext projectContext, Func<LibraryExport> referenceResolver, Func<IList<ResourceDescriptor>> resourcesResolver) { List<DiagnosticResult> diagnosticResults = new List<DiagnosticResult>(); var module = new PostSharpCompilerModule(_services, _workingDirectory); var export = referenceResolver(); if (export == null) { return null; } var incomingReferences = export.MetadataReferences; var incomingSourceReferences = export.SourceReferences; var processedIncomingReferences = new List<IMetadataReference>(incomingReferences.Count); foreach ( var reference in incomingReferences ) { var projectReference = reference as IMetadataProjectReference; if ( projectReference != null ) { // If we have a PostSharpProjectReference, we have to compile it using EmitAssembly and replace the reference by a MetadataFileReference. string referencePath = Path.Combine(_workingDirectory, projectReference.Name + ".dll"); if (!File.Exists(referencePath)) { DiagnosticResult diagnostics = projectReference.EmitAssembly(_workingDirectory); diagnosticResults.Add(diagnostics); } processedIncomingReferences.Add(new MetadataFileReference(projectReference.Name, referencePath)); } else { processedIncomingReferences.Add(reference); } } var compilationContext = _compiler.CompileProject( projectContext, processedIncomingReferences, incomingSourceReferences, resourcesResolver); if (compilationContext == null) { return null; } compilationContext.Modules.Add(module); // Project reference return new PostSharpProjectReference( new RoslynProjectReference(compilationContext), diagnosticResults, _workingDirectory ); }