diff --git a/src/NuGetUtility/NuGetUtility.csproj b/src/NuGetUtility/NuGetUtility.csproj index f3698afb..8b8722eb 100644 --- a/src/NuGetUtility/NuGetUtility.csproj +++ b/src/NuGetUtility/NuGetUtility.csproj @@ -36,18 +36,14 @@ - - - - - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/NuGetUtility/Program.cs b/src/NuGetUtility/Program.cs index 85abc631..5e72dd08 100644 --- a/src/NuGetUtility/Program.cs +++ b/src/NuGetUtility/Program.cs @@ -31,7 +31,7 @@ public class Program { [Option(ShortName = "i", LongName = "input", - Description = "The project (or solution) file who's dependencies should be analyzed")] + Description = "The project (or solution) file for which to analyze dependencies")] public string? InputFile { get; } = null; [Option(ShortName = "ji", @@ -90,9 +90,19 @@ public class Program [Option(LongName = "exclude-projects-matching", ShortName = "exclude-projects", - Description = "This option allows to specify project name(s) to exclude from the analysis. This can be useful to exclude test projects from the analysis when supplying a solution file as input. Wildcard characters (*) are supported to specify ranges of ignored projects. The input can either be a file name containing a list of project names in json format or a plain string that is then used as a single entry.")] + Description = "This option allows to specify project name(s) to exclude from the analysis. This can be useful to exclude test projects from the analysis when supplying a solution file as input. Wildcard characters (*) are supported to specify ranges of ignored projects. The input can either be a file name containing a list of project names in json format or a plain string that is then used as a single entry. Note: ignored projects will not be evaluated in any form and it's transitive dependencies will NOT be evaluated.")] public string? ExcludedProjects { get; } = null; + [Option(LongName = "build-configuration", + ShortName = "c", + Description = "This option allows to specify the build configuration to use. Generally it is not needed to specify this parameter. However when dealing with ci builds that only build a specific configuration, this parameter may be needed.")] + public string? BuildConfiguration { get; } = null; + + [Option(LongName = "platform", + ShortName = "p", + Description = "This option allows to specify the platform used to restore. Generally it is not needed to specify this parameter. However when dealing with ci builds that only build a specific configuration, this parameter may be needed.")] + public string? Platform { get; } = null; + private static string GetVersion() => typeof(Program).Assembly.GetCustomAttribute()?.InformationalVersion ?? string.Empty; @@ -107,7 +117,7 @@ private async Task OnExecuteAsync(CancellationToken cancellationToken) IFileDownloader urlLicenseFileDownloader = GetFileDownloader(httpClient); IOutputFormatter output = GetOutputFormatter(); - MsBuildAbstraction msBuild = new MsBuildAbstraction(); + MsBuildAbstraction msBuild = new MsBuildAbstraction(BuildConfiguration); var projectCollector = new ProjectsCollector(msBuild); var projectReader = new ReferencedPackageReader(msBuild, new LockFileFactory(), GetPackagesConfigReader()); var validator = new LicenseValidator.LicenseValidator(licenseMappings, @@ -152,7 +162,7 @@ private static IPackagesConfigReader GetPackagesConfigReader() #if NETFRAMEWORK return new WindowsPackagesConfigReader(); #else - return OperatingSystem.IsWindows() ? new WindowsPackagesConfigReader() : new FailingPackagesConfigReader(); + return OperatingSystem.IsWindows() ? new WindowsPackagesConfigReader() : new FailingPackagesConfigReader(); #endif } diff --git a/src/NuGetUtility/Wrapper/MsBuildWrapper/MsBuildAbstraction.cs b/src/NuGetUtility/Wrapper/MsBuildWrapper/MsBuildAbstraction.cs index e38e20de..d894fb82 100644 --- a/src/NuGetUtility/Wrapper/MsBuildWrapper/MsBuildAbstraction.cs +++ b/src/NuGetUtility/Wrapper/MsBuildWrapper/MsBuildAbstraction.cs @@ -3,7 +3,6 @@ using Microsoft.Build.Construction; using Microsoft.Build.Evaluation; -using Microsoft.Build.Exceptions; using Microsoft.Build.Execution; using Microsoft.Build.Framework; using Microsoft.Build.Locator; @@ -14,11 +13,17 @@ namespace NuGetUtility.Wrapper.MsBuildWrapper public class MsBuildAbstraction : IMsBuildAbstraction { private const string CollectPackageReferences = "CollectPackageReferences"; - private readonly Dictionary _globalProjectProperties = new(); + private readonly string? _buildConfiguration; + private readonly string? _platform; + private ProjectCollection? _projectCollection; - public MsBuildAbstraction() + public ProjectCollection ProjectCollection => _projectCollection ??= InitializeProjectCollection(_buildConfiguration, _platform); + + public MsBuildAbstraction(string? buildConfiguration = null, string? platform = null) { RegisterMsBuildLocatorIfNeeded(); + _buildConfiguration = buildConfiguration; + _platform = platform; } public IEnumerable GetPackageReferencesFromProjectForFramework(IProject project, @@ -48,9 +53,7 @@ public IProject GetProject(string projectPath) } #endif - ProjectRootElement rootElement = TryGetProjectRootElement(projectPath); - - var project = new Project(rootElement, _globalProjectProperties, null); + Project project = ProjectCollection.LoadProject(projectPath); return new ProjectWrapper(project); } @@ -70,18 +73,18 @@ private static void RegisterMsBuildLocatorIfNeeded() } } - private static ProjectRootElement TryGetProjectRootElement(string projectPath) + private static ProjectCollection InitializeProjectCollection(string? buildConfiguration, string? platform) { - try + ProjectCollection projectCollection = ProjectCollection.GlobalProjectCollection; + if (buildConfiguration != null) { - return ProjectRootElement.Open(projectPath, ProjectCollection.GlobalProjectCollection)!; + projectCollection.SetGlobalProperty("Configuration", buildConfiguration); } - catch (InvalidProjectFileException e) + if (platform != null) { - throw new MsBuildAbstractionException($"Failed to open project: {projectPath}", e); + projectCollection.SetGlobalProperty("Platform", platform); } + return projectCollection; } - - protected void AddGlobalProjectProperty(string name, string value) => _globalProjectProperties.Add(name, value); } }