mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-11-04 00:51:52 +01:00 
			
		
		
		
	This commits also adds a script that does the amalgamation of headers and .cpp files into the distributable version, removes the old `generateSingleHeader` script, and also adds a very simple compilation test for the amalgamated distribution.
		
			
				
	
	
		
			120 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/env python3
 | 
						|
 | 
						|
import os
 | 
						|
import re
 | 
						|
import datetime
 | 
						|
 | 
						|
from scriptCommon import catchPath
 | 
						|
from releaseCommon import Version
 | 
						|
 | 
						|
root_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 them
 | 
						|
copyright_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 time
 | 
						|
def 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
 | 
						|
            concatenated_headers.add(next_header)
 | 
						|
            concatenated += concatenate_file(out, os.path.join(root_path, next_header), expand_headers)
 | 
						|
 | 
						|
    return concatenated
 | 
						|
 | 
						|
 | 
						|
def 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')
 | 
						|
        for file in cpp_files:
 | 
						|
            concatenate_file(cpp, file, False)
 | 
						|
    print('Concatenated {} cpp files'.format(len(cpp_files)))
 | 
						|
 | 
						|
 | 
						|
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
 |