diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 0fb46d65d..add078413 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -151,6 +151,8 @@ if(GEN_FILES) COMMAND ${MBEDTLS_PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_ssl_debug_helpers.py + --mbedtls-root ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_ssl_debug_helpers.py ${error_headers} diff --git a/scripts/generate_ssl_debug_helpers.py b/scripts/generate_ssl_debug_helpers.py index 711bfd398..ad1f94997 100755 --- a/scripts/generate_ssl_debug_helpers.py +++ b/scripts/generate_ssl_debug_helpers.py @@ -25,8 +25,10 @@ import sys import re import os import textwrap +import argparse from mbedtls_dev import build_tree + def remove_c_comments(string): """ Remove C style comments from input string @@ -34,16 +36,19 @@ def remove_c_comments(string): string_pattern = r"(?P\".*?\"|\'.*?\')" comment_pattern = r"(?P/\*.*?\*/|//[^\r\n]*$)" pattern = re.compile(string_pattern + r'|' + comment_pattern, - re.MULTILINE|re.DOTALL) + re.MULTILINE | re.DOTALL) + def replacer(match): if match.lastgroup == 'comment': return "" return match.group() return pattern.sub(replacer, string) + class CondDirectiveNotMatch(Exception): pass + def preprocess_c_source_code(source, *classes): """ Simple preprocessor for C source code. @@ -124,7 +129,6 @@ def preprocess_c_source_code(source, *classes): assert not stack, len(stack) - class EnumDefinition: """ Generate helper functions around enumeration. @@ -153,7 +157,7 @@ class EnumDefinition: enum_pattern = re.compile(r'enum\s*(?P\w*)\s*' + r'{\s*(?P[^}]*)}' + r'\s*(?P\w*)\s*;', - re.MULTILINE|re.DOTALL) + re.MULTILINE | re.DOTALL) for match in enum_pattern.finditer(source_code, start, end): yield EnumDefinition(source_code, @@ -233,6 +237,7 @@ class EnumDefinition: prototype=self._prototype) return body, prototype + OUTPUT_C_TEMPLATE = '''\ /* Automatically generated by generate_ssl_debug_helpers.py. DO NOT EDIT. */ @@ -272,11 +277,11 @@ OUTPUT_H_TEMPLATE = '''\ ''' -def generate_ssl_debug_helpers(target_dir): +def generate_ssl_debug_helpers(output_directory, mbedtls_root): """ Generate functions of debug helps """ - with open('include/mbedtls/ssl.h') as f: + with open(os.path.join(mbedtls_root, 'include/mbedtls/ssl.h')) as f: source_code = remove_c_comments(f.read()) definitions = dict() @@ -292,19 +297,38 @@ def generate_ssl_debug_helpers(target_dir): definitions[start] = definition prototypes[start] = prototype - functions = [str(v) for _, v in sorted(definitions.items())] - with open(os.path.join(target_dir, 'ssl_debug_helpers_generated.c'), 'w') as f: - f.write(OUTPUT_C_TEMPLATE.format(functions='\n'.join(functions))) + function_definitions = [str(v) for _, v in sorted(definitions.items())] + function_prototypes = [str(v) for _, v in sorted(prototypes.items())] + if output_directory == sys.stdout: + sys.stdout.write(OUTPUT_H_TEMPLATE.format( + functions='\n'.join(function_prototypes))) + sys.stdout.write(OUTPUT_C_TEMPLATE.format( + functions='\n'.join(function_definitions))) + else: + with open(os.path.join(output_directory, 'ssl_debug_helpers_generated.c'), 'w') as f: + f.write(OUTPUT_C_TEMPLATE.format( + functions='\n'.join(function_definitions))) - functions = [str(v) for _, v in sorted(prototypes.items())] - with open(os.path.join(target_dir, 'ssl_debug_helpers_generated.h'), 'w') as f: - f.write(OUTPUT_H_TEMPLATE.format(functions='\n'.join(functions))) + with open(os.path.join(output_directory, 'ssl_debug_helpers_generated.h'), 'w') as f: + f.write(OUTPUT_H_TEMPLATE.format( + functions='\n'.join(function_prototypes))) +def main(): + """ + Command line entry + """ + parser = argparse.ArgumentParser() + parser.add_argument('--mbedtls-root', nargs='?', default=build_tree.guess_mbedtls_root(), + help='root directory of mbedtls source code') + parser.add_argument('output_directory', nargs='?', + default=sys.stdout, help='source/header files location') + args = parser.parse_args() + + generate_ssl_debug_helpers(args.output_directory, args.mbedtls_root) + return 0 if __name__ == '__main__': - build_tree.chdir_to_root() - OUTPUT_FILE_DIR = sys.argv[1] if len(sys.argv) == 2 else "library" - generate_ssl_debug_helpers(OUTPUT_FILE_DIR) + sys.exit(main()) diff --git a/scripts/mbedtls_dev/build_tree.py b/scripts/mbedtls_dev/build_tree.py index 772410473..aee68f140 100644 --- a/scripts/mbedtls_dev/build_tree.py +++ b/scripts/mbedtls_dev/build_tree.py @@ -17,12 +17,15 @@ # limitations under the License. import os +import inspect + def looks_like_mbedtls_root(path: str) -> bool: """Whether the given directory looks like the root of the Mbed TLS source tree.""" return all(os.path.isdir(os.path.join(path, subdir)) for subdir in ['include', 'library', 'programs', 'tests']) + def chdir_to_root() -> None: """Detect the root of the Mbed TLS source tree and change to it. @@ -36,3 +39,21 @@ def chdir_to_root() -> None: os.chdir(d) return raise Exception('Mbed TLS source tree not found') + + +def guess_mbedtls_root(): + """Guess mbedTLS source code directory. + + Return the first possible mbedTLS root directory + """ + dirs = set({}) + for i in inspect.stack(): + path = os.path.dirname(i.filename) + for d in ['.', os.path.pardir, os.path.join(*([os.path.pardir]*2))]: + d = os.path.abspath(os.path.join(path, d)) + if d in dirs: + continue + dirs.add(d) + if looks_like_mbedtls_root(d): + return d + raise Exception('Mbed TLS source tree not found')