diff --git a/CMakeLists.txt b/CMakeLists.txt index 4807db5..df17dce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -190,7 +190,7 @@ if(SAFETYHOOK_AMALGAMATE) # amalgamate add_custom_command( OUTPUT ${AMALGAMATED_FILE} ${AMALGAMATED_HEADER} DEPENDS ${HEADER_FILES} ${SOURCE_FILES} ${AMALGAMATE_SCRIPT} - COMMAND ${Python3_EXECUTABLE} ${AMALGAMATE_SCRIPT} ${AMALGAMATED_FILE} ${AMALGAMATED_HEADER} + COMMAND ${Python3_EXECUTABLE} ${AMALGAMATE_SCRIPT} MAIN_DEPENDENCY ${AMALGAMATE_SCRIPT} COMMENT "Amalgamating" ) diff --git a/amalgamate.py b/amalgamate.py index 2f2b51c..2a705cf 100644 --- a/amalgamate.py +++ b/amalgamate.py @@ -4,9 +4,12 @@ from typing import List, Set from glob import glob from shutil import rmtree +from textwrap import dedent import os import re +import sys +import argparse SAFETYHOOK_ROOT = Path(__file__).resolve().parent PUBLIC_INCLUDE_PATHS = [ @@ -18,6 +21,10 @@ OUTPUT_DIR = SAFETYHOOK_ROOT / 'amalgamated-dist' FILE_HEADER = ['// DO NOT EDIT. This file is auto-generated by `amalgamate.py`.', ''] +parser = argparse.ArgumentParser(description='bundles cpp and hpp files together') +parser.add_argument('--polyfill', action='store_true', + help='replace std::except with a polyfill so it can be compiled on C++20 or older. https://raw.githubusercontent.com/TartanLlama/expected/master/include/tl/expected.hpp') + # Python versions before 3.10 don't have the root_dir argument for glob, so we # crudely emulate it here. @@ -155,7 +162,25 @@ def merge_sources(*, source_dir: Path, covered_headers: Set[Path]): return output +def do_polyfill(content): + return content.replace('#include ', + dedent(''' + #if __has_include("tl/expected.hpp") + #include "tl/expected.hpp" + #elif __has_include("expected.hpp") + #include "expected.hpp" + #else + #error "No polyfill found" + #endif + ''')) \ + .replace('std::expected', 'tl::expected') \ + .replace('std::unexpected', 'tl::unexpected') + + def main(): + args = parser.parse_args() + polyfill = args.polyfill is True + if OUTPUT_DIR.exists(): print('Output directory exists. Deleting.') rmtree(OUTPUT_DIR) @@ -164,20 +189,26 @@ def main(): covered_headers = set() with open(OUTPUT_DIR / 'safetyhook.hpp', 'w') as f: - f.write('\n'.join(FILE_HEADER + merge_headers( + content = '\n'.join(FILE_HEADER + merge_headers( header='safetyhook.hpp', search_paths=PUBLIC_INCLUDE_PATHS, covered_headers=covered_headers, stack=[], - ))) + )) + if polyfill: + content = do_polyfill(content) + f.write(content) print(covered_headers) with open(OUTPUT_DIR / 'safetyhook.cpp', 'w') as f: - f.write('\n'.join(FILE_HEADER + merge_sources( + content = '\n'.join(FILE_HEADER + merge_sources( source_dir=SAFETYHOOK_ROOT / 'src', covered_headers=covered_headers, - ))) + )) + if polyfill: + content = do_polyfill(content) + f.write(content) if __name__ == '__main__': diff --git a/cmake.toml b/cmake.toml index 70abb24..df17b9f 100644 --- a/cmake.toml +++ b/cmake.toml @@ -97,7 +97,7 @@ set(AMALGAMATE_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/amalgamate.py) add_custom_command( OUTPUT ${AMALGAMATED_FILE} ${AMALGAMATED_HEADER} DEPENDS ${HEADER_FILES} ${SOURCE_FILES} ${AMALGAMATE_SCRIPT} - COMMAND ${Python3_EXECUTABLE} ${AMALGAMATE_SCRIPT} ${AMALGAMATED_FILE} ${AMALGAMATED_HEADER} + COMMAND ${Python3_EXECUTABLE} ${AMALGAMATE_SCRIPT} MAIN_DEPENDENCY ${AMALGAMATE_SCRIPT} COMMENT "Amalgamating" )