def __preprocess(self, match): raw_incl = match if isinstance(match, str) else match.group(1) incl = raw_incl.strip().lower() if incl in self.__processed_includes: return '' self.__processed_includes.append(incl) text = utils.read_all_text_from_file(Path(utils.entry_script_dir(), '..', 'include', 'toml++', incl).resolve(), logger=True).strip() + '\n' text = text.replace('\r\n', '\n') # convert windows newlines text = self.__re_strip_blocks.sub('', text, 0) # strip {{ }} blocks self.__current_level += 1 text = self.__re_includes.sub(lambda m : self.__preprocess(m), text, 0) self.__current_level -= 1 if (self.__current_level == 1): header_text = '↓ ' + raw_incl lpad = 20 + ((25 * (self.__header_indent % 4)) - int((len(header_text) + 4) / 2)) self.__header_indent += 1 text = '#if 1 {}\n{}\n\n#endif {}\n'.format( utils.make_divider(header_text, lpad, line_length=113), text, utils.make_divider('↑ ' + raw_incl, lpad, line_length=113) ) return '\n\n' + text + '\n\n' # will get merged later
def main(): extern_root = Path(utils.entry_script_dir(), '..', 'external').resolve() utils.assert_existing_directory(extern_root) assert extern_root.exists() all_tests = { 'valid': dict(), 'invalid': dict() } load_valid_inputs(all_tests, extern_root) load_invalid_inputs(all_tests, extern_root) for validity, sources in all_tests.items(): for source, tests in sources.items(): write_test_file('{}/{}'.format(source, validity), tests )
def main(): extern_root = Path(utils.entry_script_dir(), '..', 'external').resolve() utils.assert_existing_directory(extern_root) assert extern_root.exists() tests = {'valid': dict(), 'invalid': dict()} load_valid_inputs(tests, extern_root) load_invalid_inputs(tests, extern_root) for test_type, test_groups in tests.items(): for test_group, test_cases in test_groups.items(): write_test_file('{}/{}'.format(test_group, test_type), test_cases)
def main(): hpp_path = Path(utils.entry_script_dir(), '..', 'toml.hpp').resolve() hash1 = utils.sha1(utils.read_all_text_from_file(hpp_path, logger=True)) print(rf'Hash 1: {hash1}') utils.run_python_script(r'generate_single_header.py') hash2 = utils.sha1(utils.read_all_text_from_file(hpp_path, logger=True)) print(rf'Hash 2: {hash2}') if (hash1 != hash2): print( "toml.hpp wasn't up-to-date!\nRun generate_single_header.py before your commit to prevent this error.", file=sys.stderr) return 1 print("toml.hpp was up-to-date") return 0
def main(): # establish local directories root_dir = utils.entry_script_dir().parent include_dir = Path(root_dir, 'include', 'toml++') # preprocess header(s) toml_h = str(Preprocessor(Path(include_dir, 'toml.h'))) # strip various things: if 1: for i in range(3): # trailing whitespace toml_h = re.sub('([^ \t])[ \t]+\n', r'\1\n', toml_h) # explicit 'strip this' blocks toml_h = re.sub(r'(?:\n[ \t]*)?//[#!][ \t]*[{][{].*?//[#!][ \t]*[}][}].*?\n', '\n', toml_h, flags=re.S) # spdx license identifiers toml_h = re.sub(r'^\s*//\s*SPDX-License-Identifier:.+?$', '', toml_h, 0, re.I | re.M) # double blank lines toml_h = re.sub('\n(?:[ \t]*\n[ \t]*)+\n', '\n\n', toml_h) # magic comments blank_line = r'(?:[ \t]*\n)' comment_line = r'(?:[ \t]*//(?:[/#!<]| ?(?:---|===|\^\^\^|vvv))[^\n]*\n)' toml_h = re.sub(rf'\n{comment_line}{blank_line}+{comment_line}', '\n', toml_h) toml_h = re.sub(rf'([{{,])\s*\n(?:{comment_line}|{blank_line})+', r'\1\n', toml_h) toml_h = re.sub(rf'{comment_line}+', '\n', toml_h) # weird spacing edge case between } and pp directives toml_h = re.sub('\n[}]\n#', r'\n}\n\n#', toml_h, re.S) # enable warnings -> disable warnings toml_h = re.sub('(TOML_ENABLE_WARNINGS;)\n[ \t\n]*\n(TOML_DISABLE_WARNINGS;)', r'', toml_h) # blank lines between consecutive TOML_XXXXX_WARNINGS statements toml_h = re.sub('(TOML_[A-Z_]+?_WARNINGS;)\n[ \t\n]*\n(TOML_[A-Z_]+?_WARNINGS;)', r'\1\n\2', toml_h) # blank lines between consecutive #includes toml_h = re.sub('[#]\s*include\s*<(.+?)>\n[ \t\n]*\n[#]\s*include\s*<(.+?)>', r'#include <\1>\n#include <\2>', toml_h) # blank lines following opening brackets or a comma toml_h = re.sub(r'([^@][({,])\n\n', r'\1\n', toml_h) # blank lines preceeding closing brackets toml_h = re.sub(r'\n\n([ \t]*[})])', r'\n\1', toml_h) # ensure only one trailing newline toml_h = toml_h.strip() + '\n' # change TOML_LIB_SINGLE_HEADER to 1 toml_h = re.sub( '#\s*define\s+TOML_LIB_SINGLE_HEADER\s+[0-9]+', '#define TOML_LIB_SINGLE_HEADER 1', toml_h, 0, re.I ) # read version number version_h = utils.read_all_text_from_file(Path(include_dir, 'impl/version.h'), logger=True) match = re.search( r'#\s*define\s+TOML_LIB_MAJOR\s+([0-9]+)[^0-9].*' + r'#\s*define\s+TOML_LIB_MINOR\s+([0-9]+)[^0-9].*' + r'#\s*define\s+TOML_LIB_PATCH\s+([0-9]+)[^0-9]', version_h, re.I | re.S) if match is None: raise Exception("could not find TOML_LIB_MAJOR, TOML_LIB_MINOR or TOML_LIB_PATCH impl/version.h") version = rf'{int(match[1])}.{int(match[2])}.{int(match[3])}' print(rf'Library version: {version}') # build the preamble (license etc) preamble = [] preamble.append(rf''' // toml++ v{version} // https://github.com/marzer/tomlplusplus // SPDX-License-Identifier: MIT''') preamble.append(r''' // - THIS FILE WAS ASSEMBLED FROM MULTIPLE HEADER FILES BY A SCRIPT - PLEASE DON'T EDIT IT DIRECTLY - // // If you wish to submit a contribution to toml++, hooray and thanks! Before you crack on, please be aware that this // file was assembled from a number of smaller files by a python script, and code contributions should not be made // against it directly. You should instead make your changes in the relevant source file(s). The file names of the files // that contributed to this header can be found at the beginnings and ends of the corresponding sections of this file.''') preamble.append(r''' // TOML Language Specifications: // latest: https://github.com/toml-lang/toml/blob/master/README.md // v1.0.0: https://toml.io/en/v1.0.0 // v0.5.0: https://toml.io/en/v0.5.0 // changelog: https://github.com/toml-lang/toml/blob/master/CHANGELOG.md''') preamble.append(utils.read_all_text_from_file(Path(utils.entry_script_dir(), '..', 'LICENSE').resolve(), logger=True)) # write the output with StringIO(newline='\n') as output: # build in a string buffer write = lambda txt, end='\n': print(txt, file=output, end=end) if (len(preamble) > 0): write(utils.make_divider()) for pre in preamble: write('//') for line in pre.strip().splitlines(): if len(line) == 0: write('//') continue if not line.startswith('//'): write('// ', end = '') write(line) write('//') write(utils.make_divider()) write(toml_h) write('') output_str = output.getvalue().strip() # analyze the output to find any potentially missing #undefs if 1: re_define = re.compile(r'^\s*#\s*define\s+([a-zA-Z0-9_]+)(?:$|\s|\()') re_undef = re.compile(r'^\s*#\s*undef\s+([a-zA-Z0-9_]+)(?:$|\s|//)') defines = dict() for output_line in output_str.splitlines(): defined = True m = re_define.match(output_line) if not m: defined = False m = re_undef.match(output_line) if m: defines[m.group(1)] = defined ignore_list = ( # macros that are meant to stay public (user configs etc) r'INCLUDE_TOMLPLUSPLUS_H', r'POXY_IMPLEMENTATION_DETAIL', r'TOML_ALL_INLINE', r'TOML_API', r'TOML_CONCAT', r'TOML_CONCAT_1', r'TOML_CONFIG_HEADER', r'TOML_ENABLE_FORMATTERS', r'TOML_ENABLE_PARSER', r'TOML_ENABLE_SIMD', r'TOML_ENABLE_UNRELEASED_FEATURES', r'TOML_ENABLE_WINDOWS_COMPAT', r'TOML_EXCEPTIONS', r'TOML_EXTERN_TEMPLATES', r'TOML_HEADER_ONLY', r'TOML_LANG_MAJOR', r'TOML_LANG_MINOR', r'TOML_LANG_PATCH', r'TOML_LIB_MAJOR', r'TOML_LIB_MINOR', r'TOML_LIB_PATCH', r'TOML_LIB_SINGLE_HEADER', r'TOML_MAX_NESTED_VALUES', r'TOML_NAMESPACE_END', r'TOML_NAMESPACE_START', r'TOML_OPTIONAL_TYPE', r'TOML_SMALL_FLOAT_TYPE', r'TOML_SMALL_INT_TYPE', r'TOML_UNDEF_MACROS', r'TOMLPLUSPLUS_H', ) set_defines = [] for define, currently_set in defines.items(): if currently_set and define not in ignore_list: set_defines.append(define) if len(set_defines) > 0: set_defines.sort() print(f"Potentially missing #undefs:") for define in set_defines: print(f"\t#undef {define}") # write the output file output_file_path = Path(utils.entry_script_dir(), '..', 'toml.hpp').resolve() print("Writing to {}".format(output_file_path)) with open(output_file_path,'w', encoding='utf-8', newline='\n') as output_file: print(output_str, file=output_file)
def main(): # preprocess header(s) source_text = str(Preprocessor('toml.h')) # strip various things: # 'pragma once' source_text = re.sub(r'^\s*#\s*pragma\s+once\s*$', '', source_text, 0, re.I | re.M) # clang-format directives source_text = re.sub(r'^\s*//\s*clang-format\s+.+?$', '', source_text, 0, re.I | re.M) # spdx license identifiers source_text = re.sub(r'^\s*//\s*SPDX-License-Identifier:.+?$', '', source_text, 0, re.I | re.M) # 'magic' comment blocks (incl. doxygen) source_text = re.sub('(?:(?:\n|^)[ \t]*//[/#!<]+[^\n]*)+\n', '\n', source_text, 0, re.I | re.M) # 'magic' comments (incl. doxygen) source_text = re.sub('(?://[/#!<].*?)\n', '\n', source_text, 0, re.I | re.M) # remove trailing whitespace source_text = re.sub('([^ \t])[ \t]+\n', '\\1\n', source_text, 0, re.I | re.M) # bookended namespace blocks source_text = re.sub('}\n+TOML_NAMESPACE_END\n+TOML_NAMESPACE_START\n+{\n+', '\n', source_text, 0, re.I | re.M) source_text = re.sub('}\n+TOML_IMPL_NAMESPACE_END\n+TOML_IMPL_NAMESPACE_START\n+{\n+', '\n', source_text, 0, re.I | re.M) # blank lines before some preprocessor directives #source_text = re.sub('\n+\n(\s*)#\s*(elif|else|endif)(.*?)\n', '\n\\1#\\2\\3\n', source_text, 0, re.I | re.M) # blank lines after some preprocessor directives #source_text = re.sub('#\s*(if|ifn?def|elif|else)(.*?)\n\n+', '#\\1\\2\n', source_text, 0, re.I | re.M) # blank lines after opening braces source_text = re.sub('[{]\s*\n\s*\n+', '{\n', source_text, 0, re.I | re.M) # double newlines source_text = re.sub('\n(?:[ \t]*\n[ \t]*)+\n', '\n\n', source_text, 0, re.I | re.M) # source_text = re.sub( # blank lines between various preprocessor directives # '[#](endif(?:\s*//[^\n]*)?)\n{2,}[#](ifn?(?:def)?|define)', # '#\\1\n#\\2', # source_text, 0, re.I | re.M # ) return_type_pattern \ = r'(?:' \ + r'(?:\[\[nodiscard\]\]\s*)?' \ + r'(?:(?:friend|explicit|virtual|inline|const|operator)\s+)*' \ + r'(?:' \ + r'bool|int64_t|(?:const_)?iterator|double|void' \ + r'|node(?:_(?:view|of)<.+?>|)?|table|array|value(?:<.+?>)?' \ + r'|T|U|parse_(?:error|result)' \ + r')' \ + r'(?:\s*[&*]+)?' \ + r'(?:\s*[(]\s*[)])?' \ + r'\s+' \ + r')' blank_lines_between_returns_pattern = '({}[^\n]+)\n\n([ \t]*{})'.format(return_type_pattern, return_type_pattern) for i in range(0, 5): # remove blank lines between simple one-liner definitions source_text = re.sub('(using .+?;)\n\n([ \t]*using)', '\\1\n\\2', source_text, 0, re.I | re.M) source_text = re.sub( '([a-zA-Z_][a-zA-Z0-9_]*[ \t]+[a-zA-Z_][a-zA-Z0-9_]*[ \t]*;)' \ + '\n\n([ \t]*[a-zA-Z_][a-zA-Z0-9_]*[ \t]+[a-zA-Z_][a-zA-Z0-9_]*[ \t]*;)', '\\1\n\\2', source_text, 0, re.I | re.M) source_text = re.sub(blank_lines_between_returns_pattern, '\\1\n\\2', source_text, 0, re.I | re.M) source_text = source_text.strip() + '\n' # change TOML_LIB_SINGLE_HEADER to 1 source_text = re.sub( '#\s*define\s+TOML_LIB_SINGLE_HEADER\s+[0-9]+', '#define TOML_LIB_SINGLE_HEADER 1', source_text, 0, re.I ) # extract library version library_version = { 'major': 0, 'minor': 0, 'patch': 0 } match = re.search(r'^\s*#\s*define\s+TOML_LIB_MAJOR\s+([0-9]+)\s*$', source_text, re.I | re.M) if match is not None: library_version['major'] = match.group(1) match = re.search(r'^\s*#\s*define\s+TOML_LIB_MINOR\s+([0-9]+)\s*$', source_text, re.I | re.M) if match is not None: library_version['minor'] = match.group(1) match = re.search(r'^\s*#\s*define\s+TOML_LIB_(?:REVISION|PATCH)\s+([0-9]+)\s*$', source_text, re.I | re.M) if match is not None: library_version['patch'] = match.group(1) # build the preamble (license etc) preamble = [] preamble.append(''' // toml++ v{major}.{minor}.{patch} // https://github.com/marzer/tomlplusplus // SPDX-License-Identifier: MIT'''.format(**library_version)) preamble.append(''' // - THIS FILE WAS ASSEMBLED FROM MULTIPLE HEADER FILES BY A SCRIPT - PLEASE DON'T EDIT IT DIRECTLY - // // If you wish to submit a contribution to toml++, hooray and thanks! Before you crack on, please be aware that this // file was assembled from a number of smaller files by a python script, and code contributions should not be made // against it directly. You should instead make your changes in the relevant source file(s). The file names of the files // that contributed to this header can be found at the beginnings and ends of the corresponding sections of this file.''') preamble.append(''' // TOML Language Specifications: // latest: https://github.com/toml-lang/toml/blob/master/README.md // v1.0.0: https://toml.io/en/v1.0.0 // v0.5.0: https://toml.io/en/v0.5.0 // changelog: https://github.com/toml-lang/toml/blob/master/CHANGELOG.md''') preamble.append(utils.read_all_text_from_file(Path(utils.entry_script_dir(), '..', 'LICENSE').resolve(), logger=True)) # write the output with StringIO(newline='\n') as output: # build in a string buffer write = lambda txt, end='\n': print(txt, file=output, end=end) if (len(preamble) > 0): write(utils.make_divider()) for pre in preamble: write('//') for line in pre.strip().splitlines(): if len(line) == 0: write('//') continue if not line.startswith('//'): write('// ', end = '') write(line) write('//') write(utils.make_divider()) write(source_text) write('') output_str = output.getvalue().strip() # analyze the output to find any potentially missing #undefs re_define = re.compile(r'^\s*#\s*define\s+([a-zA-Z0-9_]+)(?:$|\s|\()') re_undef = re.compile(r'^\s*#\s*undef\s+([a-zA-Z0-9_]+)(?:$|\s|//)') defines = dict() for output_line in output_str.splitlines(): defined = True m = re_define.match(output_line) if not m: defined = False m = re_undef.match(output_line) if m: defines[m.group(1)] = defined ignore_list = ( # macros that are meant to stay public (user configs etc) 'INCLUDE_TOMLPLUSPLUS_H', 'TOML_API', 'TOML_UNRELEASED_FEATURES', 'TOML_LARGE_FILES', 'TOML_PARSER', 'TOML_WINDOWS_COMPAT', 'TOML_EXCEPTIONS', 'TOML_LIB_SINGLE_HEADER', 'TOML_LIB_MAJOR', 'TOML_LIB_MINOR', 'TOML_LIB_PATCH', 'TOML_LANG_MAJOR', 'TOML_LANG_MINOR', 'TOML_LANG_PATCH', 'TOML_UNDEF_MACROS', 'TOML_HEADER_ONLY', 'TOML_ALL_INLINE' ) set_defines = [] for define, currently_set in defines.items(): if currently_set and define not in ignore_list: set_defines.append(define) if len(set_defines) > 0: set_defines.sort() print(f"Potentially missing #undefs:") for define in set_defines: print(f"\t#undef {define}") # write the output file output_file_path = Path(utils.entry_script_dir(), '..', 'toml.hpp').resolve() print("Writing to {}".format(output_file_path)) with open(output_file_path,'w', encoding='utf-8', newline='\n') as output_file: print(output_str, file=output_file)
def write_test_file(name, all_tests): for test in all_tests: unicode = requires_unicode(str(test)) if not unicode and not isinstance(test.expected(), bool): unicode = requires_unicode(test.expected().render()) if unicode: test.add_condition(r'UNICODE_LITERALS_OK') tests_by_group = {} for test in all_tests: if test.group() not in tests_by_group: tests_by_group[test.group()] = {} cond = test.condition() if cond not in tests_by_group[test.group()]: tests_by_group[test.group()][cond] = [] tests_by_group[test.group()][cond].append(test) all_tests = tests_by_group test_file_path = Path(utils.entry_script_dir(), '..', 'tests', rf'conformance_{sanitize(name.strip())}.cpp').resolve() print(rf'Writing to {test_file_path}') with open(test_file_path, 'w', encoding='utf-8', newline='\n') as test_file: write = lambda txt,end='\n': print(txt, file=test_file, end=end) # preamble write('// This file is a part of toml++ and is subject to the the terms of the MIT license.') write('// Copyright (c) Mark Gillard <*****@*****.**>') write('// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.') write('// SPDX-License-Identifier: MIT') write('//-----') write('// this file was generated by generate_conformance_tests.py - do not modify it directly') write('') write('#include "tests.h"') write('using namespace toml::impl;') write('') # test data write('TOML_DISABLE_WARNINGS; // unused variable spam') write('') write('namespace') write('{', end='') for group, conditions in all_tests.items(): for condition, tests in conditions.items(): write('') if condition != '': write(f'#if {condition}'); write('') for test in tests: write(f'\t{test}') if condition != '': write('') write(f'#endif // {condition}'); write('}') write('') write('TOML_ENABLE_WARNINGS;') write('') # tests write(f'TEST_CASE("conformance - {name}")') write('{', end='') for group, conditions in all_tests.items(): for condition, tests in conditions.items(): if condition != '': write('') write(f'#if {condition}'); for test in tests: write('') expected = test.expected() if isinstance(expected, bool): if expected: write(f'\tparsing_should_succeed(FILE_LINE_ARGS, {test.identifier()}); // {test.name()}') else: write(f'\tparsing_should_fail(FILE_LINE_ARGS, {test.identifier()}); // {test.name()}') else: s = expected.render('\t\t') write(f'\tparsing_should_succeed(FILE_LINE_ARGS, {test.identifier()}, [](toml::table&& tbl) // {test.name()}') write('\t{') write(f'\t\tconst auto expected = {s};') write('\t\tREQUIRE(tbl == expected);') write('\t});') if condition != '': write('') write(f'#endif // {condition}'); write('}') write('')
def main(): mode_keys = ['!!debug', '!x86', 'cpplatest', 'unrel', 'noexcept'] modes = [[]] for n in range(1, len(mode_keys)): for combo in itertools.combinations(mode_keys, n): modes.append([i for i in combo]) modes.append(mode_keys) for mode in modes: if '!x86' not in mode: mode.insert(0, '!x64') if '!!debug' not in mode: mode.insert(0, '!!release') mode.sort() for i in range(0, len(mode)): while mode[i].startswith('!'): mode[i] = mode[i][1:] modes.sort() test_root = Path(utils.entry_script_dir(), '..', 'tests', 'vs').resolve() uuid_namespace = UUID('{51C7001B-048C-4AF0-B598-D75E78FF31F0}') configuration_name = lambda x: 'Debug' if x.lower( ) == 'debug' else 'Release' platform_name = lambda x: 'Win32' if x == 'x86' else x for mode in modes: file_path = Path(test_root, 'test_{}.vcxproj'.format('_'.join(mode))) print(f"Writing to {file_path}") with open(file_path, 'w', encoding='utf-8-sig', newline='\r\n') as file: write = lambda txt: print(txt, file=file) write(r''' <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="{configuration}|{platform}"> <Configuration>{configuration}</Configuration> <Platform>{platform}</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <VCProjectVersion>16.0</VCProjectVersion> <ProjectGuid>{{{uuid}}}</ProjectGuid> <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|{platform}'" Label="Configuration"> <ConfigurationType>Application</ConfigurationType> <UseDebugLibraries>true</UseDebugLibraries> <PlatformToolset>v142</PlatformToolset> <CharacterSet>MultiByte</CharacterSet> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|{platform}'" Label="Configuration"> <ConfigurationType>Application</ConfigurationType> <UseDebugLibraries>false</UseDebugLibraries> <PlatformToolset>v142</PlatformToolset> <WholeProgramOptimization>true</WholeProgramOptimization> <CharacterSet>MultiByte</CharacterSet> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="PropertySheets"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <Import Project="../../toml++.props" /> <ItemDefinitionGroup> <ClCompile> <AdditionalIncludeDirectories>..\tests;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <ExceptionHandling>{exceptions}</ExceptionHandling> <PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeaderFile>tests.h</PrecompiledHeaderFile> <PreprocessorDefinitions>TOML_UNRELEASED_FEATURES={unreleased_features};%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>LEAK_TESTS=1;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions Condition="'%(ExceptionHandling)'=='false'">_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions Condition="'%(ExceptionHandling)'=='false'">SHOULD_HAVE_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions Condition="'%(ExceptionHandling)'!='false'">SHOULD_HAVE_EXCEPTIONS=1;%(PreprocessorDefinitions)</PreprocessorDefinitions> <LanguageStandard>std{standard}</LanguageStandard> <MultiProcessorCompilation>true</MultiProcessorCompilation> </ClCompile> </ItemDefinitionGroup> <PropertyGroup> <LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory> </PropertyGroup> <ItemGroup> <ClCompile Include="..\conformance_burntsushi_invalid.cpp" /> <ClCompile Include="..\conformance_burntsushi_valid.cpp" /> <ClCompile Include="..\conformance_iarna_invalid.cpp" /> <ClCompile Include="..\conformance_iarna_valid.cpp" /> <ClCompile Include="..\impl_catch2.cpp"> <PrecompiledHeader>NotUsing</PrecompiledHeader> </ClCompile> <ClCompile Include="..\impl_toml.cpp"> <PrecompiledHeader>NotUsing</PrecompiledHeader> </ClCompile> <ClCompile Include="..\manipulating_arrays.cpp" /> <ClCompile Include="..\manipulating_tables.cpp" /> <ClCompile Include="..\manipulating_parse_result.cpp" /> <ClCompile Include="..\manipulating_values.cpp" /> <ClCompile Include="..\parsing_arrays.cpp" /> <ClCompile Include="..\parsing_booleans.cpp" /> <ClCompile Include="..\parsing_comments.cpp" /> <ClCompile Include="..\parsing_dates_and_times.cpp" /> <ClCompile Include="..\parsing_floats.cpp" /> <ClCompile Include="..\parsing_integers.cpp" /> <ClCompile Include="..\parsing_key_value_pairs.cpp" /> <ClCompile Include="..\parsing_spec_example.cpp" /> <ClCompile Include="..\parsing_strings.cpp" /> <ClCompile Include="..\parsing_tables.cpp" /> <ClCompile Include="..\tests.cpp"> <PrecompiledHeader>Create</PrecompiledHeader> </ClCompile> <ClCompile Include="..\unicode.cpp" /> <ClCompile Include="..\user_feedback.cpp" /> <ClCompile Include="..\using_iterators.cpp" /> <ClCompile Include="..\windows_compat.cpp" /> </ItemGroup> <ItemGroup> <Natvis Include="..\..\toml++.natvis" /> </ItemGroup> <ItemGroup> <ClInclude Include="..\catch2.h" /> <ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\settings.h" /> <ClInclude Include="..\tests.h" /> <ClInclude Include="..\tloptional.h" /> </ItemGroup> <ItemGroup> <None Include="..\cpp.hint" /> <None Include="..\meson.build" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> </Project> '''.strip().format( configuration=next( configuration_name(x) for x in mode if x in ('debug', 'release')), platform=next( platform_name(x) for x in mode if x in ('x64', 'x86')), uuid=str(uuid5(uuid_namespace, '_'.join(mode))).upper(), exceptions='false' if 'noexcept' in mode else 'Sync', unreleased_features=1 if 'unrel' in mode else 0, standard='cpplatest' if 'cpplatest' in mode else 'cpp17'))
def main(): mode_keys = [ '!!debug', '!x86', 'cpplatest', 'unrel', 'noexcept' ] modes = [ [] ] for n in range(1, len(mode_keys)): for combo in itertools.combinations(mode_keys, n): modes.append([i for i in combo]) modes.append(mode_keys) for mode in modes: if '!x86' not in mode: mode.insert(0, '!x64') if '!!debug' not in mode: mode.insert(0, '!!release') mode.sort() for i in range(0, len(mode)): while mode[i].startswith('!'): mode[i] = mode[i][1:] modes.sort() test_root = Path(utils.entry_script_dir(), '..', 'tests', 'vs').resolve() uuid_namespace = UUID('{51C7001B-048C-4AF0-B598-D75E78FF31F0}') configuration_name = lambda x: 'Debug' if x.lower() == 'debug' else 'Release' platform_name = lambda x: 'Win32' if x == 'x86' else x for mode in modes: file_path = Path(test_root, 'test_{}.vcxproj'.format('_'.join(mode))) print(f"Writing to {file_path}") with open(file_path, 'w', encoding='utf-8-sig', newline='\r\n') as file: write = lambda txt: print(txt, file=file) write(r''' <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="{configuration}|{platform}"> <Configuration>{configuration}</Configuration> <Platform>{platform}</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <VCProjectVersion>16.0</VCProjectVersion> <ProjectGuid>{{{uuid}}}</ProjectGuid> <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|{platform}'" Label="Configuration"> <ConfigurationType>Application</ConfigurationType> <UseDebugLibraries>true</UseDebugLibraries> <PlatformToolset>v142</PlatformToolset> <CharacterSet>MultiByte</CharacterSet> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|{platform}'" Label="Configuration"> <ConfigurationType>Application</ConfigurationType> <UseDebugLibraries>false</UseDebugLibraries> <PlatformToolset>v142</PlatformToolset> <WholeProgramOptimization>true</WholeProgramOptimization> <CharacterSet>MultiByte</CharacterSet> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="PropertySheets"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <Import Project="../../toml++.props" /> <ItemDefinitionGroup> <ClCompile> <AdditionalIncludeDirectories>..\tests;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <ExceptionHandling>{exceptions}</ExceptionHandling> <PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeaderFile>tests.h</PrecompiledHeaderFile> <PreprocessorDefinitions>TOML_UNRELEASED_FEATURES={unreleased_features};%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>LEAK_TESTS=1;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions Condition="'%(ExceptionHandling)'=='false'">_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions Condition="'%(ExceptionHandling)'=='false'">SHOULD_HAVE_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions Condition="'%(ExceptionHandling)'!='false'">SHOULD_HAVE_EXCEPTIONS=1;%(PreprocessorDefinitions)</PreprocessorDefinitions> <LanguageStandard>std{standard}</LanguageStandard> <MultiProcessorCompilation>true</MultiProcessorCompilation> <WarningLevel>EnableAllWarnings</WarningLevel> <DisableSpecificWarnings>%(DisableSpecificWarnings);4127</DisableSpecificWarnings> <!-- conditional expr is constant --> <DisableSpecificWarnings>%(DisableSpecificWarnings);4324</DisableSpecificWarnings> <!-- structure was padded due to alignment specifier --> <DisableSpecificWarnings>%(DisableSpecificWarnings);4464</DisableSpecificWarnings> <!-- relative include path contains '..' --> <DisableSpecificWarnings>%(DisableSpecificWarnings);4505</DisableSpecificWarnings> <!-- unreferenced local function removed --> <DisableSpecificWarnings>%(DisableSpecificWarnings);4514</DisableSpecificWarnings> <!-- unreferenced inline function has been removed --> <DisableSpecificWarnings>%(DisableSpecificWarnings);4577</DisableSpecificWarnings> <!-- 'noexcept' used with no exception handling mode specified --> <DisableSpecificWarnings>%(DisableSpecificWarnings);4582</DisableSpecificWarnings> <!-- constructor is not implicitly called --> <DisableSpecificWarnings>%(DisableSpecificWarnings);4623</DisableSpecificWarnings> <!-- default constructor was implicitly defined as deleted --> <DisableSpecificWarnings>%(DisableSpecificWarnings);4625</DisableSpecificWarnings> <!-- copy constructor was implicitly defined as deleted --> <DisableSpecificWarnings>%(DisableSpecificWarnings);4626</DisableSpecificWarnings> <!-- assignment operator was implicitly defined as deleted --> <DisableSpecificWarnings>%(DisableSpecificWarnings);4710</DisableSpecificWarnings> <!-- function not inlined --> <DisableSpecificWarnings>%(DisableSpecificWarnings);4711</DisableSpecificWarnings> <!-- function selected for automatic expansion --> <DisableSpecificWarnings>%(DisableSpecificWarnings);4738</DisableSpecificWarnings> <!-- storing 32-bit float result in memory --> <DisableSpecificWarnings>%(DisableSpecificWarnings);4820</DisableSpecificWarnings> <!-- N bytes padding added --> <DisableSpecificWarnings>%(DisableSpecificWarnings);4866</DisableSpecificWarnings> <!-- compiler may not enforce ltr eval in operator[] --> <DisableSpecificWarnings>%(DisableSpecificWarnings);4868</DisableSpecificWarnings> <!-- compiler may not enforce ltr eval in initializer list --> <DisableSpecificWarnings>%(DisableSpecificWarnings);4946</DisableSpecificWarnings> <!-- reinterpret_cast used between related classes --> <DisableSpecificWarnings>%(DisableSpecificWarnings);5026</DisableSpecificWarnings> <!-- move constructor was implicitly defined as deleted --> <DisableSpecificWarnings>%(DisableSpecificWarnings);5027</DisableSpecificWarnings> <!-- move assignment operator was implicitly defined as deleted --> <DisableSpecificWarnings>%(DisableSpecificWarnings);5039</DisableSpecificWarnings> <!-- potentially throwing function passed to 'extern "C"' --> <DisableSpecificWarnings>%(DisableSpecificWarnings);5045</DisableSpecificWarnings> <!-- Compiler will insert Spectre mitigation --> </ClCompile> </ItemDefinitionGroup> <PropertyGroup> <LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory> </PropertyGroup> <ItemGroup> <ClCompile Include="..\conformance_burntsushi_invalid.cpp" /> <ClCompile Include="..\conformance_burntsushi_valid.cpp" /> <ClCompile Include="..\conformance_iarna_invalid.cpp" /> <ClCompile Include="..\conformance_iarna_valid.cpp" /> <ClCompile Include="..\impl_catch2.cpp"> <PrecompiledHeader>NotUsing</PrecompiledHeader> </ClCompile> <ClCompile Include="..\impl_toml.cpp"> <PrecompiledHeader>NotUsing</PrecompiledHeader> </ClCompile> <ClCompile Include="..\manipulating_arrays.cpp" /> <ClCompile Include="..\manipulating_tables.cpp" /> <ClCompile Include="..\manipulating_parse_result.cpp" /> <ClCompile Include="..\manipulating_values.cpp" /> <ClCompile Include="..\parsing_arrays.cpp" /> <ClCompile Include="..\parsing_booleans.cpp" /> <ClCompile Include="..\parsing_comments.cpp" /> <ClCompile Include="..\parsing_dates_and_times.cpp" /> <ClCompile Include="..\parsing_floats.cpp" /> <ClCompile Include="..\parsing_integers.cpp" /> <ClCompile Include="..\parsing_key_value_pairs.cpp" /> <ClCompile Include="..\parsing_spec_example.cpp" /> <ClCompile Include="..\parsing_strings.cpp" /> <ClCompile Include="..\parsing_tables.cpp" /> <ClCompile Include="..\tests.cpp"> <PrecompiledHeader>Create</PrecompiledHeader> </ClCompile> <ClCompile Include="..\unicode.cpp" /> <ClCompile Include="..\user_feedback.cpp" /> <ClCompile Include="..\using_iterators.cpp" /> <ClCompile Include="..\windows_compat.cpp" /> </ItemGroup> <ItemGroup> <Natvis Include="..\..\toml++.natvis" /> </ItemGroup> <ItemGroup> <ClInclude Include="..\catch2.h" /> <ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\settings.h" /> <ClInclude Include="..\tests.h" /> <ClInclude Include="..\tloptional.h" /> </ItemGroup> <ItemGroup> <None Include="..\cpp.hint" /> <None Include="..\meson.build" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> </Project> '''.strip().format( configuration=next(configuration_name(x) for x in mode if x in ('debug', 'release')), platform=next(platform_name(x) for x in mode if x in ('x64', 'x86')), uuid=str(uuid5(uuid_namespace, '_'.join(mode))).upper(), exceptions='false' if 'noexcept' in mode else 'Sync', unreleased_features=1 if 'unrel' in mode else 0, standard='cpplatest' if 'cpplatest' in mode else 'cpp17' ))