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
This commit is contained in:
Gabe Black
2022-02-18 00:39:44 -08:00
committed by Roger Chang
parent 1ae2dfcc56
commit 083bca1e23
2 changed files with 72 additions and 23 deletions

View File

@@ -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/<defconfig file>/`
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/<build_opts file>/`
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 <build dir> <defconfig file>')
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)

View File

@@ -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: