diff options
Diffstat (limited to 'wscript')
-rwxr-xr-x | wscript | 647 |
1 files changed, 337 insertions, 310 deletions
@@ -3,7 +3,7 @@ # SPDX-License-Identifier: BSD-2-Clause # # Copyright (C) 2020 Hesham Almatary <Hesham.Almatary@cl.cam.ac.uk> -# Copyright (C) 2019, 2020 embedded brains GmbH (http://www.embedded-brains.de) +# Copyright (C) 2019, 2020 embedded brains GmbH & Co. KG # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -43,7 +43,13 @@ except: from waflib.TaskGen import after, before_method, feature is_windows_host = os.name == "nt" or sys.platform in ["msys", "cygwin"] -default_prefix = "/opt/rtems/6" +version = { + "__RTEMS_MAJOR__": "6", + "__RTEMS_MINOR__": "0", + "__RTEMS_REVISION__": "0", + "RTEMS_VERSION_CONTROL_KEY": "git" +} +default_prefix = "/opt/rtems/" + version["__RTEMS_MAJOR__"] compilers = ["gcc", "clang"] items = {} bsps = {} @@ -62,25 +68,28 @@ class VersionControlKeyHeader: @staticmethod def write(bld, filename): - if VersionControlKeyHeader._content is None: - from waflib.Build import Context - from waflib.Errors import WafError - + content = VersionControlKeyHeader._content + if content is None: content = """/* * Automatically generated. Do not edit. */ #if !defined(_RTEMS_VERSION_VC_KEY_H_) #define _RTEMS_VERSION_VC_KEY_H_ """ - try: - rev = bld.cmd_and_log( - "git rev-parse HEAD", quiet=Context.STDOUT - ).strip() - content += """#define RTEMS_VERSION_VC_KEY "{}" -""".format( - rev - ) - except WafError: + key = bld.env.RTEMS_VERSION_CONTROL_KEY + if key == "git": + from waflib.Build import Context + from waflib.Errors import WafError + + try: + key = bld.cmd_and_log("git rev-parse HEAD", + quiet=Context.STDOUT).strip() + except WafError: + key = "" + if key: + content += """#define RTEMS_VERSION_CONTROL_KEY "{}" +""".format(key) + else: content += """/* No version control key found; release? */ """ content += """#endif @@ -90,12 +99,13 @@ class VersionControlKeyHeader: f.parent.mkdir() try: if content != f.read(): - f.write(VersionControlKeyHeader._content) + f.write(content) except: - f.write(VersionControlKeyHeader._content) + f.write(content) class EnvWrapper(object): + def __init__(self, env): self._env = env @@ -112,7 +122,10 @@ class EnvWrapper(object): class Template(string.Template): - idpattern = "[_a-z][_a-z0-9:#]*" + idpattern = "[_A-Za-z][_A-Za-z0-9:#]*" + + +_VAR_PATTERN = re.compile("\\$\\{?(" + Template.idpattern + ")\\}?$") def _is_enabled_op_and(enabled, enabled_by): @@ -152,9 +165,8 @@ def _is_enabled(enabled, enabled_by): def _asm_explicit_target(self, node): - task = self.create_task( - "asm", node, self.bld.bldnode.make_node(self.target) - ) + task = self.create_task("asm", node, + self.bld.bldnode.make_node(self.target)) try: self.compiled_tasks.append(task) except AttributeError: @@ -176,7 +188,17 @@ def process_start_files(self): self.link_task.dep_nodes.extend(self.bld.start_files) +def make_tar_info_reproducible(info): + info.uid = 0 + info.gid = 0 + info.mtime = 0 + info.uname = "root" + info.gname = "root" + return info + + class Item(object): + def __init__(self, uid, data): self.uid = uid self.data = data @@ -189,8 +211,7 @@ class Item(object): uid = link["uid"] if not os.path.isabs(uid): uid = os.path.normpath( - os.path.join(os.path.dirname(self.uid), uid) - ) + os.path.join(os.path.dirname(self.uid), uid)) self._links.append(items[uid]) self.links = self._yield_links for link in self._links: @@ -203,27 +224,36 @@ class Item(object): def get_enabled_by(self): return self.data["enabled-by"] - def defaults(self, enable, variant, family): - if _is_enabled(enable, self.get_enabled_by()): + def defaults(self, enabled): + if _is_enabled(enabled, self.get_enabled_by()): for p in self.links(): - p.defaults(enable, variant, family) - self.do_defaults(variant, family) + p.defaults(enabled) + self.do_defaults(enabled) def configure(self, conf, cic): if _is_enabled(conf.env.ENABLE, self.get_enabled_by()): self.prepare_configure(conf, cic) for p in self.links(): p.configure(conf, cic) - self.do_configure(conf, cic) + try: + self.do_configure(conf, cic) + except Exception as e: + raise type(e)( + "Configuration error related to item spec:{}: {}".format( + self.uid, str(e))) def build(self, bld, bic): if _is_enabled(bld.env.ENABLE, self.get_enabled_by()): bic = self.prepare_build(bld, bic) for p in self.links(): p.build(bld, bic) - self.do_build(bld, bic) + try: + self.do_build(bld, bic) + except Exception as e: + raise type(e)("Build error related to item spec:{}: {}".format( + self.uid, str(e))) - def do_defaults(self, variant, family): + def do_defaults(self, enabled): return def prepare_configure(self, conf, cic): @@ -245,22 +275,24 @@ class Item(object): except Exception as e: ctx.fatal( "In item '{}' substitution in '{}' failed: {}".format( - self.uid, value, e - ) - ) + self.uid, value, e)) if isinstance(value, list): - return [self.substitute(ctx, subvalue) for subvalue in value] + more = [] + for item in value: + if isinstance(item, str): + m = _VAR_PATTERN.match(item) + else: + m = None + if m: + more.extend(ctx.env[m.group(1).strip("{}")]) + else: + more.append(self.substitute(ctx, item)) + return more return value def get(self, ctx, name): return self.substitute(ctx, self.data[name]) - def get_values(self, ctx, name): - more = [] - for value in self.data[name]: - more.extend(self.substitute(ctx, value).split()) - return more - def install_target(self, bld): install_path = self.data["install-path"] if install_path: @@ -275,9 +307,11 @@ class Item(object): target = os.path.splitext(source)[0] + ".o" bld( asflags=self.substitute(bld, self.data["asflags"]), - cppflags=self.substitute(bld, self.data["cppflags"]), + cppflags=bic.cppflags + + self.substitute(bld, self.data["cppflags"]), features="asm_explicit_target asm c", - includes=bic.includes + self.substitute(bld, self.data["includes"]), + includes=bic.includes + + self.substitute(bld, self.data["includes"]), source=[source], target=target, ) @@ -287,11 +321,14 @@ class Item(object): if target is None: target = os.path.splitext(source)[0] + ".o" bld( - cflags=self.substitute(bld, self.data["cflags"]), - cppflags=cppflags + self.substitute(bld, self.data["cppflags"]), + cflags=bic.cflags + self.substitute(bld, self.data["cflags"]), + cppflags=bic.cppflags + cppflags + + self.substitute(bld, self.data["cppflags"]), features="c", - includes=bic.includes + self.substitute(bld, self.data["includes"]), - rule="${CC} ${CFLAGS} ${CPPFLAGS} ${DEFINES_ST:DEFINES} ${CPPPATH_ST:INCPATHS} -c ${SRC[0]} -o ${TGT}", + includes=bic.includes + + self.substitute(bld, self.data["includes"]), + rule= + "${CC} ${CFLAGS} ${CPPFLAGS} ${DEFINES_ST:DEFINES} ${CPPPATH_ST:INCPATHS} -c ${SRC[0]} -o ${TGT}", source=[source] + deps, target=target, ) @@ -301,11 +338,15 @@ class Item(object): if target is None: target = os.path.splitext(source)[0] + ".o" bld( - cppflags=cppflags + self.substitute(bld, self.data["cppflags"]), - cxxflags=self.substitute(bld, self.data["cxxflags"]), + cppflags=bic.cppflags + cppflags + + self.substitute(bld, self.data["cppflags"]), + cxxflags=bic.cxxflags + + self.substitute(bld, self.data["cxxflags"]), features="cxx", - includes=bic.includes + self.substitute(bld, self.data["includes"]), - rule="${CXX} ${CXXFLAGS} ${CPPFLAGS} ${DEFINES_ST:DEFINES} ${CPPPATH_ST:INCPATHS} -c ${SRC[0]} -o ${TGT}", + includes=bic.includes + + self.substitute(bld, self.data["includes"]), + rule= + "${CXX} ${CXXFLAGS} ${CPPFLAGS} ${DEFINES_ST:DEFINES} ${CPPPATH_ST:INCPATHS} -c ${SRC[0]} -o ${TGT}", source=[source] + deps, target=target, ) @@ -315,14 +356,14 @@ class Item(object): from waflib.Task import Task class link(Task): - def __init__(self, item, bic, cmd, env): + + def __init__(self, item, bic, cmd, env, ldflags): super(link, self).__init__(self, env=env) self.cmd = cmd - self.ldflags = bic.ldflags + item.data["ldflags"] + self.ldflags = ldflags self.stlib = item.data["stlib"] - self.use = ( - item.data["use-before"] + bic.use + item.data["use-after"] - ) + self.use = (item.data["use-before"] + bic.use + + item.data["use-after"]) def run(self): cmd = [self.cmd] @@ -345,7 +386,8 @@ class Item(object): [], ) - tsk = link(self, bic, cmd, bld.env) + tsk = link(self, bic, cmd, bld.env, + bic.ldflags + self.substitute(bld, self.data["ldflags"])) tsk.set_inputs([bld.bldnode.make_node(s) for s in source]) tsk.set_outputs(bld.bldnode.make_node(target)) bld.add_to_group(tsk) @@ -361,6 +403,7 @@ class Item(object): from waflib.Task import Task class gnatmake(Task): + def __init__(self, bld, bic, objdir, objs, main, target, item): super(gnatmake, self).__init__(self, env=bld.env) self.objdir = objdir @@ -375,9 +418,8 @@ class Item(object): self.adaincludes.append(bld.path.make_node(i)) self.ldflags = bic.ldflags + item.data["ldflags"] self.stlib = item.data["stlib"] - self.use = ( - item.data["use-before"] + bic.use + item.data["use-after"] - ) + self.use = (item.data["use-before"] + bic.use + + item.data["use-after"]) def run(self): cwd = self.get_cwd() @@ -421,12 +463,14 @@ class Item(object): return target def ar(self, bld, source, target): - bld(rule="${AR} ${ARFLAGS} ${TGT} ${SRC}", source=source, target=target) + bld(rule="${AR} ${ARFLAGS} ${TGT} ${SRC}", + source=source, + target=target) return target def gzip(self, bld, source): target = source + ".gz" - bld(rule="${GZIP} < ${SRC} > ${TGT}", source=source, target=target) + bld(rule="${GZIP} -n < ${SRC} > ${TGT}", source=source, target=target) return target def xz(self, bld, source): @@ -435,12 +479,13 @@ class Item(object): return target def tar(self, bld, source, remove, target): + def run(task): import tarfile - tar = tarfile.TarFile( - task.outputs[0].abspath(), "w", format=tarfile.USTAR_FORMAT - ) + tar = tarfile.TarFile(task.outputs[0].abspath(), + "w", + format=tarfile.USTAR_FORMAT) srcpath = bld.path.abspath() + "/" bldpath = bld.bldnode.abspath() + "/" for src in task.inputs: @@ -448,7 +493,7 @@ class Item(object): dst = src for r in remove: dst = src.replace(srcpath + r, "").replace(bldpath + r, "") - tar.add(src, dst) + tar.add(src, dst, filter=make_tar_info_reproducible) tar.close() return 0 @@ -456,6 +501,7 @@ class Item(object): return target def bin2c(self, bld, source, name=None, target=None): + def run(task): cmd = [bld.env.BIN2C[0]] if name is not None: @@ -481,6 +527,7 @@ class Item(object): return target def rtems_rap(self, bld, base, objects, libs, target): + def run(task): cmd = [ bld.env.RTEMS_LD[0], @@ -507,14 +554,18 @@ class Item(object): class GroupItem(Item): + def __init__(self, uid, data): super(GroupItem, self).__init__(uid, data) def prepare_build(self, bld, bic): return BuildItemContext( - bic.includes + self.get_values(bld, "includes"), + bic.includes + self.substitute(bld, self.data["includes"]), + bic.cppflags + self.substitute(bld, self.data["cppflags"]), + bic.cflags + self.substitute(bld, self.data["cflags"]), + bic.cxxflags + self.substitute(bld, self.data["cxxflags"]), self.data["use-before"] + bic.use + self.data["use-after"], - bic.ldflags + self.get_values(bld, "ldflags"), + bic.ldflags + self.substitute(bld, self.data["ldflags"]), bic.objects, ) @@ -523,14 +574,14 @@ class GroupItem(Item): class ConfigFileItem(Item): + def __init__(self, uid, data): super(ConfigFileItem, self).__init__(uid, data) def do_configure(self, conf, cic): content = self.substitute(conf, self.data["content"]) - f = conf.bldnode.make_node( - conf.env.VARIANT + "/" + self.get(conf, "target") - ) + f = conf.bldnode.make_node(conf.env.VARIANT + "/" + + self.get(conf, "target")) f.parent.mkdir() f.write(content) conf.env.append_value("cfg_files", f.abspath()) @@ -540,6 +591,7 @@ class ConfigFileItem(Item): class ConfigHeaderItem(Item): + def __init__(self, uid, data): super(ConfigHeaderItem, self).__init__(uid, data) @@ -557,6 +609,7 @@ class ConfigHeaderItem(Item): class StartFileItem(Item): + def __init__(self, uid, data): super(StartFileItem, self).__init__(uid, data) @@ -575,16 +628,28 @@ class StartFileItem(Item): class ObjectsItem(Item): + def __init__(self, uid, data): super(ObjectsItem, self).__init__(uid, data) + def prepare_build(self, bld, bic): + return BuildItemContext( + bic.includes + self.substitute(bld, self.data["includes"]), + bic.cppflags + self.substitute(bld, self.data["cppflags"]), + bic.cflags + self.substitute(bld, self.data["cflags"]), + bic.cxxflags + self.substitute(bld, self.data["cxxflags"]), + bic.use, + bic.ldflags, + bic.objects, + ) + def do_build(self, bld, bic): bld.objects( - asflags=self.substitute(bld, self.data["cppflags"]), - cflags=self.substitute(bld, self.data["cflags"]), - cppflags=self.substitute(bld, self.data["cppflags"]), - cxxflags=self.substitute(bld, self.data["cxxflags"]), - includes=bic.includes + self.substitute(bld, self.data["includes"]), + asflags=bic.cppflags, + cflags=bic.cflags, + cppflags=bic.cppflags, + cxxflags=bic.cxxflags, + includes=bic.includes, source=self.data["source"], target=self.uid, ) @@ -593,6 +658,7 @@ class ObjectsItem(Item): class BSPItem(Item): + def __init__(self, uid, data): super(BSPItem, self).__init__(uid, data) arch_bsps = bsps.setdefault(data["arch"].strip(), {}) @@ -600,15 +666,22 @@ class BSPItem(Item): def prepare_build(self, bld, bic): return BuildItemContext( - bic.includes + bld.env.BSP_INCLUDES.split(), [], [], [] + bic.includes + bld.env.BSP_INCLUDES + + self.substitute(bld, self.data["includes"]), + self.substitute(bld, self.data["cppflags"]), + bld.env.BSP_CFLAGS + self.substitute(bld, self.data["cflags"]), + [], + [], + [], + [], ) def do_build(self, bld, bic): bld( - cflags=self.substitute(bld, self.data["cflags"]), - cppflags=self.substitute(bld, self.data["cppflags"]), + cflags=bic.cflags, + cppflags=bic.cppflags, features="c cstlib", - includes=bic.includes + self.substitute(bld, self.data["includes"]), + includes=bic.includes, install_path="${BSP_LIBDIR}", source=self.data["source"], target="rtemsbsp", @@ -618,19 +691,28 @@ class BSPItem(Item): class LibraryItem(Item): + def __init__(self, uid, data): super(LibraryItem, self).__init__(uid, data) def prepare_build(self, bld, bic): - return BuildItemContext(bic.includes, [], [], []) + return BuildItemContext( + bic.includes + self.substitute(bld, self.data["includes"]), + bic.cppflags + self.substitute(bld, self.data["cppflags"]), + bic.cflags + self.substitute(bld, self.data["cflags"]), + bic.cxxflags + self.substitute(bld, self.data["cxxflags"]), + bic.use, + bic.ldflags, + [], + ) def do_build(self, bld, bic): bld( - cflags=self.substitute(bld, self.data["cflags"]), - cppflags=self.substitute(bld, self.data["cppflags"]), - cxxflags=self.substitute(bld, self.data["cxxflags"]), + cflags=bic.cflags, + cppflags=bic.cppflags, + cxxflags=bic.cxxflags, features="c cxx cstlib", - includes=bic.includes + self.substitute(bld, self.data["includes"]), + includes=bic.includes, install_path=self.data["install-path"], source=self.data["source"], target=self.get(bld, "target"), @@ -640,6 +722,7 @@ class LibraryItem(Item): class TestProgramItem(Item): + def __init__(self, uid, data): super(TestProgramItem, self).__init__(uid, data) name = uid.split("/")[-1].upper().replace("-", "_") @@ -650,26 +733,36 @@ class TestProgramItem(Item): return [{"and": [{"not": self.exclude}, self.data["enabled-by"]]}] def prepare_build(self, bld, bic): - return BuildItemContext(bic.includes, bic.use, bic.ldflags, []) + return BuildItemContext( + bic.includes + self.substitute(bld, self.data["includes"]), + bic.cppflags + bld.env[self.cppflags] + + self.substitute(bld, self.data["cppflags"]), + bic.cflags + self.substitute(bld, self.data["cflags"]), + bic.cxxflags + self.substitute(bld, self.data["cxxflags"]), + self.data["use-before"] + bic.use + self.data["use-after"], + bic.ldflags + self.substitute(bld, self.data["ldflags"]), + [], + ) def do_build(self, bld, bic): bld( - cflags=self.substitute(bld, self.data["cflags"]), - cppflags=bld.env[self.cppflags] + self.substitute(bld, self.data["cppflags"]), - cxxflags=self.substitute(bld, self.data["cxxflags"]), + cflags=bic.cflags, + cppflags=bic.cppflags, + cxxflags=bic.cxxflags, features=self.data["features"], - includes=bic.includes + self.substitute(bld, self.data["includes"]), + includes=bic.includes, install_path=None, - ldflags=bic.ldflags + self.substitute(bld, self.data["ldflags"]), + ldflags=bic.ldflags, source=self.data["source"], start_files=True, stlib=self.data["stlib"], target=self.get(bld, "target"), - use=bic.objects + self.data["use-before"] + bic.use + self.data["use-after"], + use=bic.objects + bic.use, ) class AdaTestProgramItem(TestProgramItem): + def __init__(self, uid, data): super(AdaTestProgramItem, self).__init__(uid, data) @@ -688,28 +781,16 @@ class AdaTestProgramItem(TestProgramItem): class OptionItem(Item): + def __init__(self, uid, data): super(OptionItem, self).__init__(uid, data) - @staticmethod - def _is_variant(variants, variant): - for pattern in variants: - if re.match(pattern + "$", variant): - return True - return False - - def default_value(self, variant, family): - value = self.data["default"] - for default in self.data["default-by-variant"]: - if OptionItem._is_variant(default["variants"], variant): + def default_value(self, enabled): + value = None + for default in self.data["default"]: + if _is_enabled(enabled, default["enabled-by"]): value = default["value"] break - else: - family = "bsps/" + family - for default in self.data["default-by-variant"]: - if OptionItem._is_variant(default["variants"], family): - value = default["value"] - break if value is None: return value if isinstance(value, list): @@ -718,8 +799,8 @@ class OptionItem(Item): return value return self.data["format"].format(value) - def do_defaults(self, variant, family): - value = self.default_value(variant, family) + def do_defaults(self, enabled): + value = self.default_value(enabled) if value is None: return description = self.data["description"] @@ -736,56 +817,51 @@ class OptionItem(Item): def _do_append_test_cppflags(self, conf, name, state): conf.env.append_value( - "TEST_" + name.upper().replace("-", "_") + "_CPPFLAGS", state - ) + "TEST_" + name.upper().replace("-", "_") + "_CPPFLAGS", state) def _append_test_cppflags(self, conf, cic, value, arg): self._do_append_test_cppflags(conf, arg, value) return value def _assert_aligned(self, conf, cic, value, arg): - if value % arg != 0: + if value is not None and value % arg != 0: conf.fatal( "Value '{}' for option '{}' is not aligned by '{}'".format( - value, self.data["name"], arg - ) - ) + value, self.data["name"], arg)) return value def _assert_eq(self, conf, cic, value, arg): - if value != arg: - conf.fatal( - "Value '{}' for option '{}' is not equal to {}".format( - value, self.data["name"], arg - ) - ) + if value is not None and value != arg: + conf.fatal("Value '{}' for option '{}' is not equal to {}".format( + value, self.data["name"], arg)) return value def _assert_ge(self, conf, cic, value, arg): - if value < arg: + if value is not None and value < arg: conf.fatal( - "Value '{}' for option '{}' is not greater than or equal to {}".format( - value, self.data["name"], arg - ) - ) + "Value '{}' for option '{}' is not greater than or equal to {}" + .format(value, self.data["name"], arg)) return value def _assert_gt(self, conf, cic, value, arg): - if value <= arg: + if value is not None and value <= arg: conf.fatal( "Value '{}' for option '{}' is not greater than {}".format( - value, self.data["name"], arg - ) - ) + value, self.data["name"], arg)) + return value + + def _assert_in_set(self, conf, cic, value, arg): + if value is not None and value not in arg: + conf.fatal( + "Value '{}' for option '{}' is not an element of {}" + .format(value, self.data["name"], arg)) return value def _assert_in_interval(self, conf, cic, value, arg): - if value < arg[0] or value > arg[1]: + if value is not None and (value < arg[0] or value > arg[1]): conf.fatal( - "Value '{}' for option '{}' is not in closed interval [{}, {}]".format( - value, self.data["name"], arg[0], arg[1] - ) - ) + "Value '{}' for option '{}' is not in closed interval [{}, {}]" + .format(value, self.data["name"], arg[0], arg[1])) return value def _assert_int8(self, conf, cic, value, arg): @@ -795,49 +871,38 @@ class OptionItem(Item): return self._assert_in_interval(conf, cic, value, [-32768, 32767]) def _assert_int32(self, conf, cic, value, arg): - return self._assert_in_interval( - conf, cic, value, [-2147483648, 2147483647] - ) + return self._assert_in_interval(conf, cic, value, + [-2147483648, 2147483647]) def _assert_int64(self, conf, cic, value, arg): return self._assert_in_interval( - conf, cic, value, [-9223372036854775808, 9223372036854775807] - ) + conf, cic, value, [-9223372036854775808, 9223372036854775807]) def _assert_le(self, conf, cic, value, arg): - if value > arg: + if value is not None and value > arg: conf.fatal( - "Value '{}' for option '{}' is not less than or equal to {}".format( - value, self.data["name"], arg - ) - ) + "Value '{}' for option '{}' is not less than or equal to {}". + format(value, self.data["name"], arg)) return value def _assert_lt(self, conf, cic, value, arg): - if value >= arg: - conf.fatal( - "Value '{}' for option '{}' is not less than {}".format( - value, self.data["name"], arg - ) - ) + if value is not None and value >= arg: + conf.fatal("Value '{}' for option '{}' is not less than {}".format( + value, self.data["name"], arg)) return value def _assert_ne(self, conf, cic, value, arg): - if value == arg: + if value is not None and value == arg: conf.fatal( "Value '{}' for option '{}' is not unequal to {}".format( - value, self.data["name"], arg - ) - ) + value, self.data["name"], arg)) return value def _assert_power_of_two(self, conf, cic, value, arg): - if value <= 0 or (value & (value - 1)) != 0: + if value is not None and (value <= 0 or (value & (value - 1)) != 0): conf.fatal( "Value '{}' for option '{}' is not a power of two".format( - value, self.data["name"] - ) - ) + value, self.data["name"])) return value def _assert_uint8(self, conf, cic, value, arg): @@ -850,9 +915,8 @@ class OptionItem(Item): return self._assert_in_interval(conf, cic, value, [0, 4294967295]) def _assert_uint64(self, conf, cic, value, arg): - return self._assert_in_interval( - conf, cic, value, [0, 18446744073709551615] - ) + return self._assert_in_interval(conf, cic, value, + [0, 18446744073709551615]) def _check_cc(self, conf, cic, value, arg): result = conf.check_cc( @@ -926,11 +990,10 @@ class OptionItem(Item): value = cic.cp.getboolean(conf.variant, name) cic.add_option(name) except configparser.NoOptionError: - value = self.default_value(conf.env.ARCH_BSP, conf.env.ARCH_FAMILY) + value = self.default_value(conf.env.ENABLE) except ValueError as ve: - conf.fatal( - "Invalid value for configuration option {}: {}".format(name, ve) - ) + conf.fatal("Invalid value for configuration option {}: {}".format( + name, ve)) return value def _get_env(self, conf, cic, value, arg): @@ -942,17 +1005,15 @@ class OptionItem(Item): value = cic.cp.get(conf.variant, name) cic.add_option(name) except configparser.NoOptionError: - value = self.default_value(conf.env.ARCH_BSP, conf.env.ARCH_FAMILY) - if value is None: - return value + value = self.default_value(conf.env.ENABLE) + if not value: + return None try: return eval(value) except Exception as e: conf.fatal( - "Value '{}' for option '{}' is an invalid integer expression: {}".format( - value, name, e - ) - ) + "Value '{}' for option '{}' is an invalid integer expression: {}" + .format(value, name, e)) def _get_string(self, conf, cic, value, arg): name = self.data["name"] @@ -961,39 +1022,33 @@ class OptionItem(Item): cic.add_option(name) value = no_unicode(value) except configparser.NoOptionError: - value = self.default_value(conf.env.ARCH_BSP, conf.env.ARCH_FAMILY) - return value - - def _get_string_command_line(self, conf, cic, value, arg): - name = self.data["name"] - try: - value = conf.rtems_options[name] - del conf.rtems_options[name] - except KeyError: - value = arg[0] + value = self.default_value(conf.env.ENABLE) return value def _script(self, conf, cic, value, arg): - exec(arg) - return value + local_variables = { + "self": self, + "conf": conf, + "cic": cic, + "value": value + } + exec(arg, None, local_variables) + return local_variables["value"] def _test_state_benchmark(self, conf, name): self._do_append_test_cppflags(conf, name, "-DTEST_STATE_BENCHMARK=1") def _test_state_exclude(self, conf, name): conf.env.append_value( - "ENABLE", "TEST_" + name.upper().replace("-", "_") + "_EXCLUDE" - ) + "ENABLE", "TEST_" + name.upper().replace("-", "_") + "_EXCLUDE") def _test_state_expected_fail(self, conf, name): - self._do_append_test_cppflags( - conf, name, "-DTEST_STATE_EXPECTED_FAIL=1" - ) + self._do_append_test_cppflags(conf, name, + "-DTEST_STATE_EXPECTED_FAIL=1") def _test_state_indeterminate(self, conf, name): - self._do_append_test_cppflags( - conf, name, "-DTEST_STATE_INDETERMINATE=1" - ) + self._do_append_test_cppflags(conf, name, + "-DTEST_STATE_INDETERMINATE=1") def _test_state_user_input(self, conf, name): self._do_append_test_cppflags(conf, name, "-DTEST_STATE_USER_INPUT=1") @@ -1006,8 +1061,9 @@ class OptionItem(Item): "indeterminate": self._test_state_indeterminate, "user-input": self._test_state_user_input, } - for k, v in arg.items(): - actions[v](conf, k) + action = actions[arg["state"]] + for test in arg["tests"]: + action(conf, test) return value def _set_value(self, conf, cic, value, arg): @@ -1029,6 +1085,7 @@ class OptionItem(Item): "assert-eq": self._assert_eq, "assert-ge": self._assert_ge, "assert-gt": self._assert_gt, + "assert-in-set": self._assert_in_set, "assert-int8": self._assert_int8, "assert-int16": self._assert_int16, "assert-int32": self._assert_int32, @@ -1055,7 +1112,6 @@ class OptionItem(Item): "get-env": self._get_env, "get-integer": self._get_integer, "get-string": self._get_string, - "get-string-command-line": self._get_string_command_line, "script": self._script, "set-test-state": self._set_test_state, "set-value": self._set_value, @@ -1069,6 +1125,7 @@ class OptionItem(Item): class ScriptItem(Item): + def __init__(self, uid, data): super(ScriptItem, self).__init__(uid, data) @@ -1095,6 +1152,7 @@ class ScriptItem(Item): class ConfigItemContext(object): + def __init__(self, cp, path_list): self.cp = cp self.options = set() @@ -1105,8 +1163,13 @@ class ConfigItemContext(object): class BuildItemContext(object): - def __init__(self, includes, use, ldflags, objects): + + def __init__(self, includes, cppflags, cflags, cxxflags, use, ldflags, + objects): self.includes = includes + self.cppflags = cppflags + self.cflags = cflags + self.cxxflags = cxxflags self.use = use self.ldflags = ldflags self.objects = objects @@ -1237,74 +1300,81 @@ def options(ctx): rg.add_option( "--rtems-bsps", metavar="REGEX,...", - help="a comma-separated list of Python regular expressions which select the desired BSP variants (e.g. 'sparc/erc32'); it may be used in the bsp_defaults and bsp_list commands", + help= + "a comma-separated list of Python regular expressions which select the desired BSP variants (e.g. 'sparc/erc32'); it may be used in the bspdefaults and bsps commands", ) rg.add_option( "--rtems-compiler", metavar="COMPILER", - help="determines which compiler is used to list the BSP option defaults [default: 'gcc']; it may be used in the bsp_defaults command; valid compilers are: {}".format( - ", ".join(compilers) - ), + help= + "determines which compiler is used to list the BSP option defaults [default: 'gcc']; it may be used in the bspdefaults command; valid compilers are: {}" + .format(", ".join(compilers)), ) rg.add_option( "--rtems-config", metavar="CONFIG.INI,...", - help="a comma-separated list of paths to the BSP configuration option files [default: 'config.ini']; default option values can be obtained via the bsp_defaults command; it may be used in the configure command", + help= + "a comma-separated list of paths to the BSP configuration option files [default: 'config.ini']; default option values can be obtained via the bspdefaults command; it may be used in the configure command", ) rg.add_option( "--rtems-specs", metavar="SPECDIRS,...", - help="a comma-separated list of directory paths to build specification items [default: 'spec/build']; it may be used in the bsp_defaults, bsp_list, and configure commands", + help= + "a comma-separated list of directory paths to build specification items [default: 'spec/build']; it may be used in the bspdefaults, bsps, and configure commands", ) rg.add_option( "--rtems-tools", metavar="PREFIX,...", - help="a comma-separated list of prefix paths to tools, e.g. compiler, linker, etc. [default: the installation prefix]; tools are searched in the prefix path and also in a 'bin' subdirectory of the prefix path; it may be used in the configure command", + help= + "a comma-separated list of prefix paths to tools, e.g. compiler, linker, etc. [default: the installation prefix]; tools are searched in the prefix path and also in a 'bin' subdirectory of the prefix path; it may be used in the configure command", ) rg.add_option( "--rtems-top-group", metavar="UID", - help="the UID of the top-level group [default: '/grp']; it may be used in the bsp_defaults and configure commands", - ) - rg.add_option( - "--rtems-version", - metavar="VALUE", - help="sets the RTEMS major version number; it is intended for RTEMS maintainers and may be used in the bsp_defaults and configure commands", - ) - rg.add_option( - "--rtems-option", - metavar="KEY=VALUE", - action="append", - dest="rtems_options", - default=[], - help="sets the option identified by KEY to the VALUE in the build specification; it is intended for RTEMS maintainers and may be used in the bsp_defaults and configure commands", + help= + "the UID of the top-level group [default: '/grp']; it may be used in the bspdefaults and configure commands", ) def check_environment(conf): for ev in [ - "AR", - "AS", - "ASFLAGS", - "CC", - "CFLAGS", - "CPPFLAGS", - "CXX", - "CXXFLAGS", - "IFLAGS", - "LD", - "LIB", - "LINK_CC", - "LINK_CXX", - "LINKFLAGS", - "MFLAGS", - "RFLAGS", - "WFLAGS", + "AR", + "AS", + "ASFLAGS", + "CC", + "CFLAGS", + "CPPFLAGS", + "CXX", + "CXXFLAGS", + "IFLAGS", + "LD", + "LIB", + "LINK_CC", + "LINK_CXX", + "LINKFLAGS", + "MFLAGS", + "RFLAGS", + "WFLAGS", ]: if ev in os.environ: conf.msg("Environment variable set", ev, color="RED") +def configure_version(conf): + cp = configparser.ConfigParser() + version_file = "VERSION" + if cp.read([version_file]): + conf.msg("Configure RTEMS version from file", + version_file, + color="YELLOW") + for key in version: + try: + value = cp.get("RTEMS_VERSION", key) + version[key] = no_unicode(value) + except configparser.NoOptionError: + pass + + def load_config_files(ctx): cp = configparser.ConfigParser() files = ctx.options.rtems_config @@ -1338,10 +1408,8 @@ def inherit(conf, cp, bsp_map, arch, bsp, path): if not cp.has_section(base_variant): if (not arch in bsps) or (not base in bsps[arch]): conf.fatal( - "BSP variant '{}' cannot inherit options from not existing variant '{}'".format( - variant, base_variant - ) - ) + "BSP variant '{}' cannot inherit options from not existing variant '{}'" + .format(variant, base_variant)) bsp_map[bsp] = base return base top = inherit(conf, cp, bsp_map, arch, base, path + [variant]) @@ -1364,20 +1432,15 @@ def resolve_option_inheritance(conf, cp): except: conf.fatal( "Section name '{}' is a malformed 'arch/bsp' tuple".format( - variant - ) - ) + variant)) inherit(conf, cp, bsp_map, arch, bsp, []) return bsp_map def check_compiler(ctx, compiler): if compiler not in compilers: - ctx.fatal( - "Specified compiler '{}' is not one of {}".format( - compiler, compilers - ) - ) + ctx.fatal("Specified compiler '{}' is not one of {}".format( + compiler, compilers)) def get_compiler(conf, cp, variant): @@ -1408,6 +1471,9 @@ def configure_variant(conf, cp, bsp_map, path_list, top_group, variant): arch_bsp = arch + "/" + bsp_base arch_family = arch + "/" + family + for key, value in version.items(): + conf.env[key] = value + conf.env["ARCH"] = arch conf.env["ARCH_BSP"] = arch_bsp conf.env["ARCH_FAMILY"] = arch_family @@ -1429,7 +1495,6 @@ def configure_variant(conf, cp, bsp_map, path_list, top_group, variant): conf.env["TOPGROUP"] = top_group conf.env["VARIANT"] = variant - prepare_rtems_options(conf) cic = ConfigItemContext(cp, path_list) items[conf.env.TOPGROUP].configure(conf, cic) bsp_item.configure(conf, cic) @@ -1437,18 +1502,14 @@ def configure_variant(conf, cp, bsp_map, path_list, top_group, variant): options = set([o[0].upper() for o in cp.items(variant)]) for o in options.difference(cic.options): conf.msg("Unknown configuration option", o.upper(), color="RED") - for key in conf.rtems_options: - conf.msg("Unknown command line RTEMS option", key, color="RED") def check_forbidden_options(ctx, opts): for o in opts: if getattr(ctx.options, "rtems_" + o): ctx.fatal( - "The --rtems-{} command line option is not allowed in the {} command".format( - o.replace("_", "-"), ctx.cmd - ) - ) + "The --rtems-{} command line option is not allowed in the {} command" + .format(o.replace("_", "-"), ctx.cmd)) def get_path_list(conf): @@ -1468,35 +1529,14 @@ def get_top_group(ctx): top_group = "/grp" if top_group not in items: ctx.fatal( - "There is no top-level group with UID '{}' in the specification".format( - top_group - ) - ) + "There is no top-level group with UID '{}' in the specification". + format(top_group)) return top_group -def prepare_rtems_options(conf): - conf.rtems_options = {} - for x in conf.options.rtems_options: - try: - k, v = x.split("=", 1) - conf.rtems_options[k] = v - except: - conf.fatal( - "The RTEMS option '{}' is not in KEY=VALUE format".format(x) - ) - version = conf.options.rtems_version - if version is not None: - key = "__RTEMS_MAJOR__" - if conf.rtems_options.get(key, version) != version: - conf.fatal( - "Conflicting RTEMS major versions specified at the command line" - ) - conf.rtems_options[key] = version - - def configure(conf): check_forbidden_options(conf, ["compiler"]) + configure_version(conf) check_environment(conf) conf.env["SPECS"] = load_items_from_options(conf) top_group = get_top_group(conf) @@ -1522,7 +1562,8 @@ def append_variant_builds(bld): ) for var in bld.env["VARIANTS"]: - for c in (BuildContext, CleanContext, InstallContext, UninstallContext): + for c in (BuildContext, CleanContext, InstallContext, + UninstallContext): name = c.__name__.replace("Context", "").lower() class magic(c): @@ -1541,21 +1582,14 @@ def build(bld): if not bld.variant: check_forbidden_options( bld, - [ - "compiler", - "config", - "options", - "specs", - "tools", - "top_group", - "version", - ], + ["compiler", "config", "specs", "tools", "top_group"], ) load_items(bld, bld.env.SPECS) append_variant_builds(bld) return long_command_line_workaround(bld) - bic = BuildItemContext(bld.env.ARCH_INCLUDES.split(), [], [], []) + bic = BuildItemContext(bld.env.ARCH_INCLUDES.split(), [], [], [], [], [], + []) bsps[bld.env.ARCH][bld.env.BSP_BASE].build(bld, bic) items[bld.env.TOPGROUP].build(bld, bic) @@ -1564,6 +1598,7 @@ def add_log_filter(name): msg = "'" + name + "' finished successfully" class Filter: + def filter(self, rec): return not msg in rec.getMessage() @@ -1590,16 +1625,13 @@ def is_in_white_list(variant, white_list): def no_matches_error(ctx, white_list): if white_list: - ctx.fatal( - "No BSP matches with the specified patterns: '{}'".format( - "', '".join(white_list) - ) - ) + ctx.fatal("No BSP matches with the specified patterns: '{}'".format( + "', '".join(white_list))) else: ctx.fatal("The build specification contains no BSPs") -def bsp_defaults(ctx): +def bspdefaults(ctx): """get all options with default values for base BSP variants""" check_forbidden_options(ctx, ["config", "tools"]) add_log_filter(ctx.cmd) @@ -1619,32 +1651,27 @@ def bsp_defaults(ctx): if not first: print("") first = False - print( - """[{}] + print("""[{}] # Selects the compiler used to build the BSP (allowed values are "gcc" and # "clang"). Please note that the values of some options depend on the compiler # selection and changing the compiler may lead to unpredictable behaviour if # these options are not adjusted as well. Use the --rtems-compiler command line # option to get the default values for a particular compiler via -# ./waf bsp_defaults. -COMPILER = {}""".format( - variant, compiler - ) - ) +# ./waf bspdefaults. +COMPILER = {}""".format(variant, compiler)) enable = [compiler, arch, variant] bsp_item = bsps[arch][bsp] - family = arch + "/" + bsp_item.data["family"] - items[top_group].defaults(enable, variant, family) - bsp_item.defaults(enable, variant, family) + family = "bsps/" + arch + "/" + bsp_item.data["family"] + enabled = [compiler, arch, family, variant] + items[top_group].defaults(enabled) + bsp_item.defaults(enabled) if first: no_matches_error(ctx, white_list) -def bsp_list(ctx): +def bsplist(ctx): """lists base BSP variants""" - check_forbidden_options( - ctx, ["compiler", "config", "options", "tools", "top_group", "version"] - ) + check_forbidden_options(ctx, ["compiler", "config", "tools", "top_group"]) add_log_filter(ctx.cmd) load_items_from_options(ctx) white_list = get_white_list(ctx) |