public async ValueTask <object?> Run(string solutionFilePath, string projectName, CancellationToken cancellationToken = default) { _logger.LogDebug("Loading solution from {0}", solutionFilePath); var solution = await _solutionFactory.ParseFromFileAsync(solutionFilePath).ConfigureAwait(false); _logger.LogDebug("Found solution"); _logger.LogDebug("Creating build order"); var transitiveDependencies = ProjectDependencyOrganizer .GetTransitiveDependencies(solution.Projects, projectName); var buildOrder = ProjectDependencyOrganizer .CreateBuildOrder(transitiveDependencies); if (_logger.IsEnabled(LogLevel.Debug)) { _logger.LogDebug($"Build order is {string.Join(",", buildOrder.Select(x => x.Name))}"); } _logger.LogDebug("Loading dependencies"); var assemblyLoadContext = new AssemblyLoadContext(name: null, isCollectible: true); try { var projects = await LoadProjects( solution, buildOrder, assemblyLoadContext, cancellationToken); _logger.LogDebug("Compiling projects"); Assembly?assembly = null; foreach (var project in projects) { assembly = TryCompileProjectInMemory( assemblyLoadContext, project); if (assembly is null) { return(null); } } if (assembly !.EntryPoint is null) { throw new FlcException($"{projectName} does not have a Main method suitable for entry"); } _logger.LogDebug("Running {0}", projectName); return(assembly.EntryPoint.Invoke(null, null)); } finally { assemblyLoadContext.Unload(); } }
public void ShouldDetectSimpleCycles() { var projects = new[] { Project("p1", "p2"), Project("p2", "p1"), }; Assert.Throws <FlcException>(() => ProjectDependencyOrganizer.CreateBuildOrder(projects).ToList()); }
public void ShouldOrderDependenciesInPassedInOrderWhenMultipleAvailable() { var projects = new[] { Project("p1"), Project("p4", "p2", "p3"), Project("p2", "p1"), Project("p3", "p1"), }; Assert.Equal( new[] { projects[0], projects[2], projects[3], projects[1] }, ProjectDependencyOrganizer.CreateBuildOrder(projects)); }
public void ShouldIgnoreNonProjectReferences() { var projects = new[] { new ProjectInfo( "p1", new Version(0, 0), ImmutableArray.Create(""), references: ImmutableArray.Create(new Reference(Reference.ReferenceType.Assembly, "", ""))), }; Assert.Equal( projects, ProjectDependencyOrganizer.CreateBuildOrder(projects)); }
public async ValueTask <bool> Build(string solutionFilePath, string outputDirectory, bool outputCSharp, bool test, CancellationToken cancellationToken = default) { _logger.LogDebug("Loading solution from {0}", solutionFilePath); var solution = await _solutionFactory.ParseFromFileAsync(solutionFilePath).ConfigureAwait(false); _logger.LogDebug("Found solution"); _logger.LogDebug("Creating build order"); var buildOrder = ProjectDependencyOrganizer.CreateBuildOrder(solution.Projects).ToList(); if (_logger.IsEnabled(LogLevel.Debug)) { _logger.LogDebug($"Build order is {string.Join(",", buildOrder.Select(x => x.Name))}"); } _logger.LogDebug("Loading dependencies"); var assemblyLoadContext = new AssemblyLoadContext(name: null, isCollectible: true); try { var projects = await LoadProjects( solution, buildOrder, assemblyLoadContext, cancellationToken); _logger.LogDebug("Compiling projects"); var assemblies = new List <Assembly>(); foreach (var project in projects) { var assembly = await TryCompileProject( outputDirectory, outputCSharp, assemblyLoadContext, project, cancellationToken); if (assembly is null) { return(false); } assemblies.Add(assembly); } if (test) { _logger.LogDebug("Running tests"); TestResult?testResults = null; foreach (var(project, assembly) in buildOrder.Zip(assemblies)) { if (project.IsTest) { var results = TestRunner.RunTests(assembly); testResults = testResults is null ? results : results.Merge(testResults); } } _logger.LogInformation(testResults?.GetMessage() ?? "No tests found to run"); if (testResults is TestResult.Failure) { return(false); } } return(true); } finally { assemblyLoadContext.Unload(); } }