2004-12-04 11:36:36 +00:00
// (C) Copyright John Maddock 2004.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This progam scans for *.ipp files in the libs/config/test
// directory and then generates the *.cpp test files from them
// along with config_test.cpp and a Jamfile.
//
2021-03-03 17:00:24 +00:00
#define _CRT_SECURE_NO_WARNINGS
2004-12-04 11:36:36 +00:00
#include <boost/regex.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
2024-01-22 16:17:35 +03:00
#include <boost/filesystem/directory.hpp>
2004-12-04 11:36:36 +00:00
#include <boost/filesystem/fstream.hpp>
2015-10-08 10:39:09 +01:00
#include <boost/detail/lightweight_main.hpp>
2004-12-04 11:36:36 +00:00
#include <iostream>
#include <sstream>
#include <string>
2005-10-14 17:47:29 +00:00
#include <set>
2004-12-04 11:36:36 +00:00
#include <ctime>
namespace fs = boost :: filesystem ;
fs :: path config_path ;
std :: string copyright (
2021-03-06 19:58:12 +00:00
"// Copyright John Maddock 2002-21. \n "
2004-12-04 11:36:36 +00:00
"// Use, modification and distribution are subject to the \n "
"// Boost Software License, Version 1.0. (See accompanying file \n "
"// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) \n "
" \n "
2007-10-19 12:46:54 +00:00
"// See http://www.boost.org/libs/config for the most recent version."
"// \n // Revision $Id$ \n // \n " );
2004-12-04 11:36:36 +00:00
std :: stringstream config_test1 ;
2004-12-17 11:39:54 +00:00
std :: stringstream config_test1a ;
2004-12-04 11:36:36 +00:00
std :: stringstream config_test2 ;
std :: stringstream jamfile ;
2006-02-15 11:25:01 +00:00
std :: stringstream jamfile_v2 ;
2014-06-12 13:30:04 +01:00
std :: stringstream build_config_test ;
std :: stringstream build_config_jamfile ;
2005-10-14 17:47:29 +00:00
std :: set < std :: string > macro_list ;
2017-04-17 13:19:19 +01:00
std :: set < std :: string > feature_list ;
2005-10-14 17:47:29 +00:00
void write_config_info ()
{
// load the file into memory so we can scan it:
fs :: ifstream ifs ( config_path / "config_info.cpp" );
std :: string file_text ;
std :: copy ( std :: istreambuf_iterator < char > ( ifs ), std :: istreambuf_iterator < char > (), std :: back_inserter ( file_text ));
ifs . close ();
// create macro list:
std :: stringstream ss ;
for ( std :: set < std :: string >:: const_iterator i ( macro_list . begin ()), j ( macro_list . end ());
i != j ;
++ i )
{
ss << " PRINT_MACRO(" << * i << "); \n " ;
}
std :: string macros = ss . str ();
// scan for Boost macro block:
boost :: regex re ( "BEGIN \\ s+GENERATED \\ s+BLOCK \\ s+DO \\ s+NOT \\ s+EDIT \\ s+THIS[^ \\ n]+ \\ n(.*?) \\ n \\ s+// \\ s*END \\ s+GENERATED \\ s+BLOCK" );
boost :: smatch what ;
if ( boost :: regex_search ( file_text , what , re ))
{
std :: string new_text ;
new_text . append ( what . prefix (). first , what [ 1 ]. first );
new_text . append ( macros );
new_text . append ( what [ 1 ]. second , what . suffix (). second );
fs :: ofstream ofs ( config_path / "config_info.cpp" );
ofs << new_text ;
}
}
2004-12-04 11:36:36 +00:00
void write_config_test ()
{
fs :: ofstream ofs ( config_path / "config_test.cpp" );
time_t t = std :: time ( 0 );
ofs << "// This file was automatically generated on " << std :: ctime ( & t );
ofs << "// by libs/config/tools/generate.cpp \n " << copyright << std :: endl ;
ofs << "// Test file for config setup \n "
"// This file should compile, if it does not then \n "
"// one or more macros need to be defined. \n "
"// see boost_*.ipp for more details \n\n "
"// Do not edit this file, it was generated automatically by \n\n "
"#include <boost/config.hpp> \n #include <iostream> \n #include \" test.hpp \"\n\n "
"int error_count = 0; \n\n " ;
ofs << config_test1 . str () << std :: endl ;
2004-12-17 11:39:54 +00:00
ofs << config_test1a . str () << std :: endl ;
2004-12-04 11:36:36 +00:00
ofs << "int main( int, char *[] ) \n { \n " << config_test2 . str () << " return error_count; \n } \n\n " ;
}
2006-02-15 11:25:01 +00:00
void write_jamfile_v2 ()
{
2008-04-14 18:06:59 +00:00
fs :: ofstream ofs ( config_path / "all" / "Jamfile.v2" );
2006-02-15 11:25:01 +00:00
time_t t = std :: time ( 0 );
ofs << "# \n # Regression test Jamfile for boost configuration setup. \n # *** DO NOT EDIT THIS FILE BY HAND *** \n "
"# This file was automatically generated on " << std :: ctime ( & t );
ofs << "# by libs/config/tools/generate.cpp \n "
"# Copyright John Maddock. \n "
2006-07-16 15:42:19 +00:00
"# Use, modification and distribution are subject to the \n "
"# Boost Software License, Version 1.0. (See accompanying file \n "
"# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) \n "
2006-02-15 11:25:01 +00:00
"# \n # If you need to alter build preferences then set them in \n "
"# the template defined in options_v2.jam. \n # \n "
"path-constant DOT : . ; \n "
"include $(DOT)/options_v2.jam ; \n\n "
2008-04-14 18:06:59 +00:00
"run ../config_info.cpp : : : <threading>single <toolset>msvc:<runtime-link>static <toolset>msvc:<link>static ; \n "
"run ../config_info.cpp : : : <threading>multi : config_info_threaded ; \n "
"run ../math_info.cpp : : : <toolset>borland:<runtime-link>static <toolset>borland:<link>static ; \n "
"run ../config_test.cpp : : : <threading>single <toolset>msvc:<runtime-link>static <toolset>msvc:<link>static ; \n "
"run ../config_test.cpp : : : <threading>multi : config_test_threaded ; \n "
"run ../limits_test.cpp ../../../test/build//boost_test_exec_monitor ; \n "
"run ../abi/abi_test.cpp ../abi/main.cpp ; \n\n " ;
2006-02-15 11:25:01 +00:00
ofs << jamfile_v2 . str () << std :: endl ;
}
2004-12-04 11:36:36 +00:00
void write_test_file ( const fs :: path & file ,
const std :: string & macro_name ,
const std :: string & namespace_name ,
const std :: string & header_file ,
bool positive_test ,
bool expect_success )
{
if ( ! fs :: exists ( file ))
{
2011-03-15 13:17:46 +00:00
std :: cout << "Writing test file " << file . string () << std :: endl ;
2004-12-04 11:36:36 +00:00
fs :: ofstream ofs ( file );
std :: time_t t = std :: time ( 0 );
ofs << "// This file was automatically generated on " << std :: ctime ( & t );
ofs << "// by libs/config/tools/generate.cpp \n " << copyright << std :: endl ;
ofs << " \n // Test file for macro " << macro_name << std :: endl ;
if ( expect_success )
{
ofs << "// This file should compile, if it does not then \n "
"// " << macro_name << " should " ;
if ( positive_test )
ofs << "not " ;
ofs << "be defined. \n " ;
}
else
{
ofs << "// This file should not compile, if it does then \n "
"// " << macro_name << " should " ;
if ( ! positive_test )
ofs << "not " ;
ofs << "be defined. \n " ;
}
ofs << "// See file " << header_file << " for details \n\n " ;
ofs << "// Must not have BOOST_ASSERT_CONFIG set; it defeats \n "
"// the objective of this file: \n "
"#ifdef BOOST_ASSERT_CONFIG \n "
"# undef BOOST_ASSERT_CONFIG \n "
"#endif \n\n " ;
2008-10-11 15:40:44 +00:00
static const boost :: regex tr1_exp ( "BOOST_HAS_TR1.*" );
2008-07-12 12:41:52 +00:00
ofs << "#include <boost/config.hpp> \n " ;
ofs << "#include \" test.hpp \"\n\n "
2004-12-04 11:36:36 +00:00
"#if" ;
if ( positive_test != expect_success )
ofs << "n" ;
ofs << "def " << macro_name <<
" \n #include \" " << header_file <<
" \"\n #else \n " ;
if ( expect_success )
ofs << "namespace " << namespace_name << " = empty_boost; \n " ;
else
ofs << "#error \" this file should not compile \"\n " ;
ofs << "#endif \n\n " ;
ofs << "int main( int, char *[] ) \n { \n return " << namespace_name << "::test(); \n } \n\n " ;
}
else
{
2011-03-15 13:17:46 +00:00
std :: cout << "Skipping existing test file " << file . string () << std :: endl ;
2004-12-04 11:36:36 +00:00
}
}
2014-06-12 13:30:04 +01:00
void write_build_tests ()
{
fs :: ofstream ofs ( config_path / ".." / "checks" / "test_case.cpp" );
time_t t = std :: time ( 0 );
ofs << "// This file was automatically generated on " << std :: ctime ( & t );
ofs << "// by libs/config/tools/generate.cpp \n " << copyright << std :: endl ;
2017-04-17 13:19:19 +01:00
ofs << "#include <boost/config.hpp> \n\n " ;
2014-06-12 13:30:04 +01:00
ofs << build_config_test . str () << std :: endl ;
2017-04-17 13:19:19 +01:00
ofs << "int main( int, char *[] ) \n { \n " << " return 0; \n } \n\n " ;
2014-06-12 13:30:04 +01:00
}
void write_build_check_jamfile ()
{
fs :: ofstream ofs ( config_path / ".." / "checks" / "Jamfile.v2" );
time_t t = std :: time ( 0 );
ofs << "# \n # *** DO NOT EDIT THIS FILE BY HAND *** \n "
"# This file was automatically generated on " << std :: ctime ( & t );
ofs << "# by libs/config/tools/generate.cpp \n "
"# Copyright John Maddock. \n "
"# Use, modification and distribution are subject to the \n "
"# Boost Software License, Version 1.0. (See accompanying file \n "
"# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) \n\n "
"import modules ; \n import path ; \n\n "
" \n "
;
ofs << build_config_jamfile . str () << std :: endl ;
}
2021-03-03 17:00:24 +00:00
std :: map < std :: string , std :: set < std :: string >> std_version_macros ;
void categorize_macro ( const std :: string & name )
{
boost :: regex cxxNN ( "BOOST_NO_CXX( \\ d \\ d).+" );
boost :: regex cxx03 ( "BOOST_NO_.+" );
boost :: smatch what ;
if ( regex_match ( name , what , cxxNN ))
{
std_version_macros [ what [ 1 ]]. insert ( name );
}
else if ( regex_match ( name , what , cxx03 ))
{
std_version_macros [ "03" ]. insert ( name );
}
}
2004-12-04 11:36:36 +00:00
void process_ipp_file ( const fs :: path & file , bool positive_test )
{
2011-03-15 13:17:46 +00:00
std :: cout << "Info: Scanning file: " << file . string () << std :: endl ;
2004-12-04 11:36:36 +00:00
// our variables:
std :: string file_text ;
std :: string macro_name ;
std :: string namespace_name ;
fs :: path positive_file ;
fs :: path negative_file ;
// load the file into memory so we can scan it:
fs :: ifstream ifs ( file );
std :: copy ( std :: istreambuf_iterator < char > ( ifs ), std :: istreambuf_iterator < char > (), std :: back_inserter ( file_text ));
ifs . close ();
// scan for the macro name:
boost :: regex macro_regex ( "// \\ s*MACRO \\ s*: \\ s*( \\ w+)" );
boost :: smatch macro_match ;
if ( boost :: regex_search ( file_text , macro_match , macro_regex ))
{
macro_name = macro_match [ 1 ];
2005-10-14 17:47:29 +00:00
macro_list . insert ( macro_name );
2021-03-03 17:00:24 +00:00
categorize_macro ( macro_name );
2004-12-04 11:36:36 +00:00
namespace_name = boost :: regex_replace ( file_text , macro_regex , " \\ L$1" , boost :: format_first_only | boost :: format_no_copy );
}
if ( macro_name . empty ())
{
2011-03-15 13:17:46 +00:00
std :: cout << "Error: no macro definition found in " << file . string ();
2004-12-04 11:36:36 +00:00
}
else
{
std :: cout << "Info: Macroname: " << macro_name << std :: endl ;
}
// get the output filesnames:
boost :: regex file_regex ( "boost_([^.]+) \\ .ipp" );
2024-01-22 16:17:35 +03:00
positive_file = file . parent_path () / boost :: regex_replace ( file . filename (). string (), file_regex , "$1_pass.cpp" );
negative_file = file . parent_path () / boost :: regex_replace ( file . filename (). string (), file_regex , "$1_fail.cpp" );
write_test_file ( positive_file , macro_name , namespace_name , file . filename (). string (), positive_test , true );
write_test_file ( negative_file , macro_name , namespace_name , file . filename (). string (), positive_test , false );
2004-12-04 11:36:36 +00:00
2004-12-17 11:39:54 +00:00
// always create config_test data,
// positive and negative tests go to separate streams, because for some
// reason some compilers choke unless we put them in a particular order...
std :: ostream * pout = positive_test ? & config_test1a : & config_test1 ;
* pout << "#if" ;
2004-12-04 11:36:36 +00:00
if ( ! positive_test )
2004-12-17 11:39:54 +00:00
* pout << "n" ;
* pout << "def " << macro_name
2024-01-22 16:17:35 +03:00
<< " \n #include \" " << file . filename (). string () << " \"\n #else \n namespace "
2004-12-04 11:36:36 +00:00
<< namespace_name << " = empty_boost; \n #endif \n " ;
config_test2 << " if(0 != " << namespace_name << "::test()) \n "
" { \n "
" std::cerr << \" Failed test for " << macro_name << " at: \" << __FILE__ << \" : \" << __LINE__ << std::endl; \n "
" ++error_count; \n "
" } \n " ;
// always generate the jamfile data:
jamfile << "test-suite \" " << macro_name << " \" : \n "
2024-01-22 16:17:35 +03:00
"[ run " << positive_file . filename (). string () << " <template>config_options ] \n "
"[ compile-fail " << negative_file . filename (). string () << " <template>config_options ] ; \n " ;
2004-12-04 11:36:36 +00:00
2006-02-15 11:25:01 +00:00
jamfile_v2 << "test-suite \" " << macro_name << " \" : \n "
2024-01-22 16:17:35 +03:00
"[ run ../" << positive_file . filename (). string () << " ] \n "
"[ compile-fail ../" << negative_file . filename (). string () << " ] ; \n " ;
2006-02-15 11:25:01 +00:00
2014-06-12 13:30:04 +01:00
// Generate data for the Build-checks test file:
build_config_test << "#ifdef TEST_" << macro_name << std :: endl ;
2017-04-17 13:19:19 +01:00
if ( positive_test )
{
build_config_test << "# ifndef " << macro_name << " \n # error \" Feature macro " << macro_name << " is not defined. \"\n # endif \n " ;
}
else
{
build_config_test << "# ifdef " << macro_name << " \n # error \" Defect macro " << macro_name << " is defined. \"\n # endif \n " ;
}
build_config_test << "#endif \n " ;
2014-06-12 13:30:04 +01:00
// Generate data for the build-checks Jamfile:
static const boost :: regex feature_regex ( "boost_(?:no|has)_(.*)" );
std :: string feature_name = boost :: regex_replace ( namespace_name , feature_regex , " \\ 1" );
2017-04-17 13:19:19 +01:00
if ( feature_list . find ( feature_name ) == feature_list . end ())
build_config_jamfile << "obj " << feature_name << " : test_case.cpp : <define>TEST_" << macro_name << " ; \n " ;
feature_list . insert ( feature_name );
2004-12-04 11:36:36 +00:00
}
2021-03-03 17:00:24 +00:00
void fixup_cxxNN ()
{
std_version_macros . erase ( "98" );
std_version_macros [ "03" ]. erase ( "BOOST_NO_MS_INT64_NUMERIC_LIMITS" );
std_version_macros [ "03" ]. erase ( "BOOST_NO_SWPRINTF" );
std_version_macros [ "03" ]. erase ( "BOOST_NO_CXX03" );
std_version_macros [ "03" ]. erase ( "BOOST_NO_CXX11" );
std_version_macros [ "03" ]. erase ( "BOOST_NO_CXX14" );
std_version_macros [ "03" ]. erase ( "BOOST_NO_CXX17" );
//
2021-03-06 19:58:12 +00:00
// These are removed from later standard versions so we don't check them here:
2021-03-03 17:00:24 +00:00
//
2021-03-06 19:58:12 +00:00
std_version_macros [ "03" ]. erase ( "BOOST_NO_AUTO_PTR" );
std_version_macros [ "11" ]. erase ( "BOOST_NO_CXX11_ATOMIC_SMART_PTR" );
2021-08-17 17:32:09 +01:00
std_version_macros [ "11" ]. erase ( "BOOST_NO_CXX11_HDR_CODECVT" );
2021-03-03 17:00:24 +00:00
}
void write_cxxNN_asserts ()
{
std :: string previous_filename ;
for ( auto std = std_version_macros . begin (); std != std_version_macros . end (); ++ std )
{
std :: string filename = "assert_cxx" ;
filename += std -> first ;
filename += ".hpp" ;
fs :: ofstream ofs ( config_path / ".." / "include" / "boost" / "config" / filename );
time_t t = std :: time ( 0 );
ofs << "// This file was automatically generated on " << std :: ctime ( & t );
ofs << "// by libs/config/tools/generate.cpp \n " << copyright << std :: endl ;
ofs << "#include <boost/config.hpp> \n " ;
if ( previous_filename . size ())
ofs << "#include <boost/config/" << previous_filename << "> \n\n " ;
else
ofs << " \n " ;
for ( auto macro = std -> second . begin (); macro != std -> second . end (); ++ macro )
{
ofs << "#ifdef " << * macro << " \n # error \" Your compiler appears not to be fully C++" << std -> first << " compliant. Detected via defect macro " << * macro << ". \"\n #endif \n " ;
}
previous_filename = filename ;
}
}
void write_cxxNN_composite ()
{
fs :: ofstream ofs ( config_path / ".." / "include" / "boost" / "config" / "detail" / "cxx_composite.hpp" );
time_t t = std :: time ( 0 );
ofs << "// This file was automatically generated on " << std :: ctime ( & t );
ofs << "// by libs/config/tools/generate.cpp \n " << copyright << std :: endl ;
std :: string previous_macro ;
for ( auto std = std_version_macros . begin (); std != std_version_macros . end (); ++ std )
{
std :: string macro = "BOOST_NO_CXX" ;
macro += std -> first ;
bool done_first = false ;
ofs << "#if " ;
if ( previous_macro . size ())
{
ofs << "defined(" << previous_macro << ")" ;
done_first = true ;
}
for ( auto macro = std -> second . begin (); macro != std -> second . end (); ++ macro )
{
if ( done_first )
ofs << " \\\n || " ;
ofs << "defined(" << * macro << ")" ;
done_first = true ;
}
ofs << " \n # define " << macro << " \n #endif \n\n " ;
previous_macro = macro ;
}
}
2019-02-11 18:22:05 +00:00
void write_std_check ( std :: string macroname , int min_value , std :: string header , int std_version , bool primary = true )
2019-02-10 20:03:32 +00:00
{
std :: string test_name ( macroname );
while ( test_name [ 0 ] == '_' )
test_name . erase ( 0 , 1 );
2019-02-11 18:22:05 +00:00
std :: string test_basename = test_name ;
test_name . append ( "_" );
test_name . append ( 1 , std_version > 10 ? std_version / 10 + '0' : '0' );
test_name . append ( 1 , std_version % 10 + '0' );
2019-02-10 20:03:32 +00:00
fs :: ofstream ofs ( config_path / ".." / "checks" / "std" / ( test_name + ".cpp" ));
time_t t = std :: time ( 0 );
ofs << "// This file was automatically generated on " << std :: ctime ( & t );
ofs << "// by libs/config/tools/generate.cpp \n " << copyright << std :: endl ;
ofs << "#ifdef __has_include \n #if __has_include(<version>) \n #include <version> \n #endif \n #endif \n\n " ;
if ( header . size ())
{
ofs << "#include <" << header << "> \n\n " ;
}
ofs << "#ifndef " << macroname << " \n #error \" Macro << " << macroname << " is not set \"\n #endif \n\n " ;
ofs << "#if " << macroname << " < " << min_value << " \n #error \" Macro " << macroname << " had too low a value \"\n #endif \n\n " ;
ofs << "int main( int, char *[] ) \n { \n " << " return 0; \n } \n\n " ;
build_config_jamfile << "obj " << test_name << " : std/" << test_name << ".cpp ; \n " ;
2019-02-11 18:22:05 +00:00
if ( primary )
build_config_jamfile << "alias " << test_basename << " : " << test_name << " ; \n " ;
2019-02-10 20:03:32 +00:00
}
void write_std_config_checks ()
{
2023-10-13 19:11:46 +01:00
// C++23
write_std_check ( "__cpp_consteval" , 202211 , "" , 23 );
write_std_check ( "__cpp_explicit_this_parameter" , 202110 , "" , 23 );
write_std_check ( "__cpp_if_consteval" , 202106 , "" , 23 );
write_std_check ( "__cpp_implicit_move" , 202207 , "" , 23 );
write_std_check ( "__cpp_multidimensional_subscript" , 202211 , "" , 23 );
write_std_check ( "__cpp_named_character_escapes" , 202207 , "" , 23 );
write_std_check ( "__cpp_range_based_for" , 202211 , "" , 23 );
write_std_check ( "__cpp_size_t_suffix" , 202011 , "" , 23 );
write_std_check ( "__cpp_static_call_operator" , 202207 , "" , 23 );
2019-02-10 20:03:32 +00:00
// C++20
2019-02-11 18:22:05 +00:00
write_std_check ( "__cpp_impl_destroying_delete" , 201806 , "" , 20 );
write_std_check ( "__cpp_lib_destroying_delete" , 201806 , "new" , 20 );
write_std_check ( "__cpp_char8_t" , 201811 , "" , 20 );
write_std_check ( "__cpp_impl_three_way_comparison" , 201711 , "" , 20 );
write_std_check ( "__cpp_lib_three_way_comparison" , 201711 , "compare" , 20 );
write_std_check ( "__cpp_conditional_explicit" , 201806 , "" , 20 );
write_std_check ( "__cpp_nontype_template_parameter_class" , 201806 , "" , 20 );
write_std_check ( "__cpp_lib_char8_t" , 201811 , "atomic" , 20 );
write_std_check ( "__cpp_lib_concepts" , 201806 , "concepts" , 20 );
write_std_check ( "__cpp_lib_constexpr_swap_algorithms" , 201806 , "algorithm" , 20 );
write_std_check ( "__cpp_lib_constexpr_misc" , 201811 , "array" , 20 );
write_std_check ( "__cpp_lib_bind_front" , 201811 , "functional" , 20 );
write_std_check ( "__cpp_lib_is_constant_evaluated" , 201811 , "type_traits" , 20 );
write_std_check ( "__cpp_lib_erase_if" , 201811 , "string" , 20 );
write_std_check ( "__cpp_lib_list_remove_return_type" , 201806 , "forward_list" , 20 );
write_std_check ( "__cpp_lib_generic_unordered_lookup" , 201811 , "unordered_map" , 20 );
write_std_check ( "__cpp_lib_ranges" , 201811 , "algorithm" , 20 );
write_std_check ( "__cpp_lib_bit_cast" , 201806 , "bit" , 20 );
write_std_check ( "__cpp_lib_atomic_ref" , 201806 , "atomic" , 20 );
2019-02-10 20:03:32 +00:00
// C++17
2019-02-11 18:22:05 +00:00
write_std_check ( "__cpp_hex_float" , 201603 , "" , 17 );
write_std_check ( "__cpp_inline_variables" , 201606 , "" , 17 );
write_std_check ( "__cpp_aligned_new" , 201606 , "" , 17 );
write_std_check ( "__cpp_guaranteed_copy_elision" , 201606 , "" , 17 );
write_std_check ( "__cpp_noexcept_function_type" , 201510 , "" , 17 );
write_std_check ( "__cpp_fold_expressions" , 201603 , "" , 17 );
write_std_check ( "__cpp_capture_star_this" , 201603 , "" , 17 );
write_std_check ( "__cpp_constexpr" , 201603 , "" , 17 , false );
write_std_check ( "__cpp_if_constexpr" , 201606 , "" , 17 );
write_std_check ( "__cpp_range_based_for" , 201603 , "" , 17 , false );
write_std_check ( "__cpp_static_assert" , 201411 , "" , 17 , false );
2019-04-21 09:17:37 +01:00
write_std_check ( "__cpp_deduction_guides" , 201611 , "" , 17 ); // NOTE: this is the pre-std version number used by gcc-8, is this OK???
2019-02-11 18:22:05 +00:00
write_std_check ( "__cpp_nontype_template_parameter_auto" , 201606 , "" , 17 );
write_std_check ( "__cpp_namespace_attributes" , 201411 , "" , 17 );
write_std_check ( "__cpp_enumerator_attributes" , 201411 , "" , 17 );
write_std_check ( "__cpp_inheriting_constructors" , 201511 , "" , 17 , false );
write_std_check ( "__cpp_variadic_using" , 201611 , "" , 17 );
write_std_check ( "__cpp_structured_bindings" , 201606 , "" , 17 );
write_std_check ( "__cpp_aggregate_bases" , 201603 , "" , 17 );
write_std_check ( "__cpp_nontype_template_args" , 201411 , "" , 17 );
write_std_check ( "__cpp_template_template_args" , 201611 , "" , 17 );
write_std_check ( "__cpp_lib_byte" , 201603 , "cstddef" , 17 );
write_std_check ( "__cpp_lib_hardware_interference_size" , 201703 , "new" , 17 );
write_std_check ( "__cpp_lib_launder" , 201606 , "new" , 17 );
write_std_check ( "__cpp_lib_uncaught_exceptions" , 201411 , "exception" , 17 );
write_std_check ( "__cpp_lib_as_const" , 201510 , "utility" , 17 );
write_std_check ( "__cpp_lib_make_from_tuple" , 201606 , "tuple" , 17 );
write_std_check ( "__cpp_lib_apply" , 201603 , "tuple" , 17 );
write_std_check ( "__cpp_lib_optional" , 201606 , "optional" , 17 );
write_std_check ( "__cpp_lib_variant" , 201606 , "variant" , 17 );
write_std_check ( "__cpp_lib_any" , 201606 , "any" , 17 );
write_std_check ( "__cpp_lib_addressof_constexpr" , 201603 , "memory" , 17 );
write_std_check ( "__cpp_lib_raw_memory_algorithms" , 201606 , "memory" , 17 );
write_std_check ( "__cpp_lib_transparent_operators" , 201510 , "memory" , 17 , false );
write_std_check ( "__cpp_lib_enable_shared_from_this" , 201603 , "memory" , 17 );
write_std_check ( "__cpp_lib_shared_ptr_weak_type" , 201606 , "memory" , 17 );
write_std_check ( "__cpp_lib_shared_ptr_arrays" , 201611 , "memory" , 17 );
write_std_check ( "__cpp_lib_memory_resource" , 201603 , "memory_resource" , 17 );
write_std_check ( "__cpp_lib_boyer_moore_searcher" , 201603 , "functional" , 17 );
write_std_check ( "__cpp_lib_invoke" , 201411 , "functional" , 17 );
write_std_check ( "__cpp_lib_not_fn" , 201603 , "functional" , 17 );
write_std_check ( "__cpp_lib_void_t" , 201411 , "type_traits" , 17 );
write_std_check ( "__cpp_lib_bool_constant" , 201505 , "type_traits" , 17 );
write_std_check ( "__cpp_lib_type_trait_variable_templates" , 201510 , "type_traits" , 17 );
write_std_check ( "__cpp_lib_logical_traits" , 201510 , "type_traits" , 17 );
write_std_check ( "__cpp_lib_is_swappable" , 201603 , "type_traits" , 17 );
write_std_check ( "__cpp_lib_is_invocable" , 201703 , "type_traits" , 17 );
write_std_check ( "__cpp_lib_has_unique_object_representations" , 201606 , "type_traits" , 17 );
write_std_check ( "__cpp_lib_is_aggregate" , 201703 , "type_traits" , 17 );
write_std_check ( "__cpp_lib_chrono" , 201611 , "chrono" , 17 );
write_std_check ( "__cpp_lib_execution" , 201603 , "execution" , 17 );
write_std_check ( "__cpp_lib_parallel_algorithm" , 201603 , "algorithm" , 17 );
write_std_check ( "__cpp_lib_to_chars" , 201611 , "utility" , 17 );
write_std_check ( "__cpp_lib_string_view" , 201606 , "string" , 17 );
write_std_check ( "__cpp_lib_allocator_traits_is_always_equal" , 201411 , "memory" , 17 );
write_std_check ( "__cpp_lib_incomplete_container_elements" , 201505 , "forward_list" , 17 );
write_std_check ( "__cpp_lib_map_try_emplace" , 201411 , "map" , 17 );
write_std_check ( "__cpp_lib_unordered_map_try_emplace" , 201411 , "unordered_map" , 17 );
write_std_check ( "__cpp_lib_node_extract" , 201606 , "map" , 17 );
write_std_check ( "__cpp_lib_array_constexpr" , 201603 , "iterator" , 17 );
write_std_check ( "__cpp_lib_nonmember_container_access" , 201411 , "iterator" , 17 );
write_std_check ( "__cpp_lib_sample" , 201603 , "algorithm" , 17 );
write_std_check ( "__cpp_lib_clamp" , 201603 , "algorithm" , 17 );
write_std_check ( "__cpp_lib_gcd_lcm" , 201606 , "numeric" , 17 );
write_std_check ( "__cpp_lib_hypot" , 201603 , "cmath" , 17 );
write_std_check ( "__cpp_lib_math_special_functions" , 201603 , "cmath" , 17 );
write_std_check ( "__cpp_lib_filesystem" , 201703 , "filesystem" , 17 );
write_std_check ( "__cpp_lib_atomic_is_always_lock_free" , 201603 , "atomic" , 17 );
write_std_check ( "__cpp_lib_shared_mutex" , 201505 , "shared_mutex" , 17 );
write_std_check ( "__cpp_lib_scoped_lock" , 201703 , "mutex" , 17 );
2019-02-10 20:03:32 +00:00
// C++14
2019-02-11 18:22:05 +00:00
write_std_check ( "__cpp_binary_literals" , 201304 , "" , 14 );
write_std_check ( "__cpp_init_captures" , 201304 , "" , 14 );
write_std_check ( "__cpp_generic_lambdas" , 201304 , "" , 14 );
write_std_check ( "__cpp_sized_deallocation" , 201309 , "" , 14 );
write_std_check ( "__cpp_constexpr" , 201304 , "" , 14 , false );
write_std_check ( "__cpp_decltype_auto" , 201304 , "" , 14 );
write_std_check ( "__cpp_return_type_deduction" , 201304 , "" , 14 );
write_std_check ( "__cpp_aggregate_nsdmi" , 201304 , "" , 14 );
write_std_check ( "__cpp_variable_templates" , 201304 , "" , 14 );
write_std_check ( "__cpp_lib_integer_sequence" , 201304 , "utility" , 14 );
write_std_check ( "__cpp_lib_exchange_function" , 201304 , "utility" , 14 );
write_std_check ( "__cpp_lib_tuples_by_type" , 201304 , "utility" , 14 );
write_std_check ( "__cpp_lib_tuple_element_t" , 201402 , "tuple" , 14 );
write_std_check ( "__cpp_lib_make_unique" , 201304 , "memory" , 14 );
write_std_check ( "__cpp_lib_transparent_operators" , 201210 , "functional" , 14 );
write_std_check ( "__cpp_lib_integral_constant_callable" , 201304 , "type_traits" , 14 );
write_std_check ( "__cpp_lib_transformation_trait_aliases" , 201304 , "type_traits" , 14 );
write_std_check ( "__cpp_lib_result_of_sfinae" , 201210 , "functional" , 14 );
write_std_check ( "__cpp_lib_is_final" , 201402 , "type_traits" , 14 );
write_std_check ( "__cpp_lib_is_null_pointer" , 201309 , "type_traits" , 14 );
write_std_check ( "__cpp_lib_chrono_udls" , 201304 , "chrono" , 14 );
write_std_check ( "__cpp_lib_string_udls" , 201304 , "string" , 14 );
write_std_check ( "__cpp_lib_generic_associative_lookup" , 201304 , "map" , 14 );
write_std_check ( "__cpp_lib_null_iterators" , 201304 , "iterator" , 14 );
write_std_check ( "__cpp_lib_make_reverse_iterator" , 201402 , "iterator" , 14 );
write_std_check ( "__cpp_lib_robust_nonmodifying_seq_ops" , 201304 , "algorithm" , 14 );
write_std_check ( "__cpp_lib_complex_udls" , 201309 , "complex" , 14 );
write_std_check ( "__cpp_lib_quoted_string_io" , 201304 , "iomanip" , 14 );
write_std_check ( "__cpp_lib_shared_timed_mutex" , 201402 , "shared_mutex" , 14 );
2019-02-10 20:03:32 +00:00
// C++11
2019-02-11 18:22:05 +00:00
write_std_check ( "__cpp_unicode_characters" , 200704 , "" , 11 );
write_std_check ( "__cpp_raw_strings" , 200710 , "" , 11 );
write_std_check ( "__cpp_unicode_literals" , 200710 , "" , 11 );
write_std_check ( "__cpp_user_defined_literals" , 200809 , "" , 11 );
write_std_check ( "__cpp_threadsafe_static_init" , 200806 , "" , 11 );
write_std_check ( "__cpp_lambdas" , 200907 , "" , 11 );
write_std_check ( "__cpp_constexpr" , 200704 , "" , 11 );
write_std_check ( "__cpp_range_based_for" , 200907 , "" , 11 );
write_std_check ( "__cpp_static_assert" , 200410 , "" , 11 );
write_std_check ( "__cpp_decltype" , 200707 , "" , 11 );
write_std_check ( "__cpp_attributes" , 200809 , "" , 11 );
write_std_check ( "__cpp_rvalue_references" , 200610 , "" , 11 );
write_std_check ( "__cpp_variadic_templates" , 200704 , "" , 11 );
write_std_check ( "__cpp_initializer_lists" , 200806 , "" , 11 );
write_std_check ( "__cpp_explicit_conversion" , 200710 , "" , 11 );
write_std_check ( "__cpp_delegating_constructors" , 200604 , "" , 11 );
write_std_check ( "__cpp_nsdmi" , 200809 , "" , 11 );
write_std_check ( "__cpp_inheriting_constructors" , 200802 , "" , 11 );
write_std_check ( "__cpp_ref_qualifiers" , 200710 , "" , 11 );
write_std_check ( "__cpp_alias_templates" , 200704 , "" , 11 );
2019-02-10 20:03:32 +00:00
// C++98
2019-02-11 18:22:05 +00:00
write_std_check ( "__cpp_rtti" , 199711 , "" , 03 );
write_std_check ( "__cpp_exceptions" , 199711 , "" , 03 );
2019-02-10 20:03:32 +00:00
}
2004-12-04 11:36:36 +00:00
int cpp_main ( int argc , char * argv [])
{
//
// get the boost path to begin with:
//
if ( argc > 1 )
{
2011-06-01 14:51:03 +00:00
fs :: path p ( argv [ 1 ]);
2004-12-04 11:36:36 +00:00
config_path = p / "libs" / "config" / "test" ;
}
else
{
// try __FILE__:
2011-06-01 14:51:03 +00:00
fs :: path p ( __FILE__ );
2024-01-22 16:17:35 +03:00
config_path = p . parent_path (). parent_path () / "test" ;
2004-12-04 11:36:36 +00:00
}
2011-03-15 13:17:46 +00:00
std :: cout << "Info: Boost.Config test path set as: " << config_path . string () << std :: endl ;
2004-12-04 11:36:36 +00:00
2014-10-13 13:12:59 +01:00
// enumerate *.ipp files and store them in a map for now:
2004-12-04 11:36:36 +00:00
boost :: regex ipp_mask ( "boost_(?:(has)|no).* \\ .ipp" );
boost :: smatch ipp_match ;
fs :: directory_iterator i ( config_path ), j ;
2014-10-13 13:12:59 +01:00
std :: map < fs :: path , bool > files_to_process ;
2004-12-04 11:36:36 +00:00
while ( i != j )
{
2024-01-22 16:17:35 +03:00
if ( boost :: regex_match ( i -> path (). filename (). string (), ipp_match , ipp_mask ))
2004-12-04 11:36:36 +00:00
{
2014-10-13 13:12:59 +01:00
files_to_process [ * i ] = ipp_match [ 1 ]. matched ;
2004-12-04 11:36:36 +00:00
}
++ i ;
}
2014-10-13 13:12:59 +01:00
// Enumerate the files and process them, by defering this until now
// the results are always alphabetized which reduces churn in the
// generated files.
for ( std :: map < fs :: path , bool >:: const_iterator pos = files_to_process . begin (); pos != files_to_process . end (); ++ pos )
{
process_ipp_file ( pos -> first , pos -> second );
}
2021-03-03 17:00:24 +00:00
fixup_cxxNN ();
write_cxxNN_asserts ();
write_cxxNN_composite ();
2004-12-04 11:36:36 +00:00
write_config_test ();
2006-02-15 11:25:01 +00:00
write_jamfile_v2 ();
2005-10-14 17:47:29 +00:00
write_config_info ();
2019-02-10 20:03:32 +00:00
write_std_config_checks ();
2014-06-12 13:30:04 +01:00
write_build_tests ();
write_build_check_jamfile ();
2004-12-04 11:36:36 +00:00
return 0 ;
2006-02-15 11:25:01 +00:00
}
2006-07-16 15:42:19 +00:00