1 // (C) Copyright John Maddock 2004.
2 // Use, modification and distribution are subject to the
3 // Boost Software License, Version 1.0. (See accompanying file
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 // This progam scans for *.ipp files in the libs/config/test
8 // directory and then generates the *.cpp test files from them
9 // along with config_test.cpp and a Jamfile.
12 #define _CRT_SECURE_NO_WARNINGS
14 #include <boost/regex.hpp>
15 #include <boost/filesystem/path.hpp>
16 #include <boost/filesystem/operations.hpp>
17 #include <boost/filesystem/fstream.hpp>
18 #include <boost/detail/lightweight_main.hpp>
25 namespace fs
= boost::filesystem
;
29 std::string
copyright(
30 "// Copyright John Maddock 2002-21.\n"
31 "// Use, modification and distribution are subject to the \n"
32 "// Boost Software License, Version 1.0. (See accompanying file \n"
33 "// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n"
35 "// See http://www.boost.org/libs/config for the most recent version."
36 "//\n// Revision $Id$\n//\n");
38 std::stringstream config_test1
;
39 std::stringstream config_test1a
;
40 std::stringstream config_test2
;
41 std::stringstream jamfile
;
42 std::stringstream jamfile_v2
;
43 std::stringstream build_config_test
;
44 std::stringstream build_config_jamfile
;
45 std::set
<std::string
> macro_list
;
46 std::set
<std::string
> feature_list
;
48 void write_config_info()
50 // load the file into memory so we can scan it:
51 fs::ifstream
ifs(config_path
/ "config_info.cpp");
52 std::string file_text
;
53 std::copy(std::istreambuf_iterator
<char>(ifs
), std::istreambuf_iterator
<char>(), std::back_inserter(file_text
));
57 for(std::set
<std::string
>::const_iterator
i(macro_list
.begin()), j(macro_list
.end());
61 ss
<< " PRINT_MACRO(" << *i
<< ");\n";
63 std::string macros
= ss
.str();
64 // scan for Boost macro block:
65 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");
67 if(boost::regex_search(file_text
, what
, re
))
70 new_text
.append(what
.prefix().first
, what
[1].first
);
71 new_text
.append(macros
);
72 new_text
.append(what
[1].second
, what
.suffix().second
);
73 fs::ofstream
ofs(config_path
/ "config_info.cpp");
78 void write_config_test()
80 fs::ofstream
ofs(config_path
/ "config_test.cpp");
81 time_t t
= std::time(0);
82 ofs
<< "// This file was automatically generated on " << std::ctime(&t
);
83 ofs
<< "// by libs/config/tools/generate.cpp\n" << copyright
<< std::endl
;
84 ofs
<< "// Test file for config setup\n"
85 "// This file should compile, if it does not then\n"
86 "// one or more macros need to be defined.\n"
87 "// see boost_*.ipp for more details\n\n"
88 "// Do not edit this file, it was generated automatically by\n\n"
89 "#include <boost/config.hpp>\n#include <iostream>\n#include \"test.hpp\"\n\n"
90 "int error_count = 0;\n\n";
91 ofs
<< config_test1
.str() << std::endl
;
92 ofs
<< config_test1a
.str() << std::endl
;
93 ofs
<< "int main( int, char *[] )\n{\n" << config_test2
.str() << " return error_count;\n}\n\n";
96 void write_jamfile_v2()
98 fs::ofstream
ofs(config_path
/ "all" / "Jamfile.v2");
99 time_t t
= std::time(0);
100 ofs
<< "#\n# Regression test Jamfile for boost configuration setup.\n# *** DO NOT EDIT THIS FILE BY HAND ***\n"
101 "# This file was automatically generated on " << std::ctime(&t
);
102 ofs
<< "# by libs/config/tools/generate.cpp\n"
103 "# Copyright John Maddock.\n"
104 "# Use, modification and distribution are subject to the \n"
105 "# Boost Software License, Version 1.0. (See accompanying file \n"
106 "# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n"
107 "#\n# If you need to alter build preferences then set them in\n"
108 "# the template defined in options_v2.jam.\n#\n"
109 "path-constant DOT : . ;\n"
110 "include $(DOT)/options_v2.jam ;\n\n"
111 "run ../config_info.cpp : : : <threading>single <toolset>msvc:<runtime-link>static <toolset>msvc:<link>static ;\n"
112 "run ../config_info.cpp : : : <threading>multi : config_info_threaded ;\n"
113 "run ../math_info.cpp : : : <toolset>borland:<runtime-link>static <toolset>borland:<link>static ;\n"
114 "run ../config_test.cpp : : : <threading>single <toolset>msvc:<runtime-link>static <toolset>msvc:<link>static ;\n"
115 "run ../config_test.cpp : : : <threading>multi : config_test_threaded ;\n"
116 "run ../limits_test.cpp ../../../test/build//boost_test_exec_monitor ;\n"
117 "run ../abi/abi_test.cpp ../abi/main.cpp ;\n\n";
118 ofs
<< jamfile_v2
.str() << std::endl
;
122 void write_test_file(const fs::path
& file
,
123 const std::string
& macro_name
,
124 const std::string
& namespace_name
,
125 const std::string
& header_file
,
129 if(!fs::exists(file
))
131 std::cout
<< "Writing test file " << file
.string() << std::endl
;
133 fs::ofstream
ofs(file
);
134 std::time_t t
= std::time(0);
135 ofs
<< "// This file was automatically generated on " << std::ctime(&t
);
136 ofs
<< "// by libs/config/tools/generate.cpp\n" << copyright
<< std::endl
;
137 ofs
<< "\n// Test file for macro " << macro_name
<< std::endl
;
141 ofs
<< "// This file should compile, if it does not then\n"
142 "// " << macro_name
<< " should ";
145 ofs
<< "be defined.\n";
149 ofs
<< "// This file should not compile, if it does then\n"
150 "// " << macro_name
<< " should ";
153 ofs
<< "be defined.\n";
155 ofs
<< "// See file " << header_file
<< " for details\n\n";
157 ofs
<< "// Must not have BOOST_ASSERT_CONFIG set; it defeats\n"
158 "// the objective of this file:\n"
159 "#ifdef BOOST_ASSERT_CONFIG\n"
160 "# undef BOOST_ASSERT_CONFIG\n"
163 static const boost::regex
tr1_exp("BOOST_HAS_TR1.*");
165 ofs
<< "#include <boost/config.hpp>\n";
167 ofs
<< "#include \"test.hpp\"\n\n"
169 if(positive_test
!= expect_success
)
171 ofs
<< "def " << macro_name
<<
172 "\n#include \"" << header_file
<<
175 ofs
<< "namespace " << namespace_name
<< " = empty_boost;\n";
177 ofs
<< "#error \"this file should not compile\"\n";
180 ofs
<< "int main( int, char *[] )\n{\n return " << namespace_name
<< "::test();\n}\n\n";
184 std::cout
<< "Skipping existing test file " << file
.string() << std::endl
;
188 void write_build_tests()
190 fs::ofstream
ofs(config_path
/ ".." / "checks" / "test_case.cpp");
191 time_t t
= std::time(0);
192 ofs
<< "// This file was automatically generated on " << std::ctime(&t
);
193 ofs
<< "// by libs/config/tools/generate.cpp\n" << copyright
<< std::endl
;
194 ofs
<< "#include <boost/config.hpp>\n\n";
195 ofs
<< build_config_test
.str() << std::endl
;
196 ofs
<< "int main( int, char *[] )\n{\n" << " return 0;\n}\n\n";
199 void write_build_check_jamfile()
201 fs::ofstream
ofs(config_path
/ ".." / "checks" / "Jamfile.v2");
202 time_t t
= std::time(0);
203 ofs
<< "#\n# *** DO NOT EDIT THIS FILE BY HAND ***\n"
204 "# This file was automatically generated on " << std::ctime(&t
);
205 ofs
<< "# by libs/config/tools/generate.cpp\n"
206 "# Copyright John Maddock.\n"
207 "# Use, modification and distribution are subject to the \n"
208 "# Boost Software License, Version 1.0. (See accompanying file \n"
209 "# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n\n"
210 "import modules ;\nimport path ; \n\n"
213 ofs
<< build_config_jamfile
.str() << std::endl
;
216 std::map
<std::string
, std::set
<std::string
>> std_version_macros
;
219 void categorize_macro(const std::string
& name
)
221 boost::regex
cxxNN("BOOST_NO_CXX(\\d\\d).+");
222 boost::regex
cxx03("BOOST_NO_.+");
224 if (regex_match(name
, what
, cxxNN
))
226 std_version_macros
[what
[1]].insert(name
);
228 else if (regex_match(name
, what
, cxx03
))
230 std_version_macros
["03"].insert(name
);
234 void process_ipp_file(const fs::path
& file
, bool positive_test
)
236 std::cout
<< "Info: Scanning file: " << file
.string() << std::endl
;
239 std::string file_text
;
240 std::string macro_name
;
241 std::string namespace_name
;
242 fs::path positive_file
;
243 fs::path negative_file
;
245 // load the file into memory so we can scan it:
246 fs::ifstream
ifs(file
);
247 std::copy(std::istreambuf_iterator
<char>(ifs
), std::istreambuf_iterator
<char>(), std::back_inserter(file_text
));
249 // scan for the macro name:
250 boost::regex
macro_regex("//\\s*MACRO\\s*:\\s*(\\w+)");
251 boost::smatch macro_match
;
252 if(boost::regex_search(file_text
, macro_match
, macro_regex
))
254 macro_name
= macro_match
[1];
255 macro_list
.insert(macro_name
);
256 categorize_macro(macro_name
);
257 namespace_name
= boost::regex_replace(file_text
, macro_regex
, "\\L$1", boost::format_first_only
| boost::format_no_copy
);
259 if(macro_name
.empty())
261 std::cout
<< "Error: no macro definition found in " << file
.string();
265 std::cout
<< "Info: Macroname: " << macro_name
<< std::endl
;
268 // get the output filesnames:
269 boost::regex
file_regex("boost_([^.]+)\\.ipp");
270 positive_file
= file
.branch_path() / boost::regex_replace(file
.leaf().string(), file_regex
, "$1_pass.cpp");
271 negative_file
= file
.branch_path() / boost::regex_replace(file
.leaf().string(), file_regex
, "$1_fail.cpp");
272 write_test_file(positive_file
, macro_name
, namespace_name
, file
.leaf().string(), positive_test
, true);
273 write_test_file(negative_file
, macro_name
, namespace_name
, file
.leaf().string(), positive_test
, false);
275 // always create config_test data,
276 // positive and negative tests go to separate streams, because for some
277 // reason some compilers choke unless we put them in a particular order...
278 std::ostream
* pout
= positive_test
? &config_test1a
: &config_test1
;
282 *pout
<< "def " << macro_name
283 << "\n#include \"" << file
.leaf().string() << "\"\n#else\nnamespace "
284 << namespace_name
<< " = empty_boost;\n#endif\n";
286 config_test2
<< " if(0 != " << namespace_name
<< "::test())\n"
288 " std::cerr << \"Failed test for " << macro_name
<< " at: \" << __FILE__ << \":\" << __LINE__ << std::endl;\n"
292 // always generate the jamfile data:
293 jamfile
<< "test-suite \"" << macro_name
<< "\" : \n"
294 "[ run " << positive_file
.leaf().string() << " <template>config_options ]\n"
295 "[ compile-fail " << negative_file
.leaf().string() << " <template>config_options ] ;\n";
297 jamfile_v2
<< "test-suite \"" << macro_name
<< "\" : \n"
298 "[ run ../" << positive_file
.leaf().string() << " ]\n"
299 "[ compile-fail ../" << negative_file
.leaf().string() << " ] ;\n";
301 // Generate data for the Build-checks test file:
302 build_config_test
<< "#ifdef TEST_" << macro_name
<< std::endl
;
305 build_config_test
<< "# ifndef " << macro_name
<< "\n# error \"Feature macro " << macro_name
<< " is not defined.\"\n# endif\n";
309 build_config_test
<< "# ifdef " << macro_name
<< "\n# error \"Defect macro " << macro_name
<< " is defined.\"\n# endif\n";
311 build_config_test
<< "#endif\n";
313 // Generate data for the build-checks Jamfile:
314 static const boost::regex
feature_regex("boost_(?:no|has)_(.*)");
315 std::string feature_name
= boost::regex_replace(namespace_name
, feature_regex
, "\\1");
316 if(feature_list
.find(feature_name
) == feature_list
.end())
317 build_config_jamfile
<< "obj " << feature_name
<< " : test_case.cpp : <define>TEST_" << macro_name
<< " ;\n";
318 feature_list
.insert(feature_name
);
323 std_version_macros
.erase("98");
324 std_version_macros
["03"].erase("BOOST_NO_MS_INT64_NUMERIC_LIMITS");
325 std_version_macros
["03"].erase("BOOST_NO_SWPRINTF");
326 std_version_macros
["03"].erase("BOOST_NO_CXX03");
327 std_version_macros
["03"].erase("BOOST_NO_CXX11");
328 std_version_macros
["03"].erase("BOOST_NO_CXX14");
329 std_version_macros
["03"].erase("BOOST_NO_CXX17");
331 // These are removed from later standard versions so we don't check them here:
333 std_version_macros
["03"].erase("BOOST_NO_AUTO_PTR");
334 std_version_macros
["11"].erase("BOOST_NO_CXX11_ATOMIC_SMART_PTR");
335 std_version_macros
["11"].erase("BOOST_NO_CXX11_HDR_CODECVT");
338 void write_cxxNN_asserts()
340 std::string previous_filename
;
341 for (auto std
= std_version_macros
.begin(); std
!= std_version_macros
.end(); ++std
)
343 std::string filename
= "assert_cxx";
344 filename
+= std
->first
;
346 fs::ofstream
ofs(config_path
/ ".." / "include" / "boost" / "config" / filename
);
347 time_t t
= std::time(0);
348 ofs
<< "// This file was automatically generated on " << std::ctime(&t
);
349 ofs
<< "// by libs/config/tools/generate.cpp\n" << copyright
<< std::endl
;
350 ofs
<< "#include <boost/config.hpp>\n";
351 if (previous_filename
.size())
352 ofs
<< "#include <boost/config/" << previous_filename
<< ">\n\n";
356 for (auto macro
= std
->second
.begin(); macro
!= std
->second
.end(); ++macro
)
358 ofs
<< "#ifdef " << *macro
<< "\n# error \"Your compiler appears not to be fully C++" << std
->first
<< " compliant. Detected via defect macro " << *macro
<< ".\"\n#endif\n";
361 previous_filename
= filename
;
365 void write_cxxNN_composite()
367 fs::ofstream
ofs(config_path
/ ".." / "include" / "boost" / "config" / "detail" / "cxx_composite.hpp");
368 time_t t
= std::time(0);
369 ofs
<< "// This file was automatically generated on " << std::ctime(&t
);
370 ofs
<< "// by libs/config/tools/generate.cpp\n" << copyright
<< std::endl
;
372 std::string previous_macro
;
373 for (auto std
= std_version_macros
.begin(); std
!= std_version_macros
.end(); ++std
)
375 std::string macro
= "BOOST_NO_CXX";
378 bool done_first
= false;
381 if (previous_macro
.size())
383 ofs
<< "defined(" << previous_macro
<< ")";
387 for (auto macro
= std
->second
.begin(); macro
!= std
->second
.end(); ++macro
)
391 ofs
<< "defined(" << *macro
<< ")";
394 ofs
<< "\n# define " << macro
<< "\n#endif\n\n";
396 previous_macro
= macro
;
400 void write_std_check(std::string macroname
, int min_value
, std::string header
, int std_version
, bool primary
= true)
402 std::string
test_name(macroname
);
403 while (test_name
[0] == '_')
404 test_name
.erase(0, 1);
405 std::string test_basename
= test_name
;
406 test_name
.append("_");
407 test_name
.append(1, std_version
> 10 ? std_version
/ 10 + '0' : '0');
408 test_name
.append(1, std_version
% 10 + '0');
409 fs::ofstream
ofs(config_path
/ ".." / "checks" / "std" / (test_name
+ ".cpp"));
410 time_t t
= std::time(0);
411 ofs
<< "// This file was automatically generated on " << std::ctime(&t
);
412 ofs
<< "// by libs/config/tools/generate.cpp\n" << copyright
<< std::endl
;
413 ofs
<< "#ifdef __has_include\n#if __has_include(<version>)\n#include <version>\n#endif\n#endif\n\n";
416 ofs
<< "#include <" << header
<< ">\n\n";
418 ofs
<< "#ifndef " << macroname
<< "\n#error \"Macro << " << macroname
<< " is not set\"\n#endif\n\n";
419 ofs
<< "#if " << macroname
<< " < " << min_value
<< "\n#error \"Macro " << macroname
<< " had too low a value\"\n#endif\n\n";
420 ofs
<< "int main( int, char *[] )\n{\n" << " return 0;\n}\n\n";
422 build_config_jamfile
<< "obj " << test_name
<< " : std/" << test_name
<< ".cpp ;\n";
424 build_config_jamfile
<< "alias " << test_basename
<< " : " << test_name
<< " ;\n";
427 void write_std_config_checks()
430 write_std_check("__cpp_impl_destroying_delete", 201806, "", 20);
431 write_std_check("__cpp_lib_destroying_delete", 201806, "new", 20);
432 write_std_check("__cpp_char8_t", 201811, "", 20);
433 write_std_check("__cpp_impl_three_way_comparison", 201711, "", 20);
434 write_std_check("__cpp_lib_three_way_comparison", 201711, "compare", 20);
435 write_std_check("__cpp_conditional_explicit", 201806, "", 20);
436 write_std_check("__cpp_nontype_template_parameter_class", 201806, "", 20);
437 write_std_check("__cpp_lib_char8_t", 201811, "atomic", 20);
438 write_std_check("__cpp_lib_concepts", 201806, "concepts", 20);
439 write_std_check("__cpp_lib_constexpr_swap_algorithms", 201806, "algorithm", 20);
440 write_std_check("__cpp_lib_constexpr_misc", 201811, "array", 20);
441 write_std_check("__cpp_lib_bind_front", 201811, "functional", 20);
442 write_std_check("__cpp_lib_is_constant_evaluated", 201811, "type_traits", 20);
443 write_std_check("__cpp_lib_erase_if", 201811, "string", 20);
444 write_std_check("__cpp_lib_list_remove_return_type", 201806, "forward_list", 20);
445 write_std_check("__cpp_lib_generic_unordered_lookup", 201811, "unordered_map", 20);
446 write_std_check("__cpp_lib_ranges", 201811, "algorithm", 20);
447 write_std_check("__cpp_lib_bit_cast", 201806, "bit", 20);
448 write_std_check("__cpp_lib_atomic_ref", 201806, "atomic", 20);
450 write_std_check("__cpp_hex_float", 201603, "", 17);
451 write_std_check("__cpp_inline_variables", 201606, "", 17);
452 write_std_check("__cpp_aligned_new", 201606, "", 17);
453 write_std_check("__cpp_guaranteed_copy_elision", 201606, "", 17);
454 write_std_check("__cpp_noexcept_function_type", 201510, "", 17);
455 write_std_check("__cpp_fold_expressions", 201603, "", 17);
456 write_std_check("__cpp_capture_star_this", 201603, "", 17);
457 write_std_check("__cpp_constexpr", 201603, "", 17, false);
458 write_std_check("__cpp_if_constexpr", 201606, "", 17);
459 write_std_check("__cpp_range_based_for", 201603, "", 17, false);
460 write_std_check("__cpp_static_assert", 201411, "", 17, false);
461 write_std_check("__cpp_deduction_guides", 201611, "", 17); // NOTE: this is the pre-std version number used by gcc-8, is this OK???
462 write_std_check("__cpp_nontype_template_parameter_auto", 201606, "", 17);
463 write_std_check("__cpp_namespace_attributes", 201411, "", 17);
464 write_std_check("__cpp_enumerator_attributes", 201411, "", 17);
465 write_std_check("__cpp_inheriting_constructors", 201511, "", 17, false);
466 write_std_check("__cpp_variadic_using", 201611, "", 17);
467 write_std_check("__cpp_structured_bindings", 201606, "", 17);
468 write_std_check("__cpp_aggregate_bases", 201603, "", 17);
469 write_std_check("__cpp_nontype_template_args", 201411, "", 17);
470 write_std_check("__cpp_template_template_args", 201611, "", 17);
471 write_std_check("__cpp_lib_byte", 201603, "cstddef", 17);
472 write_std_check("__cpp_lib_hardware_interference_size", 201703, "new", 17);
473 write_std_check("__cpp_lib_launder", 201606, "new", 17);
474 write_std_check("__cpp_lib_uncaught_exceptions", 201411, "exception", 17);
475 write_std_check("__cpp_lib_as_const", 201510, "utility", 17);
476 write_std_check("__cpp_lib_make_from_tuple", 201606, "tuple", 17);
477 write_std_check("__cpp_lib_apply", 201603, "tuple", 17);
478 write_std_check("__cpp_lib_optional", 201606, "optional", 17);
479 write_std_check("__cpp_lib_variant", 201606, "variant", 17);
480 write_std_check("__cpp_lib_any", 201606, "any", 17);
481 write_std_check("__cpp_lib_addressof_constexpr", 201603, "memory", 17);
482 write_std_check("__cpp_lib_raw_memory_algorithms", 201606, "memory", 17);
483 write_std_check("__cpp_lib_transparent_operators", 201510, "memory", 17, false);
484 write_std_check("__cpp_lib_enable_shared_from_this", 201603, "memory", 17);
485 write_std_check("__cpp_lib_shared_ptr_weak_type", 201606, "memory", 17);
486 write_std_check("__cpp_lib_shared_ptr_arrays", 201611, "memory", 17);
487 write_std_check("__cpp_lib_memory_resource", 201603, "memory_resource", 17);
488 write_std_check("__cpp_lib_boyer_moore_searcher", 201603, "functional", 17);
489 write_std_check("__cpp_lib_invoke", 201411, "functional", 17);
490 write_std_check("__cpp_lib_not_fn", 201603, "functional", 17);
491 write_std_check("__cpp_lib_void_t", 201411, "type_traits", 17);
492 write_std_check("__cpp_lib_bool_constant", 201505, "type_traits", 17);
493 write_std_check("__cpp_lib_type_trait_variable_templates", 201510, "type_traits", 17);
494 write_std_check("__cpp_lib_logical_traits", 201510, "type_traits", 17);
495 write_std_check("__cpp_lib_is_swappable", 201603, "type_traits", 17);
496 write_std_check("__cpp_lib_is_invocable", 201703, "type_traits", 17);
497 write_std_check("__cpp_lib_has_unique_object_representations", 201606, "type_traits", 17);
498 write_std_check("__cpp_lib_is_aggregate", 201703, "type_traits", 17);
499 write_std_check("__cpp_lib_chrono", 201611, "chrono", 17);
500 write_std_check("__cpp_lib_execution", 201603, "execution", 17);
501 write_std_check("__cpp_lib_parallel_algorithm", 201603, "algorithm", 17);
502 write_std_check("__cpp_lib_to_chars", 201611, "utility", 17);
503 write_std_check("__cpp_lib_string_view", 201606, "string", 17);
504 write_std_check("__cpp_lib_allocator_traits_is_always_equal", 201411, "memory", 17);
505 write_std_check("__cpp_lib_incomplete_container_elements", 201505, "forward_list", 17);
506 write_std_check("__cpp_lib_map_try_emplace", 201411, "map", 17);
507 write_std_check("__cpp_lib_unordered_map_try_emplace", 201411, "unordered_map", 17);
508 write_std_check("__cpp_lib_node_extract", 201606, "map", 17);
509 write_std_check("__cpp_lib_array_constexpr", 201603, "iterator", 17);
510 write_std_check("__cpp_lib_nonmember_container_access", 201411, "iterator", 17);
511 write_std_check("__cpp_lib_sample", 201603, "algorithm", 17);
512 write_std_check("__cpp_lib_clamp", 201603, "algorithm", 17);
513 write_std_check("__cpp_lib_gcd_lcm", 201606, "numeric", 17);
514 write_std_check("__cpp_lib_hypot", 201603, "cmath", 17);
515 write_std_check("__cpp_lib_math_special_functions", 201603, "cmath", 17);
516 write_std_check("__cpp_lib_filesystem", 201703, "filesystem", 17);
517 write_std_check("__cpp_lib_atomic_is_always_lock_free", 201603, "atomic", 17);
518 write_std_check("__cpp_lib_shared_mutex", 201505, "shared_mutex", 17);
519 write_std_check("__cpp_lib_scoped_lock", 201703, "mutex", 17);
521 write_std_check("__cpp_binary_literals", 201304, "", 14);
522 write_std_check("__cpp_init_captures", 201304, "", 14);
523 write_std_check("__cpp_generic_lambdas", 201304, "", 14);
524 write_std_check("__cpp_sized_deallocation", 201309, "", 14);
525 write_std_check("__cpp_constexpr", 201304, "", 14, false);
526 write_std_check("__cpp_decltype_auto", 201304, "", 14);
527 write_std_check("__cpp_return_type_deduction", 201304, "", 14);
528 write_std_check("__cpp_aggregate_nsdmi", 201304, "", 14);
529 write_std_check("__cpp_variable_templates", 201304, "", 14);
530 write_std_check("__cpp_lib_integer_sequence", 201304, "utility", 14);
531 write_std_check("__cpp_lib_exchange_function", 201304, "utility", 14);
532 write_std_check("__cpp_lib_tuples_by_type", 201304, "utility", 14);
533 write_std_check("__cpp_lib_tuple_element_t", 201402, "tuple", 14);
534 write_std_check("__cpp_lib_make_unique", 201304, "memory", 14);
535 write_std_check("__cpp_lib_transparent_operators", 201210, "functional", 14);
536 write_std_check("__cpp_lib_integral_constant_callable", 201304, "type_traits", 14);
537 write_std_check("__cpp_lib_transformation_trait_aliases", 201304, "type_traits", 14);
538 write_std_check("__cpp_lib_result_of_sfinae", 201210, "functional", 14);
539 write_std_check("__cpp_lib_is_final", 201402, "type_traits", 14);
540 write_std_check("__cpp_lib_is_null_pointer", 201309, "type_traits", 14);
541 write_std_check("__cpp_lib_chrono_udls", 201304, "chrono", 14);
542 write_std_check("__cpp_lib_string_udls", 201304, "string", 14);
543 write_std_check("__cpp_lib_generic_associative_lookup", 201304, "map", 14);
544 write_std_check("__cpp_lib_null_iterators", 201304, "iterator", 14);
545 write_std_check("__cpp_lib_make_reverse_iterator", 201402, "iterator", 14);
546 write_std_check("__cpp_lib_robust_nonmodifying_seq_ops", 201304, "algorithm", 14);
547 write_std_check("__cpp_lib_complex_udls", 201309, "complex", 14);
548 write_std_check("__cpp_lib_quoted_string_io", 201304, "iomanip", 14);
549 write_std_check("__cpp_lib_shared_timed_mutex", 201402, "shared_mutex", 14);
551 write_std_check("__cpp_unicode_characters", 200704, "", 11);
552 write_std_check("__cpp_raw_strings", 200710, "", 11);
553 write_std_check("__cpp_unicode_literals", 200710, "", 11);
554 write_std_check("__cpp_user_defined_literals", 200809, "", 11);
555 write_std_check("__cpp_threadsafe_static_init", 200806, "", 11);
556 write_std_check("__cpp_lambdas", 200907, "", 11);
557 write_std_check("__cpp_constexpr", 200704, "", 11);
558 write_std_check("__cpp_range_based_for", 200907, "", 11);
559 write_std_check("__cpp_static_assert", 200410, "", 11);
560 write_std_check("__cpp_decltype", 200707, "", 11);
561 write_std_check("__cpp_attributes", 200809, "", 11);
562 write_std_check("__cpp_rvalue_references", 200610, "", 11);
563 write_std_check("__cpp_variadic_templates", 200704, "", 11);
564 write_std_check("__cpp_initializer_lists", 200806, "", 11);
565 write_std_check("__cpp_explicit_conversion", 200710, "", 11);
566 write_std_check("__cpp_delegating_constructors", 200604, "", 11);
567 write_std_check("__cpp_nsdmi", 200809, "", 11);
568 write_std_check("__cpp_inheriting_constructors", 200802, "", 11);
569 write_std_check("__cpp_ref_qualifiers", 200710, "", 11);
570 write_std_check("__cpp_alias_templates", 200704, "", 11);
572 write_std_check("__cpp_rtti", 199711, "", 03);
573 write_std_check("__cpp_exceptions", 199711, "", 03);
576 int cpp_main(int argc
, char* argv
[])
579 // get the boost path to begin with:
584 config_path
= p
/ "libs" / "config" / "test" ;
589 fs::path
p(__FILE__
);
590 config_path
= p
.branch_path().branch_path() / "test";
592 std::cout
<< "Info: Boost.Config test path set as: " << config_path
.string() << std::endl
;
594 // enumerate *.ipp files and store them in a map for now:
595 boost::regex
ipp_mask("boost_(?:(has)|no).*\\.ipp");
596 boost::smatch ipp_match
;
597 fs::directory_iterator
i(config_path
), j
;
598 std::map
<fs::path
, bool> files_to_process
;
601 if(boost::regex_match(i
->path().leaf().string(), ipp_match
, ipp_mask
))
603 files_to_process
[*i
] = ipp_match
[1].matched
;
607 // Enumerate the files and process them, by defering this until now
608 // the results are always alphabetized which reduces churn in the
610 for(std::map
<fs::path
, bool>::const_iterator pos
= files_to_process
.begin(); pos
!= files_to_process
.end(); ++pos
)
612 process_ipp_file(pos
->first
, pos
->second
);
615 write_cxxNN_asserts();
616 write_cxxNN_composite();
620 write_std_config_checks();
622 write_build_check_jamfile();