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

Microsoft.Build.Traversal conflicts with .NET 8 SDK simplified output paths #509

Open
brantburnett opened this issue Dec 4, 2023 · 4 comments
Labels
Bug Something isn't working

Comments

@brantburnett
Copy link

When using the new .NET 8 simplified output paths feature with multiple dirs.proj projects using Microsoft.Build.Traversal they conflict with each other. The automatic ArtifactsProjectName determined by the .NET 8 SDK for all of the projects is dirs so they end up sharing a obj path within the artifacts directory, overwriting each other.

The only workaround I have found so far is to manually set the ArtifactsProjectName differently for each project. However, this must be done before the Microsoft.Build.Traversal SDK is imported. This means the simple Sdk="Microsoft.Build.Traversal" mechanism doesn't work and props and targets must be imported separately, which is messier and more difficult.

@jeffkl
Copy link
Contributor

jeffkl commented Dec 4, 2023

Traversal projects don't really produce any output, do you think it would be okay to just disable the simplified output paths feature all together for them?

<PropertyGroup>
  <UseArtifactsOutput Condition="'$(UseArtifactsOutput)' == ''">false</UseArtifactsOutput>
</PropertyGroup>

@jeffkl jeffkl added the Bug Something isn't working label Dec 4, 2023
@brantburnett
Copy link
Author

brantburnett commented Dec 4, 2023

They do produce a variety of outputs, primarily related to the NuGet restore process.

Snag_f771d62

While using the artifacts directory could be disabled, this would lose some of the purpose of the directory, at least in my view. While there are many advantages to it, one advantage is a single directory that can be deleted to do a "clean" rather than something more aggressive like git clean -xdf that also nukes VS caches and user options. This is pretty valuable for large repositories with many projects, which is also the main use case for Microsoft.Build.Traversal.

Regardless, if the decision is not to support the artifacts directory, then it should probably be disabled by default within Microsoft.Build.Traversal before Microsoft.NET.Sdk is imported.

@jeffkl
Copy link
Contributor

jeffkl commented Dec 4, 2023

Yes the only real output is the intermediate folder (obj) but the project itself doesn't output anything like an assembly (bin folder).

The only other option I can think of is to uniquify the directory name under the artifacts which can be tricky. Since each traversal project is probably named dirs.proj, we could somehow change the full-ish path to a string like:

ArtifactsPath Actual Path
artifacts\root-dirs D:\MyProject\dirs.proj
artifacts\root-src-dirs D:\MyProject\src\dirs.proj
artifacts\root-src-something-dirs D:\MyProject\src\something\dirs.proj

This could end up exceeding path length limits. Alternatively, we could preserve the paths like this:

ArtifactsPath Actual Path
artifacts\dirs D:\MyProject\dirs.proj
artifacts\src\dirs D:\MyProject\src\dirs.proj
artifacts\src\something\dirs D:\MyProject\src\something\dirs.proj

Does anyone else have a suggestion?

@brantburnett
Copy link
Author

brantburnett commented Dec 13, 2023

FWIW this is the workaround I'm using now. It's clearly not quite right for general inclusion because it makes some assumptions, but it may be helpful. It uses the nested directory approach.

Note: This is in Directory.Build.props

<Project>
  <PropertyGroup>
    <!-- Put all artifacts beneath /artifacts instead of project bin/obj directories -->
    <ArtifactsPath Condition=" '$(ArtifactsPath)' == '' ">$(MSBuildThisFileDirectory)artifacts\</ArtifactsPath>
  </PropertyGroup>

  <!-- Avoid conflicts with dirs.proj having the same name -->
  <PropertyGroup Condition=" '$(MSBuildProjectFile)' == 'dirs.proj' ">
    <_TraversalProjectRelativeToRoot>$([MSBuild]::MakeRelative('$(MSBuildThisFileDirectory)', '$(MSBuildProjectDirectory)'))</_TraversalProjectRelativeToRoot>
    <ArtifactsProjectName>dirs\$(_TraversalProjectRelativeToRoot)</ArtifactsProjectName>
  </PropertyGroup>
</Project>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants