Files
gem5/site_scons/gem5_scons/kconfig.py
Gabe Black db3a6e8e84 scons: Use Kconfig to configure gem5.
These are not yet consumed by anything, but convert all the settings
from SCons variables to Kconfig variables.

If you have existing SConsopts files which need to be converted, you
should take a look at KCONFIG.md to learn about how kconfig is used in
gem5. You should decide if any variables need to be available to C++ or
kconfig itself, and whether those are options which should be detected
automatically, or should be up to the user. Options which should be
measured automatically should still be in SConsopts files, while user
facing options should be added to new or existing Kconfig files.

Generally, make sure you're storing c++/kconfig visible options in
env['CONF'][...]. Also remove references to sticky_vars since persistent
options should now be handled with kconfig, and export_vars since
everything in env['CONF'] is now exported automatically.

Switch SCons/gem5 to use Kconfig for configuration, except EXTRAS which
is still a sticky SCons variable. This is necessary because EXTRAS also
controls what config options exist. If it came from Kconfig itself, then
there would be a circular dependency. This dependency could
theoretically be handled by reparsing the Kconfig when EXTRAS
directories were added or removed, but that would be complicated, and
isn't supported by kconfiglib. It wouldn't be worth the significant
effort it would take to add it, just to use Kconfig more purely.

Change-Id: I29ab1940b2d7b0e6635a490452d05befe5b4a2c9
2023-11-23 08:26:10 +08:00

117 lines
4.4 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
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
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
return kconfig_env
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 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)
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.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}")