Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define the MS Build design time as read-only data structure #254

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 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 @@
// 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;
Loading