wpf icon indicating copy to clipboard operation
wpf copied to clipboard

UseArtifactsOutput breaks multi-target WPF build

Open znakeeye opened this issue 1 year ago • 5 comments

Description

Combining TargetFrameworks and UseArtifactsOutput breaks the Rebuild task. A regular Build succeeds.

Rebuild started at 14:16...
1>------ Rebuild All started: Project: WpfBuildError, Configuration: Debug Any CPU ------
Restored C:\source\WpfBuildError\WpfBuildError\WpfBuildError.csproj (in 2 ms).
1>CSC : error CS2012: Cannot open 'C:\source\WpfBuildError\artifacts\obj\WpfBuildError\debug_\WpfBuildError.dll' for writing -- 'The process cannot access the file 'C:\source\WpfBuildError\artifacts\obj\WpfBuildError\debug_\WpfBuildError.dll' because it is being used by another process.'
1>Done building project "WpfBuildError_1hckbbpn_wpftmp.csproj" -- FAILED.
1>WpfBuildError -> C:\source\WpfBuildError\artifacts\bin\WpfBuildError\debug_net6.0-windows\WpfBuildError.dll
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========
========== Rebuild completed at 14:16 and took 04,746 seconds ==========

Two properties are needed to encounter this bug:

WpfBuildError.csproj

<TargetFrameworks>net6.0-windows;net8.0-windows</TargetFrameworks>

Directory.Build.props

<UseArtifactsOutput>true</UseArtifactsOutput>

Reproduction Steps

  1. Open sample project: WpfBuildError.zip
  2. Rebuild the solution. (A regular Build succeeds.)

Expected behavior

The project should compile.

Actual behavior

The project dos not compile.

Regression?

No response

Known Workarounds

Don't set UseArtifactsOutput (and be very unhappy about the artifact mess on disk)...

Impact

We cannot update our projects to .NET 8 since we need some consuming systems to target .NET 6. Basically, this is a showstopper.

Any workaround is very much appreciated!

Configuration

Running Visual Studio 17.10.3 and the bundled .NET SDK 8.0.302.

Other information

No response

znakeeye avatar Aug 12 '24 12:08 znakeeye

I think it is the SDK's issues. ~~And It has a little resemblance to https://github.com/dotnet/wpf/issues/9524, but not the same issues.~~

lindexi avatar Aug 13 '24 00:08 lindexi

I have the same issue - it always seems to be on a fresh build that it occurs.

Additionally, disabling parallel builds (via setting maximum number of parallel project builds in VS) seems to cause the issue to disappear at the cost of a significantly slower build. This helps for local development but still does not fix the issue when built on the command line (CI for example).

TrubbleAC avatar Feb 23 '25 23:02 TrubbleAC

@znakeeye I think I have found a workaround - if you create a Directory.Build.targets file with the following contents I no longer have the issue:

<Project>
    <PropertyGroup Condition="'$(UseArtifactsOutput)' == 'true'">
        <IntermediateOutputPath>$(BaseIntermediateOutputPath)$(ArtifactsPivots)\</IntermediateOutputPath>
    </PropertyGroup>
</Project>

I took the IntermediateOutputPath value from Microsoft.NET.DefaultOutputPaths.targets in the .NET SDK. This should be the default intermediate output path with the configuration you provided but I suspect something in the WPF build process overrides it (or a related property).

I am not 100% confident that this won't break some odd usage where the path is computed differently but for my projects it seems to be working.

TrubbleAC avatar Feb 24 '25 00:02 TrubbleAC

Hi, I do see the issue on my side too.

When digging deeper, we can see that the the TargetFramework is removed from the IntermediateOutputPath when generating the "wpftmp" project :

https://github.com/dotnet/wpf/blob/e188e3587630e370a711fe9566a9011a7c5a181b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/Microsoft.WinFX.targets#L449

As explained here:

https://github.com/dotnet/wpf/blob/e188e3587630e370a711fe9566a9011a7c5a181b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/Microsoft.WinFX.targets#L413-L421

We can also see that it's testing this condition $(AppendTargetFrameworkToOutputPath)' == 'true'.

When using artifacts output you don't need to set it to true, it will be handled by the pivots automatically.

So I feel like a less intrusive workaround would be to set:

<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>

jairbubbles avatar May 06 '25 14:05 jairbubbles

The comment says "Undo TargetFramework and RID append set in Microsoft.NET.RuntimeIdentifierInference.targets", but is Microsoft.NET.RuntimeIdentifierInference.targets appending the TargetFramework in the first place? Microsoft.NET.RuntimeIdentifierInference.targets seems to handle AppendRuntimeIdentifierToOutputPath but not AppendTargetFrameworkToOutputPath, so it seems like this code may be trying to undo something that was never done.

bkeryan avatar Oct 21 '25 21:10 bkeryan