Generated component .g.h derives the *.xaml.g.h include path from the WinRT component name instead of the actual XAML item path
Describe the bug
C++/WinRT generated component headers automatically probe for a corresponding XAML-generated header.
The generated code has the form:
#if defined(WINRT_FORCE_INCLUDE_MYTYPE_XAML_G_H) || __has_include("<calculated-component-path>.xaml.g.h")
#include "<calculated-component-path>.xaml.g.h"
#else
namespace winrt::...::implementation
{
template <typename D, typename... I>
using MyTypeT = MyType_base<D, I...>;
}
#endifThe path is currently calculated from:
get_generated_component_filename(type)which is based on the WinRT metadata type name and the component root.
For example, for:
component root:
OpenNet
runtime class:
OpenNet.UI.Xaml.Control.TaskStatusIndicatorC++/WinRT can generate:
#include "UI/Xaml/Control/TaskStatusIndicator.xaml.g.h"when the non-prefix/nested-directory component filename convention is used.
Problem
The WinRT runtime namespace and the physical MSBuild/XAML item path are different concepts.
C++/WinRT has access to the WinRT metadata type:
OpenNet.UI.Xaml.Control.TaskStatusIndicatorbut does not inherently know whether the corresponding XAML source file is physically located at:
UI/Xaml/Control/TaskStatusIndicator.xamlor another project path.
For example, a project can conceptually have:
Physical project path:
Views/Controls/TaskStatusIndicator.xaml
x:Class / WinRT type:
OpenNet.UI.Xaml.Control.TaskStatusIndicatorThose two paths do not necessarily need to be identical.
In that situation the C++/WinRT generated .g.h can probe a namespace-derived path while the XAML compiler emits the actual *.xaml.g.h according to the XAML/MSBuild item path.
Why this is difficult to fix at the source level
get_generated_component_filename(type) can correctly determine the component-relative C++/WinRT component filename, because that information comes from WinRT metadata.
However, the physical XAML item path is owned by the XAML/MSBuild build pipeline rather than WinRT metadata.
Therefore the same calculated component filename may not always be sufficient to identify the corresponding XAML-generated header.
Reproduction
Create a C++/WinRT WinUI component type where the runtime namespace does not match the physical XAML folder layout.
For example:
namespace TestApp.UI.Controls
{
runtimeclass TestControl : Microsoft.UI.Xaml.Controls.UserControl
{
TestControl();
}
}but place the XAML item under a different project path, such as:
Views/Custom/TestControl.xamlwith:
<UserControl
x:Class="TestApp.UI.Controls.TestControl">Build the project and compare:
- the path probed by the generated
TestControl.g.h; - the actual path of
TestControl.xaml.g.hemitted by the XAML compiler.
If these differ, __has_include(...) does not find the generated XAML header unless the project manually modifies include search paths.
Current workaround
A project can add the actual XAML-generated output directory to the compiler's additional include directories so that the generated probe happens to resolve.
That can make the project build, but it does not remove the underlying assumption that the XAML physical path can be reconstructed from the WinRT component name.
Expected behavior
Ideally, the XAML build integration and C++/WinRT should have an explicit way to associate:
WinRT runtimeclass
->
actual generated *.xaml.g.hrather than requiring C++/WinRT to infer the XAML file's physical path only from the metadata namespace.
Possible approaches might include:
- MSBuild-provided metadata;
- a generated mapping;
- a configurable force-include path;
- another explicit contract between the XAML compiler and C++/WinRT.
I am not proposing a specific implementation, only that the current namespace-derived path assumption should not be the only way to locate the XAML-generated implementation header.
Related
The WinUI item-template side of nested-folder namespace/path generation is tracked separately here: microsoft/WindowsAppSDK#6688
NuGet package version
2.4.0
Windows version
No response
Additional context
No response
Source: microsoft/microsoft-ui-xaml