Skip to content

Commit

Permalink
Define the MS Build design time as read-only data structure.
Browse files Browse the repository at this point in the history
  • Loading branch information
Corniel committed Feb 20, 2024
1 parent cead556 commit ad158b4
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 25 deletions.
23 changes: 3 additions & 20 deletions src/Buildalyzer/Environment/BuildEnvironment.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.NetworkInformation;

namespace Buildalyzer.Environment;

Expand Down Expand Up @@ -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);

Expand All @@ -128,7 +111,7 @@ public BuildEnvironment(
_additionalEnvironmentVariables = CopyItems(_environmentVariables, additionalEnvironmentVariables);
}

private Dictionary<string, string> CopyItems(Dictionary<string, string> destination, IDictionary<string, string> source)
private Dictionary<string, string> CopyItems(Dictionary<string, string> destination, IEnumerable<KeyValuePair<string, string>> source)
{
if (source != null)
{
Expand Down
52 changes: 48 additions & 4 deletions src/Buildalyzer/Environment/MsBuildProperties.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
namespace Buildalyzer.Environment;
using System;
using System.Collections.Generic;

namespace Buildalyzer.Environment;

public static class MsBuildProperties
{
Expand All @@ -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);
Expand All @@ -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);

/// <summary>
/// Gets the MS Build properties equivalent to Visual Studio's DesignTime build.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
public static readonly IReadOnlyDictionary<string, string> DesignTime = new Dictionary<string, string>(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

Check warning on line 66 in src/Buildalyzer/Environment/MsBuildProperties.cs

View workflow job for this annotation

GitHub Actions / Build (windows-latest)

Check warning on line 66 in src/Buildalyzer/Environment/MsBuildProperties.cs

View workflow job for this annotation

GitHub Actions / Build (windows-latest)

Check warning on line 66 in src/Buildalyzer/Environment/MsBuildProperties.cs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest)

Check warning on line 66 in src/Buildalyzer/Environment/MsBuildProperties.cs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest)

Check warning on line 66 in src/Buildalyzer/Environment/MsBuildProperties.cs

View workflow job for this annotation

GitHub Actions / Build (macos-latest)

Check warning on line 66 in src/Buildalyzer/Environment/MsBuildProperties.cs

View workflow job for this annotation

GitHub Actions / Build (macos-latest)

[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",
};
}
3 changes: 2 additions & 1 deletion tests/Buildalyzer.Tests/Buildalyzer.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="LibGit2Sharp" Version="0.27.0-preview-0175" />
<PackageReference Include="NUnit" Version="4.0.1" />
<PackageReference Include="NUnit3TestAdapter" Version="*" PrivateAssets="all" />
Expand All @@ -15,7 +16,7 @@
</ItemGroup>

<ItemGroup Label="Analyzers">
<PackageReference Include="NUnit.Analyzers" Version="*" PrivateAssets="All"/>
<PackageReference Include="NUnit.Analyzers" Version="*" PrivateAssets="All" />
</ItemGroup>

<ItemGroup>
Expand Down
29 changes: 29 additions & 0 deletions tests/Buildalyzer.Tests/Environment/MsBuildPropertiesFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Buildalyzer.Environment;
using FluentAssertions;

namespace Buildalyzer.Tests.Environment;

public class MsBuildPropertiesFixture
{
[Test]
public void Provides_DesignTime_properties()

Check warning on line 9 in tests/Buildalyzer.Tests/Environment/MsBuildPropertiesFixture.cs

View workflow job for this annotation

GitHub Actions / Build (windows-latest)

Remove the underscores from member name Buildalyzer.Tests.Environment.MsBuildPropertiesFixture.Provides_DesignTime_properties() (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1707)

Check warning on line 9 in tests/Buildalyzer.Tests/Environment/MsBuildPropertiesFixture.cs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest)

Remove the underscores from member name Buildalyzer.Tests.Environment.MsBuildPropertiesFixture.Provides_DesignTime_properties() (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1707)

Check warning on line 9 in tests/Buildalyzer.Tests/Environment/MsBuildPropertiesFixture.cs

View workflow job for this annotation

GitHub Actions / Build (macos-latest)

Remove the underscores from member name Buildalyzer.Tests.Environment.MsBuildPropertiesFixture.Provides_DesignTime_properties() (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1707)
{
MsBuildProperties.DesignTime.Should().BeEquivalentTo(new Dictionary<string, string>
{
["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",
});
}
}
6 changes: 6 additions & 0 deletions tests/Buildalyzer.Tests/Properties/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -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;

0 comments on commit ad158b4

Please sign in to comment.