private LibraryExport ExportProject(ProjectDescription project, string aspect) { Logger.TraceInformation($"[{nameof(LibraryExporter)}]: {nameof(ExportProject)}({project.Identity.Name}, {aspect}, {project.Framework}, {_configuration})"); var key = Tuple.Create(project.Identity.Name, project.Framework, _configuration, aspect); return _compilationEngine.CompilationCache.Cache.Get<ProjectExportContext>(key, ctx => { var metadataReferences = new List<IMetadataReference>(); var sourceReferences = new List<ISourceReference>(); var context = new ProjectExportContext(); // Create the compilation context var compilationContext = project.Project.ToCompilationContext(project.Framework, _configuration, aspect); if (!string.IsNullOrEmpty(project.TargetFrameworkInfo?.AssemblyPath)) { // Project specifies a pre-compiled binary. We're done! var assemblyPath = ResolvePath(project.Project, _configuration, project.TargetFrameworkInfo.AssemblyPath); var pdbPath = ResolvePath(project.Project, _configuration, project.TargetFrameworkInfo.PdbPath); metadataReferences.Add(new CompiledProjectMetadataReference(compilationContext, assemblyPath, pdbPath)); } else { // We need to compile the project. var compilerTypeInfo = project.Project.CompilerServices?.ProjectCompiler ?? Project.DefaultCompiler; // Create the project exporter var exporter = _compilationEngine.CreateProjectExporter(project.Project, project.Framework, _configuration); context.LoadContext = _compilationEngine.CreateBuildLoadContext(project.Project, _configuration); // Get the exports for the project dependencies var projectDependenciesExport = new Lazy<LibraryExport>(() => exporter.GetAllDependencies(project.Identity.Name, aspect)); // Find the project compiler var projectCompiler = _compilationEngine.GetCompiler(compilerTypeInfo, context.LoadContext); Logger.TraceInformation($"[{nameof(LibraryExporter)}]: GetProjectReference({compilerTypeInfo.TypeName}, {project.Identity.Name}, {project.Framework}, {aspect})"); // Resolve the project export IMetadataProjectReference projectReference = projectCompiler.CompileProject( compilationContext, () => projectDependenciesExport.Value, () => CompositeResourceProvider.Default.GetResources(project.Project), _configuration); metadataReferences.Add(projectReference); // Shared sources foreach (var sharedFile in project.Project.Files.SharedFiles) { sourceReferences.Add(new SourceFileReference(sharedFile)); } } context.Export = new LibraryExport(metadataReferences, sourceReferences); return context; }).Export; }
public PublishProject(ProjectDescription projectDescription) { _projectDescription = projectDescription; }
private LibraryExport GetAllExports( ProjectDescription project, string aspect, Func<LibraryDescription, bool> include) { var dependencyStopWatch = Stopwatch.StartNew(); Logger.TraceInformation($"[{nameof(LibraryExporter)}]: Resolving references for '{project.Identity.Name}' {aspect}"); var references = new Dictionary<string, IMetadataReference>(StringComparer.OrdinalIgnoreCase); var sourceReferences = new Dictionary<string, ISourceReference>(StringComparer.OrdinalIgnoreCase); // Walk the dependency tree and resolve the library export for all references to this project var queue = new Queue<Node>(); var processed = new HashSet<string>(StringComparer.OrdinalIgnoreCase); var rootNode = new Node { Library = project }; queue.Enqueue(rootNode); while (queue.Count > 0) { var node = queue.Dequeue(); // Skip it if we've already seen it if (!processed.Add(node.Library.Identity.Name)) { continue; } if (include(node.Library)) { LibraryExport libraryExport = null; if (node.Library == project) { // We know it's a project so skip the lookup libraryExport = ExportProject(project, aspect: null, exporter: this); } else { libraryExport = GetExport(node.Library, aspect: null); } if (libraryExport != null) { if (node.Parent == rootNode) { // Only export sources from first level dependencies ProcessExport(libraryExport, references, sourceReferences); } else { // Skip source exports from anything else ProcessExport(libraryExport, references, sourceReferences: null); } } } foreach (var dependency in node.Library.Dependencies) { var childNode = new Node { Library = LibraryManager.GetLibraryDescription(dependency.Name), Parent = node }; queue.Enqueue(childNode); } } dependencyStopWatch.Stop(); Logger.TraceInformation($"[{nameof(LibraryExporter)}]: Resolved {references.Count} references for '{project.Identity.Name}' in {dependencyStopWatch.ElapsedMilliseconds}ms"); return new LibraryExport( references.Values.ToList(), sourceReferences.Values.ToList()); }