]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/config/tools/generate.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / config / tools / generate.cpp
CommitLineData
7c673cae
FG
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)
5
6//
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.
10//
11
1e59de90
TL
12#define _CRT_SECURE_NO_WARNINGS
13
7c673cae
FG
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>
19#include <iostream>
20#include <sstream>
21#include <string>
22#include <set>
23#include <ctime>
24
25namespace fs = boost::filesystem;
26
27fs::path config_path;
28
29std::string copyright(
1e59de90 30"// Copyright John Maddock 2002-21.\n"
7c673cae
FG
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"
34"\n"
35"// See http://www.boost.org/libs/config for the most recent version."
36"//\n// Revision $Id$\n//\n");
37
38std::stringstream config_test1;
39std::stringstream config_test1a;
40std::stringstream config_test2;
41std::stringstream jamfile;
42std::stringstream jamfile_v2;
43std::stringstream build_config_test;
44std::stringstream build_config_jamfile;
45std::set<std::string> macro_list;
b32b8144 46std::set<std::string> feature_list;
7c673cae
FG
47
48void write_config_info()
49{
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));
54 ifs.close();
55 // create macro list:
56 std::stringstream ss;
57 for(std::set<std::string>::const_iterator i(macro_list.begin()), j(macro_list.end());
58 i != j;
59 ++i)
60 {
61 ss << " PRINT_MACRO(" << *i << ");\n";
62 }
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");
66 boost::smatch what;
67 if(boost::regex_search(file_text, what, re))
68 {
69 std::string new_text;
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");
74 ofs << new_text;
75 }
76}
77
78void write_config_test()
79{
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";
94}
95
96void write_jamfile_v2()
97{
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;
119
120}
121
122void 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,
126 bool positive_test,
127 bool expect_success)
128{
129 if(!fs::exists(file))
130 {
131 std::cout << "Writing test file " << file.string() << std::endl;
132
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;
138
139 if(expect_success)
140 {
141 ofs << "// This file should compile, if it does not then\n"
142 "// " << macro_name << " should ";
143 if(positive_test)
144 ofs << "not ";
145 ofs << "be defined.\n";
146 }
147 else
148 {
149 ofs << "// This file should not compile, if it does then\n"
150 "// " << macro_name << " should ";
151 if(!positive_test)
152 ofs << "not ";
153 ofs << "be defined.\n";
154 }
155 ofs << "// See file " << header_file << " for details\n\n";
156
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"
161 "#endif\n\n";
162
163 static const boost::regex tr1_exp("BOOST_HAS_TR1.*");
164
165 ofs << "#include <boost/config.hpp>\n";
166
7c673cae
FG
167 ofs << "#include \"test.hpp\"\n\n"
168 "#if";
169 if(positive_test != expect_success)
170 ofs << "n";
171 ofs << "def " << macro_name <<
172 "\n#include \"" << header_file <<
173 "\"\n#else\n";
174 if(expect_success)
175 ofs << "namespace " << namespace_name << " = empty_boost;\n";
176 else
177 ofs << "#error \"this file should not compile\"\n";
178 ofs << "#endif\n\n";
179
180 ofs << "int main( int, char *[] )\n{\n return " << namespace_name << "::test();\n}\n\n";
181 }
182 else
183 {
184 std::cout << "Skipping existing test file " << file.string() << std::endl;
185 }
186}
187
188void write_build_tests()
189{
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;
b32b8144 194 ofs << "#include <boost/config.hpp>\n\n";
7c673cae 195 ofs << build_config_test.str() << std::endl;
b32b8144 196 ofs << "int main( int, char *[] )\n{\n" << " return 0;\n}\n\n";
7c673cae
FG
197}
198
199void write_build_check_jamfile()
200{
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"
211 "\n"
7c673cae
FG
212 ;
213 ofs << build_config_jamfile.str() << std::endl;
214}
215
1e59de90
TL
216std::map<std::string, std::set<std::string>> std_version_macros;
217
218
219void categorize_macro(const std::string& name)
220{
221 boost::regex cxxNN("BOOST_NO_CXX(\\d\\d).+");
222 boost::regex cxx03("BOOST_NO_.+");
223 boost::smatch what;
224 if (regex_match(name, what, cxxNN))
225 {
226 std_version_macros[what[1]].insert(name);
227 }
228 else if (regex_match(name, what, cxx03))
229 {
230 std_version_macros["03"].insert(name);
231 }
232}
233
7c673cae
FG
234void process_ipp_file(const fs::path& file, bool positive_test)
235{
236 std::cout << "Info: Scanning file: " << file.string() << std::endl;
237
238 // our variables:
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;
244
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));
248 ifs.close();
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))
253 {
254 macro_name = macro_match[1];
255 macro_list.insert(macro_name);
1e59de90 256 categorize_macro(macro_name);
7c673cae
FG
257 namespace_name = boost::regex_replace(file_text, macro_regex, "\\L$1", boost::format_first_only | boost::format_no_copy);
258 }
259 if(macro_name.empty())
260 {
261 std::cout << "Error: no macro definition found in " << file.string();
262 }
263 else
264 {
265 std::cout << "Info: Macroname: " << macro_name << std::endl;
266 }
267
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);
274
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;
279 *pout << "#if";
280 if(!positive_test)
281 *pout << "n";
282 *pout << "def " << macro_name
283 << "\n#include \"" << file.leaf().string() << "\"\n#else\nnamespace "
284 << namespace_name << " = empty_boost;\n#endif\n";
285
286 config_test2 << " if(0 != " << namespace_name << "::test())\n"
287 " {\n"
288 " std::cerr << \"Failed test for " << macro_name << " at: \" << __FILE__ << \":\" << __LINE__ << std::endl;\n"
289 " ++error_count;\n"
290 " }\n";
291
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";
296
297 jamfile_v2 << "test-suite \"" << macro_name << "\" : \n"
298 "[ run ../" << positive_file.leaf().string() << " ]\n"
299 "[ compile-fail ../" << negative_file.leaf().string() << " ] ;\n";
300
301 // Generate data for the Build-checks test file:
302 build_config_test << "#ifdef TEST_" << macro_name << std::endl;
b32b8144
FG
303 if (positive_test)
304 {
305 build_config_test << "# ifndef " << macro_name << "\n# error \"Feature macro " << macro_name << " is not defined.\"\n# endif\n";
306 }
307 else
308 {
309 build_config_test << "# ifdef " << macro_name << "\n# error \"Defect macro " << macro_name << " is defined.\"\n# endif\n";
310 }
311 build_config_test << "#endif\n";
7c673cae
FG
312
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");
b32b8144
FG
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);
7c673cae
FG
319}
320
1e59de90
TL
321void fixup_cxxNN()
322{
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");
330 //
331 // These are removed from later standard versions so we don't check them here:
332 //
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");
336}
337
338void write_cxxNN_asserts()
339{
340 std::string previous_filename;
341 for (auto std = std_version_macros.begin(); std != std_version_macros.end(); ++std)
342 {
343 std::string filename = "assert_cxx";
344 filename += std->first;
345 filename += ".hpp";
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";
353 else
354 ofs << "\n";
355
356 for (auto macro = std->second.begin(); macro != std->second.end(); ++macro)
357 {
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";
359 }
360
361 previous_filename = filename;
362 }
363}
364
365void write_cxxNN_composite()
366{
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;
371
372 std::string previous_macro;
373 for (auto std = std_version_macros.begin(); std != std_version_macros.end(); ++std)
374 {
375 std::string macro = "BOOST_NO_CXX";
376 macro += std->first;
377
378 bool done_first = false;
379 ofs << "#if ";
380
381 if (previous_macro.size())
382 {
383 ofs << "defined(" << previous_macro << ")";
384 done_first = true;
385 }
386
387 for (auto macro = std->second.begin(); macro != std->second.end(); ++macro)
388 {
389 if (done_first)
390 ofs << "\\\n || ";
391 ofs << "defined(" << *macro << ")";
392 done_first = true;
393 }
394 ofs << "\n# define " << macro << "\n#endif\n\n";
395
396 previous_macro = macro;
397 }
398}
399
92f5a8d4
TL
400void write_std_check(std::string macroname, int min_value, std::string header, int std_version, bool primary = true)
401{
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";
414 if (header.size())
415 {
416 ofs << "#include <" << header << ">\n\n";
417 }
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";
421
422 build_config_jamfile << "obj " << test_name << " : std/" << test_name << ".cpp ;\n";
423 if(primary)
424 build_config_jamfile << "alias " << test_basename << " : " << test_name << " ;\n";
425}
426
427void write_std_config_checks()
428{
429 // C++20
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);
449 // C++17
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);
520 // C++14
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);
550 // C++11
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);
571 // C++98
572 write_std_check("__cpp_rtti", 199711, "", 03);
573 write_std_check("__cpp_exceptions", 199711, "", 03);
574}
575
7c673cae
FG
576int cpp_main(int argc, char* argv[])
577{
578 //
579 // get the boost path to begin with:
580 //
581 if(argc > 1)
582 {
583 fs::path p(argv[1]);
584 config_path = p / "libs" / "config" / "test" ;
585 }
586 else
587 {
588 // try __FILE__:
589 fs::path p(__FILE__);
590 config_path = p.branch_path().branch_path() / "test";
591 }
592 std::cout << "Info: Boost.Config test path set as: " << config_path.string() << std::endl;
593
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;
599 while(i != j)
600 {
601 if(boost::regex_match(i->path().leaf().string(), ipp_match, ipp_mask))
602 {
603 files_to_process[*i] = ipp_match[1].matched;
604 }
605 ++i;
606 }
607 // Enumerate the files and process them, by defering this until now
608 // the results are always alphabetized which reduces churn in the
609 // generated files.
610 for(std::map<fs::path, bool>::const_iterator pos = files_to_process.begin(); pos != files_to_process.end(); ++pos)
611 {
612 process_ipp_file(pos->first, pos->second);
613 }
1e59de90
TL
614 fixup_cxxNN();
615 write_cxxNN_asserts();
616 write_cxxNN_composite();
7c673cae
FG
617 write_config_test();
618 write_jamfile_v2();
619 write_config_info();
92f5a8d4 620 write_std_config_checks();
7c673cae
FG
621 write_build_tests();
622 write_build_check_jamfile();
623 return 0;
624}
625