blob: 8ad89408884128369ebb8d5502c922dd0a0850ac [file] [log] [blame]
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:])