@@ -32,14 +32,14 @@ static MsvcRuntimeType parse_msvcRuntimeType(const std::string &name) {
3232
3333using TomlBasicValue = toml::basic_value<toml::discard_comments, tsl::ordered_map, std::vector>;
3434
35- static std::string format_key_error (const std::string &error , const toml::key &ky, const TomlBasicValue &value) {
35+ static std::string format_key_message (const std::string &message , const toml::key &ky, const TomlBasicValue &value) {
3636 auto loc = value.location ();
3737 auto line_number_str = std::to_string (loc.line ());
3838 auto line_width = line_number_str.length ();
3939 auto line_str = loc.line_str ();
4040
4141 std::ostringstream oss;
42- oss << " [error] " << error << ' \n ' ;
42+ oss << message << " \n " ;
4343 oss << " --> " << loc.file_name () << ' :' << loc.line () << ' \n ' ;
4444
4545 oss << std::string (line_width + 2 , ' ' ) << " |\n " ;
@@ -57,6 +57,14 @@ static std::string format_key_error(const std::string &error, const toml::key &k
5757 return oss.str ();
5858}
5959
60+ static void throw_key_error (const std::string &error, const toml::key &ky, const TomlBasicValue &value) {
61+ throw std::runtime_error (format_key_message (" [error] " + error, ky, value));
62+ }
63+
64+ static void print_key_warning (const std::string &message, const toml::key &ky, const TomlBasicValue &value) {
65+ puts (format_key_message (" [warning] " + message, ky, value).c_str ());
66+ }
67+
6068class TomlChecker {
6169 const TomlBasicValue &m_v;
6270 tsl::ordered_set<toml::key> m_visited;
@@ -133,27 +141,27 @@ class TomlChecker {
133141 const auto &ky = itr.first ;
134142 if (m_conditionVisited.contains (ky)) {
135143 if (!conditions.contains (ky)) {
136- throw std::runtime_error ( format_key_error ( " Unknown condition '" + ky + " '" , ky, itr.second ) );
144+ throw_key_error ( " Unknown condition '" + ky + " '" , ky, itr.second );
137145 }
138146
139147 for (const auto &jtr : itr.second .as_table ()) {
140148 if (!m_visited.contains (jtr.first )) {
141- throw std::runtime_error ( format_key_error ( " Unknown key '" + jtr.first + " '" , jtr.first , jtr.second ) );
149+ throw_key_error ( " Unknown key '" + jtr.first + " '" , jtr.first , jtr.second );
142150 }
143151 }
144152 } else if (!m_visited.contains (ky)) {
145153 if (itr.second .is_table ()) {
146154 for (const auto &jtr : itr.second .as_table ()) {
147155 if (!m_visited.contains (jtr.first )) {
148- throw std::runtime_error ( format_key_error ( " Unknown key '" + jtr.first + " '" , jtr.first , jtr.second ) );
156+ throw_key_error ( " Unknown key '" + jtr.first + " '" , jtr.first , jtr.second );
149157 }
150158 }
151159 }
152- throw std::runtime_error ( format_key_error ( " Unknown key '" + ky + " '" , ky, itr.second ) );
160+ throw_key_error ( " Unknown key '" + ky + " '" , ky, itr.second );
153161 } else if (ky == " condition" ) {
154162 std::string condition = itr.second .as_string ();
155163 if (!conditions.contains (condition)) {
156- throw std::runtime_error ( format_key_error ( " Unknown condition '" + condition + " '" , condition, itr.second ) );
164+ throw_key_error ( " Unknown condition '" + condition + " '" , condition, itr.second );
157165 }
158166 }
159167 }
@@ -191,7 +199,7 @@ class TomlCheckerRoot {
191199 if (check_root) {
192200 for (const auto &itr : m_root.as_table ()) {
193201 if (!m_visisted.contains (itr.first )) {
194- throw std::runtime_error ( format_key_error ( " Unknown key '" + itr.first + " '" , itr.first , itr.second ) );
202+ throw_key_error ( " Unknown key '" + itr.first + " '" , itr.first , itr.second );
195203 }
196204 }
197205 }
@@ -219,7 +227,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
219227 cmake.required (" version" , cmake_version);
220228
221229 if (cmake.contains (" bin-dir" )) {
222- throw std::runtime_error (" bin-dir has been renamed to build-dir" );
230+ throw_key_error (" bin-dir has been renamed to build-dir" , " bin-dir " , cmake. find ( " bin-dir " ) );
223231 }
224232
225233 cmake.optional (" build-dir" , build_dir);
@@ -297,7 +305,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
297305 error += " - " + type_name + " \n " ;
298306 }
299307 error.pop_back (); // Remove last newline
300- throw std::runtime_error ( format_key_error ( error, msvc_runtime, project.find (" msvc-runtime" ) ));
308+ throw_key_error ( error, msvc_runtime, project.find (" msvc-runtime" ));
301309 }
302310 }
303311 }
@@ -319,11 +327,21 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
319327 }
320328 }
321329
322- if (checker.contains (" settings " )) {
330+ if (checker.contains (" variables " )) {
323331 using set_map = tsl::ordered_map<std::string, TomlBasicValue>;
324- const auto &sets = toml::find<set_map>(toml, " settings" );
325- for (const auto &itr : sets) {
326- Setting s;
332+ auto vars = toml::find<set_map>(toml, " variables" );
333+ if (checker.contains (" settings" )) {
334+ print_key_warning (" [settings] has been renamed to [variables]" , " settings" , toml.at (" settings" ));
335+ const auto &sets = toml::find<set_map>(toml, " settings" );
336+ for (const auto &itr : sets) {
337+ if (!vars.insert (itr).second ) {
338+ throw_key_error (" Key '" + itr.first + " ' shadows existing variable" , itr.first , itr.second );
339+ }
340+ }
341+ }
342+
343+ for (const auto &itr : vars) {
344+ Variable s;
327345 s.name = itr.first ;
328346 const auto &value = itr.second ;
329347 if (value.is_boolean ()) {
@@ -344,7 +362,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
344362 setting.optional (" cache" , s.cache );
345363 setting.optional (" force" , s.force );
346364 }
347- settings .push_back (s);
365+ variables .push_back (s);
348366 }
349367 }
350368
@@ -454,7 +472,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
454472 } else if (is_cmake_arg (key)) {
455473 // allow passthrough of ExternalProject options
456474 } else if (!c.visisted (key)) {
457- throw std::runtime_error ( format_key_error ( " Unknown key '" + argItr.first + " '" , argItr.first , argItr.second ) );
475+ throw_key_error ( " Unknown key '" + argItr.first + " '" , argItr.first , argItr.second );
458476 }
459477
460478 // Make sure not to emit keys like "condition" in the FetchContent call
@@ -469,7 +487,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
469487 }
470488
471489 if (checker.contains (" bin" )) {
472- throw std::runtime_error (" [[bin]] has been renamed to [[ target]] " );
490+ throw_key_error (" [[bin]] has been renamed to [target.<name>] " , " " , toml. at ( " bin " ) );
473491 }
474492
475493 auto parse_target = [&](const std::string &name, TomlChecker &t, bool isTemplate) {
@@ -508,7 +526,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
508526 }
509527 }
510528 error.pop_back (); // Remove last newline
511- throw std::runtime_error ( format_key_error ( error, target.type_name , t.find (" type" ) ));
529+ throw_key_error ( error, target.type_name , t.find (" type" ));
512530 }
513531
514532 t.optional (" sources" , target.sources );
@@ -570,7 +588,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
570588 } else {
571589 report = &t.find (condItr.first ).as_table ().find (" msvc-runtime" ).value ();
572590 }
573- throw std::runtime_error ( format_key_error ( error, condItr.second , *report) );
591+ throw_key_error ( error, condItr.second , *report);
574592 }
575593 }
576594 }
@@ -626,13 +644,13 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
626644
627645 for (const auto &type_name : targetTypeNames) {
628646 if (name == type_name) {
629- throw std::runtime_error ( format_key_error ( " Reserved template name '" + name + " '" , name, itr.second ) );
647+ throw_key_error ( " Reserved template name '" + name + " '" , name, itr.second );
630648 }
631649 }
632650
633651 for (const auto &tmplate : templates) {
634652 if (name == tmplate.outline .name ) {
635- throw std::runtime_error ( format_key_error ( " Template '" + name + " ' already defined" , name, itr.second ) );
653+ throw_key_error ( " Template '" + name + " ' already defined" , name, itr.second );
636654 }
637655 }
638656
@@ -707,7 +725,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
707725 package.features .emplace_back (feature);
708726 }
709727 } else {
710- throw std::runtime_error (" Invalid vcpkg package '" + package_str + " '" );
728+ throw_key_error (" Invalid package name '" + package_str + " '" , " packages " , p );
711729 }
712730 vcpkg.packages .emplace_back (std::move (package));
713731 }
0 commit comments