Open brantburnett opened 11 months ago
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>
They do produce a variety of outputs, primarily related to the NuGet restore process.
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.
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?
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>
When using the new .NET 8 simplified output paths feature with multiple
dirs.proj
projects usingMicrosoft.Build.Traversal
they conflict with each other. The automaticArtifactsProjectName
determined by the .NET 8 SDK for all of the projects isdirs
so they end up sharing aobj
path within theartifacts
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 theMicrosoft.Build.Traversal
SDK is imported. This means the simpleSdk="Microsoft.Build.Traversal"
mechanism doesn't work andprops
andtargets
must be imported separately, which is messier and more difficult.