public CompilationContext CompileProject( Project project, ILibraryKey target, IEnumerable<IMetadataReference> incomingReferences, IEnumerable<ISourceReference> incomingSourceReferences, IList<IMetadataReference> outgoingReferences) { var path = project.ProjectDirectory; var name = project.Name; var isMainAspect = string.IsNullOrEmpty(target.Aspect); var isPreprocessAspect = string.Equals(target.Aspect, "preprocess", StringComparison.OrdinalIgnoreCase); if (!string.IsNullOrEmpty(target.Aspect)) { name += "!" + target.Aspect; } _watcher.WatchProject(path); _watcher.WatchFile(project.ProjectFilePath); if (_cacheContextAccessor.Current != null) { _cacheContextAccessor.Current.Monitor(new FileWriteTimeCacheDependency(project.ProjectFilePath)); if (isMainAspect) { // Monitor the trigger {projectName}_BuildOutputs var buildOutputsName = project.Name + "_BuildOutputs"; _cacheContextAccessor.Current.Monitor(_namedDependencyProvider.GetNamedDependency(buildOutputsName)); } } var exportedReferences = incomingReferences.Select(ConvertMetadataReference); Trace.TraceInformation("[{0}]: Compiling '{1}'", GetType().Name, name); var sw = Stopwatch.StartNew(); var compilationSettings = project.GetCompilerOptions(target.TargetFramework, target.Configuration) .ToCompilationSettings(target.TargetFramework); var sourceFiles = Enumerable.Empty<String>(); if (isMainAspect) { sourceFiles = project.SourceFiles; } else if (isPreprocessAspect) { sourceFiles = project.PreprocessSourceFiles; } var parseOptions = new CSharpParseOptions(languageVersion: compilationSettings.LanguageVersion, preprocessorSymbols: compilationSettings.Defines); IList<SyntaxTree> trees = GetSyntaxTrees( project, 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); var aniSw = Stopwatch.StartNew(); Trace.TraceInformation("[{0}]: Scanning '{1}' for assembly neutral interfaces", GetType().Name, name); var assemblyNeutralWorker = new AssemblyNeutralWorker(compilation, embeddedReferences); assemblyNeutralWorker.FindTypeCompilations(compilation.Assembly.GlobalNamespace); assemblyNeutralWorker.OrderTypeCompilations(); var assemblyNeutralTypeDiagnostics = assemblyNeutralWorker.GenerateTypeCompilations(); assemblyNeutralWorker.Generate(); aniSw.Stop(); Trace.TraceInformation("[{0}]: Found {1} assembly neutral interfaces for '{2}' in {3}ms", GetType().Name, assemblyNeutralWorker.TypeCompilations.Count(), name, aniSw.ElapsedMilliseconds); foreach (var t in assemblyNeutralWorker.TypeCompilations) { outgoingReferences.Add(new EmbeddedMetadataReference(t)); } var newCompilation = assemblyNeutralWorker.Compilation; newCompilation = ApplyVersionInfo(newCompilation, project, parseOptions); var compilationContext = new CompilationContext(newCompilation, incomingReferences.Concat(outgoingReferences).ToList(), assemblyNeutralTypeDiagnostics, project); var modules = new List<ICompileModule>(); if (isMainAspect && project.PreprocessSourceFiles.Any()) { try { modules = GetCompileModules(target).Modules; } 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); } Trace.TraceError("[{0}]: Failed loading meta assembly '{1}'", GetType().Name, name); } else { Trace.TraceError("[{0}]: Failed loading meta assembly '{1}':\n {2}", GetType().Name, name, ex); } } } if (modules.Count > 0) { var precompSw = Stopwatch.StartNew(); foreach (var module in modules) { module.BeforeCompile(compilationContext); } precompSw.Stop(); Trace.TraceInformation("[{0}]: Compile modules ran in in {1}ms", GetType().Name, precompSw.ElapsedMilliseconds); } sw.Stop(); Trace.TraceInformation("[{0}]: Compiled '{1}' in {2}ms", GetType().Name, name, sw.ElapsedMilliseconds); return compilationContext; }