| import getopt |
| import os |
| import re |
| import sys |
| from meson2python import meson2python |
| from jinja2 import Environment, FileSystemLoader |
| from pathlib import Path |
| |
| environment = Environment( |
| loader=FileSystemLoader(Path(__file__).parent.resolve() / 'templates/') |
| ) |
| generator_template = environment.get_template('generate_python_build.txt') |
| |
| |
| # Converts the given |file_name| from meson to python, and writes the python code |
| # to the given |file|. Code is indented by |output_indent|. When a subdir command |
| # is found, the meson.build build in that subdir is converted by recursively invoking |
| # this function. |
| def process_meson(file_name: str, output_indent: str = ''): |
| python_code = '' |
| python_code += ( |
| output_indent |
| + '########################################################################################################################' |
| ) |
| python_code += '\n' + output_indent + f'### Begin conversion from: {file_name}' |
| python_code += ( |
| '\n' |
| + output_indent |
| + '########################################################################################################################' |
| ) |
| |
| print('Processing: ' + file_name) |
| sys.stdout.flush() |
| |
| content = meson2python(file_name) |
| inside_literal = False |
| |
| for line in content.splitlines(): |
| # Remove line terminator |
| line = line.rstrip() |
| |
| # Check for multiline literals. |
| # We ignore literals that start and end on one line, though that may cause |
| # problems for the line processing below. |
| matches = re.findall(r"'''", line) |
| |
| literal_delimiter_count = len(matches) |
| |
| line_prefix = '' |
| line_suffix = '' |
| if literal_delimiter_count == 1: |
| inside_literal = not inside_literal |
| literal_line_split = line.split(r"'''") |
| if inside_literal: |
| line = literal_line_split[0] |
| line_suffix = r"'''" + literal_line_split[1] |
| else: |
| line_prefix = literal_line_split[0] + r"'''" |
| line = literal_line_split[1] |
| elif literal_delimiter_count == 0 or literal_delimiter_count == 2: |
| if inside_literal: |
| # Don't match anything while inside literal |
| line_prefix = line |
| line = '' |
| else: |
| exit('Unhandled literal in line: ' + line) |
| |
| # Recurse into subdirs |
| match = re.match("( *)subdir\('([a-zA-Z0-9_\-/]+)'\)", line) |
| if match is not None: |
| subdir_output_indent = match.group(1) + output_indent |
| current_dir = os.path.dirname(file_name) |
| next_dir = os.path.join(current_dir, match.group(2)) |
| next_file = os.path.join(next_dir, 'meson.build') |
| # Ensure the build definitions are aware of the changing directory |
| python_code += f"\n{subdir_output_indent}set_relative_dir('{next_dir}')" |
| python_code += '\n' + process_meson(next_file, subdir_output_indent) |
| python_code += f"\n{subdir_output_indent}set_relative_dir('{current_dir}')" |
| continue |
| |
| python_code += f'\n{output_indent + line_prefix + line + line_suffix}' |
| python_code += ( |
| '\n' |
| + output_indent |
| + '########################################################################################################################' |
| ) |
| python_code += '\n' + output_indent + f'### End conversion from: {file_name}' |
| python_code += ( |
| '\n' |
| + output_indent |
| + '########################################################################################################################' |
| ) |
| return python_code |
| |
| |
| def generate(target: str): |
| if not (target == 'android' or target == 'fuchsia'): |
| exit('Target must be android or fuchsia') |
| |
| output_file_name = 'generate_%s_build.py' % target |
| print('Writing to: ' + output_file_name) |
| |
| meson_options = process_meson('meson_options.txt') |
| meson_build = process_meson('meson.build') |
| content = generator_template.render( |
| meson_options=meson_options, |
| meson_build=meson_build, |
| ) |
| with open(output_file_name, 'w') as file: |
| file.write(content) |
| |
| |
| def usage(): |
| print('Usage: -t [android|fuchsia]') |
| sys.exit() |
| |
| |
| def main(argv): |
| target = 'android' |
| try: |
| opts, args = getopt.getopt( |
| argv, |
| 'ht:', |
| [ |
| 'help', |
| 'target=', |
| ], |
| ) |
| for opt, arg in opts: |
| if opt in ('-h', '--help'): |
| usage() |
| elif opt in ('-t', '--target'): |
| target = arg |
| except getopt.GetoptError as _: |
| usage() |
| |
| generate(target) |
| |
| |
| if __name__ == '__main__': |
| main(sys.argv[1:]) |