From 199e13619a359fbfc191c19dec49027e0437ed2a Mon Sep 17 00:00:00 2001 From: YexuanXiao Date: Mon, 27 Apr 2026 03:02:44 +0800 Subject: [PATCH] Cleanup WINRT_EXPORT --- cppwinrt/code_writers.h | 95 +++++++++++++++++++++++++++-------------- cppwinrt/file_writers.h | 51 +++++++++++++++++++--- strings/base_macros.h | 6 +-- 3 files changed, 110 insertions(+), 42 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index f419d97b5..ebcd3da9d 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -194,7 +194,18 @@ namespace cppwinrt [[nodiscard]] static finish_with wrap_impl_namespace(writer& w) { - auto format = R"(WINRT_EXPORT namespace winrt::impl + auto format = R"(WINRT_EXPORT extern "C++" namespace winrt::impl +{ +)"; + + w.write(format); + + return { w, write_close_namespace }; + } + + [[nodiscard]] static finish_with wrap_impl_namespace_without_export(writer& w) + { + auto format = R"(extern "C++" namespace winrt::impl { )"; @@ -205,7 +216,7 @@ namespace cppwinrt [[nodiscard]] static finish_with wrap_std_namespace(writer& w) { - w.write(R"(WINRT_EXPORT namespace std + w.write(R"(extern "C++" namespace std { )"); @@ -214,7 +225,7 @@ namespace cppwinrt [[nodiscard]] static finish_with wrap_type_namespace(writer& w, std::string_view const& ns) { - auto format = R"(WINRT_EXPORT namespace winrt::@ + auto format = R"(WINRT_EXPORT extern "C++" namespace winrt::@ { )"; @@ -225,7 +236,7 @@ namespace cppwinrt [[nodiscard]] static finish_with wrap_type_namespace_without_export(writer& w, std::string_view const& ns) { - auto format = R"(namespace winrt::@ + auto format = R"(extern "C++" namespace winrt::@ { )"; @@ -1548,7 +1559,7 @@ namespace cppwinrt } } - static void write_consume(writer& w, TypeDef const& type) + static void write_consume_type(writer& w, TypeDef const& type) { auto generics = type.GenericParam(); auto guard{ w.push_generic_params(generics) }; @@ -1561,51 +1572,71 @@ namespace cppwinrt auto type_namespace = type.TypeNamespace(); auto impl_name = get_impl_name(type_namespace, type_name); - + if (empty(generics)) { - auto format = R"( template + auto format = R"( template struct consume_% { %%% }; - template <> struct consume<%> - { - template using type = consume_%; - }; )"; - - w.write(format, - impl_name, - bind_each(type.MethodList()), - bind(type), - bind(type), - type, - impl_name); + impl_name, + bind_each(type.MethodList()), + bind(type), + bind(type)); } else { - auto format = R"( template + auto format = R"( template struct consume_% { %%% }; - template <%> struct consume<%> +)"; + w.write(format, + bind(generics), + impl_name, + bind_each(type.MethodList()), + bind(type), + bind(type)); + } + } + + static void write_consume_specialization(writer& w, TypeDef const& type) + { + auto generics = type.GenericParam(); + auto guard{ w.push_generic_params(generics) }; + auto type_name = type.TypeName(); + + if (!empty(generics)) + { + type_name = remove_tick(type_name); + } + + auto type_namespace = type.TypeNamespace(); + auto impl_name = get_impl_name(type_namespace, type_name); + + if (empty(generics)) + { + auto format = R"( template <> struct consume<%> + { + template using type = consume_%; + }; +)"; + w.write(format, type, impl_name); + } + else + { + auto format = R"( template <%> struct consume<%> { template using type = consume_%; }; )"; - - w.write(format, - bind(generics), - impl_name, - bind_each(type.MethodList()), - bind(type), - bind(type), - bind(generics), - type, - impl_name, - bind_list(", ", generics)); + bind(generics), + type, + impl_name, + bind_list(", ", generics)); } } diff --git a/cppwinrt/file_writers.h b/cppwinrt/file_writers.h index 6f9b4db5d..ee6542683 100644 --- a/cppwinrt/file_writers.h +++ b/cppwinrt/file_writers.h @@ -44,6 +44,11 @@ namespace cppwinrt { auto wrap_file_guard = wrap_open_file_guard(w, "BASE"); + if (settings.modules) + { + w.write("#ifndef WINRT_CONSUME_MODULE\n"); + } + { // In module builds, generated projection headers must be "module-aware": // When `WINRT_MODULE` is defined (inside a module interface unit), suppress textual includes so the @@ -52,6 +57,13 @@ namespace cppwinrt auto wrap_includes_guard = wrap_module_aware_includes_guard(w, settings.modules); w.write(strings::base_includes); } + if (settings.modules) + { + w.write(R"( +extern "C++" +{ +)"); + } w.write(strings::base_macros); w.write(strings::base_types); @@ -85,6 +97,18 @@ namespace cppwinrt w.write(strings::base_coroutine_threadpool); w.write(strings::base_natvis); w.write(strings::base_version); + + if (settings.modules) + { + w.write(R"( +} // extern "C++" +)"); + } + + if (settings.modules) + { + w.write("#endif\n"); + } } w.flush_to_file(settings.output_folder + "winrt/base.h"); } @@ -142,7 +166,7 @@ namespace cppwinrt w.write_each(members.contracts); } { - auto wrap_impl = wrap_impl_namespace(w); + auto wrap_impl = wrap_impl_namespace_without_export(w); w.write_each(members.interfaces, "interface_category"); w.write_each(members.classes, "class_category"); w.write_each(members.enums, "enum_category"); @@ -165,10 +189,19 @@ namespace cppwinrt w.write_each(members.classes); w.write_each(members.interfaces); w.write_each(members.delegates); - w.write_each(members.interfaces); w.write_each(members.structs); } + { + auto wrap_impl = wrap_impl_namespace(w); + w.write_each(members.interfaces); + } + + { + auto wrap_impl = wrap_impl_namespace_without_export(w); + w.write_each(members.interfaces); + } + if (settings.modules) { get_namespace_module_imports(c, ns, w, module_imports); @@ -353,22 +386,28 @@ export import winrt.numerics; write_module_global_fragment(w); w.write(R"( +// Include in advance so that all of numerics's dependencies can be in the global module fragment +#if __has_include() && __has_include() +#include +#include +#include +#endif + export module winrt.numerics; // Module dependencies: // - (none) -#if __has_include() +#if __has_include() && __has_include() #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 5244) #endif -#include - #define _WINDOWS_NUMERICS_NAMESPACE_ winrt::Windows::Foundation::Numerics #define _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ export extern "C++" namespace winrt::Windows::Foundation::Numerics #define _WINDOWS_NUMERICS_END_NAMESPACE_ -#include +// Double quotes are intentionally used because compilers (MSVC and Clang) consider system headers should not be module implementation files. +#include "windowsnumerics.impl.h" #undef _WINDOWS_NUMERICS_NAMESPACE_ #undef _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ #undef _WINDOWS_NUMERICS_END_NAMESPACE_ diff --git a/strings/base_macros.h b/strings/base_macros.h index 612e2beb9..baae26dca 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -27,13 +27,11 @@ #pragma warning(disable : 4630) #endif -#ifndef WINRT_EXPORT #ifdef WINRT_MODULE -#define WINRT_EXPORT export extern "C++" +#define WINRT_EXPORT export #else #define WINRT_EXPORT #endif -#endif // pulls in large, hard-to-control legacy headers. In header builds we keep the // existing behavior, but in module builds it's provided by the winrt.numerics module. @@ -41,7 +39,7 @@ #ifdef WINRT_IMPL_NUMERICS #define _WINDOWS_NUMERICS_NAMESPACE_ winrt::Windows::Foundation::Numerics -#define _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ WINRT_EXPORT namespace winrt::Windows::Foundation::Numerics +#define _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ extern "C++" namespace winrt::Windows::Foundation::Numerics #define _WINDOWS_NUMERICS_END_NAMESPACE_ #include #undef _WINDOWS_NUMERICS_NAMESPACE_