@ -32,14 +32,14 @@ static MsvcRuntimeType parse_msvcRuntimeType(const std::string &name) {
using TomlBasicValue = toml : : basic_value < toml : : discard_comments , tsl : : ordered_map , std : : vector > ;
static std : : string format_key_ error( const std : : string & error , const toml : : key & ky , const TomlBasicValue & value ) {
static std : : string format_key_ message( const std : : string & message , const toml : : key & ky , const TomlBasicValue & value ) {
auto loc = value . location ( ) ;
auto line_number_str = std : : to_string ( loc . line ( ) ) ;
auto line_width = line_number_str . length ( ) ;
auto line_str = loc . line_str ( ) ;
std : : ostringstream oss ;
oss < < " [error] " < < error < < ' \n ' ;
oss < < message < < " \n " ;
oss < < " --> " < < loc . file_name ( ) < < ' : ' < < loc . line ( ) < < ' \n ' ;
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
return oss . str ( ) ;
}
static void throw_key_error ( const std : : string & error , const toml : : key & ky , const TomlBasicValue & value ) {
throw std : : runtime_error ( format_key_message ( " [error] " + error , ky , value ) ) ;
}
static void print_key_warning ( const std : : string & message , const toml : : key & ky , const TomlBasicValue & value ) {
puts ( format_key_message ( " [warning] " + message , ky , value ) . c_str ( ) ) ;
}
class TomlChecker {
const TomlBasicValue & m_v ;
tsl : : ordered_set < toml : : key > m_visited ;
@ -133,27 +141,27 @@ class TomlChecker {
const auto & ky = itr . first ;
if ( m_conditionVisited . contains ( ky ) ) {
if ( ! conditions . contains ( ky ) ) {
throw std : : runtime_error ( format _key_error( " Unknown condition ' " + ky + " ' " , ky , itr . second ) ) ;
throw _key_error( " Unknown condition ' " + ky + " ' " , ky , itr . second ) ;
}
for ( const auto & jtr : itr . second . as_table ( ) ) {
if ( ! m_visited . contains ( jtr . first ) ) {
throw std : : runtime_error ( format _key_error( " Unknown key ' " + jtr . first + " ' " , jtr . first , jtr . second ) ) ;
throw _key_error( " Unknown key ' " + jtr . first + " ' " , jtr . first , jtr . second ) ;
}
}
} else if ( ! m_visited . contains ( ky ) ) {
if ( itr . second . is_table ( ) ) {
for ( const auto & jtr : itr . second . as_table ( ) ) {
if ( ! m_visited . contains ( jtr . first ) ) {
throw std : : runtime_error ( format _key_error( " Unknown key ' " + jtr . first + " ' " , jtr . first , jtr . second ) ) ;
throw _key_error( " Unknown key ' " + jtr . first + " ' " , jtr . first , jtr . second ) ;
}
}
}
throw std : : runtime_error ( format _key_error( " Unknown key ' " + ky + " ' " , ky , itr . second ) ) ;
throw _key_error( " Unknown key ' " + ky + " ' " , ky , itr . second ) ;
} else if ( ky = = " condition " ) {
std : : string condition = itr . second . as_string ( ) ;
if ( ! conditions . contains ( condition ) ) {
throw std : : runtime_error ( format _key_error( " Unknown condition ' " + condition + " ' " , condition , itr . second ) ) ;
throw _key_error( " Unknown condition ' " + condition + " ' " , condition , itr . second ) ;
}
}
}
@ -191,7 +199,7 @@ class TomlCheckerRoot {
if ( check_root ) {
for ( const auto & itr : m_root . as_table ( ) ) {
if ( ! m_visisted . contains ( itr . first ) ) {
throw std : : runtime_error ( format _key_error( " Unknown key ' " + itr . first + " ' " , itr . first , itr . second ) ) ;
throw _key_error( " Unknown key ' " + itr . first + " ' " , itr . first , itr . second ) ;
}
}
}
@ -219,7 +227,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
cmake . required ( " version " , cmake_version ) ;
if ( cmake . contains ( " bin-dir " ) ) {
throw std : : runtime _error( " bin-dir has been renamed to build-dir " ) ;
throw_key _error( " bin-dir has been renamed to build-dir " , " bin-dir " , cmake . find ( " bin-dir " ) ) ;
}
cmake . optional ( " build-dir " , build_dir ) ;
@ -297,7 +305,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
error + = " - " + type_name + " \n " ;
}
error . pop_back ( ) ; // Remove last newline
throw std : : runtime_error ( format _key_error( error , msvc_runtime , project . find ( " msvc-runtime " ) ) ) ;
throw _key_error( error , msvc_runtime , project . find ( " msvc-runtime " ) ) ;
}
}
}
@ -319,11 +327,21 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
}
}
if ( checker . contains ( " setting s" ) ) {
if ( checker . contains ( " variable s" ) ) {
using set_map = tsl : : ordered_map < std : : string , TomlBasicValue > ;
const auto & sets = toml : : find < set_map > ( toml , " settings " ) ;
for ( const auto & itr : sets ) {
Setting s ;
auto vars = toml : : find < set_map > ( toml , " variables " ) ;
if ( checker . contains ( " settings " ) ) {
print_key_warning ( " [settings] has been renamed to [variables] " , " settings " , toml . at ( " settings " ) ) ;
const auto & sets = toml : : find < set_map > ( toml , " settings " ) ;
for ( const auto & itr : sets ) {
if ( ! vars . insert ( itr ) . second ) {
throw_key_error ( " Key ' " + itr . first + " ' shadows existing variable " , itr . first , itr . second ) ;
}
}
}
for ( const auto & itr : vars ) {
Variable s ;
s . name = itr . first ;
const auto & value = itr . second ;
if ( value . is_boolean ( ) ) {
@ -344,7 +362,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
setting . optional ( " cache " , s . cache ) ;
setting . optional ( " force " , s . force ) ;
}
setting s. push_back ( s ) ;
variable s. push_back ( s ) ;
}
}
@ -454,7 +472,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
} else if ( is_cmake_arg ( key ) ) {
// allow passthrough of ExternalProject options
} else if ( ! c . visisted ( key ) ) {
throw std : : runtime_error ( format _key_error( " Unknown key ' " + argItr . first + " ' " , argItr . first , argItr . second ) ) ;
throw _key_error( " Unknown key ' " + argItr . first + " ' " , argItr . first , argItr . second ) ;
}
// 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
}
if ( checker . contains ( " bin " ) ) {
throw std : : runtime_error ( " [[bin]] has been renamed to [[target]] " ) ;
throw_key_error ( " [[bin]] has been renamed to [target.<name>] " , " " , toml . at ( " bin " ) ) ;
}
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
}
}
error . pop_back ( ) ; // Remove last newline
throw std : : runtime_error ( format _key_error( error , target . type_name , t . find ( " type " ) ) ) ;
throw _key_error( error , target . type_name , t . find ( " type " ) ) ;
}
t . optional ( " sources " , target . sources ) ;
@ -570,7 +588,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
} else {
report = & t . find ( condItr . first ) . as_table ( ) . find ( " msvc-runtime " ) . value ( ) ;
}
throw std : : runtime_error ( format _key_error( error , condItr . second , * report ) ) ;
throw _key_error( error , condItr . second , * report ) ;
}
}
}
@ -626,13 +644,13 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
for ( const auto & type_name : targetTypeNames ) {
if ( name = = type_name ) {
throw std : : runtime_error ( format _key_error( " Reserved template name ' " + name + " ' " , name , itr . second ) ) ;
throw _key_error( " Reserved template name ' " + name + " ' " , name , itr . second ) ;
}
}
for ( const auto & tmplate : templates ) {
if ( name = = tmplate . outline . name ) {
throw std : : runtime_error ( format _key_error( " Template ' " + name + " ' already defined " , name , itr . second ) ) ;
throw _key_error( " Template ' " + name + " ' already defined " , name , itr . second ) ;
}
}
@ -707,7 +725,7 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
package . features . emplace_back ( feature ) ;
}
} else {
throw std : : runtime _error( " Invalid vcpkg package '" + package_str + " ' " ) ;
throw_key _error( " Invalid package name '" + package_str + " ' " , " packages " , p ) ;
}
vcpkg . packages . emplace_back ( std : : move ( package ) ) ;
}