C++20 module support v2#1575
Conversation
…-> WINRT_IMPORT_MODULE
…t_base/winrt_numerics Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
…names and built ifc files. Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: YexuanXiao <bizwen@nykz.org> Co-authored-by: Copilot <copilot@github.com>
There was a problem hiding this comment.
Pull request overview
This PR introduces v2 C++20 module support for C++/WinRT by generating per-namespace named modules (e.g., import winrt.Windows.Foundation;) with SCC (cycle) consolidation, updates the projection/base strings to be module-export-friendly, and adds MSBuild + test coverage for module generation/consumption.
Changes:
- Extend
cppwinrt.exeto generate per-namespace.ixxfiles (with Tarjan SCC cycle breaking) and emit module-aware guards/exports in generated headers. - Add MSBuild plumbing (
CppWinRTBuildModule, include/exclude filters,CppWinRTConsumeModule,.ixxdiscovery) plus docs describing usage and internals. - Add new standalone + NuGet integration test projects that build and consume the generated modules end-to-end.
Reviewed changes
Copilot reviewed 93 out of 93 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| test/test_cpp20_module/test_cpp20_module.vcxproj | New standalone VS project that runs cppwinrt with -modules and compiles generated .ixx files. |
| test/test_cpp20_module/pch.h | Catch2 PCH header for module test. |
| test/test_cpp20_module/pch.cpp | Builds the PCH for module test. |
| test/test_cpp20_module/main.cpp | Catch2 runner for module test using import winrt_base;. |
| test/test_cpp20_module/foundation.cpp | Module-mode tests for Windows.Foundation APIs. |
| test/test_cpp20_module/coroutines.cpp | Module-mode coroutine tests using IAsync* types. |
| test/test_cpp20_module/collections.cpp | Module-mode collections tests (vector/map/iterable). |
| test/nuget/TestModuleConsumerApp/pch.h | PCH header for NuGet consumer app test. |
| test/nuget/TestModuleConsumerApp/pch.cpp | Builds the PCH for NuGet consumer app test. |
| test/nuget/TestModuleConsumerApp/main.cpp | Consumer app importing platform + component modules. |
| test/nuget/TestModuleConsumerApp/TestModuleConsumerApp.vcxproj | Consumer app MSBuild config exercising CppWinRTConsumeModule. |
| test/nuget/TestModuleConsumerApp/PropertySheet.props | Minimal property sheet for NuGet consumer app project. |
| test/nuget/TestModuleComponent2/pch.h | PCH header for component 2 test. |
| test/nuget/TestModuleComponent2/pch.cpp | Builds the PCH for component 2 test. |
| test/nuget/TestModuleComponent2/TestModuleComponent2.vcxproj | Component 2 MSBuild config with module generation + consumption. |
| test/nuget/TestModuleComponent2/TestModuleComponent2.idl | IDL for GreeterGroup runtimeclass. |
| test/nuget/TestModuleComponent2/TestModuleComponent2.def | DEF exports for component DLL activation. |
| test/nuget/TestModuleComponent2/PropertySheet.props | Minimal property sheet for component 2. |
| test/nuget/TestModuleComponent2/GreeterGroup.h | Component implementation header for GreeterGroup. |
| test/nuget/TestModuleComponent2/GreeterGroup.cpp | Component implementation TU using module imports. |
| test/nuget/TestModuleComponent1/pch.h | PCH header for component 1 test. |
| test/nuget/TestModuleComponent1/pch.cpp | Builds the PCH for component 1 test. |
| test/nuget/TestModuleComponent1/TestModuleComponent1.vcxproj | Component 1 MSBuild config with module generation + consumption. |
| test/nuget/TestModuleComponent1/TestModuleComponent1.idl | IDL for Greeter runtimeclass. |
| test/nuget/TestModuleComponent1/TestModuleComponent1.def | DEF exports for component DLL activation. |
| test/nuget/TestModuleComponent1/PropertySheet.props | Minimal property sheet for component 1. |
| test/nuget/TestModuleComponent1/Greeter.h | Component implementation header for Greeter. |
| test/nuget/TestModuleComponent1/Greeter.cpp | Component implementation TU using module imports. |
| test/nuget/TestModuleBuilder/pch.h | PCH header for “builder” static lib project. |
| test/nuget/TestModuleBuilder/pch.cpp | Builds the PCH for module builder. |
| test/nuget/TestModuleBuilder/TestModuleBuilder.vcxproj | Static lib project that pre-builds platform modules. |
| test/nuget/TestModuleBuilder/PropertySheet.props | Minimal property sheet for module builder. |
| test/nuget/TestModuleApp/pch.h | PCH header for single-project module app test. |
| test/nuget/TestModuleApp/pch.cpp | Builds the PCH for single-project module app test. |
| test/nuget/TestModuleApp/main.cpp | Single-project app importing platform modules + exercising component types. |
| test/nuget/TestModuleApp/TestModuleApp.vcxproj | Single-project module build + consumption configuration. |
| test/nuget/TestModuleApp/TestModuleApp.idl | IDL for test component types including XAML inheritance scenario. |
| test/nuget/TestModuleApp/TestModuleApp.def | DEF exports for TestModuleApp DLL activation. |
| test/nuget/TestModuleApp/PropertySheet.props | Minimal property sheet for single-project module app. |
| test/nuget/TestModuleApp/ModuleTestHelper.h | Component implementation header for helper runtimeclass. |
| test/nuget/TestModuleApp/ModuleTestHelper.cpp | Component implementation TU using module imports. |
| test/nuget/TestModuleApp/CustomDependencyObject.h | Component implementation header for XAML-derived runtimeclass. |
| test/nuget/TestModuleApp/CustomDependencyObject.cpp | Component implementation TU importing XAML and foundation modules. |
| test/nuget/NuGetTest.sln | Adds the new module test projects to NuGetTest solution. |
| strings/base_xaml_typename.h | Switches winrt::impl namespace blocks to WINRT_EXPORT for module export. |
| strings/base_windows.h | Same: exports winrt::impl content under modules. |
| strings/base_types.h | Same: exports winrt::impl blocks under modules. |
| strings/base_string_operators.h | Same: exports winrt::impl blocks under modules. |
| strings/base_string_input.h | Same: exports winrt::impl blocks under modules. |
| strings/base_string.h | Same: exports winrt::impl blocks under modules. |
| strings/base_std_hash.h | Exports winrt::impl and std specializations via WINRT_EXPORT. |
| strings/base_reference_produce.h | Exports winrt::impl blocks under modules. |
| strings/base_natvis.h | Exports natvis helpers under WINRT_EXPORT winrt::impl. |
| strings/base_meta.h | Exports winrt::impl meta helpers under modules. |
| strings/base_marshaler.h | Exports winrt::impl marshaler helpers under modules. |
| strings/base_macros.h | Adds numerics include guard for module/import builds + exports winrt::impl. |
| strings/base_iterator.h | Exports winrt::impl iterator helpers under modules. |
| strings/base_implements.h | Exports winrt::impl implements helpers under modules. |
| strings/base_identity.h | Exports winrt::impl identity helpers under modules. |
| strings/base_foundation.h | Exports winrt::impl foundation helpers under modules. |
| strings/base_fast_forward.h | Exports winrt::impl fast-forward helpers under modules. |
| strings/base_events.h | Exports winrt::impl event helpers under modules. |
| strings/base_error.h | Exports winrt::impl error helpers under modules. |
| strings/base_delegate.h | Exports winrt::impl delegate helpers under modules. |
| strings/base_coroutine_threadpool.h | Exports winrt::impl and std coroutine specializations under modules. |
| strings/base_coroutine_foundation.h | Exports winrt::impl and std coroutine specializations under modules. |
| strings/base_composable.h | Exports winrt::impl composable helpers under modules. |
| strings/base_com_ptr.h | Exports winrt::impl com_ptr helpers under modules. |
| strings/base_collections_vector.h | Exports winrt::impl collections helpers under modules. |
| strings/base_collections_map.h | Exports winrt::impl and std tuple specializations under modules. |
| strings/base_collections_input_vector_view.h | Exports winrt::impl collections helpers under modules. |
| strings/base_collections_input_vector.h | Exports winrt::impl collections helpers under modules. |
| strings/base_collections_input_map_view.h | Exports winrt::impl collections helpers under modules. |
| strings/base_collections_input_map.h | Exports winrt::impl collections helpers under modules. |
| strings/base_collections_input_iterable.h | Exports winrt::impl collections helpers under modules. |
| strings/base_collections_base.h | Exports winrt::impl collections base helpers under modules. |
| strings/base_collections.h | Exports winrt::impl collections helpers under modules. |
| strings/base_array.h | Exports winrt::impl array helpers under modules. |
| strings/base_agile_ref.h | Exports winrt::impl agile_ref helpers under modules. |
| strings/base_activation.h | Exports winrt::impl activation helpers under modules. |
| strings/base_abi.h | Exports winrt::impl ABI helpers under modules. |
| nuget/readme.md | Documents new module-related MSBuild properties/metadata. |
| nuget/modules.md | Adds user guide for enabling/building/consuming modules. |
| nuget/Microsoft.Windows.CppWinRT.targets | Adds module properties, .ixx discovery target, and ProjectReference metadata flow. |
| docs/modules-design.md | Adds maintainer-focused design doc for per-namespace modules + SCC + MSBuild flow. |
| cppwinrt/settings.h | Adds generator settings for modules + include/exclude filter sets. |
| cppwinrt/main.cpp | Adds CLI flags, module filter construction, dependency collection, SCC detection, and .ixx generation. |
| cppwinrt/file_writers.h | Adds module writers (module.h, base/numerics/namespace .ixx), module-aware include guards, and component import/include dual-path. |
| cppwinrt/component_writers.h | Adjusts component module.g.cpp generation to avoid base include when modules enabled. |
| cppwinrt/code_writers.h | Adds module-aware include guard helper and exports winrt::impl namespace blocks via WINRT_EXPORT. |
| cppwinrt.sln | Adds new standalone module test project to main solution. |
| .github/instructions/modules.instructions.md | Adds module-specific agent instructions. |
| .github/instructions/cppwinrt.instructions.md | Adds repo-wide agent instructions including module notes and build/test steps. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <copilot@github.com>
0a5d1f6 to
d5d1821
Compare
Co-authored-by: Copilot <copilot@github.com>
|
I think we can append a module export list at the end of each base_*.h file and guard it with #ifdef WINRT_MODULE
export namespace winrt
{
using winrt::xxx;
}
#endifI think this approach is the most maintainable. I've tried this approach on my fork, and I think it's pretty good. It removes |
This comment was marked as resolved.
This comment was marked as resolved.
|
@DefaultRyan I discovered that the reason MSVC generates warning 5244 for windowsnumerics.impl.h is that it uses angle bracket #include instead of double quotes because compilers (MSVC and Clang) consider that system headers should not be treated as module implementation files. Therefore, it can be changed to double quotes and a comment can be added to prevent regression, instead of suppressing the warning. |
|
I believe I have discovered a bug in MSVC, but I am unable to reproduce it in a new project. In short, the pattern like this: |
|
@DefaultRyan Nine days after the last commit about module, I opened a new simple PR for my fork that does a basic cleanup of WINRT_EXPORT and extern "C++". Other cleanups require large scale modifications to base*.h. If you think it's time to do these cleanups, you should take a look, it's designed not to break the existing base*.h patterns. |
|
|
||
| // Module declaration (owner namespace) | ||
| w.write("// This module is an SCC owner (cycle breaker). The following namespaces\n"); | ||
| w.write("// form a dependency cycle and are consolidated into this single module:\n"); |
There was a problem hiding this comment.
I'm curious if there is data on what cycles exist and how big they are. Using the output of your build would probably make that pretty simple to grep for.
There was a problem hiding this comment.
Here's what I've got, assuming I scanned the ixx files correctly. Out of 342 Windows.* namespaces
- Most namespaces (248) don't participare in cycles.
- There are a few mini-cycles, like
Windows.Foundation<->Windows.Foundation.Collections, orWindows.AI.Actions<->Windows.AI.Actions.Hosting - A couple of mid-sized cycles.
Windows.UI.Xaml.*andWindows.Media.Audio.*tend to interconnect. - There is one massive cycle (62 namespaces!) encompassing cross-references all over the place. I'll see if I can easily cook up a diagram or something for it.
There was a problem hiding this comment.
For lolz, here's a table of the interdependencies. For extra lolz, I generated a mermaid diagram after that.
A quick perusal suggests that most of this is because tons of namespaces depend on Windows.Storage.Streams, Windows.Storage.Streams depends on Windows.System, and Windows.System depends on a surprising bunch of random bits.
| Source (Windows.) | Dependencies (Windows.) |
|---|---|
| ApplicationModel | ApplicationModel_Activation, ApplicationModel_Appointments, ApplicationModel_Appointments_AppointmentsProvider, ApplicationModel_AppService, ApplicationModel_Background, ApplicationModel_Calls, ApplicationModel_Contacts, ApplicationModel_Contacts_Provider, ApplicationModel_Core, ApplicationModel_DataTransfer, ApplicationModel_DataTransfer_ShareTarget, ApplicationModel_Email, ApplicationModel_Search, ApplicationModel_UserDataAccounts, ApplicationModel_UserDataAccounts_Provider, ApplicationModel_UserDataTasks, ApplicationModel_Wallet, Devices_Bluetooth_Background, Devices_Bluetooth_GenericAttributeProfile, Devices_Sensors, Devices_SmartCards, Devices_Sms, Security_Authentication_Web_Core, Security_Credentials, Storage, Storage_Streams, System, System_RemoteSystems, UI_Notifications |
| ApplicationModel_Activation | ApplicationModel, ApplicationModel_Appointments_AppointmentsProvider, ApplicationModel_Background, ApplicationModel_Calls, ApplicationModel_Contacts, ApplicationModel_Contacts_Provider, ApplicationModel_DataTransfer_ShareTarget, ApplicationModel_Search, ApplicationModel_UserDataAccounts_Provider, ApplicationModel_Wallet, Devices_Enumeration, Media_SpeechRecognition, Security_Authentication_Web_Provider, Storage, Storage_Pickers_Provider, Storage_Provider, Storage_Search, System, UI_Notifications, UI_ViewManagement |
| ApplicationModel_Appointments | ApplicationModel, ApplicationModel_Appointments_AppointmentsProvider, System |
| ApplicationModel_Appointments_AppointmentsProvider | ApplicationModel_Appointments |
| ApplicationModel_AppService | ApplicationModel, System, System_RemoteSystems |
| ApplicationModel_Background | ApplicationModel, ApplicationModel_Activation, Devices_Bluetooth, Devices_Bluetooth_Advertisement, Devices_Bluetooth_Background, Devices_Bluetooth_GenericAttributeProfile, Devices_Sensors, Devices_SmartCards, Devices_Sms, Networking, Networking_Sockets, Storage, Storage_Provider, System, UI_Notifications |
| ApplicationModel_Calls | ApplicationModel, ApplicationModel_Contacts, Devices_Enumeration, System |
| ApplicationModel_Contacts | ApplicationModel, ApplicationModel_Contacts_Provider, Data_Text, Storage_Streams, System, UI_ViewManagement |
| ApplicationModel_Contacts_Provider | ApplicationModel_Contacts |
| ApplicationModel_Core | ApplicationModel, ApplicationModel_Activation, System, UI_Core |
| ApplicationModel_DataTransfer | ApplicationModel, ApplicationModel_DataTransfer_ShareTarget, Security_EnterpriseData, Storage, Storage_Streams |
| ApplicationModel_DataTransfer_ShareTarget | ApplicationModel_Contacts, ApplicationModel_DataTransfer, Storage_Streams |
| ApplicationModel_Email | ApplicationModel, ApplicationModel_Appointments, Security_Cryptography_Certificates, Storage_Streams, System |
| ApplicationModel_Search | ApplicationModel, Storage, Storage_Streams |
| ApplicationModel_UserDataAccounts | ApplicationModel, ApplicationModel_Appointments, ApplicationModel_Contacts, ApplicationModel_Email, ApplicationModel_UserDataAccounts_Provider, ApplicationModel_UserDataTasks, Storage_Streams, System |
| ApplicationModel_UserDataAccounts_Provider | ApplicationModel_UserDataAccounts |
| ApplicationModel_UserDataTasks | ApplicationModel, System |
| ApplicationModel_Wallet | ApplicationModel, Storage_Streams |
| Data_Text | UI_Text_Core |
| Data_Xml_Dom | Storage, Storage_Streams |
| Devices_Bluetooth | Devices_Bluetooth_Advertisement, Devices_Bluetooth_Background, Devices_Bluetooth_GenericAttributeProfile, Devices_Bluetooth_Rfcomm, Devices_Enumeration, Networking, Storage_Streams |
| Devices_Bluetooth_Advertisement | Devices_Bluetooth, Storage_Streams |
| Devices_Bluetooth_Background | Devices_Bluetooth, Devices_Bluetooth_Advertisement, Devices_Bluetooth_GenericAttributeProfile, Devices_Bluetooth_Rfcomm, Networking_Sockets, Storage_Streams |
| Devices_Bluetooth_GenericAttributeProfile | Devices_Bluetooth, Devices_Enumeration, Storage_Streams |
| Devices_Bluetooth_Rfcomm | Devices_Bluetooth, Devices_Enumeration, Networking, Networking_Sockets, Storage_Streams |
| Devices_Enumeration | ApplicationModel_Background, Security_Credentials, Storage_Streams |
| Devices_Sensors | Graphics_Display |
| Devices_SmartCards | Security_Cryptography_Core, Storage_Streams |
| Devices_Sms | Storage_Streams |
| Globalization | System |
| Graphics_Display | Storage_Streams |
| Media_SpeechRecognition | Globalization, Storage |
| Networking | ApplicationModel_Activation, ApplicationModel_Background, Networking_Connectivity, Networking_Sockets, Storage_Streams, System |
| Networking_Connectivity | Networking, Storage_Streams |
| Networking_Sockets | ApplicationModel_Background, Networking, Networking_Connectivity, Security_Credentials, Security_Cryptography_Certificates, Storage_Streams, Web |
| Security_Authentication_Web_Core | Security_Credentials, System |
| Security_Authentication_Web_Provider | Security_Authentication_Web_Core, Security_Credentials, Security_Cryptography_Core, Storage_Streams, System, Web_Http |
| Security_Credentials | Security_Cryptography_Core, Storage_Streams, System |
| Security_Cryptography_Certificates | Networking, Storage_Streams |
| Security_Cryptography_Core | Security_Cryptography_Certificates, Storage_Streams |
| Security_EnterpriseData | Networking, Storage, Storage_Streams |
| Storage | Storage_FileProperties, Storage_Pickers_Provider, Storage_Provider, Storage_Search, Storage_Streams, System |
| Storage_FileProperties | Storage, Storage_Streams |
| Storage_Pickers_Provider | Storage |
| Storage_Provider | Storage, Storage_Search, Storage_Streams |
| Storage_Search | Data_Text, Storage, Storage_FileProperties, Storage_Streams |
| Storage_Streams | Storage, System |
| System | ApplicationModel, ApplicationModel_AppService, Networking, Security_Credentials, Storage, Storage_Search, Storage_Streams, System_Diagnostics, System_RemoteSystems, UI_ViewManagement |
| System_Diagnostics | ApplicationModel_AppService, System |
| System_RemoteSystems | ApplicationModel_AppService, Networking, Security_Credentials, System |
| UI_Composition | System, UI_Core |
| UI_Core | System, UI_Composition, UI_Input, UI_WindowManagement |
| UI_Input | ApplicationModel_Core, Storage_Streams, System, UI_Composition, UI_Core, UI_Text, UI_WindowManagement |
| UI_Notifications | ApplicationModel, Data_Xml_Dom, System |
| UI_Text | Storage_Streams, UI_Text_Core |
| UI_Text_Core | Globalization, UI_Text, UI_ViewManagement |
| UI_ViewManagement | Devices_Enumeration, UI_Core, UI_WindowManagement |
| UI_WindowManagement | System, UI_Composition |
| Web | Globalization, Security_Credentials, Storage_Streams, System, System_Diagnostics, Web_Http, Web_Http_Filters, Web_Http_Headers |
| Web_Http | Globalization, Networking_Sockets, Security_Cryptography_Certificates, Storage_Streams, System, System_Diagnostics, Web, Web_Http_Filters, Web_Http_Headers |
| Web_Http_Filters | Networking_Sockets, Security_Credentials, Security_Cryptography_Certificates, System, Web_Http |
| Web_Http_Headers | Globalization, Networking, Storage_Streams, Web_Http |
graph LR
ApplicationModel_Activation --> ApplicationModel
ApplicationModel_Activation --> ApplicationModel_Appointments_AppointmentsProvider
ApplicationModel_Activation --> ApplicationModel_Background
ApplicationModel_Activation --> ApplicationModel_Calls
ApplicationModel_Activation --> ApplicationModel_Contacts
ApplicationModel_Activation --> ApplicationModel_Contacts_Provider
ApplicationModel_Activation --> ApplicationModel_DataTransfer_ShareTarget
ApplicationModel_Activation --> ApplicationModel_Search
ApplicationModel_Activation --> ApplicationModel_UserDataAccounts_Provider
ApplicationModel_Activation --> ApplicationModel_Wallet
ApplicationModel_Activation --> Devices_Enumeration
ApplicationModel_Activation --> Media_SpeechRecognition
ApplicationModel_Activation --> Security_Authentication_Web_Provider
ApplicationModel_Activation --> Storage
ApplicationModel_Activation --> Storage_Pickers_Provider
ApplicationModel_Activation --> Storage_Provider
ApplicationModel_Activation --> Storage_Search
ApplicationModel_Activation --> System
ApplicationModel_Activation --> UI_Notifications
ApplicationModel_Activation --> UI_ViewManagement
ApplicationModel_Appointments_AppointmentsProvider --> ApplicationModel_Appointments
ApplicationModel_Appointments --> ApplicationModel
ApplicationModel_Appointments --> ApplicationModel_Appointments_AppointmentsProvider
ApplicationModel_Appointments --> System
ApplicationModel_AppService --> ApplicationModel
ApplicationModel_AppService --> System
ApplicationModel_AppService --> System_RemoteSystems
ApplicationModel_Background --> ApplicationModel
ApplicationModel_Background --> ApplicationModel_Activation
ApplicationModel_Background --> Devices_Bluetooth
ApplicationModel_Background --> Devices_Bluetooth_Advertisement
ApplicationModel_Background --> Devices_Bluetooth_Background
ApplicationModel_Background --> Devices_Bluetooth_GenericAttributeProfile
ApplicationModel_Background --> Devices_Sensors
ApplicationModel_Background --> Devices_SmartCards
ApplicationModel_Background --> Devices_Sms
ApplicationModel_Background --> Networking
ApplicationModel_Background --> Networking_Sockets
ApplicationModel_Background --> Storage
ApplicationModel_Background --> Storage_Provider
ApplicationModel_Background --> System
ApplicationModel_Background --> UI_Notifications
ApplicationModel_Calls --> ApplicationModel
ApplicationModel_Calls --> ApplicationModel_Contacts
ApplicationModel_Calls --> Devices_Enumeration
ApplicationModel_Calls --> System
ApplicationModel_Contacts_Provider --> ApplicationModel_Contacts
ApplicationModel_Contacts --> ApplicationModel
ApplicationModel_Contacts --> ApplicationModel_Contacts_Provider
ApplicationModel_Contacts --> Data_Text
ApplicationModel_Contacts --> Storage_Streams
ApplicationModel_Contacts --> System
ApplicationModel_Contacts --> UI_ViewManagement
ApplicationModel_Core --> ApplicationModel
ApplicationModel_Core --> ApplicationModel_Activation
ApplicationModel_Core --> System
ApplicationModel_Core --> UI_Core
ApplicationModel_DataTransfer_ShareTarget --> ApplicationModel_Contacts
ApplicationModel_DataTransfer_ShareTarget --> ApplicationModel_DataTransfer
ApplicationModel_DataTransfer_ShareTarget --> Storage_Streams
ApplicationModel_DataTransfer --> ApplicationModel
ApplicationModel_DataTransfer --> ApplicationModel_DataTransfer_ShareTarget
ApplicationModel_DataTransfer --> Security_EnterpriseData
ApplicationModel_DataTransfer --> Storage
ApplicationModel_DataTransfer --> Storage_Streams
ApplicationModel_Email --> ApplicationModel
ApplicationModel_Email --> ApplicationModel_Appointments
ApplicationModel_Email --> Security_Cryptography_Certificates
ApplicationModel_Email --> Storage_Streams
ApplicationModel_Email --> System
ApplicationModel_Search --> ApplicationModel
ApplicationModel_Search --> Storage
ApplicationModel_Search --> Storage_Streams
ApplicationModel_UserDataAccounts_Provider --> ApplicationModel_UserDataAccounts
ApplicationModel_UserDataAccounts --> ApplicationModel
ApplicationModel_UserDataAccounts --> ApplicationModel_Appointments
ApplicationModel_UserDataAccounts --> ApplicationModel_Contacts
ApplicationModel_UserDataAccounts --> ApplicationModel_Email
ApplicationModel_UserDataAccounts --> ApplicationModel_UserDataAccounts_Provider
ApplicationModel_UserDataAccounts --> ApplicationModel_UserDataTasks
ApplicationModel_UserDataAccounts --> Storage_Streams
ApplicationModel_UserDataAccounts --> System
ApplicationModel_UserDataTasks --> ApplicationModel
ApplicationModel_UserDataTasks --> System
ApplicationModel_Wallet --> ApplicationModel
ApplicationModel_Wallet --> Storage_Streams
ApplicationModel --> ApplicationModel_Activation
ApplicationModel --> ApplicationModel_Appointments
ApplicationModel --> ApplicationModel_Appointments_AppointmentsProvider
ApplicationModel --> ApplicationModel_AppService
ApplicationModel --> ApplicationModel_Background
ApplicationModel --> ApplicationModel_Calls
ApplicationModel --> ApplicationModel_Contacts
ApplicationModel --> ApplicationModel_Contacts_Provider
ApplicationModel --> ApplicationModel_Core
ApplicationModel --> ApplicationModel_DataTransfer
ApplicationModel --> ApplicationModel_DataTransfer_ShareTarget
ApplicationModel --> ApplicationModel_Email
ApplicationModel --> ApplicationModel_Search
ApplicationModel --> ApplicationModel_UserDataAccounts
ApplicationModel --> ApplicationModel_UserDataAccounts_Provider
ApplicationModel --> ApplicationModel_UserDataTasks
ApplicationModel --> ApplicationModel_Wallet
ApplicationModel --> Devices_Bluetooth_Background
ApplicationModel --> Devices_Bluetooth_GenericAttributeProfile
ApplicationModel --> Devices_Sensors
ApplicationModel --> Devices_SmartCards
ApplicationModel --> Devices_Sms
ApplicationModel --> Security_Authentication_Web_Core
ApplicationModel --> Security_Credentials
ApplicationModel --> Storage
ApplicationModel --> Storage_Streams
ApplicationModel --> System
ApplicationModel --> System_RemoteSystems
ApplicationModel --> UI_Notifications
Data_Text --> UI_Text_Core
Data_Xml_Dom --> Storage
Data_Xml_Dom --> Storage_Streams
Devices_Bluetooth_Advertisement --> Devices_Bluetooth
Devices_Bluetooth_Advertisement --> Storage_Streams
Devices_Bluetooth_Background --> Devices_Bluetooth
Devices_Bluetooth_Background --> Devices_Bluetooth_Advertisement
Devices_Bluetooth_Background --> Devices_Bluetooth_GenericAttributeProfile
Devices_Bluetooth_Background --> Devices_Bluetooth_Rfcomm
Devices_Bluetooth_Background --> Networking_Sockets
Devices_Bluetooth_Background --> Storage_Streams
Devices_Bluetooth_GenericAttributeProfile --> Devices_Bluetooth
Devices_Bluetooth_GenericAttributeProfile --> Devices_Enumeration
Devices_Bluetooth_GenericAttributeProfile --> Storage_Streams
Devices_Bluetooth_Rfcomm --> Devices_Bluetooth
Devices_Bluetooth_Rfcomm --> Devices_Enumeration
Devices_Bluetooth_Rfcomm --> Networking
Devices_Bluetooth_Rfcomm --> Networking_Sockets
Devices_Bluetooth_Rfcomm --> Storage_Streams
Devices_Bluetooth --> Devices_Bluetooth_Advertisement
Devices_Bluetooth --> Devices_Bluetooth_Background
Devices_Bluetooth --> Devices_Bluetooth_GenericAttributeProfile
Devices_Bluetooth --> Devices_Bluetooth_Rfcomm
Devices_Bluetooth --> Devices_Enumeration
Devices_Bluetooth --> Networking
Devices_Bluetooth --> Storage_Streams
Devices_Enumeration --> ApplicationModel_Background
Devices_Enumeration --> Security_Credentials
Devices_Enumeration --> Storage_Streams
Devices_Sensors --> Graphics_Display
Devices_SmartCards --> Security_Cryptography_Core
Devices_SmartCards --> Storage_Streams
Devices_Sms --> Storage_Streams
Globalization --> System
Graphics_Display --> Storage_Streams
Media_SpeechRecognition --> Globalization
Media_SpeechRecognition --> Storage
Networking_Connectivity --> Networking
Networking_Connectivity --> Storage_Streams
Networking_Sockets --> ApplicationModel_Background
Networking_Sockets --> Networking
Networking_Sockets --> Networking_Connectivity
Networking_Sockets --> Security_Credentials
Networking_Sockets --> Security_Cryptography_Certificates
Networking_Sockets --> Storage_Streams
Networking_Sockets --> Web
Networking --> ApplicationModel_Activation
Networking --> ApplicationModel_Background
Networking --> Networking_Connectivity
Networking --> Networking_Sockets
Networking --> Storage_Streams
Networking --> System
Security_Authentication_Web_Core --> Security_Credentials
Security_Authentication_Web_Core --> System
Security_Authentication_Web_Provider --> Security_Authentication_Web_Core
Security_Authentication_Web_Provider --> Security_Credentials
Security_Authentication_Web_Provider --> Security_Cryptography_Core
Security_Authentication_Web_Provider --> Storage_Streams
Security_Authentication_Web_Provider --> System
Security_Authentication_Web_Provider --> Web_Http
Security_Credentials --> Security_Cryptography_Core
Security_Credentials --> Storage_Streams
Security_Credentials --> System
Security_Cryptography_Certificates --> Networking
Security_Cryptography_Certificates --> Storage_Streams
Security_Cryptography_Core --> Security_Cryptography_Certificates
Security_Cryptography_Core --> Storage_Streams
Security_EnterpriseData --> Networking
Security_EnterpriseData --> Storage
Security_EnterpriseData --> Storage_Streams
Storage_FileProperties --> Storage
Storage_FileProperties --> Storage_Streams
Storage_Pickers_Provider --> Storage
Storage_Provider --> Storage
Storage_Provider --> Storage_Search
Storage_Provider --> Storage_Streams
Storage_Search --> Data_Text
Storage_Search --> Storage
Storage_Search --> Storage_FileProperties
Storage_Search --> Storage_Streams
Storage_Streams --> Storage
Storage_Streams --> System
Storage --> Storage_FileProperties
Storage --> Storage_Pickers_Provider
Storage --> Storage_Provider
Storage --> Storage_Search
Storage --> Storage_Streams
Storage --> System
System_Diagnostics --> ApplicationModel_AppService
System_Diagnostics --> System
System_RemoteSystems --> ApplicationModel_AppService
System_RemoteSystems --> Networking
System_RemoteSystems --> Security_Credentials
System_RemoteSystems --> System
System --> ApplicationModel
System --> ApplicationModel_AppService
System --> Networking
System --> Security_Credentials
System --> Storage
System --> Storage_Search
System --> Storage_Streams
System --> System_Diagnostics
System --> System_RemoteSystems
System --> UI_ViewManagement
UI_Composition --> System
UI_Composition --> UI_Core
UI_Core --> System
UI_Core --> UI_Composition
UI_Core --> UI_Input
UI_Core --> UI_WindowManagement
UI_Input --> ApplicationModel_Core
UI_Input --> Storage_Streams
UI_Input --> System
UI_Input --> UI_Composition
UI_Input --> UI_Core
UI_Input --> UI_Text
UI_Input --> UI_WindowManagement
UI_Notifications --> ApplicationModel
UI_Notifications --> Data_Xml_Dom
UI_Notifications --> System
UI_Text_Core --> Globalization
UI_Text_Core --> UI_Text
UI_Text_Core --> UI_ViewManagement
UI_Text --> Storage_Streams
UI_Text --> UI_Text_Core
UI_ViewManagement --> Devices_Enumeration
UI_ViewManagement --> UI_Core
UI_ViewManagement --> UI_WindowManagement
UI_WindowManagement --> System
UI_WindowManagement --> UI_Composition
Web_Http_Filters --> Networking_Sockets
Web_Http_Filters --> Security_Credentials
Web_Http_Filters --> Security_Cryptography_Certificates
Web_Http_Filters --> System
Web_Http_Filters --> Web_Http
Web_Http_Headers --> Globalization
Web_Http_Headers --> Networking
Web_Http_Headers --> Storage_Streams
Web_Http_Headers --> Web_Http
Web_Http --> Globalization
Web_Http --> Networking_Sockets
Web_Http --> Security_Cryptography_Certificates
Web_Http --> Storage_Streams
Web_Http --> System
Web_Http --> System_Diagnostics
Web_Http --> Web
Web_Http --> Web_Http_Filters
Web_Http --> Web_Http_Headers
Web --> Globalization
Web --> Security_Credentials
Web --> Storage_Streams
Web --> System
Web --> System_Diagnostics
Web --> Web_Http
Web --> Web_Http_Filters
There was a problem hiding this comment.
Seems like this huge reference cycle means that the SCC ends up with a massive amount of code.
|
|
||
| ## Requirements | ||
|
|
||
| - MSVC v145 toolset (Visual Studio 2026) or later recommended |
There was a problem hiding this comment.
Worth calling out a patch level on top of just v145? It seems like very recent fixes are needed for this to work at all. Even the RTM build of VS 2026 is too old (I think).
There was a problem hiding this comment.
I'm not sure. The runner image has "only" VS2026 18.2, with the 14.50 MSVC build tools. I know 18.0 RTM shipped with some version of 14.50, but not sure how much older it is, and what the differences are.
I think the main point is that this is building and running on the 14.50 MSVC build tools, and so far doesn't do anything that requires the newer 14.51 tools (which are planned for VS 18.6).
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
…generates into winrt/macros.h Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Scottj1s
left a comment
There was a problem hiding this comment.
First part of comments - GH is failing to add any more atm
| ## Common Gotchas | ||
|
|
||
| - Module IFCs are NOT compatible across toolset versions — always clean rebuild when switching | ||
| - PCH and modules can coexist but PCH must NOT contain imports from WinRT headers when using modules, and winrt imports are preferred over textual inclusion |
There was a problem hiding this comment.
Given the sharp edges of combining modules with pches (which strikes me as basically an anti-pattern anyway), should we MSBuild warn a user about mixing & matching?
|
|
||
| ## Common Gotchas | ||
|
|
||
| - Module IFCs are NOT compatible across toolset versions — always clean rebuild when switching |
There was a problem hiding this comment.
this reminds me - do we still have the #pragma detect mismatch protection to prevent mixing cppwinrt versions across a build? that was a snag I ran into in early experiments (due do it being macro-based). do we have a test case to validate?
There was a problem hiding this comment.
TLDR; Good point. Fix incoming.
Full version:
I had to think about this one for a sec, and I think there might be a small gap, which I'll try to test for.
But at the same time, modules offer stronger built-in protection for some cases.
To refresh my memory and review what we have, here is what I believe works right now:
- The
#pragma detect_mismatchandcheck_versionare still present inbase.h, and therefore thewinrt_basemodule. - "header mode" still works the same, defends against "multiple version of base.h" as well as "base.h is a different version than this namespace header".
- Headers and
winrt_basehaving different versions should still hit the#pragma detect_mismatch - Importing multiple versions of
winrt_baseinto a binary should still hit the#pragma detect_mismatch - It is probably quite hard to import multiple versions of
winrt_baseinto a translation unit, even if they were the sameCPPWINRT_VERSION, but if you manage to pull it off, I'd still expect#pragma detect_mismatchto catch it.
The gap is:
- Namespace module imports
winrt_baseof a different version. (We still have a single version ofwinrt_basein the binary, but a namespace module of a different version is importing it)
We're probably covered on many of the "scary" cases, like silent ODR violations of base types causing undefined behavior, but not all of it. The interesting machinery types are all owned by winrt_base, and the various namespace modules mostly build on it to create the WinRT projections. ABI-breaking changes to types in base would probably cause a build error, e.g. "wrong number of parameters in winrt::some_function" or " type bar doesn't exist in namespace winrt". But an update could violate assumptions on how those building blocks are supposed to be used, and do so in a way that doesn't break the build.
When compiling the namespace modules, we're importing winrt_base instead of #including base.h. Both base.h and all the modules #include base_macros.h, but CPPWINRT_VERSION-related stuff is directly in base.h, so the namespace modules don't see it.
| & "_build\$target_platform\$target_configuration\cppwinrt.exe" -in local -out _build\$target_platform\$target_configuration -verbose | ||
|
|
||
| - name: Remove module test projects on v143 | ||
| if: matrix.toolchain.platform_toolset == 'v143' |
There was a problem hiding this comment.
do we detect/enforce v145 requirement? is there a graceful degradation path to v143, et al? is that not worthwhile?
There was a problem hiding this comment.
There are fundemental limitations in the v143 toolset. One particular pain point is that v143 modules don't like the auto return types. This breaks the "quality of life" improvements we made that turn missing headers into compile erros instead of link errors.
Here's a CI run when it aattempted to use v143: https://github.com/microsoft/cppwinrt/actions/runs/24921696485/job/72984385782
Even after working around that by wrapping the return type like WINRT_IMPL_AUTO(FooReturnType), there was still a bit of pain. I'm not sure how worthwhile it is to try and light it up for v143, especially when I look at the list of bugfixes that have been going into v145. (See https://devblogs.microsoft.com/cppblog/c-language-updates-in-msvc-build-tools-v14-50/#c++-modules and https://devblogs.microsoft.com/cppblog/msvc-build-tools-version-14-51-release-candidate-now-available/#tickets-fixed)
There was a problem hiding this comment.
However, rather than relying on a cryptic build error to leave a user wondering if they held it wrong, we could issue a #warning or #error if we detect trying to build a module using _MSC_VER less than 1950.
I'm leaning towards a warning like "This probably won't work on this version", rather than forbidding it. I bet winrt_base still (mostly) works on v143, as it doesn't deal with splitting decls and defs across namespace impl headers and all that. Thoughts?
| { | ||
| continue; | ||
| } | ||
| if (settings.module_filter.empty() || settings.module_filter.includes(members)) |
There was a problem hiding this comment.
if module_filter is empty, should/does it fall back to CppWinRTInclude/CppWinRTExclude settings?
|
|
||
| group.get(); | ||
|
|
||
| // Generate per-namespace module interface files (.ixx) |
There was a problem hiding this comment.
does this include subnamespaces? i.e., is there compositional support for importing any level of namespace, as there is for #inclusion?
import winrt // give me everything
import winrt.Microsoft // give me all of WinAppSDK
import winrt.Microsoft.UI.Xaml // give me all of WinUI3
...
There was a problem hiding this comment.
I didn't think we had this compositional support today via inclusion. Windows.UI.Xaml is a distinct namespace that has its own types distinct from the subnamespaces. For example, #include <winrt/Windows.UI.Xaml.h> completely omits WUX.Resources, WUX.Printing, WUX.Markup, etc...
There was a problem hiding this comment.
Correct, this is not true even today.
|
|
||
| **Linker errors for component constructors** — You may be importing a component's internal module instead of building your own reference projection. Remove explicit `/reference` flags for component IFCs and ensure your project has `CppWinRTBuildModule=true` so it builds reference projection modules from the component's `.winmd`. | ||
|
|
||
| **Redefinition errors** — Don't mix `#include` and `import` for the same namespace in the same translation unit. Use `import` consistently. |
There was a problem hiding this comment.
is this something we can detect in MSBuild, break the build, and issue a diagnostic?
There was a problem hiding this comment.
I'll clarify the doc. This guidance exists because violating it will break the build. In the C++ kingdom of "foot guns", the addition of modules both introduces new foot guns, and provides opportunities to hold old foot guns in new ways. 😉
For the first case, you can do that with headers today. If component A.dll somehow consuming component B.dll's projection headers that were built with -opt. The direct construction functions that bypass activation factories wouldn't exist in component B, resulting in a linker error.
For the second case, MSVC++ modules currently don't like it if you import and then #include. You get redefinition errors. The guidance is to try and avoid that.
I'm also going to update and flesh out this guidance based on lessons learned from the Terminal prototype.
| } | ||
| ``` | ||
|
|
||
| ## C++20 Modules |
There was a problem hiding this comment.
meta: how do plan to message out? last update to https://learn.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/news was March 2020, so there's lots of content we could announce, not necessarily just 3.0-specific work like modules. will we also coordinate a VSIX update with DevDiv for generic natvis support?
| <ItemGroup Label="ProjectConfigurations"> | ||
| <ProjectConfiguration Include="Debug|ARM64"> | ||
| <Configuration>Debug</Configuration> | ||
| <Platform>ARM64</Platform> |
There was a problem hiding this comment.
have we confirmed compat with arm64ec? cl.exe and link.exe are deeply involved there, so wouldn't surprise me if there's a bad interaction with modules. if so, we should provide MSBuild diagnostic.
There was a problem hiding this comment.
It seems to work for me. On my ARM64 Surface Pro, I successfully built and ran both the x64 and arm64 configurations.
Is this what you were thinking, or is there something deeper I need to worry about?
There was a problem hiding this comment.
do we have a sample that also consumes the Windows SDK headers? that was a major incompatibility when I was experimenting
There was a problem hiding this comment.
By Windows SDK headers, do you mean the non-cppwinrt headers, like <Windows.h> and <Unknwn.h>?
There was a problem hiding this comment.
also - test cases for mixing & matching import/include across WinAppSDK, WindowsSDK, std? there was that include-after-import bug in cl.exe for a while.
There was a problem hiding this comment.
Include after import is still broken in MSVC AFAIK.
| auto wrap_includes = wrap_module_aware_includes_guard(w, true); | ||
| w.write(strings::base_includes); | ||
| } | ||
| w.write("#include \"winrt/base_macros.h\"\n"); |
There was a problem hiding this comment.
Use write_include to use "" or <> depending on settings.
| w.write(strings::base_natvis); | ||
| w.write(strings::base_version); | ||
|
|
||
| w.write("#endif // WINRT_IMPORT_MODULE\n"); |
| write_namespace_special(w, ns); | ||
|
|
||
| write_close_file_guard(w); | ||
| w.write("#endif\n"); // WINRT_IMPORT_MODULE |
There was a problem hiding this comment.
This endif doesn't seem to have a matching ifdef
There was a problem hiding this comment.
It's below the call to w.swap(). It mirrors the write_open_file_guard()/write_close_file_guard() pair.
There was a problem hiding this comment.
Ahh slightly confusing. Might be good to add a comment.
| write_preamble(w); | ||
| write_include_guard(w); | ||
|
|
||
| w.write("#ifdef WINRT_IMPORT_MODULE\n"); |
There was a problem hiding this comment.
This also has a #else before the #endif. I'm adding a trailing comment to the #else to make this clearer.
There was a problem hiding this comment.
Should be able to use wrap_ifdef nonetheless, no?
|
|
||
| if (settings.modules) | ||
| { | ||
| // The .g.h handles its own imports, but the implementation .h |
There was a problem hiding this comment.
Ideally implementers would also be able to use ixx for their types, not headers.
There was a problem hiding this comment.
I'll think about it. It sounds nice, but I'm not sure how much value it provides in practice. Also, it carries some implications:
- Currently, you're under no obligation to use the component-generated
Class.g.cppandClass.g.hfiles. It's highly recommended, and good luck keeping your code up to date when C++/WinRT changes the codegen in that area, but if folks feel like breaking the warranty and going off-road, they can do that. And in either case, they don't have to add anything to the project. Just#include(or not) the .g.* files from theirClass.cppandClass.hfiles. Making this a module means that our targets should add these Class Implementation ixx files to the build by default, and we need to consider whether that needs to be configurable. - The XAML compiler emits module-unaware code. In my Terminal prototype, I've managed to work around the places where it includes projection headers. I have a module preamble that imports the types instead and defines
WINRT_IMPORT_MODULEto make those later inclusions inert. But XAML also generatesXamlMetaDataProvider.hthat includes cppwinrt'sXamlMetaDataProvider.g.h, which I hesitate to workaround in the same way, because importing implementation modules into the project's module preamble header seems... gross.
Folks should definitely continue investigating these line of thinking though, but for a future commit.
| import std; | ||
| export import winrt_numerics; | ||
|
|
||
| #if __has_include(<windowsnumerics.impl.h>) |
There was a problem hiding this comment.
Why is this here if export import winrt_numerics is right above?
| @@ -0,0 +1,7 @@ | |||
| module; | |||
| #define WINRT_IMPL_BUILD_MODULE | |||
| #include <version> | |||
There was a problem hiding this comment.
Why not move these includes to base_macros.h?
|
|
||
| export module winrt_numerics; | ||
|
|
||
| #if __has_include(<windowsnumerics.impl.h>) |
There was a problem hiding this comment.
As mentionned earlier, make this its own string instead of duplicating it.
| #ifdef _DEBUG | ||
| #include <crtdbg.h> | ||
| #endif // _DEBUG | ||
| #include "winrt/base_macros.h" |
There was a problem hiding this comment.
This should be write_includes in code to use the "" or <> depending on project settings. This string isn't needed.
| (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); | ||
| _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); | ||
| (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); | ||
| return Catch::Session().run(argc, argv); |
There was a problem hiding this comment.
Can we maybe add some tests that exercise the std specializations, like format or maps, to ensure those are properly working?
There was a problem hiding this comment.
Good idea, I'll add some more. I've already added modules test cases to check range-based for and structured binding across IKeyValuePair<K, V>, and the latter requires exporting specializations of std::tuple_size and std::tuple_element, which I originally missed.
There was a problem hiding this comment.
I know the format specializations used to trigger ICEs, so I'm curious if they are still problematic.
|
In module builds with legacy COM enabled, TrustLevel, IUnknown, and GUID should be placed in the global module fragment. C++/WinRT should not provide them within the module implementation. I forgot about this issue before. |
C++20 Module Support v2: Per-Namespace Modules (
import winrt.Windows.Foundation;)Overview
This PR adds per-namespace C++20 module support to C++/WinRT, building on the approach pioneered by @YexuanXiao's cppwinrtplus fork. Instead of a single monolithic
import winrt;module (v1), each WinRT namespace gets its own named module:This provides finer-grained imports, better build parallelism, and first-class support for component authoring with modules.
Key Design Decisions
1. Unconditional guards, flag-controlled generation
Module awareness (guards,
WINRT_EXPORT) is always present in projection headers. The-modulesflag controls.ixxgeneration and whether generated component files (module.g.cpp, stub.cpp) useimportvs#include. Projection headers themselves are identical regardless of-modules.2. All three projections generate modules uniformly
When
CppWinRTBuildModule=true,-modulesis passed to the platform, reference, and component projections. There is no special module-specific handling that distinguishes these projections — the existing differences (e.g.,-optfor components,-compfor component stubs) are pre-existing behavior.3. Per-ProjectReference IFC consumption
CppWinRTConsumeModuleis metadata on aProjectReference, not a project-level property. When set, it suppresses-moduleson the platform projection (since IFCs are already available from the referenced project) but does not affect the reference or component projections. This gives precise control over which pre-built IFCs to reuse.4. SCC consolidation for cyclic namespaces
Tarjan's algorithm groups cyclic namespaces. The alphabetically-first namespace owns the module; others re-export it. Users can
import winrt.AnyNamespace;regardless of SCC membership.What's in This PR
Code generator (
cppwinrt/)main.cpp-modules,-module_include,-module_excludeCLI options. Two-pass namespace loop: first populates module namespace set, then generates headers with dependency collection. Tarjan's SCC algorithm. .ixx generation loop.file_writers.hwrite_macros_h(),write_module_preamble(),write_base_ixx(),write_numerics_ixx(),write_namespace_ixx(),write_namespace_scc_owner_ixx(),write_namespace_reexport_ixx(). UnconditionalWINRT_IMPORT_MODULE/WINRT_IMPL_BUILD_MODULEguards on all generated headers. Component.g.hdual-path (import vs include).base.hnow#includeswinrt/base_macros.hinstead of inlining macros.code_writers.hwrap_module_aware_includes_guard()updated comment.wrap_impl_namespace()usesWINRT_EXPORT namespace winrt::impl.settings.hbool modules,std::set module_include/exclude,winmd::reader::filter module_filter.String literals (
strings/)namespace winrt::impl→WINRT_EXPORT namespace winrt::implnamespace std→WINRT_IMPL_STD_EXPORT namespace stdbase_macros.hrefactored as canonical shared macroswinrt/base_macros.h, used by bothbase.hand.ixxglobal fragmentsbase_source_location.hslim_source_location(split frombase_macros.h)base_module_ixx_preamble.h.ixxfilesbase_module_base_ixx.hwinrt_base.ixxtemplatebase_module_numerics_ixx.hwinrt_numerics.ixxtemplatebase_extern.hWINRT_EXPORTto handler function pointers for module/non-module linkagebase_fast_forward.hWINRT_EXPORTfallback definitionMSBuild integration (
nuget/)User-facing properties:
CppWinRTBuildModule-modulesfor all three projections, generating.ixxfiles alongside headersCppWinRTModuleIncludeCppWinRTModuleExcludeCppWinRTConsumeModule.ixxgeneration and uses pre-built IFCs from the referenced projectInternal targets (not directly configured by users):
CppWinRTAddModuleInterfaces.ixxfiles and adds them as ClCompile items with module compilation metadataCppWinRTGetModuleOutputsCppWinRTResolveModuleReferencesCppWinRTGetModuleOutputson ProjectReferences tagged withCppWinRTConsumeModuleTest projects
test/test_cpp20_module/test/nuget/TestModuleBuilder/test/nuget/TestModuleComponent1/test/nuget/TestModuleComponent2/test/nuget/TestModuleConsumerApp/test/nuget/TestModuleApp/Documentation
nuget/modules.mddocs/modules-design.md.github/instructions/cppwinrt.instructions.md.github/instructions/modules.instructions.mdBefore / After: User Code
Header mode (unchanged)
Module mode (new)
Component authoring with modules
Before / After: Generated Code
Namespace header (
winrt/Windows.Foundation.h) — guard changesBefore (no module awareness):
After (unconditional module guards):
New: Generated module interface (
winrt.Windows.Foundation.ixx)New: SCC owner module (cycle breaker)
When namespaces form dependency cycles (e.g.,
Windows.Foundation↔Windows.Foundation.Collections), the alphabetically-first namespace becomes the SCC owner:New: Component
.g.h(dual-path)Differences from the cppwinrtplus Fork
This implementation shares the same core architecture as @YexuanXiao's cppwinrtplus fork — per-namespace modules, Tarjan SCC cycle breaking,
WINRT_EXPORTmacro — but diverges in several areas:Module naming
winrt.basewinrt_basewinrt.numericswinrt_numerics<Namespace>.ixx(e.g.Windows.Foundation.ixx)winrt.<Namespace>.ixx(e.g.winrt.Windows.Foundation.ixx)The
winrt.prefix on namespace modules avoids potential collisions if other code generators produce modules with the same namespace names. Thewinrt_base/winrt_numericsunderscore form avoids a dotted name that could imply a namespace hierarchy.Module namespace filtering
cppwinrtplus uses a
CppWinRT.configXML file in the solution directory with<exclude><prefix>elements to exclude namespaces from module generation. This PR uses-module_include/-module_excludeCLI flags with prefix matching, exposed asCppWinRTModuleInclude/CppWinRTModuleExcludeMSBuild properties. The CLI approach integrates directly into MSBuild response files without needing a separate config file, and supports both include and exclude semantics.Guard macros
WINRT_MODULEWINRT_IMPL_BUILD_MODULEWINRT_CONSUME_MODULEWINRT_IMPORT_MODULE-modulesflagMaking guards unconditional means the
-modulesflag controls.ixxgeneration and module-aware component code generation (.g.cpp,module.g.cpp, stub.cpp), but does NOT change the content of projection headers — they work in both module and header mode without regeneration.Builder/consumer architecture
cppwinrtplus does not have a concept of sharing pre-built IFCs across projects — each project builds all its own modules. This PR introduces:
CppWinRTBuildModule— project-level property to enable module generation for all three projectionsCppWinRTConsumeModule— per-ProjectReference metadata that suppresses platform.ixxgeneration and lets the project use pre-built IFCs from the referenced project insteadCppWinRTGetModuleOutputs/CppWinRTResolveModuleReferences— Internal MSBuild targets for cross-project IFC path resolutionAcknowledgements
Credit to @YexuanXiao and the cppwinrtplus fork for the per-namespace module architecture, SCC algorithm, and initial demonstration of viability. Also @sylveon, @Scottj1s, and @zadjii-msft for early module exploration and feedback on v1.