diff --git a/src/Buildalyzer/Environment/BuildEnvironment.cs b/src/Buildalyzer/Environment/BuildEnvironment.cs index f3608cfb..3a098e3f 100644 --- a/src/Buildalyzer/Environment/BuildEnvironment.cs +++ b/src/Buildalyzer/Environment/BuildEnvironment.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Net.NetworkInformation; namespace Buildalyzer.Environment; @@ -101,25 +102,7 @@ public BuildEnvironment( }; if (DesignTime) { - // The actual design-time tasks aren't available outside of Visual Studio, - // so we can't do a "real" design-time build and have to fake it with various global properties - // See https://github.com/dotnet/msbuild/blob/fb700f90493a0bf47623511edf28b1d6c114e4fa/src/Tasks/Microsoft.CSharp.CurrentVersion.targets#L320 - // To diagnose build failures in design-time mode, generate a binary log and find the filing target, - // then see if there's a condition or property that can be used to modify it's behavior or turn it off - _globalProperties.Add(MsBuildProperties.DesignTimeBuild, "true"); - _globalProperties.Add(MsBuildProperties.BuildingProject, "false"); // Supports Framework projects: https://github.com/dotnet/project-system/blob/main/docs/design-time-builds.md#determining-whether-a-target-is-running-in-a-design-time-build - _globalProperties.Add(MsBuildProperties.BuildProjectReferences, "false"); - _globalProperties.Add(MsBuildProperties.SkipCompilerExecution, "true"); - _globalProperties.Add(MsBuildProperties.DisableRarCache, "true"); - _globalProperties.Add(MsBuildProperties.AutoGenerateBindingRedirects, "false"); - _globalProperties.Add(MsBuildProperties.CopyBuildOutputToOutputDirectory, "false"); - _globalProperties.Add(MsBuildProperties.CopyOutputSymbolsToOutputDirectory, "false"); - _globalProperties.Add(MsBuildProperties.CopyDocumentationFileToOutputDirectory, "false"); - _globalProperties.Add(MsBuildProperties.ComputeNETCoreBuildOutputFiles, "false"); // Prevents the CreateAppHost task from running, which doesn't add the apphost.exe to the files to copy - _globalProperties.Add(MsBuildProperties.SkipCopyBuildProduct, "true"); - _globalProperties.Add(MsBuildProperties.AddModules, "false"); - _globalProperties.Add(MsBuildProperties.UseCommonOutputDirectory, "true"); // This is used in a condition to prevent copying in _CopyFilesMarkedCopyLocal - _globalProperties.Add(MsBuildProperties.GeneratePackageOnBuild, "false"); // Prevent NuGet.Build.Tasks.Pack.targets from running the pack targets (since we didn't build anything) + _globalProperties = CopyItems(_globalProperties, MsBuildProperties.DesignTime); } _additionalGlobalProperties = CopyItems(_globalProperties, additionalGlobalProperties); @@ -128,7 +111,7 @@ public BuildEnvironment( _additionalEnvironmentVariables = CopyItems(_environmentVariables, additionalEnvironmentVariables); } - private Dictionary CopyItems(Dictionary destination, IDictionary source) + private Dictionary CopyItems(Dictionary destination, IEnumerable> source) { if (source != null) { diff --git a/src/Buildalyzer/Environment/MsBuildProperties.cs b/src/Buildalyzer/Environment/MsBuildProperties.cs index 9e6d8e15..4b0b8897 100644 --- a/src/Buildalyzer/Environment/MsBuildProperties.cs +++ b/src/Buildalyzer/Environment/MsBuildProperties.cs @@ -1,4 +1,7 @@ -namespace Buildalyzer.Environment; +using System; +using System.Collections.Generic; + +namespace Buildalyzer.Environment; public static class MsBuildProperties { @@ -12,8 +15,11 @@ public static class MsBuildProperties public const string TargetFramework = nameof(TargetFramework); // Design-time Build - public const string DesignTimeBuild = nameof(DesignTimeBuild); // New project system (https://github.com/dotnet/project-system/blob/main/docs/design-time-builds.md#determining-whether-a-target-is-running-in-a-design-time-build) - public const string BuildingProject = nameof(BuildingProject); // Legacy (https://github.com/dotnet/project-system/blob/main/docs/design-time-builds.md#determining-whether-a-target-is-running-in-a-design-time-build) + // New project system (https://github.com/dotnet/project-system/blob/main/docs/design-time-builds.md#determining-whether-a-target-is-running-in-a-design-time-build) + public const string DesignTimeBuild = nameof(DesignTimeBuild); + + // Legacy (https://github.com/dotnet/project-system/blob/main/docs/design-time-builds.md#determining-whether-a-target-is-running-in-a-design-time-build) + public const string BuildingProject = nameof(BuildingProject); public const string BuildProjectReferences = nameof(BuildProjectReferences); public const string SkipCompilerExecution = nameof(SkipCompilerExecution); public const string ProvideCommandLineArgs = nameof(ProvideCommandLineArgs); @@ -39,5 +45,43 @@ public static class MsBuildProperties // Others public const string GenerateResourceMSBuildArchitecture = nameof(GenerateResourceMSBuildArchitecture); public const string NonExistentFile = nameof(NonExistentFile); - public const string NoAutoResponse = nameof(NoAutoResponse); // See https://github.com/daveaglick/Buildalyzer/issues/211 + + // See https://github.com/daveaglick/Buildalyzer/issues/211 + public const string NoAutoResponse = nameof(NoAutoResponse); + + /// + /// Gets the MS Build properties equivalent to Visual Studio's DesignTime build. + /// + /// + /// The actual design-time tasks aren't available outside of Visual Studio, + /// so we can't do a "real" design-time build and have to fake it with various global properties + /// See https://github.com/dotnet/msbuild/blob/fb700f90493a0bf47623511edf28b1d6c114e4fa/src/Tasks/Microsoft.CSharp.CurrentVersion.targets#L320 + /// To diagnose build failures in design-time mode, generate a binary log and find the filing target, + /// then see if there's a condition or property that can be used to modify it's behavior or turn it off. + /// + public static readonly IReadOnlyDictionary DesignTime = new Dictionary(StringComparer.OrdinalIgnoreCase) + { + [DesignTimeBuild] = "true", + + // Supports Framework projects: https://github.com/dotnet/project-system/blob/main/docs/design-time-builds.md#determining-whether-a-target-is-running-in-a-design-time-build + [BuildingProject] = "false", + [BuildProjectReferences] = "false", + [SkipCompilerExecution] = "true", + [DisableRarCache] = "true", + [AutoGenerateBindingRedirects] = "false", + [CopyBuildOutputToOutputDirectory] = "false", + [CopyOutputSymbolsToOutputDirectory] = "false", + [CopyDocumentationFileToOutputDirectory] = "false", + + // Prevents the CreateAppHost task from running, which doesn't add the apphost.exe to the files to copy + [ComputeNETCoreBuildOutputFiles] = "false", + [SkipCopyBuildProduct] = "true", + [AddModules] = "false", + + // This is used in a condition to prevent copying in _CopyFilesMarkedCopyLocal + [UseCommonOutputDirectory] = "true", + + // Prevent NuGet.Build.Tasks.Pack.targets from running the pack targets (since we didn't build anything) + [GeneratePackageOnBuild] = "false", + }; } \ No newline at end of file diff --git a/tests/Buildalyzer.Tests/Buildalyzer.Tests.csproj b/tests/Buildalyzer.Tests/Buildalyzer.Tests.csproj index 4a5ec500..9a6751c4 100644 --- a/tests/Buildalyzer.Tests/Buildalyzer.Tests.csproj +++ b/tests/Buildalyzer.Tests/Buildalyzer.Tests.csproj @@ -6,6 +6,7 @@ + @@ -15,7 +16,7 @@ - + diff --git a/tests/Buildalyzer.Tests/Environment/MsBuildPropertiesFixture.cs b/tests/Buildalyzer.Tests/Environment/MsBuildPropertiesFixture.cs new file mode 100644 index 00000000..8f8c33d9 --- /dev/null +++ b/tests/Buildalyzer.Tests/Environment/MsBuildPropertiesFixture.cs @@ -0,0 +1,29 @@ +using Buildalyzer.Environment; +using FluentAssertions; + +namespace Buildalyzer.Tests.Environment; + +public class MsBuildPropertiesFixture +{ + [Test] + public void Provides_DesignTime_properties() + { + MsBuildProperties.DesignTime.Should().BeEquivalentTo(new Dictionary + { + ["DesignTimeBuild"] = "true", + ["BuildingProject"] = "false", + ["BuildProjectReferences"] = "false", + ["SkipCompilerExecution"] = "true", + ["DisableRarCache"] = "true", + ["AutoGenerateBindingRedirects"] = "false", + ["CopyBuildOutputToOutputDirectory"] = "false", + ["CopyOutputSymbolsToOutputDirectory"] = "false", + ["CopyDocumentationFileToOutputDirectory"] = "false", + ["ComputeNETCoreBuildOutputFiles"] = "false", + ["SkipCopyBuildProduct"] = "true", + ["AddModules"] = "false", + ["UseCommonOutputDirectory"] = "true", + ["GeneratePackageOnBuild"] = "false", + }); + } +} diff --git a/tests/Buildalyzer.Tests/Properties/GlobalUsings.cs b/tests/Buildalyzer.Tests/Properties/GlobalUsings.cs new file mode 100644 index 00000000..f06262c9 --- /dev/null +++ b/tests/Buildalyzer.Tests/Properties/GlobalUsings.cs @@ -0,0 +1,6 @@ +global using System; +global using System.Collections.Generic; +global using System.Linq; +global using System.Text; +global using System.Threading.Tasks; +global using NUnit.Framework; \ No newline at end of file