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
Nobody has claimed this yet.
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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