Skip to content

Commit 546491d

Browse files
committed
Test component project is building. Checkpoint with some documentation added.
1 parent 79d8003 commit 546491d

20 files changed

+1134
-8
lines changed

cppwinrt/code_writers.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,19 @@ namespace cppwinrt
3737

3838
static void write_version_assert(writer& w)
3939
{
40+
// When WINRT_IMPL_SKIP_INCLUDES is defined, base.h is already available
41+
// from the imported winrt module. However, macros don't cross module
42+
// boundaries, so we include a lightweight header with just the macros.
43+
auto format_guard = R"(#ifdef WINRT_IMPL_SKIP_INCLUDES
44+
#include "winrt/base_macros.h"
45+
#else
46+
)";
47+
auto format_end = R"(#endif
48+
)";
49+
w.write(format_guard);
4050
w.write_root_include("base");
51+
w.write(format_end);
52+
4153
auto format = R"(static_assert(winrt::check_version(CPPWINRT_VERSION, "%"), "Mismatched C++/WinRT headers.");
4254
#define CPPWINRT_VERSION "%"
4355
)";
@@ -137,7 +149,7 @@ namespace cppwinrt
137149

138150
if (found != c.namespaces().end() && has_projected_types(found->second))
139151
{
140-
w.write_root_include(parent);
152+
w.write_root_include_guarded(parent);
141153
}
142154
else
143155
{

cppwinrt/component_writers.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,14 @@ namespace cppwinrt
136136

137137
static void write_module_g_cpp(writer& w, std::vector<TypeDef> const& classes)
138138
{
139-
w.write_root_include("base");
139+
if (settings.component_module)
140+
{
141+
w.write("import std;\nimport winrt;\n");
142+
}
143+
else
144+
{
145+
w.write_root_include("base");
146+
}
140147
auto format = R"(%
141148
bool __stdcall %_can_unload_now() noexcept
142149
{
@@ -397,6 +404,14 @@ catch (...) { return winrt::to_hresult(); }
397404
return;
398405
}
399406

407+
// In module mode, the constructor/static definitions are already exported
408+
// from the winrt module (via the namespace header folded into winrt.ixx).
409+
// Only the winrt_make_* factory function above is needed.
410+
if (settings.component_module)
411+
{
412+
return;
413+
}
414+
400415
auto wrap_type = wrap_type_namespace(w, type_namespace);
401416

402417
for (auto&&[factory_name, factory] : get_factories(w, type))

cppwinrt/file_writers.h

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,57 @@ namespace cppwinrt
4646
w.flush_to_file(settings.output_folder + "winrt/base.h");
4747
}
4848

49+
// Lightweight header containing only the preprocessor macros needed by
50+
// generated namespace headers. Used when WINRT_IMPL_SKIP_INCLUDES is
51+
// defined (i.e., consuming component headers after 'import winrt;').
52+
// Macros don't cross module boundaries, so this provides the macros
53+
// that base.h would normally supply.
54+
static void write_base_macros_h()
55+
{
56+
writer w;
57+
write_preamble(w);
58+
w.write(R"(#pragma once
59+
60+
// This header provides the preprocessor macros needed by generated C++/WinRT
61+
// headers when the full base.h is not #included (e.g., when using 'import winrt;').
62+
// Macros are not exported across C++20 module boundaries, so this lightweight
63+
// header must be included textually.
64+
65+
#ifndef CPPWINRT_VERSION
66+
#define CPPWINRT_VERSION "%"
67+
#endif
68+
69+
#ifndef WINRT_EXPORT
70+
#define WINRT_EXPORT
71+
#endif
72+
73+
#if defined(_MSC_VER)
74+
#define WINRT_IMPL_EMPTY_BASES __declspec(empty_bases)
75+
#else
76+
#define WINRT_IMPL_EMPTY_BASES
77+
#endif
78+
79+
#if defined(_MSC_VER)
80+
#define WINRT_IMPL_NOVTABLE __declspec(novtable)
81+
#else
82+
#define WINRT_IMPL_NOVTABLE
83+
#endif
84+
85+
#if defined(__clang__) && defined(__has_attribute)
86+
#if __has_attribute(__lto_visibility_public__)
87+
#define WINRT_IMPL_PUBLIC __attribute__((lto_visibility_public))
88+
#else
89+
#define WINRT_IMPL_PUBLIC
90+
#endif
91+
#else
92+
#define WINRT_IMPL_PUBLIC
93+
#endif
94+
95+
#define WINRT_IMPL_ABI_DECL WINRT_IMPL_NOVTABLE WINRT_IMPL_PUBLIC
96+
)", CPPWINRT_VERSION_STRING);
97+
w.flush_to_file(settings.output_folder + "winrt/base_macros.h");
98+
}
99+
49100
static void write_fast_forward_h(std::vector<TypeDef> const& classes)
50101
{
51102
writer w;
@@ -139,7 +190,7 @@ namespace cppwinrt
139190

140191
for (auto&& depends : w.depends)
141192
{
142-
w.write_depends(depends.first, '0');
193+
w.write_depends_guarded(depends.first, '0');
143194
}
144195

145196
w.write_depends(w.type_namespace, '0');
@@ -169,7 +220,7 @@ namespace cppwinrt
169220

170221
for (auto&& depends : w.depends)
171222
{
172-
w.write_depends(depends.first, impl);
223+
w.write_depends_guarded(depends.first, impl);
173224
}
174225

175226
w.write_depends(w.type_namespace, '1');
@@ -224,7 +275,7 @@ namespace cppwinrt
224275

225276
for (auto&& depends : w.depends)
226277
{
227-
w.write_depends(depends.first, '2');
278+
w.write_depends_guarded(depends.first, '2');
228279
}
229280

230281
w.write_depends(w.type_namespace, '2');
@@ -250,9 +301,22 @@ namespace cppwinrt
250301
write_preamble(w);
251302
write_include_guard(w);
252303

253-
for (auto&& depends : w.depends)
304+
if (settings.component_module)
305+
{
306+
// In module mode, both SDK and component types are available from
307+
// 'import winrt;' (the component projection is folded into the
308+
// winrt.ixx module). Only macros need a textual include since
309+
// they don't cross module boundaries.
310+
w.write("#include \"winrt/base_macros.h\"\n");
311+
w.write("import std;\n");
312+
w.write("import winrt;\n");
313+
}
314+
else
254315
{
255-
w.write_depends(depends.first);
316+
for (auto&& depends : w.depends)
317+
{
318+
w.write_depends(depends.first);
319+
}
256320
}
257321

258322
auto filename = settings.output_folder + get_generated_component_filename(type) + ".g.h";

cppwinrt/main.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ namespace cppwinrt
3939
{ "fastabi", 0, 0 }, // Enable support for the Fast ABI
4040
{ "ignore_velocity", 0, 0 }, // Ignore feature staging metadata and always include implementations
4141
{ "synchronous", 0, 0 }, // Instructs cppwinrt to run on a single thread to avoid file system issues in batch builds
42+
{ "module", 0, 0, {}, "Generate component files using 'import winrt;' instead of #include" },
4243
};
4344

4445
static void print_usage(writer& w)
@@ -172,6 +173,13 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder
172173
settings.component_lib = args.value("library", "winrt");
173174
settings.component_opt = args.exists("optimize");
174175
settings.component_ignore_velocity = args.exists("ignore_velocity");
176+
settings.component_module = args.exists("module");
177+
178+
if (settings.component_module)
179+
{
180+
// Module mode disables the PCH include in generated files
181+
settings.component_pch.clear();
182+
}
175183

176184
if (settings.component_pch == ".")
177185
{
@@ -373,6 +381,7 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder
373381
if (settings.base)
374382
{
375383
write_base_h();
384+
write_base_macros_h();
376385
ixx.flush_to_file(settings.output_folder + "winrt/winrt.ixx");
377386
}
378387

cppwinrt/settings.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ namespace cppwinrt
3131

3232
bool fastabi{};
3333
std::map<winmd::reader::TypeDef, winmd::reader::TypeDef> fastabi_cache;
34+
35+
bool component_module{}; // Generate component files using 'import winrt;' instead of #include
3436
};
3537

3638
extern settings_type settings;

cppwinrt/type_writers.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,19 @@ namespace cppwinrt
564564
settings.brackets ? '>' : '\"');
565565
}
566566

567+
void write_root_include_guarded(std::string_view const& include)
568+
{
569+
auto format = R"(#ifndef WINRT_IMPL_SKIP_INCLUDES
570+
#include %winrt/%.h%
571+
#endif
572+
)";
573+
574+
write(format,
575+
settings.brackets ? '<' : '\"',
576+
include,
577+
settings.brackets ? '>' : '\"');
578+
}
579+
567580
void write_depends(std::string_view const& ns, char impl = 0)
568581
{
569582
if (impl)
@@ -576,6 +589,18 @@ namespace cppwinrt
576589
}
577590
}
578591

592+
void write_depends_guarded(std::string_view const& ns, char impl = 0)
593+
{
594+
if (impl)
595+
{
596+
write_root_include_guarded(write_temp("impl/%.%", ns, impl));
597+
}
598+
else
599+
{
600+
write_root_include_guarded(ns);
601+
}
602+
}
603+
579604
void save_header(char impl = 0)
580605
{
581606
auto filename{ settings.output_folder + "winrt/" };

0 commit comments

Comments
 (0)