@@ -96,6 +96,36 @@ class TomlChecker {
9696 visit (ky);
9797 }
9898
99+ template <typename T>
100+ void optional_append (const toml::key &ky, Condition<T> &destination) {
101+ // TODO: this algorithm in O(n) over the amount of keys, kinda bad
102+ const auto &table = m_v.as_table ();
103+ for (const auto &itr : table) {
104+ const auto &key = itr.first ;
105+ const auto &value = itr.second ;
106+ T *dest = nullptr ;
107+ if (value.is_table ()) {
108+ if (value.contains (ky)) {
109+ dest = &destination[key];
110+ }
111+ } else if (key == ky) {
112+ dest = &destination[" " ];
113+ }
114+ if (dest != nullptr ) {
115+ const auto &items = toml::find<T>(m_v, ky);
116+ dest->insert (dest->end (), items.begin (), items.end ());
117+ }
118+ }
119+
120+ // Handle visiting logic
121+ for (const auto &itr : destination) {
122+ if (!itr.first .empty ()) {
123+ m_conditionVisited.emplace (itr.first , true );
124+ }
125+ }
126+ visit (ky);
127+ }
128+
99129 template <typename T>
100130 void optional (const toml::key &ky, T &destination) {
101131 // TODO: this currently doesn't allow you to get an optional map<string, X>
@@ -105,6 +135,17 @@ class TomlChecker {
105135 visit (ky);
106136 }
107137
138+ template <typename T>
139+ void optional_append (const toml::key &ky, T &destination) {
140+ // TODO: this currently doesn't allow you to get an optional map<string, X>
141+ if (m_v.contains (ky)) {
142+ const auto &items = toml::find<T>(m_v, ky);
143+ destination.insert (destination.end (), items.begin (), items.end ());
144+ }
145+ visit (ky);
146+ }
147+
148+
108149 template <typename T>
109150 void required (const toml::key &ky, T &destination) {
110151 destination = toml::find<T>(m_v, ky);
@@ -386,94 +427,124 @@ Project::Project(const Project *parent, const std::string &path, bool build) {
386427 throw std::runtime_error (" [[bin]] has been renamed to [[target]]" );
387428 }
388429
389- if (toml.contains (" target" )) {
390- const auto &ts = toml::find (toml, " target " ). as_table () ;
430+ if (toml.contains (" target" ) || toml. contains ( " template " ) ) {
431+ auto is_template = true ;
391432
392- for (const auto &itr : ts) {
393- const auto &value = itr.second ;
433+ for (const auto &ts : {&toml::find (toml, " template" ), &toml::find (toml, " target" )}) {
434+ for (const auto &itr : ts->as_table ()) {
435+ const auto &value = itr.second ;
436+ auto &t = checker.create (value);
437+ std::string template_name;
394438
395- Target target;
396- target.name = itr.first ;
439+ if (!is_template) {
440+ t.optional (" template" , template_name);
441+ }
397442
398- auto &t = checker.create (value);
399- std::string type;
400- t.required (" type" , type);
401- target.type = to_enum<TargetType>(type, " target type" );
443+ Target target;
444+ auto from_template = false ;
402445
403- t.optional (" headers" , target.headers );
404- t.optional (" sources" , target.sources );
446+ if (!template_name.empty ()) {
447+ for (const auto & template_ : templates) {
448+ if (template_name == template_.name ) {
449+ from_template = true ;
450+ target = template_;
451+ }
452+ }
405453
406- t.optional (" compile-definitions" , target.compile_definitions );
407- t.optional (" private-compile-definitions" , target.private_compile_definitions );
454+ if (!from_template) {
455+ throw std::runtime_error (" Could not find template named " + template_name);
456+ }
457+ }
408458
409- t.optional (" compile-features" , target.compile_features );
410- t.optional (" private-compile-features" , target.private_compile_features );
459+ target.name = itr.first ;
411460
412- t.optional (" compile-options" , target.compile_options );
413- t.optional (" private-compile-options" , target.private_compile_options );
461+ if (!from_template) {
462+ std::string type;
463+ t.required (" type" , type);
464+ target.type = to_enum<TargetType>(type, " target type" );
465+ }
414466
415- t. optional ( " include-directories " , target.include_directories );
416- t. optional ( " private-include-directories " , target.private_include_directories );
467+ t. optional_append ( " headers " , target.headers );
468+ t. optional_append ( " sources " , target.sources );
417469
418- t. optional ( " link-directories " , target.link_directories );
419- t. optional (" private-link-directories " , target.private_link_directories );
470+ t. optional_append ( " compile-definitions " , target.compile_definitions );
471+ t. optional_append (" private-compile-definitions " , target.private_compile_definitions );
420472
421- t. optional ( " link-libraries " , target.link_libraries );
422- t. optional (" private-link-libraries " , target.private_link_libraries );
473+ t. optional_append ( " compile-features " , target.compile_features );
474+ t. optional_append (" private-compile-features " , target.private_compile_features );
423475
424- t. optional ( " link -options" , target.link_options );
425- t. optional (" private-link -options" , target.private_link_options );
476+ t. optional_append ( " compile -options" , target.compile_options );
477+ t. optional_append (" private-compile -options" , target.private_compile_options );
426478
427- t. optional ( " precompile-headers " , target.precompile_headers );
428- t. optional (" private-precompile-headers " , target.private_precompile_headers );
479+ t. optional_append ( " include-directories " , target.include_directories );
480+ t. optional_append (" private-include-directories " , target.private_include_directories );
429481
430- if (!target.headers .empty ()) {
431- auto &sources = target.sources .nth (0 ).value ();
432- const auto &headers = target.headers .nth (0 )->second ;
433- sources.insert (sources.end (), headers.begin (), headers.end ());
434- }
482+ t.optional_append (" link-directories" , target.link_directories );
483+ t.optional_append (" private-link-directories" , target.private_link_directories );
435484
436- t. optional ( " condition " , target.condition );
437- t. optional ( " alias " , target.alias );
485+ t. optional_append ( " link-libraries " , target.link_libraries );
486+ t. optional_append ( " private-link-libraries " , target.private_link_libraries );
438487
439- if (t.contains (" properties" )) {
440- auto store_property = [&target](const toml::key &k, const TomlBasicValue &v, const std::string &condition) {
441- if (v.is_array ()) {
442- std::string property_list;
443- for (const auto &list_val : v.as_array ()) {
444- if (!property_list.empty ()) {
445- property_list += ' ;' ;
488+ t.optional_append (" link-options" , target.link_options );
489+ t.optional_append (" private-link-options" , target.private_link_options );
490+
491+ t.optional_append (" precompile-headers" , target.precompile_headers );
492+ t.optional_append (" private-precompile-headers" , target.private_precompile_headers );
493+
494+ if (!target.headers .empty ()) {
495+ auto &sources = target.sources .nth (0 ).value ();
496+ const auto &headers = target.headers .nth (0 )->second ;
497+ sources.insert (sources.end (), headers.begin (), headers.end ());
498+ }
499+
500+ t.optional (" condition" , target.condition );
501+ t.optional (" alias" , target.alias );
502+
503+ if (t.contains (" properties" )) {
504+ auto store_property = [&target](const toml::key &k, const TomlBasicValue &v, const std::string &condition) {
505+ if (v.is_array ()) {
506+ std::string property_list;
507+ for (const auto &list_val : v.as_array ()) {
508+ if (!property_list.empty ()) {
509+ property_list += ' ;' ;
510+ }
511+ property_list += list_val.as_string ();
446512 }
447- property_list += list_val.as_string ();
513+ target.properties [condition][k] = property_list;
514+ } else if (v.is_boolean ()) {
515+ target.properties [condition][k] = v.as_boolean () ? " ON" : " OFF" ;
516+ } else {
517+ target.properties [condition][k] = v.as_string ();
448518 }
449- target.properties [condition][k] = property_list;
450- } else if (v.is_boolean ()) {
451- target.properties [condition][k] = v.as_boolean () ? " ON" : " OFF" ;
452- } else {
453- target.properties [condition][k] = v.as_string ();
454- }
455- };
456-
457- const auto &props = t.find (" properties" ).as_table ();
458- for (const auto &propKv : props) {
459- const auto &k = propKv.first ;
460- const auto &v = propKv.second ;
461- if (v.is_table ()) {
462- for (const auto &condKv : v.as_table ()) {
463- store_property (condKv.first , condKv.second , k);
519+ };
520+
521+ const auto &props = t.find (" properties" ).as_table ();
522+ for (const auto &propKv : props) {
523+ const auto &k = propKv.first ;
524+ const auto &v = propKv.second ;
525+ if (v.is_table ()) {
526+ for (const auto &condKv : v.as_table ()) {
527+ store_property (condKv.first , condKv.second , k);
528+ }
529+ } else {
530+ store_property (k, v, " " );
464531 }
465- } else {
466- store_property (k, v, " " );
467532 }
468533 }
469- }
470534
471- t.optional (" cmake-before" , target.cmake_before );
472- t.optional (" cmake-after" , target.cmake_after );
473- t.optional (" include-before" , target.include_before );
474- t.optional (" include-after" , target.include_after );
535+ t.optional (" cmake-before" , target.cmake_before );
536+ t.optional (" cmake-after" , target.cmake_after );
537+ t.optional_append (" include-before" , target.include_before );
538+ t.optional_append (" include-after" , target.include_after );
539+
540+ if (is_template) {
541+ templates.push_back (target);
542+ } else {
543+ targets.push_back (target);
544+ }
545+ }
475546
476- targets. push_back (target) ;
547+ is_template = false ;
477548 }
478549 }
479550
0 commit comments