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
168 lines
5.9 KiB
Python
168 lines
5.9 KiB
Python
# Copyright 2022 Google LLC
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions are
|
|
# met: redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer;
|
|
# redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution;
|
|
# neither the name of the copyright holders nor the names of its
|
|
# contributors may be used to endorse or promote products derived from
|
|
# this software without specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
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):
|
|
"""
|
|
Prepare the required env vars for Kconfiglib
|
|
return the Scons env with Kconfiglib env
|
|
|
|
:param env: Scons env
|
|
:param base_kconfig: path to the Top-level Kconfig file
|
|
:param config_path: path to the configuration file
|
|
"""
|
|
kconfig_env = env.Clone()
|
|
for key, val in kconfig_env["CONF"].items():
|
|
if isinstance(val, bool):
|
|
val = "y" if val else "n"
|
|
kconfig_env["ENV"][key] = val
|
|
kconfig_env["ENV"]["CONFIG_"] = ""
|
|
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")
|
|
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
|
|
"""
|
|
kconfig_env = _prep_env(env, base_kconfig, config_out)
|
|
kconfig_env["CONFIG_IN"] = config_in
|
|
if (
|
|
kconfig_env.Execute(
|
|
'"${DEFCONFIG_PY}" --kconfig "${BASE_KCONFIG}" ' '"${CONFIG_IN}"'
|
|
)
|
|
!= 0
|
|
):
|
|
error("Failed to run defconfig")
|
|
|
|
|
|
def menuconfig(
|
|
env, base_kconfig, config_path, main_menu_text, style="aquatic"
|
|
):
|
|
"""
|
|
Interface of handling menuconfig.py of Kconfiglib
|
|
"""
|
|
kconfig_env = _prep_env(env, base_kconfig, config_path)
|
|
kconfig_env["ENV"]["MENUCONFIG_STYLE"] = style
|
|
kconfig_env["ENV"]["MAIN_MENU_TEXT"] = main_menu_text
|
|
if kconfig_env.Execute('"${MENUCONFIG_PY}" "${BASE_KCONFIG}"') != 0:
|
|
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
|
|
|
|
:param env: Scons env
|
|
:param base_kconfig: path to the Top-level Kconfig file
|
|
:param config_path: path to the configuration file
|
|
"""
|
|
kconfig_env = _prep_env(env, base_kconfig, config_path)
|
|
|
|
kconfig = _process_kconfig(kconfig_env, base_kconfig)
|
|
|
|
kconfig.load_config(config_path)
|
|
for sym in kconfig.unique_defined_syms:
|
|
val = sym.str_value
|
|
if sym.type == kconfiglib.BOOL:
|
|
env["CONF"][sym.name] = True if val == "y" else False
|
|
elif sym.type == kconfiglib.TRISTATE:
|
|
warning("No way to configure modules for now")
|
|
env["CONF"][sym.name] = True if val == "y" else False
|
|
elif sym.type == kconfiglib.INT:
|
|
if not val:
|
|
val = "0"
|
|
env["CONF"][sym.name] = int(val, 0)
|
|
elif sym.type == kconfiglib.HEX:
|
|
if not val:
|
|
val = "0"
|
|
env["CONF"][sym.name] = int(val, 16)
|
|
elif sym.type == kconfiglib.STRING:
|
|
env["CONF"][sym.name] = val
|
|
elif sym.type == kconfiglib.UNKNOWN:
|
|
warning(f'Config symbol "{sym.name}" has unknown type')
|
|
env["CONF"][sym.name] = val
|
|
else:
|
|
type_name = kconfiglib.TYPE_TO_STR[sym.type]
|
|
error(f"Unrecognized symbol type {type_name}")
|