microsoft / microsoft-ui-xaml

Windows UI Library: the latest Windows 10 native controls and Fluent styles for your applications
MIT License
6.36k stars 678 forks source link

C++/WinRT XAML controls created in subdirectories will not compile #7390

Closed haydenmc closed 1 year ago

haydenmc commented 2 years ago

Describe the bug

When creating a XAML control in a subdirectory in a C++/WinRT project, compilation fails.

Steps to reproduce the bug

1.) Create a new "Blank App (C++/WinRT)" UWP project 2.) Select "show all files" in Visual Studio Solution Explorer so you can create a real, non-virtual folder

show all files icon

3.) Create new directory "Controls" 4.) Create a new item "Blank User Control (C++/WinRT)" inside of the Controls folder 5.) Build

Actual behavior:

1>XamlTypeInfo.Impl.g.cpp
1>[...]\UWPScratch\UWPScratch\Controls\BlankUserControl.cpp(14,9): error C3861: 'InitializeComponent': identifier not found
1>[...]\UWPScratch\UWPScratch\Controls\BlankUserControl.cpp(29,9): error C3861: 'Button': identifier not found
1>C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\XamlCompiler\Microsoft.Windows.UI.Xaml.Common.targets(486,5): error MSB4181: The "CompileXaml" task returned false but did not log an error.
1>Done building project "UWPScratch.vcxproj" -- FAILED.

Expected behavior

Expect: Successful build

Screenshots

No response

NuGet package version

Microsoft.UI.Xaml 2.7.1

Windows app type

Device form factor

No response

Windows version

Windows Insider Build (xxxxx)

Additional context

I found BlankUserControl.g.h contains the following lines (generated here by cppwinrt.exe):

#if defined(WINRT_FORCE_INCLUDE_BLANKUSERCONTROL_XAML_G_H) || __has_include("BlankUserControl.xaml.g.h")
#include "BlankUserControl.xaml.g.h"
#else

namespace winrt::UWPScratch::implementation
{
    template <typename D, typename... I>
    using BlankUserControlT = BlankUserControl_base<D, I...>;
}

#endif

I believe the issue is __has_include("BlankUserControl.xaml.g.h") pointing to the wrong path.

Since BlankUserControl.xaml.g.h is not in the include path (it should be Controls/BlankUserControl.xaml.g.h), the XAML generated header file gets skipped along with the necessary definitions.

Workaround: Adding $(GeneratedFilesDir)Controls to the include paths allows the build to succeed but is less than ideal as it pollutes the root include directory with files from the Controls subdirectory.

I opened an issue in the cppwinrt repo but was told it belongs here instead. https://github.com/microsoft/cppwinrt/issues/1168

haydenmc commented 2 years ago

Per a comment in the issue I opened in C++/WinRT, this might be by-design, as it is expected that the namespace match the folder structure: https://github.com/microsoft/cppwinrt/issues/1168#issuecomment-1188105383

This issue is caused because in cppwinrt (and XAML in general), it is expected for subfolder to represents namespaces. If the original file was declared to be in the UWPScratch.Controls namespace, everything would have built fine. Additionally, the suggested fix of adjusting the path in cppwinrt-generated code would mean existing valid code using subfolders for namespaces would break, because now their include path is incorrect.

github-actions[bot] commented 1 year ago

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 5 days.