blob: b978daa481cae04696fcf77ca05f0abb077973ee [file] [log] [blame]
#!/usr/bin/env python3
import re
import sys
from argparse import ArgumentParser
# This is a very dumb regex based method of translating from
# gn variable declarations and simple if statements to the
# equivalent cmake code. It only supports a few constructs and
# assumes the code is formatted a certain way. ANGLE gn files
# are auto-formatted so this should work most of the time.
# The output may need a bit of manual fixup, but it beats
# translating the whole thing by hand. If new constructs
# are added to the ANGLE gn files, hopefully we can just add
# a few extra regexes here.
parser = ArgumentParser(prog='gni-to-cmake', description='converts a .gni file to .cmake', usage='%(prog)s [options]')
parser.add_argument('gni', help='the .gni file to parse')
parser.add_argument('cmake', help='the .cmake file to output')
parser.add_argument('--prepend', default='', help='the path to prepend to each file name')
args = parser.parse_args()
with open(args.gni, 'r', encoding="utf-8") as gni:
file = gni.read()
# Prepend path to every string.
file = re.sub(r'"((\\\"|[^"])+)"', '"' + args.prepend + r'\1"', file)
# Remove import, assert, config, and angle_source_set statements.
file = re.sub(r'^\s*(import|assert|config|angle_source_set)\([^)]+\)( {.*})?$', r'', file, flags=re.MULTILINE|re.DOTALL)
# Translate gn single line list declaration:
file = re.sub(r'\[ ((?:"[^"]*",? )*)\]$', r' \1)', file, flags=re.MULTILINE)
# Translate gn single line list append:
file = re.sub(r'^(\s*)(\w+) \+= (\w+)$', r'\1 set(\2, "${\2};${\3}")', file, flags=re.MULTILINE)
# Translate gn list declaration:
# variable_name = [
# "file/name/foo.cpp",
# ]
# to cmake list declaration:
# set(variable_name
# "file/name/foo.cpp"
# )
file = re.sub(r'^(\s*)(\w+) = ?\[?', r'\1\1set(\2', file, flags=re.MULTILINE)
file = re.sub(r'^(\s*)("[^"]+"),$', r'\1\1\2', file, flags=re.MULTILINE)
file = re.sub(r'^(\s*)]$', r'\1\1)', file, flags=re.MULTILINE)
# Translate list append fom gn to cmake
file = re.sub(r'^(\s*)(\w+) \+= ?\[?', r'\1\1list(APPEND \2', file, flags=re.MULTILINE)
# Translate if statements from gn to cmake
file = re.sub(r'^(\s*)((?:} else )?)if \((.+)\) {$', r'\1\1\2if(\3)', file, flags=re.MULTILINE)
file = re.sub(r'^} else if$', r'elseif', file, flags=re.MULTILINE)
file = re.sub(r'^(\s*)} else {$', r'\1\1else()', file, flags=re.MULTILINE)
file = re.sub(r'^(\s*)}$', r'\1\1endif()', file, flags=re.MULTILINE)
# Translate logic ops from gn to cmake
file = re.sub(r' \|\| ', r' OR ', file, flags=re.MULTILINE)
file = re.sub(r' \&\& ', r' AND ', file, flags=re.MULTILINE)
file = re.sub(r' == ', r' STREQUAL ', file, flags=re.MULTILINE)
file = re.sub(r'!', r' NOT ', file, flags=re.MULTILINE)
with open(args.cmake, 'w', encoding="utf-8") as cmake:
cmake.write('# This file was generated with the command:\n')
cmake.write('# ' + ' '.join(['"' + arg.replace('"', '\\"') + '"' for arg in sys.argv]))
cmake.write('\n\n')
cmake.write(file)