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