microsoft / microsoft/microsoft-ui-xaml

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

Open
#11,525 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area-C++/WinRT area-XamlCompiler bug team-Core
Dominant language
C++
Stars
8.4k
Forks
942
Avg merge
2d 7h
Merged PRs (30d)
105

Description

### 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(".xaml.g.h")

#include ".xaml.g.h"

#else

namespace winrt::...::implementation
{
template
using MyTypeT = MyType_base;
}

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

```text
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:

```text
OpenNet.UI.Xaml.Control.TaskStatusIndicator
```

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

```text
UI/Xaml/Control/TaskStatusIndicator.xaml
```

or another project path.

For example, a project can conceptually have:

```text
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:

```text
Views/Custom/TestControl.xaml
```

with:

```xml

```

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:

```text
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_

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing get_generated_component_filename(type) and the generated component .g.h include probe. Reproduce the mismatch using a runtime class under TestApp.UI.Controls with XAML at Views/Custom/TestControl.xaml, then compare the probed path with the emitted TestControl.xaml.g.h path. Done requires an explicit association or configuration path that no longer depends only on the WinRT namespace.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
build-system, desktop
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.