Generated component .g.h derives the *.xaml.g.h include path from the WinRT component name instead of the actual XAML item path

Author: hoshiizumiyaCreated Aug 14, 2026Updated Sep 18, 2026
Labelsbugarea-XamlCompilerarea-C++/WinRTteam-Core

Describe the bug

C++/WinRT generated component headers automatically probe for a corresponding XAML-generated header.

The generated code has the form:

cpp
#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...>;
}

#endif

The path is currently calculated from:

cpp
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.TaskStatusIndicator

C++/WinRT can generate:

cpp
#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.TaskStatusIndicator

but does not inherently know whether the corresponding XAML source file is physically located at:

UI/Xaml/Control/TaskStatusIndicator.xaml

or 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.TaskStatusIndicator

Those 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:

idl
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.xaml

with:

xml
<UserControl
    x:Class="TestApp.UI.Controls.TestControl">

Build the project and compare:

  1. the path probed by the generated TestControl.g.h;
  2. the actual path of TestControl.xaml.g.h emitted 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.h

rather 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