| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 | #!/usr/bin/env python3import osimport reimport datetimefrom scriptCommon import catchPathfrom releaseCommon import Versionroot_path = os.path.join(catchPath, 'src')starting_header = os.path.join(root_path, 'catch2', 'catch_all.hpp')output_header = os.path.join(catchPath, 'extras', 'catch_amalgamated.hpp')output_cpp = os.path.join(catchPath, 'extras', 'catch_amalgamated.cpp')# These are the copyright comments in each file, we want to ignore themcopyright_lines = ['//              Copyright Catch2 Authors\n','// Distributed under the Boost Software License, Version 1.0.\n','//   (See accompanying file LICENSE_1_0.txt or copy at\n','//        https://www.boost.org/LICENSE_1_0.txt)\n','// SPDX-License-Identifier: BSL-1.0\n',]# The header of the amalgamated file: copyright information + explanation# what this file is.file_header = '''\//              Copyright Catch2 Authors// Distributed under the Boost Software License, Version 1.0.//   (See accompanying file LICENSE_1_0.txt or copy at//        https://www.boost.org/LICENSE_1_0.txt)// SPDX-License-Identifier: BSL-1.0//  Catch v{version_string}//  Generated: {generation_time}//  ----------------------------------------------------------//  This file is an amalgamation of multiple different files.//  You probably shouldn't edit it directly.//  ----------------------------------------------------------'''# Returns file header with proper version string and generation timedef formatted_file_header(version):    return file_header.format(version_string=version.getVersionString(),                              generation_time=datetime.datetime.now())# Which headers were already concatenated (and thus should not be# processed again)concatenated_headers = set()internal_include_parser = re.compile(r'\s*#include <(catch2/.*)>.*')def concatenate_file(out, filename: str, expand_headers: bool) -> int:    # Gathers statistics on how many headers were expanded    concatenated = 1    with open(filename, mode='r', encoding='utf-8') as input:        for line in input:            if line in copyright_lines:                continue            m = internal_include_parser.match(line)            # anything that isn't a Catch2 header can just be copied to            # the resulting file            if not m:                out.write(line)                continue            # TBD: We can also strip out include guards from our own            # headers, but it wasn't worth the time at the time of writing            # this script.            # We do not want to expand headers for the cpp file            # amalgamation but neither do we want to copy them to output            if not expand_headers:                continue            next_header = m.group(1)            # We have to avoid re-expanding the same header over and            # over again, or the header will end up with couple            # hundred thousands lines (~300k as of preview3 :-) )            if next_header in concatenated_headers:                continue            # Skip including the auto-generated user config file,            # because it has not been generated yet at this point.            # The code around it should be written so that just not including            # it is equivalent with all-default user configuration.            if next_header == 'catch2/catch_user_config.hpp':                concatenated_headers.add(next_header)                continue            concatenated_headers.add(next_header)            concatenated += concatenate_file(out, os.path.join(root_path, next_header), expand_headers)    return concatenateddef generate_header():    with open(output_header, mode='w', encoding='utf-8') as header:        header.write(formatted_file_header(Version()))        header.write('#ifndef CATCH_AMALGAMATED_HPP_INCLUDED\n')        header.write('#define CATCH_AMALGAMATED_HPP_INCLUDED\n')        print('Concatenated {} headers'.format(concatenate_file(header, starting_header, True)))        header.write('#endif // CATCH_AMALGAMATED_HPP_INCLUDED\n')def generate_cpp():    from glob import glob    cpp_files = sorted(glob(os.path.join(root_path, 'catch2', '**/*.cpp'), recursive=True))    with open(output_cpp, mode='w', encoding='utf-8') as cpp:        cpp.write(formatted_file_header(Version()))        cpp.write('\n#include "catch_amalgamated.hpp"\n')        concatenate_file(cpp, os.path.join(root_path, 'catch2/internal/catch_windows_h_proxy.hpp'), False)        for file in cpp_files:            concatenate_file(cpp, file, False)    print('Concatenated {} cpp files'.format(len(cpp_files)))if __name__ == "__main__":    generate_header()    generate_cpp()# Notes:# * For .cpp files, internal includes have to be stripped and rewritten# * for .hpp files, internal includes have to be resolved and included# * The .cpp file needs to start with `#include "catch_amalgamated.hpp"# * include guards can be left/stripped, doesn't matter# * *.cpp files should be included sorted, to minimize diffs between versions# * *.hpp files should also be somehow sorted -> use catch_all.hpp as the# *       entrypoint# * allow disabling main in the .cpp amalgamation
 |