@@ -76,14 +76,7 @@ namespace cppwinrt
7676 return ;
7777 }
7878
79- if (settings.component_opt )
80- {
81- auto format = R"( void* winrt_make_%();
82- )" ;
83-
84- w.write (format, get_impl_name (type.TypeNamespace (), type.TypeName ()));
85- }
86- else
79+ if (!settings.component_opt )
8780 {
8881 auto format = R"( #include "%.h"
8982)" ;
@@ -105,42 +98,86 @@ namespace cppwinrt
10598
10699 if (settings.component_opt )
107100 {
108- auto format = R"(
109- if (requal(name, L"%.%"))
110- {
111- return winrt_make_%();
112- }
101+ auto format = R"( void* winrt_make_%();
113102)" ;
114103
115- w.write (format,
116- type_namespace,
117- type_name,
118- impl_name);
104+ w.write (format, impl_name);
119105 }
120106 else
121107 {
122- auto format = R"(
123- if (requal(name, L"%.%"))
124- {
125- return winrt::detach_abi(winrt::make<winrt::@::factory_implementation::%>());
126- }
108+ auto format = R"( void* winrt_make_%()
109+ {
110+ return winrt::detach_abi(winrt::make<winrt::@::factory_implementation::%>());
111+ }
127112)" ;
128113
129114 w.write (format,
130- type_namespace,
131- type_name,
115+ impl_name,
132116 type_namespace,
133117 type_name);
134118 }
135119 }
136120
121+ static void add_component_manifest_entry (TypeDef const & type, std::vector<std::string>& manifest)
122+ {
123+ if (!has_factory_members (type) || is_always_disabled (type))
124+ {
125+ return ;
126+ }
127+
128+ std::string name;
129+ name += type.TypeNamespace ();
130+ name += ' .' ;
131+ name += type.TypeName ();
132+ manifest.push_back (std::move (name));
133+ }
134+
137135 static void write_module_g_cpp (writer& w, std::vector<TypeDef> const & classes)
138136 {
139137 if (!settings.modules )
140138 {
141139 w.write_root_include (" base" );
142140 }
143- auto format = R"( %
141+
142+ for (auto && type : classes)
143+ {
144+ write_component_include (w, type);
145+ }
146+
147+ std::vector<std::string> manifest;
148+
149+ for (auto && type : classes)
150+ {
151+ add_component_manifest_entry (type, manifest);
152+ }
153+
154+ // Sort the strings so that binary search can be used.
155+ std::sort (manifest.begin (), manifest.end ());
156+
157+ w.write (" #define WINRT_ACTIVATION_TABLE(X)\\\n " );
158+
159+ for (std::size_t i = 0 ; i + 1 < manifest.size (); ++i)
160+ {
161+ w.write (std::string{ " X(winrt_make_" } + get_impl_name (manifest[i]) + " , L\" " + manifest[i] + " \" ) \\\n " );
162+ }
163+
164+ if (!manifest.empty ())
165+ {
166+ w.write (std::string{ " X(winrt_make_" } + get_impl_name (manifest.back ()) + " , L\" " + manifest.back () + " \" )\n " );
167+ }
168+
169+ auto declarations = R"(
170+ #define WINRT_DECLARE_FUNC(func, name) void* func();
171+ WINRT_ACTIVATION_TABLE(WINRT_DECLARE_FUNC)
172+ )" ;
173+ w.write (declarations);
174+
175+ for (auto && type : classes)
176+ {
177+ write_component_activation (w, type);
178+ }
179+
180+ auto format = R"(
144181bool __stdcall %_can_unload_now() noexcept
145182{
146183 if (winrt::get_module_lock())
@@ -154,20 +191,31 @@ bool __stdcall %_can_unload_now() noexcept
154191
155192void* __stdcall %_get_activation_factory([[maybe_unused]] std::wstring_view const& name)
156193{
157- auto requal = [](std::wstring_view const& left, std::wstring_view const& right) noexcept
194+ #if %
195+ static constexpr std::wstring_view names[] =
158196 {
159- return std::equal(left.rbegin(), left.rend(), right.rbegin(), right.rend());
197+ #define WINRT_NAME_LIST(func, name) name,
198+ WINRT_ACTIVATION_TABLE(WINRT_NAME_LIST)
160199 };
161- %
200+
201+ using make_t = void* (*)();
202+ static constexpr make_t makes[] =
203+ {
204+ #define WINRT_MAKE_LIST(func, name) func,
205+ WINRT_ACTIVATION_TABLE(WINRT_MAKE_LIST)
206+ };
207+
208+ auto it = std::lower_bound(std::begin(names), std::end(names), name);
209+ if (it != std::end(names) && *it == name)
210+ {
211+ return makes[it - std::begin(names)]();
212+ }
213+ #endif
162214 return nullptr;
163215}
164216)" ;
165217
166- w.write (format,
167- bind_each<write_component_include>(classes),
168- settings.component_lib ,
169- settings.component_lib ,
170- bind_each<write_component_activation>(classes));
218+ w.write (format, settings.component_lib , settings.component_lib , manifest.empty () ? 0 : 1 );
171219
172220 if (settings.component_lib != " winrt" )
173221 {
@@ -379,21 +427,8 @@ catch (...) { return winrt::to_hresult(); }
379427 {
380428 auto type_name = type.TypeName ();
381429 auto type_namespace = type.TypeNamespace ();
382- auto impl_name = get_impl_name (type_namespace, type_name);
383430
384- if (has_factory_members (w, type))
385- {
386- auto format = R"( void* winrt_make_%()
387- {
388- return winrt::detach_abi(winrt::make<winrt::@::factory_implementation::%>());
389- }
390- )" ;
391-
392- w.write (format,
393- impl_name,
394- type_namespace,
395- type_name);
396- }
431+ write_component_activation (w, type);
397432
398433 if (!settings.component_opt )
399434 {
0 commit comments