Skip to content

Instantly share code, notes, and snippets.

@yashi
Created September 24, 2018 12:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yashi/f3fbf2fc2062486f60211296324c5f2b to your computer and use it in GitHub Desktop.
Save yashi/f3fbf2fc2062486f60211296324c5f2b to your computer and use it in GitHub Desktop.
compiler driver for zephyr
#!/usr/bin/env python3
import os
import sys
import re
import subprocess
import argparse
import unittest
compiler_options = [
('-Os', '-O2', ), # optimize for speed
('-g', '-g', ), # enable debug
('-E', '--preproc_only', ),
('-o', '--output_file', True),
('-x', None, True),
('-P', ),
('-MF', None, True),
('-MD', ),
('-MT', None, True),
('-Wl,--whole-archive', ),
('-Wl,--no-whole-archive', ),
('-Wl,-Map', None, True),
('-T', ),
# warnings
('-Wall', ),
('-Werror=implicit-int', ),
('-Wformat', ),
('-Wformat-security', ),
('-Wno-format-zero-length', ),
('-Wno-main', ),
('-Wno-pointer-sign', ),
('-Wno-unused-but-set-variable', ),
# optimizations
('-fdata-sections', ),
('-ffreestanding', ),
('-ffunction-sections', ),
('-fno-asynchronous-unwind-tables', ),
('-fno-defer-pop', ),
('-fno-pic', ),
('-fno-pie', ),
('-fno-reorder-functions', ),
('-fno-strict-overflow', ),
('-fno-strict-overview', ),
('-imacros', '--preinclude', True),
# misc
('-mabi=aapcs', ),
('-mbig-endian', ),
('-std=c99', '--c99', ),
('-xassembler-with-cpp', ),
]
def iterfixed(seq, times, defaultitem=None):
for i in range(times):
if i < len(seq):
yield seq[i]
else:
yield defaultitem
class Translator:
class TranslationTemplate:
def __init__(self, original, translated=None, has_arg=None):
self.original = original
self.translated = translated
self.has_arg = has_arg
def __repr__(self):
return "({}, {}, {})".format(self.original, self.translated, self.has_arg)
def __init__(self):
self.table = {}
self.parser = argparse.ArgumentParser(allow_abbrev=False)
self.parsed = False
def __repr__(self):
ret = "<{} at {}".format(type(self).__qualname__, hex(id(self)))
if self.parsed:
ret += " parsed"
if not self.table:
ret += " ()"
else:
ret += "\n"
for value in self.table.values():
ret = ret + " " + repr(value) + "\n"
ret += ">"
return ret
def add(self, trans):
if type(trans) is not tuple:
raise TypeError
original, translated, has_arg = iterfixed(trans, 3)
temp = self.TranslationTemplate(original, translated, has_arg)
self.table[temp.original] = temp
if has_arg:
self.parser.add_argument(original, help=argparse.SUPPRESS, nargs=1)
else:
self.parser.add_argument(
original, help=argparse.SUPPRESS, action='store_true')
def learn(self, trans):
for t in trans:
self.add(t)
def parse(self, argv=None):
args, self.unknown = self.parser.parse_known_args(None)
self.given = {k: v for k, v in vars(args).items() if v}
self.parsed = True
def translate(self):
def translate_1(_arg):
# let's try single hypen first
# hypen is converted to underscore in argparse
# convert it back
arg = "-" + _arg.replace('_', '-')
if arg in self.table:
opt = self.table[arg].translated
if opt and self.table[arg].has_arg:
param = self.given[_arg]
if param:
return [opt] + param
else:
return opt
#return opt.join(param)
else:
return opt
else:
print(f"!!!!! oops: {arg} is not in translation table")
return arg
def flatten(seq):
l = []
for x in seq:
if isinstance(x, list):
for y in x:
l.append(y)
else:
l.append(x)
return l
if not self.parsed:
self.parse(None)
return [flatten(filter(None, map(translate_1, self.given))), self.unknown]
class MyTest(unittest.TestCase):
def test_parse_simple_flag(self):
translator = Translator()
translator.learn(compiler_options)
translator.parse("-Os".split())
self.assertEqual(translator.given, {'Os': True})
def test_parse_equal_and_arg(self):
translator = Translator()
translator.learn(compiler_options)
translator.parse("-Werror=implicit-int".split())
self.assertEqual(translator.given, {'Werror=implicit_int': True})
def test_translate(self):
translator = Translator()
translator.learn(compiler_options)
translator.parse("-Os".split())
argv, _ = translator.translate()
self.assertEqual(argv, ["-O2"])
def test_translate_multi(self):
translator = Translator()
translator.learn(compiler_options)
translator.parse("-Os -g".split())
argv, _ = translator.translate()
self.assertEqual(argv, ["-O2", "-g"])
def test_translate_hypen(self):
translator = Translator()
translator.learn(compiler_options)
translator.parse("-Werror=implicit-int".split())
argv, _ = translator.translate()
self.assertEqual(argv, [])
def convert_unknown(args):
pat = re.compile(r"-L(.+)")
def l_to_search_path(s, pat):
if pat.match(s):
return s.replace('-L', '--search_path=')
else:
return s
return [l_to_search_path(x, pat) for x in args]
def main():
compiler = os.path.join(os.environ['CGT_ROOT_DIR'], "bin/armcl")
translator = Translator()
translator.learn(compiler_options)
argv, unknown = translator.translate()
converted_unknown = convert_unknown(unknown)
cmd = [compiler] + argv + converted_unknown
ret = subprocess.run(cmd)
sys.exit(ret.returncode)
if __name__ == '__main__':
main()
else:
#suite = unittest.TestLoader().loadTestsFromName('test_translate_with_prog', MyTest)
suite = unittest.TestLoader().loadTestsFromTestCase(MyTest)
unittest.TextTestRunner(verbosity=3).run(suite)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment