From 083bca1e239c3d4b5b1d690dfcf13227eaea2a0a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Fri, 18 Feb 2022 00:39:44 -0800 Subject: [PATCH] scons: Hook in the kconfig setconfig utility. This little utility lets you set particular values in an existing config without having to open up the whole menuconfig interface. Also reorganize things in kconfig.py a little to help share code between wrappers. Change-Id: I7cba0c0ef8d318d6c39e49c779ebb2bbdc3d94c8 --- SConstruct | 33 +++++++++++------ site_scons/gem5_scons/kconfig.py | 62 +++++++++++++++++++++++++------- 2 files changed, 72 insertions(+), 23 deletions(-) diff --git a/SConstruct b/SConstruct index e27a97eb40..5ae1080cff 100755 --- a/SConstruct +++ b/SConstruct @@ -260,8 +260,9 @@ Targets: ######################################################################## kconfig_actions = ( - 'menuconfig', 'defconfig', + 'menuconfig', + 'setconfig', ) Help(""" @@ -283,6 +284,15 @@ Kconfig: kernel versions will typically (but not always) apply here as well. Kconfig tools: + defconfig: + Set up a config using values specified in a defconfig file, or if no + value is given, use the default. The second argument specifies the + defconfig file. A defconfig file in the build_opts directory can be + implicitly specified in the build path via `build//` + + scons defconfig build/foo/bar build_opts/MIPS + + menuconfig: Opens the menuconfig editor which will let you view and edit config values, and view help text. menuconfig runs in text mode. @@ -290,13 +300,11 @@ Kconfig tools: scons menuconfig build/foo/bar - defconfig: - Set up a config using values specified in a defconfig file, or if no - value is given, use the default. The second argument specifies the - defconfig file. A defconfig file in the defconfig directory can be - implicitly specified in the build path via `build//` + setconfig: + Set values in an existing config directory as specified on the command + line. For example, to enable gem5's built in systemc kernel: - scons defconfig build/foo/bar build_opts/MIPS + scons setconfig build/foo/bar USE_SYSTEMC=y """, append=True) # Take a list of paths (or SCons Nodes) and return a list with all @@ -817,15 +825,18 @@ for variant_path in variant_paths: # Handle any requested kconfig action, then exit. if kconfig_action: - if kconfig_action == 'menuconfig': - kconfig.menuconfig(env, kconfig_file.abspath, config_file.abspath, - variant_path) - elif kconfig_action == 'defconfig': + if kconfig_action == 'defconfig': if len(kconfig_args) != 1: error('Usage: scons defconfig ') defconfig_path = makePathAbsolute(kconfig_args[0]) kconfig.defconfig(env, kconfig_file.abspath, defconfig_path, config_file.abspath) + elif kconfig_action == 'menuconfig': + kconfig.menuconfig(env, kconfig_file.abspath, config_file.abspath, + variant_path) + elif kconfig_action == 'setconfig': + kconfig.setconfig(env, kconfig_file.abspath, config_file.abspath, + ARGUMENTS) else: error(f'Unrecognized kconfig action {kconfig_action}') Exit(0) diff --git a/site_scons/gem5_scons/kconfig.py b/site_scons/gem5_scons/kconfig.py index d609e24875..0251fdd8ea 100644 --- a/site_scons/gem5_scons/kconfig.py +++ b/site_scons/gem5_scons/kconfig.py @@ -28,6 +28,12 @@ import os from . import error import kconfiglib +_kconfig_helpers = { + "DEFCONFIG_PY": "defconfig.py", + "MENUCONFIG_PY": "menuconfig.py", + "SETCONFIG_PY": "setconfig.py", +} + def _prep_env(env, base_kconfig, config_path=None): """ @@ -47,17 +53,31 @@ def _prep_env(env, base_kconfig, config_path=None): if config_path: kconfig_env["ENV"]["KCONFIG_CONFIG"] = config_path + kconfig_env["BASE_KCONFIG"] = base_kconfig + ext = env.Dir("#ext") kconfiglib_dir = ext.Dir("Kconfiglib") - defconfig_py = kconfiglib_dir.File("defconfig.py") - menuconfig_py = kconfiglib_dir.File("menuconfig.py") - - kconfig_env["DEFCONFIG_PY"] = defconfig_py - kconfig_env["MENUCONFIG_PY"] = menuconfig_py - kconfig_env["BASE_KCONFIG"] = base_kconfig + for key, name in _kconfig_helpers.items(): + kconfig_env[key] = kconfiglib_dir.File(name) return kconfig_env +def _process_kconfig(env, base_kconfig): + """ + Create the kconfig instance by given Scons env vars + + :param env: Scons env + :param base_kconfig: path to the Top-level Kconfig file + """ + saved_env = os.environ + try: + os.environ.update({key: str(val) for key, val in env["ENV"].items()}) + kconfig = kconfiglib.Kconfig(filename=base_kconfig) + finally: + os.environ = saved_env + return kconfig + + def defconfig(env, base_kconfig, config_in, config_out): """ Interface of handling defconfig.py of Kconfiglib @@ -86,6 +106,29 @@ def menuconfig( error("Failed to run menuconfig") +def setconfig(env, base_kconfig, config_path, assignments): + """ + Interface of handling setconfig.py of Kconfiglib + """ + kconfig_env = _prep_env(env, base_kconfig, config_path) + + kconfig = _process_kconfig(kconfig_env, base_kconfig) + sym_names = list(sym.name for sym in kconfig.unique_defined_syms) + + filtered = dict( + {key: val for key, val in assignments.items() if key in sym_names} + ) + + setconfig_cmd_parts = ['"${SETCONFIG_PY}" --kconfig "${BASE_KCONFIG}"'] + for key, val in filtered.items(): + if isinstance(val, bool): + val = "y" if val else "n" + setconfig_cmd_parts.append(f"{key}={val}") + setconfig_cmd = " ".join(setconfig_cmd_parts) + if kconfig_env.Execute(setconfig_cmd) != 0: + error("Failed to run setconfig") + + def update_env(env, base_kconfig, config_path): """ Update the Scons' env["CONF"] options from kconfig env @@ -96,12 +139,7 @@ def update_env(env, base_kconfig, config_path): """ kconfig_env = _prep_env(env, base_kconfig, config_path) - saved_env = os.environ - os.environ.update( - {key: str(val) for key, val in kconfig_env["ENV"].items()} - ) - kconfig = kconfiglib.Kconfig(filename=base_kconfig) - os.environ = saved_env + kconfig = _process_kconfig(kconfig_env, base_kconfig) kconfig.load_config(config_path) for sym in kconfig.unique_defined_syms: