dotnet / msbuild

The Microsoft Build Engine (MSBuild) is the build platform for .NET and Visual Studio.
https://docs.microsoft.com/visualstudio/msbuild/msbuild
MIT License
5.23k stars 1.35k forks source link

In a Directory.Build.props file, determine the Sdk value #5255

Closed Pilchie closed 1 week ago

Pilchie commented 4 years ago

From @kieronlanning on Tuesday, April 7, 2020 1:35:27 PM

In a Directory.Build.props file how can I determine if the project has the Microsoft.NET.Sdk.Web or the Microsoft.NET.Sdk referenced?

Aside from opening the entire file and using some Regex to pull the Sdk attribute value out from either the Project element, or an Import element and setting a property, I'm not sure of the best direction to take...

Currently I'm doing this, which isn't an ideal solution:

<PropertyGroup>
 <SdkProjectName>$([System.Text.RegularExpressions.Regex]::Match(`$([System.IO.File]::ReadAllText(`$(MSBuildProjectFullPath)`))`, `(?s-i)(?:^|\s|>)(?s-i)(?:^|\s|&gt;)&lt;\s*(?:Project|Import)\s(?:[^&gt;]*?)\s?Sdk\s*=&quot;(?&lt;sdkproj&gt;.*?)&quot;`).Groups['sdkproj'].Value)</SdkProjectName>
</PropertyGroup>    

Document Details

Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

Copied from original issue: dotnet/aspnetcore#20649

kieronlanning commented 4 years ago

I've found some interesting properties thanks to the dotnet msbuild -pp:fullproject.xml {project-file}.csproj, like UsingMicrosoftNETSdkWeb and UsingMicrosoftNETSdk.

UsingMicrosoftNETSdkWeb looked promising, but it’s set you true, even when a project is using Microsoft.NET.Sdk. Most likely because it references a project that is using Microsoft.NET.Sdk.Web (think a test project for example).

rainersigwald commented 4 years ago

What do you want to do with this information? There's no easy way to access global project state, intentionally, and this would be something like that. UsingMicrosoftNETSdkWeb and friends are indeed the suggested solution.

UsingMicrosoftNETSdkWeb looked promising, but it’s set you true, even when a project is using Microsoft.NET.Sdk. Most likely because it references a project that is using Microsoft.NET.Sdk.Web (think a test project for example).

Can you give an example? I tried with a trivial dotnet new xunit pointing to a dotnet new web and it didn't have UsingMicrosoftNETSdkWeb in the test project.

kieronlanning commented 4 years ago

@rainersigwald We have some quite involved Directory.Build.props and Directory.Build.targets that automate a lot of the cruft about creating new microservices projects.

Doing things like:

  <!-- Add some web project package references -->
  <ItemGroup Condition="'$(IsWebSdkProject)' == 'true'">
    <PackageReference Include="Microsoft.VisualStudio.Azure.Kubernetes.Tools.Targets" Version="$(MSK8sToolsTarget_Version)" />
    <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="$(MSContainerToolsTarget_Version)" />
  </ItemGroup>

Making sure appsetting.*.json files are correctly copied to the output directory (including fixing a pet-peeve, nesting those appsetting.*.json files in non-web projects in VS 2019!):


  <!-- Try and nest the appsettings when it's not a web sdk project. -->
  <ItemGroup Condition="'$(IsSdkProject)' == 'true' AND '$(IsWebSdkProject)' == 'false'">
    <Content Include=".\appsettings.*.json">
      <DependentUpon>appsettings.json</DependentUpon>
    </Content>
    <Content Include="appsettings*.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    </Content>
  </ItemGroup>