Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 63 additions & 32 deletions cppwinrt/code_writers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
)";

Expand All @@ -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
{
)");

Expand All @@ -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::@
{
)";

Expand All @@ -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::@
{
)";

Expand Down Expand Up @@ -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) };
Expand All @@ -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 <typename D>
auto format = R"( template <typename D>
struct consume_%
{
%%% };
template <> struct consume<%>
{
template <typename D> using type = consume_%<D>;
};
)";


w.write(format,
impl_name,
bind_each<write_consume_declaration>(type.MethodList()),
bind<write_fast_consume_declarations>(type),
bind<write_consume_extensions>(type),
type,
impl_name);
impl_name,
bind_each<write_consume_declaration>(type.MethodList()),
bind<write_fast_consume_declarations>(type),
bind<write_consume_extensions>(type));
}
else
{
auto format = R"( template <typename D, %>
auto format = R"( template <typename D, %>
struct consume_%
{
%%% };
template <%> struct consume<%>
)";
w.write(format,
bind<write_generic_typenames>(generics),
impl_name,
bind_each<write_consume_declaration>(type.MethodList()),
bind<write_fast_consume_declarations>(type),
bind<write_consume_extensions>(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 <typename D> using type = consume_%<D>;
};
)";
w.write(format, type, impl_name);
}
else
{
auto format = R"( template <%> struct consume<%>
{
template <typename D> using type = consume_%<D, %>;
};
)";


w.write(format,
bind<write_generic_typenames>(generics),
impl_name,
bind_each<write_consume_declaration>(type.MethodList()),
bind<write_fast_consume_declarations>(type),
bind<write_consume_extensions>(type),
bind<write_generic_typenames>(generics),
type,
impl_name,
bind_list(", ", generics));
bind<write_generic_typenames>(generics),
type,
impl_name,
bind_list(", ", generics));
}
}

Expand Down
51 changes: 45 additions & 6 deletions cppwinrt/file_writers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand Down Expand Up @@ -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");
}
Expand Down Expand Up @@ -142,7 +166,7 @@ namespace cppwinrt
w.write_each<write_forward>(members.contracts);
}
{
auto wrap_impl = wrap_impl_namespace(w);
auto wrap_impl = wrap_impl_namespace_without_export(w);
w.write_each<write_category>(members.interfaces, "interface_category");
w.write_each<write_category>(members.classes, "class_category");
w.write_each<write_category>(members.enums, "enum_category");
Expand All @@ -165,10 +189,19 @@ namespace cppwinrt
w.write_each<write_default_interface>(members.classes);
w.write_each<write_interface_abi>(members.interfaces);
w.write_each<write_delegate_abi>(members.delegates);
w.write_each<write_consume>(members.interfaces);
w.write_each<write_struct_abi>(members.structs);
}

{
auto wrap_impl = wrap_impl_namespace(w);
w.write_each<write_consume_type>(members.interfaces);
}

{
auto wrap_impl = wrap_impl_namespace_without_export(w);
w.write_each<write_consume_specialization>(members.interfaces);
}

if (settings.modules)
{
get_namespace_module_imports(c, ns, w, module_imports);
Expand Down Expand Up @@ -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(<directxmath.h>) && __has_include(<windowsnumerics.impl.h>)
#include <stdexcept>
#include <limits>
#include <directxmath.h>
#endif

export module winrt.numerics;

// Module dependencies:
// - (none)

#if __has_include(<windowsnumerics.impl.h>)
#if __has_include(<directxmath.h>) && __has_include(<windowsnumerics.impl.h>)
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 5244)
#endif
#include <directxmath.h>

#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 <windowsnumerics.impl.h>
// 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_
Expand Down
6 changes: 2 additions & 4 deletions strings/base_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,19 @@
#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

// <windowsnumerics.impl.h> 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.
#if !(defined(WINRT_MODULE) || defined(WINRT_CONSUME_MODULE))

#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 <windowsnumerics.impl.h>
#undef _WINDOWS_NUMERICS_NAMESPACE_
Expand Down