From 69daff573ba6ecc96c261e3c33b38ba4a5eff4aa Mon Sep 17 00:00:00 2001 From: Peter Barker Date: Fri, 14 Feb 2025 15:51:39 +1100 Subject: [PATCH] Tools: add and use linux_hwdef.py like chibios_hwdef.py - but for Linux --- Tools/ardupilotwaf/boards.py | 14 ++++ Tools/ardupilotwaf/linux.py | 146 +++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 Tools/ardupilotwaf/linux.py diff --git a/Tools/ardupilotwaf/boards.py b/Tools/ardupilotwaf/boards.py index 3fc9d33bce..3f1597743d 100644 --- a/Tools/ardupilotwaf/boards.py +++ b/Tools/ardupilotwaf/boards.py @@ -1398,10 +1398,14 @@ class linux(Board): self.with_can = False def configure_env(self, cfg, env): + if hasattr(self, 'hwdef'): + cfg.env.HWDEF = self.hwdef if cfg.options.board == 'linux': self.with_can = True super(linux, self).configure_env(cfg, env) + cfg.load('linux') + env.BOARD_CLASS = "LINUX" env.DEFINES.update( @@ -1470,8 +1474,18 @@ class linux(Board): HAL_PARAM_DEFAULTS_PATH='"@ROMFS/defaults.parm"', ) + def pre_build(self, bld): + '''pre-build hook that gets called before dynamic sources''' + from waflib.Context import load_tool + module = load_tool('linux', [], with_sys_path=True) + fun = getattr(module, 'pre_build', None) + if fun: + fun(bld) + super(linux, self).pre_build(bld) + def build(self, bld): super(linux, self).build(bld) + bld.load('linux') if bld.options.upload: waflib.Options.commands.append('rsync') # Avoid infinite recursion diff --git a/Tools/ardupilotwaf/linux.py b/Tools/ardupilotwaf/linux.py new file mode 100644 index 0000000000..9e3a65de87 --- /dev/null +++ b/Tools/ardupilotwaf/linux.py @@ -0,0 +1,146 @@ +# encoding: utf-8 + +""" +Waf tool for Linux build + +AP_FLAKE8_CLEAN +""" + +from waflib.TaskGen import after_method, before_method, feature + +import os +import pickle +import sys +import traceback + +sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), '../../libraries/AP_HAL_Linux/hwdef/scripts')) +import linux_hwdef # noqa:501 + + +@feature('linux_ap_library', 'linux_ap_program') +@before_method('process_source') +def linux_dynamic_env(self): + # The generated files from configuration possibly don't exist if it's just + # a list command (TODO: figure out a better way to address that). + if self.bld.cmd == 'list': + return + + def exec_command(self, cmd, **kw): + kw['stdout'] = sys.stdout + return super(exec_command, self).exec_command(cmd, **kw) + + +@feature('linux_ap_program') +@after_method('process_source') +def linux_firmware(self): + pass + + +def load_env_vars(env): + '''optionally load extra environment variables from env.py in the build directory''' + print("Checking for env.py") + env_py = os.path.join(env.BUILDROOT, 'env.py') + if not os.path.exists(env_py): + print("No env.py found") + return + e = pickle.load(open(env_py, 'rb')) + for k in e.keys(): + v = e[k] + if k in env: + if isinstance(env[k], dict): + a = v.split('=') + env[k][a[0]] = '='.join(a[1:]) + print("env updated %s=%s" % (k, v)) + elif isinstance(env[k], list): + env[k].append(v) + print("env appended %s=%s" % (k, v)) + else: + env[k] = v + print("env added %s=%s" % (k, v)) + else: + env[k] = v + print("env set %s=%s" % (k, v)) + + +def configure(cfg): + + def srcpath(path): + return cfg.srcnode.make_node(path).abspath() + + def bldpath(path): + return bldnode.make_node(path).abspath() + + env = cfg.env + bldnode = cfg.bldnode.make_node(cfg.variant) + env.SRCROOT = srcpath('') + env.BUILDROOT = bldpath('') + + def srcpath(path): + return cfg.srcnode.make_node(path).abspath() + + def bldpath(path): + return bldnode.make_node(path).abspath() + env.AP_PROGRAM_FEATURES += ['linux_ap_program'] + + try: + generate_hwdef_h(env) + except Exception as e: + print(get_exception_stacktrace(e)) + cfg.fatal("Failed to generate hwdef") + load_env_vars(cfg.env) + + +def get_exception_stacktrace(e): + ret = "%s\n" % e + ret += ''.join(traceback.format_exception(type(e), + e, + tb=e.__traceback__)) + return ret + + +def generate_hwdef_h(env): + '''run linux_hwdef.py''' + hwdef_dir = os.path.join(env.SRCROOT, 'libraries/AP_HAL_Linux/hwdef') + + if len(env.HWDEF) == 0: + env.HWDEF = os.path.join(hwdef_dir, env.BOARD, 'hwdef.dat') + hwdef_out = env.BUILDROOT + if not os.path.exists(hwdef_out): + os.mkdir(hwdef_out) + hwdef = [env.HWDEF] + if env.HWDEF_EXTRA: + hwdef.append(env.HWDEF_EXTRA) + lh = linux_hwdef.LinuxHWDef( + outdir=hwdef_out, + hwdef=hwdef, + quiet=False, + ) + lh.run() + + +def pre_build(bld): + '''pre-build hook to change dynamic sources''' + load_env_vars(bld.env) + if bld.env.HAL_NUM_CAN_IFACES: + bld.get_board().with_can = True + if bld.env.WITH_LITTLEFS: + bld.get_board().with_littlefs = True + hwdef_h = os.path.join(bld.env.BUILDROOT, 'hwdef.h') + if not os.path.exists(hwdef_h): + print("Generating hwdef.h") + try: + generate_hwdef_h(bld.env) + except Exception: + bld.fatal(f"Failed to process hwdef.dat {hwdef_h}") + + +def build(bld): + bld( + # build hwdef.h from hwdef.dat. This is needed after a waf clean + source=bld.path.ant_glob(bld.env.HWDEF), + rule="", + group='dynamic_sources', + target=[ + bld.bldnode.find_or_declare('hwdef.h'), + ] + )