Skip to content
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
42 changes: 42 additions & 0 deletions MSBuild.sln
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MSBuild.VSSetup.Arm64", "sr
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Build.Analyzers", "src\Analyzers\Microsoft.Build.Analyzers.csproj", "{512E01F7-2899-433B-93E2-D63B43AF0420}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Build.Analyzers.UnitTests", "src\Analyzers.UnitTests\Microsoft.Build.Analyzers.UnitTests.csproj", "{B18BAE17-D78F-4F89-B7A4-808C05E64D73}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -1384,6 +1386,46 @@ Global
{512E01F7-2899-433B-93E2-D63B43AF0420}.Release-MONO|x64.Build.0 = Release-MONO|x64
{512E01F7-2899-433B-93E2-D63B43AF0420}.Release-MONO|x86.ActiveCfg = Release-MONO|Any CPU
{512E01F7-2899-433B-93E2-D63B43AF0420}.Release-MONO|x86.Build.0 = Release-MONO|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug|ARM64.ActiveCfg = Debug|arm64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug|ARM64.Build.0 = Debug|arm64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug|x64.ActiveCfg = Debug|x64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug|x64.Build.0 = Debug|x64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug|x86.ActiveCfg = Debug|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug|x86.Build.0 = Debug|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug-MONO|Any CPU.ActiveCfg = Debug-MONO|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug-MONO|Any CPU.Build.0 = Debug-MONO|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug-MONO|ARM64.ActiveCfg = Debug-MONO|arm64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug-MONO|ARM64.Build.0 = Debug-MONO|arm64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug-MONO|x64.ActiveCfg = Debug-MONO|x64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug-MONO|x64.Build.0 = Debug-MONO|x64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug-MONO|x86.ActiveCfg = Debug-MONO|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Debug-MONO|x86.Build.0 = Debug-MONO|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.MachineIndependent|Any CPU.ActiveCfg = MachineIndependent|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.MachineIndependent|Any CPU.Build.0 = MachineIndependent|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.MachineIndependent|ARM64.ActiveCfg = MachineIndependent|arm64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.MachineIndependent|ARM64.Build.0 = MachineIndependent|arm64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.MachineIndependent|x64.ActiveCfg = MachineIndependent|x64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.MachineIndependent|x64.Build.0 = MachineIndependent|x64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.MachineIndependent|x86.ActiveCfg = MachineIndependent|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.MachineIndependent|x86.Build.0 = MachineIndependent|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release|Any CPU.Build.0 = Release|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release|ARM64.ActiveCfg = Release|arm64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release|ARM64.Build.0 = Release|arm64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release|x64.ActiveCfg = Release|x64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release|x64.Build.0 = Release|x64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release|x86.ActiveCfg = Release|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release|x86.Build.0 = Release|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release-MONO|Any CPU.ActiveCfg = Release-MONO|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release-MONO|Any CPU.Build.0 = Release-MONO|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release-MONO|ARM64.ActiveCfg = Release-MONO|arm64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release-MONO|ARM64.Build.0 = Release-MONO|arm64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release-MONO|x64.ActiveCfg = Release-MONO|x64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release-MONO|x64.Build.0 = Release-MONO|x64
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release-MONO|x86.ActiveCfg = Release-MONO|Any CPU
{B18BAE17-D78F-4F89-B7A4-808C05E64D73}.Release-MONO|x86.Build.0 = Release-MONO|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
21 changes: 21 additions & 0 deletions eng/BootStrapMSBuild.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project>

<!--
Construct a location of MSBuild bootstrap folder - to be used for deployment and for tests
relying on bootstrapped MSBuild
-->

<PropertyGroup>
<BootstrapDestination>$(ArtifactsBinDir)bootstrap\</BootstrapDestination>
<BootstrapDestination Condition="'$(Platform)' == 'x64' or '$(Platform)' == 'arm64'">$(BootstrapDestination)$(Platform)\</BootstrapDestination>
<BootstrapDestination>$(BootstrapDestination)$(TargetFramework.ToLowerInvariant())\MSBuild\</BootstrapDestination>
</PropertyGroup>

<PropertyGroup Condition="$(TargetFramework.StartsWith('net4'))">
<BootstrapBinaryDestination>$(BootstrapDestination)$(TargetMSBuildToolsVersion)\Bin</BootstrapBinaryDestination>
</PropertyGroup>

<PropertyGroup Condition="!$(TargetFramework.StartsWith('net4'))">
<BootstrapBinaryDestination>$(BootstrapDestination)</BootstrapBinaryDestination>
</PropertyGroup>
</Project>
6 changes: 2 additions & 4 deletions eng/BootStrapMSBuild.targets
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
<Project>

<Import Project="..\..\eng\BootStrapMSBuild.props" />

<!--
Copies the binaries of MSBuild to a bootstrap folder so we can rebuild msbuild with itself.
On netcore and mono it performs a directory copy.
On full framework it performs a more involved deployment.
-->

<PropertyGroup>
<BootstrapDestination>$(ArtifactsBinDir)bootstrap\</BootstrapDestination>
<BootstrapDestination Condition="'$(Platform)' == 'x64' or '$(Platform)' == 'arm64'">$(BootstrapDestination)$(Platform)\</BootstrapDestination>
<BootstrapDestination>$(BootstrapDestination)$(TargetFramework.ToLowerInvariant())\MSBuild\</BootstrapDestination>

<!-- TODO: Mono build should use BootstrapNetCore logic -->
<BootstrapDependsOn Condition="$(TargetFramework.StartsWith('net4'))">BootstrapFull</BootstrapDependsOn>
<BootstrapDependsOn Condition="!$(TargetFramework.StartsWith('net4'))">BootstrapNetCore</BootstrapDependsOn>
Expand Down
14 changes: 14 additions & 0 deletions src/Analyzers.UnitTests/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

global using NativeMethodsShared = Microsoft.Build.Framework.NativeMethods;

namespace Microsoft.Build.Analyzers.UnitTests;

[System.AttributeUsage(System.AttributeTargets.Assembly)]
internal sealed class BootstrapLocationAttribute(string bootstrapRoot, string bootstrapMsbuildBinaryLocation)
: System.Attribute
{
public string BootstrapRoot { get; } = bootstrapRoot;
public string BootstrapMsbuildBinaryLocation { get; } = bootstrapMsbuildBinaryLocation;
}
37 changes: 37 additions & 0 deletions src/Analyzers.UnitTests/BootstrapRunner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Build.UnitTests.Shared;
using Xunit.Abstractions;

namespace Microsoft.Build.Analyzers.UnitTests
{
internal static class BootstrapRunner
{
// This should ideally be part of RunnerUtilities - however then we'd need to enforce
// all test projects to import the BootStrapMSBuild.props file and declare the BootstrapLocationAttribute.
// Better solution would be to have a single test utility project - instead of linked code files.
public static string ExecBootstrapedMSBuild(string msbuildParameters, out bool successfulExit, bool shellExecute = false, ITestOutputHelper outputHelper = null)
{
var binaryFolder = Assembly.GetExecutingAssembly()
.GetCustomAttribute<BootstrapLocationAttribute>()!
.BootstrapMsbuildBinaryLocation;

#if NET
string pathToExecutable = EnvironmentProvider.GetDotnetExePath()!;
msbuildParameters = Path.Combine(binaryFolder, "msbuild.dll") + " " + msbuildParameters;
#else
string pathToExecutable =
Path.Combine(binaryFolder, "msbuild.exe");
#endif
return RunnerUtilities.RunProcessAndGetOutput(pathToExecutable, msbuildParameters, out successfulExit, shellExecute, outputHelper);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Build.UnitTests;
Expand All @@ -13,7 +14,7 @@
using Xunit;
using Xunit.Abstractions;

namespace Microsoft.Build.Engine.UnitTests.Analyzers
namespace Microsoft.Build.Analyzers.UnitTests
{
public class EndToEndTests
{
Expand All @@ -27,8 +28,6 @@ public EndToEndTests(ITestOutputHelper output)
}

[Fact]
// WARNING!: this test is using a bootstrap - so a build.cmd needs to be run prior this test can properly capture the
// changes in the production code
public void SampleAnalyzerIntegrationTest()
{
using (TestEnvironment env = TestEnvironment.Create())
Expand Down Expand Up @@ -113,7 +112,7 @@ public void SampleAnalyzerIntegrationTest()
// env.SetEnvironmentVariable("MSBUILDNOINPROCNODE", "1");
env.SetEnvironmentVariable("MSBUILDLOGPROPERTIESANDITEMSAFTEREVALUATION", "1");
// string output = RunnerUtilities.ExecMSBuild($"{projectFile.Path} /m:1 -nr:False", out bool success);
string output = RunnerUtilities.ExecBootstrapedMSBuild($"{projectFile.Path} /m:1 -nr:False -restore", out bool success);
string output = BootstrapRunner.ExecBootstrapedMSBuild($"{projectFile.Path} /m:1 -nr:False -restore", out bool success);
_env.Output.WriteLine(output);
success.ShouldBeTrue();
// The conflicting outputs warning appears
Expand Down
94 changes: 94 additions & 0 deletions src/Analyzers.UnitTests/Microsoft.Build.Analyzers.UnitTests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<Project Sdk="Microsoft.NET.Sdk">

<Import Project="..\Shared\FileSystemSources.proj" />
<Import Project="..\Shared\DebuggingSources.proj" />

<PropertyGroup>
<TargetFrameworks>$(RuntimeOutputTargetFrameworks)</TargetFrameworks>
<PlatformTarget>$(RuntimeOutputPlatformTarget)</PlatformTarget>
<IsPackable>false</IsPackable>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<RootNamespace>Microsoft.Build.Analyzers.UnitTests</RootNamespace>
<AssemblyName>Microsoft.Build.Analyzers.UnitTests</AssemblyName>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Analyzers\Microsoft.Build.Analyzers.csproj" />
<ProjectReference Include="..\Xunit.NetCore.Extensions\Xunit.NetCore.Extensions.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="System.Collections.Immutable" />
<PackageReference Include="FluentAssertions" />
<PackageReference Include="Microsoft.IO.Redist" Condition="'$(FeatureMSIORedist)' == 'true'" />
<PackageReference Include="Microsoft.VisualStudio.Setup.Configuration.Interop" PrivateAssets="all" Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'" />
<PackageReference Include="Shouldly" />
<PackageReference Include="System.Net.Http" />
</ItemGroup>

<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>

<ItemGroup>
<Compile Include="..\Shared\UnitTests\TestEnvironment.cs" >
<Link>Shared\TestEnvironment.cs</Link>
</Compile>

<Compile Include="..\Shared\FileUtilities.cs" >
<Link>Shared\FileUtilities.cs</Link>
</Compile>
<Compile Include="..\Shared\TempFileUtilities.cs" >
<Link>Shared\TempFileUtilities.cs</Link>
</Compile>
<Compile Include="..\Shared\ErrorUtilities.cs" >
<Link>Shared\ErrorUtilities.cs</Link>
</Compile>
<Compile Include="..\Shared\EscapingUtilities.cs" >
<Link>Shared\EscapingUtilities.cs</Link>
</Compile>
<Compile Include="..\Shared\BuildEnvironmentHelper.cs" >
<Link>Shared\BuildEnvironmentHelper.cs</Link>
</Compile>
<Compile Include="..\Shared\ProcessExtensions.cs" >
<Link>Shared\ProcessExtensions.cs</Link>
</Compile>
<Compile Include="..\Shared\ResourceUtilities.cs" >
<Link>Shared\ResourceUtilities.cs</Link>
</Compile>
<Compile Include="..\Shared\ExceptionHandling.cs" >
<Link>Shared\ExceptionHandling.cs</Link>
</Compile>
<Compile Include="..\Shared\FileUtilitiesRegex.cs" >
<Link>Shared\FileUtilitiesRegex.cs</Link>
</Compile>
<Compile Include="..\Shared\UnitTests\AssemblyResources.cs" >
<Link>Shared\AssemblyResources.cs</Link>
</Compile>
<Compile Include="..\UnitTests.Shared\RunnerUtilities.cs" >
<Link>Shared\RunnerUtilities.cs</Link>
</Compile>
<Compile Include="..\UnitTests.Shared\EnvironmentProvider.cs" >
<Link>Shared\EnvironmentProvider.cs</Link>
</Compile>
</ItemGroup>

<ItemGroup>
<None Include="..\Shared\UnitTests\App.config">
<Link>App.config</Link>
<SubType>Designer</SubType>
</None>
<None Include="..\Shared\UnitTests\xunit.runner.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

<Import Project="..\..\eng\BootStrapMSBuild.props" />

<ItemGroup>
<AssemblyAttribute Include="Microsoft.Build.Analyzers.UnitTests.BootstrapLocationAttribute">
<_Parameter1>$(ArtifactsBinDir)</_Parameter1>
<_Parameter2>$(BootstrapBinaryDestination)</_Parameter2>
</AssemblyAttribute>
</ItemGroup>
</Project>
1 change: 1 addition & 0 deletions src/Framework/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
[assembly: InternalsVisibleTo("Microsoft.Build.Conversion.Core, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")]

[assembly: InternalsVisibleTo("Microsoft.Build.Engine.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010015c01ae1f50e8cc09ba9eac9147cf8fd9fce2cfe9f8dce4f7301c4132ca9fb50ce8cbf1df4dc18dd4d210e4345c744ecb3365ed327efdbc52603faa5e21daa11234c8c4a73e51f03bf192544581ebe107adee3a34928e39d04e524a9ce729d5090bfd7dad9d10c722c0def9ccc08ff0a03790e48bcd1f9b6c476063e1966a1c4")]
[assembly: InternalsVisibleTo("Microsoft.Build.Analyzers.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010015c01ae1f50e8cc09ba9eac9147cf8fd9fce2cfe9f8dce4f7301c4132ca9fb50ce8cbf1df4dc18dd4d210e4345c744ecb3365ed327efdbc52603faa5e21daa11234c8c4a73e51f03bf192544581ebe107adee3a34928e39d04e524a9ce729d5090bfd7dad9d10c722c0def9ccc08ff0a03790e48bcd1f9b6c476063e1966a1c4")]
// Ideally we wouldn't need to IVT to OM.UnitTests, which is supposed to test
// only the public surface area of Microsoft.Build. However, there's a bunch
// of shared code in Framework that's used there, and we can still avoid IVT
Expand Down
18 changes: 0 additions & 18 deletions src/UnitTests.Shared/RunnerUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,24 +33,6 @@ public static string ExecMSBuild(string msbuildParameters, out bool successfulEx
return ExecMSBuild(PathToCurrentlyRunningMsBuildExe, msbuildParameters, out successfulExit, outputHelper: outputHelper);
}

/// <summary>
/// Invoke the currently running msbuild and return the stdout, stderr, and process exit status.
/// This method may invoke msbuild via other runtimes.
/// </summary>
public static string ExecBootstrapedMSBuild(string msbuildParameters, out bool successfulExit, bool shellExecute = false, ITestOutputHelper outputHelper = null)
{
// TODO: use proper way of passing the bootsrtrap location: https://github.com/dotnet/msbuild/issues/9729
string basePath = PathToCurrentlyRunningMsBuildExe.Substring(0, PathToCurrentlyRunningMsBuildExe.IndexOf(@"artifacts\bin", StringComparison.InvariantCultureIgnoreCase));
#if NET
string pathToExecutable = EnvironmentProvider.GetDotnetExePath();
msbuildParameters = Path.Combine(basePath, @"artifacts\bin\bootstrap\net8.0\MSBuild\msbuild.dll") + " " + msbuildParameters;
#else
string pathToExecutable =
Path.Combine(basePath, @"artifacts\bin\bootstrap\net472\MSBuild\Current\Bin\amd64\msbuild.exe");
#endif
return RunProcessAndGetOutput(pathToExecutable, msbuildParameters, out successfulExit, shellExecute, outputHelper);
}

/// <summary>
/// Invoke msbuild.exe with the given parameters and return the stdout, stderr, and process exit status.
/// This method may invoke msbuild via other runtimes.
Expand Down