microsoft / WindowsAppSDK

The Windows App SDK empowers all Windows desktop apps with modern Windows UI, APIs, and platform features, including back-compat support, shipped via NuGet.
https://docs.microsoft.com/windows/apps/windows-app-sdk/
MIT License
3.81k stars 320 forks source link

Build fails when multiple WinUI 3 projects have the same output folder #4811

Open Ajith-GS opened 2 days ago

Ajith-GS commented 2 days ago

Describe the bug

We have multiple independent WinUI3 application projects with the same output folder. For example, two projects, App1 and App2, have the same output folder. The build of App2 will fail if the output folder contains the binary files of App1 and vice versa. The error will be as follows:

Image

But we would like to know why this is happening because both projects are completely independent. Is there any project property or proper method available to tackle the issue?

Steps to reproduce the bug

  1. Create two C++ WinUI3 project using "Blank App, Packaged (WinUI 3 in Desktop)" template.
  2. Configure the same output folder for both applications.
  3. Make them as unpackaged application using the steps described in the following link. https://learn.microsoft.com/en-us/windows/apps/winui/winui3/create-your-first-winui3-app#unpackaged-create-a-new-project-for-an-unpackaged-c-or-c-winui-3-desktop-app
  4. Build the first application
  5. Build the second application.

Expected behavior

Build process of both projects should be successful.

Screenshots

No response

NuGet package version

Windows App SDK 1.6.1: 1.6.240923002

Packaging type

Unpackaged

Windows version

Windows 10 version 22H2 (19045, 2022 Update)

IDE

Visual Studio 2022

Additional context

No response

DarranRowe commented 2 days ago

This actually looks like it is somehow sharing $(GeneratedFilesDir) directory. If you set Visual Studio to diagnostic logging, can you find where this build variable is being set? As far as I know, this should only be set in one of two places, Microsoft.Cpp.AppContainerApplication.props which is part of Visual Studio, or Microsoft.Windows.CppWinRT.targets which is part of the C++/WinRT NuGet package.

From what I have seen, WinUI 3 projects pick up the value from Microsoft.Cpp.AppContainerApplication.props, and this value isn't rooted to any particular directory.

Ajith-GS commented 1 day ago

This actually looks like it is somehow sharing $(GeneratedFilesDir) directory. If you set Visual Studio to diagnostic logging, can you find where this build variable is being set? As far as I know, this should only be set in one of two places, Microsoft.Cpp.AppContainerApplication.props which is part of Visual Studio, or Microsoft.Windows.CppWinRT.targets which is part of the C++/WinRT NuGet package.

From what I have seen, WinUI 3 projects pick up the value from Microsoft.Cpp.AppContainerApplication.props, and this value isn't rooted to any particular directory.

Hi, I have checked the VS diagnostic log and couldn't find any Generated Files directory shared by both projects. Also, another observation is that if we remove the App1.winmd file from the output directory before building App2, the build of App2 will be successful and vice versa. It seems like the .winmd file is causing the issue here.

DarranRowe commented 1 day ago

That is interesting. The other option is that the Xaml compiler is picking up the .winmd files from the output directory. This would also explain why only one of the projects fail.

If you want to verify this, look for the CompileXaml task in the diagnostic log file.

1>  Using "CompileXaml" task from assembly "C:\Users\Darran\source\repos\Meh\packages\Microsoft.WindowsAppSDK.1.6.240923002\build\..\tools\net472\Microsoft.UI.Xaml.Markup.Compiler.dll".
1>  Task "CompileXaml"

Once you have found this, look for the ReferenceAssemblies task parameter.

1>    Task Parameter:
1>        ReferenceAssemblies=

Then check the list of .winmd files to see if there are any unexpected entries in the list. Be aware that the Xaml compiler is run twice for each application. You can distinguish between which run it is by looking for the IsPass1 task parameter.