• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import getopt
2import os
3import re
4import sys
5from meson2python import *
6
7
8# Converts the given |file_name| from meson to python, and writes the python code
9# to the given |file|.  Code is indented by |output_indent|.  When a subdir command
10# is found, the meson.build build in that subdir is converted by recursively invoking
11# this function.
12def process_meson(file, file_name: str, output_indent: str):
13  print(
14      output_indent
15      + '########################################################################################################################',
16      file=file,
17  )
18  print(output_indent + '### Begin conversion from: ' + file_name, file=file)
19  print(
20      output_indent
21      + '########################################################################################################################',
22      file=file,
23  )
24
25  print('Processing: ' + file_name)
26  sys.stdout.flush()
27
28  content = meson2python(file_name)
29
30  inside_literal = False
31
32  for line in content.splitlines():
33    # Remove line terminator
34    line = line.rstrip()
35
36    # Check for multiline literals.
37    # We ignore literals that start and end on one line, though that may cause
38    # problems for the line processing below.
39    matches = re.findall(r"'''", line)
40
41    literal_delimiter_count = len(matches)
42
43    line_prefix = ''
44    line_suffix = ''
45    if literal_delimiter_count == 1:
46      inside_literal = not inside_literal
47      literal_line_split = line.split(r"'''")
48      if inside_literal:
49        line = literal_line_split[0]
50        line_suffix = r"'''" + literal_line_split[1]
51      else:
52        line_prefix = literal_line_split[0] + r"'''"
53        line = literal_line_split[1]
54    elif literal_delimiter_count == 0 or literal_delimiter_count == 2:
55      if inside_literal:
56        # Don't match anything while inside literal
57        line_prefix = line
58        line = ''
59    else:
60      exit('Unhandled literal in line: ' + line)
61
62    # Recurse into subdirs
63    match = re.match("( *)subdir\('([a-zA-Z0-9_/]+)'\)", line)
64    if match != None:
65      subdir_output_indent = match.group(1) + output_indent
66      current_dir = os.path.dirname(file_name)
67      next_dir = os.path.join(current_dir, match.group(2))
68      next_file = os.path.join(next_dir, 'meson.build')
69      # Ensure the build definitions are aware of the changing directory
70      print(
71          subdir_output_indent + "set_relative_dir('%s')" % next_dir, file=file
72      )
73      process_meson(file, next_file, subdir_output_indent)
74      print(
75          subdir_output_indent + "set_relative_dir('%s')" % current_dir,
76          file=file,
77      )
78      continue
79
80    print(output_indent + line_prefix + line + line_suffix, file=file)
81
82  print(
83      output_indent
84      + '########################################################################################################################',
85      file=file,
86  )
87  print(output_indent + '### End conversion from: ' + file_name, file=file)
88  print(
89      output_indent
90      + '########################################################################################################################',
91      file=file,
92  )
93
94
95def generate(target: str):
96  if not (target == 'android' or target == 'fuchsia'):
97    exit('Target must be android or fuchsia')
98
99  output_file_name = 'generate_%s_build.py' % target
100  print('Writing to: ' + output_file_name)
101
102  with open(output_file_name, 'w') as file:
103    print('import sys', file=file)
104    print('###', file=file)
105    print(
106        '########################################################################################################################',
107        file=file,
108    )
109    print('###', file=file)
110    print('### Pull in the definitions meson is expecting', file=file)
111    print('###', file=file)
112    print('from meson_common import *', file=file)
113    print('from meson_%s import *' % target, file=file)
114    print('###', file=file)
115    print(
116        '########################################################################################################################',
117        file=file,
118    )
119    print('', file=file)
120
121    print('### Open the build definition file', file=file)
122    print('open_output_file()', file=file)
123
124    process_meson(file, 'meson_options.txt', output_indent='')
125
126    print('###', file=file)
127    print('### Process command line arguments for setting options', file=file)
128    print('if __name__ == "__main__":', file=file)
129    print('  for arg in sys.argv[1:]:', file=file)
130    print(
131        '    match = re.match(r"-D([a-zA-Z0-9-]+)=([a-zA-Z0-9-]*)", arg)',
132        file=file,
133    )
134    print('    if not match:', file=file)
135    print(
136        '      exit("Invalid arg: %s should be -Doption=value" % arg)',
137        file=file,
138    )
139    print('    set_option(match.group(1), match.group(2))', file=file)
140    print('###', file=file)
141
142    print('### These definitions must be inside the module', file=file)
143    print('def get_variable(name: str):', file=file)
144    print('  return globals()[name]', file=file)
145    print('', file=file)
146
147    print('### Load config', file=file)
148    print('load_config_file()', file=file)
149    print('', file=file)
150
151    process_meson(file, 'meson.build', output_indent='')
152
153    print('### Close the build definition file', file=file)
154    print('close_output_file()', file=file)
155
156    file.close()
157
158
159def usage():
160  print('Usage: -t [android|fuchsia]')
161  sys.exit()
162
163
164def main(argv):
165  target = 'android'
166  try:
167    opts, args = getopt.getopt(
168        argv,
169        'ht:',
170        [
171            'help',
172            'target=',
173        ],
174    )
175    for opt, arg in opts:
176      if opt in ('-h', '--help'):
177        usage()
178      elif opt in ('-t', '--target'):
179        target = arg
180  except getopt.GetoptError as err:
181    usage()
182
183  generate(target)
184
185
186if __name__ == '__main__':
187  main(sys.argv[1:])
188