forked from Archive/PX4-Autopilot
NuttX build include and use Kconfiglib (python)
This commit is contained in:
parent
b3bb625c71
commit
9fd0bbe30f
|
@ -129,7 +129,7 @@ add_custom_command(
|
|||
${CMAKE_CURRENT_BINARY_DIR}/nuttx_copy.stamp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/apps_copy.stamp
|
||||
WORKING_DIRECTORY ${NUTTX_DIR}
|
||||
COMMENT "Copying NuttX config ${NUTTX_CONFIG} and configuring"
|
||||
COMMENT "Copying NuttX config ${NUTTX_CONFIG}"
|
||||
)
|
||||
|
||||
# NuttX defconfig
|
||||
|
@ -141,14 +141,13 @@ if (NOT config_expanded)
|
|||
add_custom_command(
|
||||
OUTPUT ${NUTTX_DIR}/.config
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${NUTTX_DEFCONFIG} ${NUTTX_DIR}/.config
|
||||
COMMAND kconfig-tweak --set-str CONFIG_APPS_DIR "../apps"
|
||||
COMMAND make --no-print-directory --silent -C ${NUTTX_DIR} CONFIG_ARCH_BOARD_CUSTOM=y olddefconfig
|
||||
COMMAND PATH=${CMAKE_CURRENT_SOURCE_DIR}/tools:$ENV{PATH} make --no-print-directory --silent -C ${NUTTX_DIR} CONFIG_ARCH_BOARD_CUSTOM=y CONFIG_APPS_DIR="../apps" olddefconfig > nuttx_olddefconfig.log
|
||||
DEPENDS
|
||||
${NUTTX_DEFCONFIG}
|
||||
${NUTTX_DIR}/configs/dummy/Kconfig
|
||||
${CMAKE_CURRENT_BINARY_DIR}/nuttx_copy_config_dir.stamp
|
||||
WORKING_DIRECTORY ${NUTTX_DIR}
|
||||
COMMENT "Copying NuttX config ${NUTTX_CONFIG} and configuring"
|
||||
COMMENT "Copying NuttX compressed config ${NUTTX_CONFIG} and inflating"
|
||||
)
|
||||
else()
|
||||
# copy uncompressed PX4 defconfig into nuttx
|
||||
|
@ -160,7 +159,7 @@ else()
|
|||
${NUTTX_DIR}/configs/dummy/Kconfig
|
||||
${CMAKE_CURRENT_BINARY_DIR}/nuttx_copy_config_dir.stamp
|
||||
WORKING_DIRECTORY ${NUTTX_DIR}
|
||||
COMMENT "Copying NuttX uncompressed config ${NUTTX_CONFIG} and configuring"
|
||||
COMMENT "Copying NuttX uncompressed config ${NUTTX_CONFIG}"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
@ -189,11 +188,8 @@ else()
|
|||
endif()
|
||||
|
||||
# context
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${NUTTX_DIR}/include/nuttx/version.h
|
||||
${NUTTX_DIR}/include/nuttx/config.h
|
||||
COMMAND make ${nuttx_build_options} --no-print-directory CONFIG_ARCH_BOARD_CUSTOM=y context ${nuttx_build_output}
|
||||
add_custom_command(OUTPUT ${NUTTX_DIR}/include/nuttx/version.h ${NUTTX_DIR}/include/nuttx/config.h
|
||||
COMMAND make ${nuttx_build_options} --no-print-directory CONFIG_ARCH_BOARD_CUSTOM=y context > nuttx_context.log
|
||||
DEPENDS ${NUTTX_DIR}/.config
|
||||
WORKING_DIRECTORY ${NUTTX_DIR}
|
||||
${nuttx_build_uses_terminal}
|
||||
|
@ -251,7 +247,7 @@ endif()
|
|||
# libapps.a
|
||||
add_custom_command(OUTPUT ${APPS_DIR}/libapps.a ${APPS_DIR}/platform/.built
|
||||
COMMAND find ${APPS_DIR} -name \*.o -delete
|
||||
COMMAND make ${nuttx_build_options} --no-print-directory -C ../apps TOPDIR="${NUTTX_DIR}" libapps.a ${nuttx_build_output}
|
||||
COMMAND make ${nuttx_build_options} --no-print-directory -C ../apps TOPDIR="${NUTTX_DIR}" libapps.a > nuttx_apps.log
|
||||
DEPENDS ${nuttx_builtin_list} ${NUTTX_DIR}/include/nuttx/version.h ${NUTTX_DIR}/include/nuttx/config.h
|
||||
WORKING_DIRECTORY ${NUTTX_DIR}
|
||||
${nuttx_build_uses_terminal}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
#! /bin/bash
|
||||
|
||||
echo "DEBUG: kconfiglib kconfig-conf wrapper, arguments: ${@}"
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
|
||||
export APPSDIR="`pwd`/../apps"
|
||||
export CONFIG_ARCH_BOARD_CUSTOM=y
|
||||
|
||||
if [ "${1}" = "--olddefconfig" ]; then
|
||||
PYTHONPATH=${DIR} python ${DIR}/olddefconfig.py > /dev/null
|
||||
else
|
||||
echo "ERROR: ${@} unsupported"
|
||||
exit 1
|
||||
fi
|
|
@ -0,0 +1,12 @@
|
|||
#! /bin/bash
|
||||
|
||||
echo "DEBUG: kconfiglib kconfig-tweak wrapper, arguments: ${@}"
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
|
||||
export APPSDIR="`pwd`/../apps"
|
||||
|
||||
# Example:
|
||||
# kconfig-tweak --set-str CONFIG_APPS_DIR ../apps
|
||||
# becomes
|
||||
# python setconfig.py CONFIG_APPS_DIR=../apps
|
||||
PYTHONPATH=${DIR} python ${DIR}/setconfig.py --kconfig=Kconfig ${2}=${3} > /dev/null
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,243 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (c) 2018-2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
# Implements oldconfig functionality:
|
||||
#
|
||||
# 1. Load existing .config
|
||||
# 2. Prompt the user for the value of all modifiable symbols/choices that
|
||||
# aren't already set in the .config
|
||||
# 3. Write new .config
|
||||
#
|
||||
# The default input/output filename is '.config'. A different filename can be
|
||||
# passed in the KCONFIG_CONFIG environment variable.
|
||||
#
|
||||
# Unlike 'make oldconfig', this script doesn't print menu titles and comments,
|
||||
# but gives Kconfig definition locations. Printing menus and comments would be
|
||||
# pretty easy to add: Look at the parents of each item and print all menu
|
||||
# prompts and comments unless they have already been printed (assuming you want
|
||||
# to skip "irrelevant" menus).
|
||||
#
|
||||
# Entering '?' displays the help text of the symbol/choice, if any.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
|
||||
from kconfiglib import Symbol, Choice, BOOL, TRISTATE, HEX, standard_kconfig
|
||||
|
||||
|
||||
# Python 2/3 compatibility hack
|
||||
if sys.version_info[0] < 3:
|
||||
input = raw_input
|
||||
|
||||
|
||||
# Note: Used as the entry point in setup.py
|
||||
def _main():
|
||||
# Earlier symbols in Kconfig files might depend on later symbols and become
|
||||
# visible if their values change. This flag is set to True if the value of
|
||||
# any symbol changes, in which case we rerun the oldconfig to check for new
|
||||
# visible symbols.
|
||||
global conf_changed
|
||||
|
||||
kconf = standard_kconfig()
|
||||
kconf.load_config()
|
||||
|
||||
while True:
|
||||
conf_changed = False
|
||||
|
||||
for node in kconf.node_iter():
|
||||
oldconfig(node)
|
||||
|
||||
if not conf_changed:
|
||||
break
|
||||
|
||||
kconf.write_config()
|
||||
|
||||
|
||||
def oldconfig(node):
|
||||
"""
|
||||
Prompts the user for a value if node.item is a visible symbol/choice with
|
||||
no user value.
|
||||
"""
|
||||
# See main()
|
||||
global conf_changed
|
||||
|
||||
# Only symbols and choices can be configured
|
||||
if not isinstance(node.item, (Symbol, Choice)):
|
||||
return
|
||||
|
||||
# Skip symbols and choices that aren't visible
|
||||
if not node.item.visibility:
|
||||
return
|
||||
|
||||
# Skip symbols and choices that don't have a prompt (at this location)
|
||||
if not node.prompt:
|
||||
return
|
||||
|
||||
if isinstance(node.item, Symbol):
|
||||
sym = node.item
|
||||
|
||||
# Skip symbols that already have a user value
|
||||
if sym.user_value is not None:
|
||||
return
|
||||
|
||||
# Skip symbols that can only have a single value, due to selects
|
||||
if len(sym.assignable) == 1:
|
||||
return
|
||||
|
||||
# Skip symbols in choices in y mode. We ask once for the entire choice
|
||||
# instead.
|
||||
if sym.choice and sym.choice.tri_value == 2:
|
||||
return
|
||||
|
||||
# Loop until the user enters a valid value or enters a blank string
|
||||
# (for the default value)
|
||||
while True:
|
||||
val = input("{} ({}) [{}] ".format(
|
||||
node.prompt[0], _name_and_loc_str(sym),
|
||||
_default_value_str(sym)))
|
||||
|
||||
if val == "?":
|
||||
_print_help(node)
|
||||
continue
|
||||
|
||||
# Substitute a blank string with the default value the symbol
|
||||
# would get
|
||||
if not val:
|
||||
val = sym.str_value
|
||||
|
||||
# Automatically add a "0x" prefix for hex symbols, like the
|
||||
# menuconfig interface does. This isn't done when loading .config
|
||||
# files, hence why set_value() doesn't do it automatically.
|
||||
if sym.type == HEX and not val.startswith(("0x", "0X")):
|
||||
val = "0x" + val
|
||||
|
||||
old_str_val = sym.str_value
|
||||
|
||||
# Kconfiglib itself will print a warning here if the value
|
||||
# is invalid, so we don't need to bother
|
||||
if sym.set_value(val):
|
||||
# Valid value input. We're done with this node.
|
||||
|
||||
if sym.str_value != old_str_val:
|
||||
conf_changed = True
|
||||
|
||||
return
|
||||
|
||||
else:
|
||||
choice = node.item
|
||||
|
||||
# Skip choices that already have a visible user selection...
|
||||
if choice.user_selection and choice.user_selection.visibility == 2:
|
||||
# ...unless there are new visible symbols in the choice. (We know
|
||||
# they have y (2) visibility in that case, because m-visible
|
||||
# symbols get demoted to n-visibility in y-mode choices, and the
|
||||
# user-selected symbol had visibility y.)
|
||||
for sym in choice.syms:
|
||||
if sym is not choice.user_selection and sym.visibility and \
|
||||
sym.user_value is None:
|
||||
# New visible symbols in the choice
|
||||
break
|
||||
else:
|
||||
# No new visible symbols in the choice
|
||||
return
|
||||
|
||||
# Get a list of available selections. The mode of the choice limits
|
||||
# the visibility of the choice value symbols, so this will indirectly
|
||||
# skip choices in n and m mode.
|
||||
options = [sym for sym in choice.syms if sym.visibility == 2]
|
||||
|
||||
if not options:
|
||||
# No y-visible choice value symbols
|
||||
return
|
||||
|
||||
# Loop until the user enters a valid selection or a blank string (for
|
||||
# the default selection)
|
||||
while True:
|
||||
print("{} ({})".format(node.prompt[0], _name_and_loc_str(choice)))
|
||||
|
||||
for i, sym in enumerate(options, 1):
|
||||
print("{} {}. {} ({})".format(
|
||||
">" if sym is choice.selection else " ",
|
||||
i,
|
||||
# Assume people don't define choice symbols with multiple
|
||||
# prompts. That generates a warning anyway.
|
||||
sym.nodes[0].prompt[0],
|
||||
sym.name))
|
||||
|
||||
sel_index = input("choice[1-{}]: ".format(len(options)))
|
||||
|
||||
if sel_index == "?":
|
||||
_print_help(node)
|
||||
continue
|
||||
|
||||
# Pick the default selection if the string is blank
|
||||
if not sel_index:
|
||||
choice.selection.set_value(2)
|
||||
break
|
||||
|
||||
try:
|
||||
sel_index = int(sel_index)
|
||||
except ValueError:
|
||||
print("Bad index", file=sys.stderr)
|
||||
continue
|
||||
|
||||
if not 1 <= sel_index <= len(options):
|
||||
print("Bad index", file=sys.stderr)
|
||||
continue
|
||||
|
||||
# Valid selection
|
||||
|
||||
if options[sel_index - 1].tri_value != 2:
|
||||
conf_changed = True
|
||||
|
||||
options[sel_index - 1].set_value(2)
|
||||
break
|
||||
|
||||
# Give all of the non-selected visible choice symbols the user value n.
|
||||
# This makes it so that the choice is no longer considered new once we
|
||||
# do additional passes, if the reason that it was considered new was
|
||||
# that it had new visible choice symbols.
|
||||
#
|
||||
# Only giving visible choice symbols the user value n means we will
|
||||
# prompt for the choice again if later user selections make more new
|
||||
# choice symbols visible, which is correct.
|
||||
for sym in choice.syms:
|
||||
if sym is not choice.user_selection and sym.visibility:
|
||||
sym.set_value(0)
|
||||
|
||||
|
||||
def _name_and_loc_str(sc):
|
||||
# Helper for printing the name of the symbol/choice 'sc' along with the
|
||||
# location(s) in the Kconfig files where it is defined. Unnamed choices
|
||||
# return "choice" instead of the name.
|
||||
|
||||
return "{}, defined at {}".format(
|
||||
sc.name or "choice",
|
||||
", ".join("{}:{}".format(node.filename, node.linenr)
|
||||
for node in sc.nodes))
|
||||
|
||||
|
||||
def _print_help(node):
|
||||
print("\n" + (node.help or "No help text\n"))
|
||||
|
||||
|
||||
def _default_value_str(sym):
|
||||
# Returns the "m/M/y" string in e.g.
|
||||
#
|
||||
# TRISTATE_SYM prompt (TRISTATE_SYM, defined at Kconfig:9) [n/M/y]:
|
||||
#
|
||||
# For string/int/hex, returns the default value as-is.
|
||||
|
||||
if sym.type in (BOOL, TRISTATE):
|
||||
return "/".join(("NMY" if sym.tri_value == tri else "nmy")[tri]
|
||||
for tri in sym.assignable)
|
||||
|
||||
# string/int/hex
|
||||
return sym.str_value
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
_main()
|
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (c) 2018-2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
# Works like 'make olddefconfig', updating an old .config file or creating a
|
||||
# new one by filing in default values for all new symbols. This is the same as
|
||||
# picking the default selection for all symbols in oldconfig, or entering the
|
||||
# menuconfig interface and immediately saving.
|
||||
#
|
||||
# The default output filename is '.config'. A different filename can be passed
|
||||
# in the KCONFIG_CONFIG environment variable.
|
||||
|
||||
import kconfiglib
|
||||
|
||||
|
||||
def main():
|
||||
kconf = kconfiglib.standard_kconfig()
|
||||
kconf.load_config()
|
||||
kconf.write_config()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -0,0 +1,87 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (c) 2019, Ulf Magnusson
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
import kconfiglib
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description="""
|
||||
Simple utility for setting configuration values from the command line.
|
||||
|
||||
Sample usage:
|
||||
|
||||
$ setconfig FOO_SUPPORT=y BAR_BITS=8
|
||||
|
||||
Note: Symbol names should not be prefixed with 'CONFIG_'.
|
||||
|
||||
The exit status on errors is 1.
|
||||
|
||||
The default input/output configuration file is '.config'. A different filename
|
||||
can be passed in the KCONFIG_CONFIG environment variable.
|
||||
""")
|
||||
|
||||
parser.add_argument(
|
||||
"--kconfig",
|
||||
default="Kconfig",
|
||||
help="Base Kconfig file (default: Kconfig)")
|
||||
|
||||
parser.add_argument(
|
||||
"--no-check-exists",
|
||||
dest='check_exists',
|
||||
action='store_false',
|
||||
help="Ignore assignments to non-existent symbols instead of erroring "
|
||||
"out")
|
||||
|
||||
parser.add_argument(
|
||||
"--no-check-value",
|
||||
dest='check_value',
|
||||
action='store_false',
|
||||
help="Ignore assignments that didn't \"take\" (where the symbol got a "
|
||||
"different value, e.g. due to unsatisfied dependencies) instead "
|
||||
"of erroring out")
|
||||
|
||||
parser.add_argument(
|
||||
"assignments",
|
||||
metavar="ASSIGNMENT",
|
||||
nargs="*",
|
||||
help="A 'NAME=value' assignment")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
kconf = kconfiglib.Kconfig(args.kconfig)
|
||||
kconf.load_config()
|
||||
|
||||
for arg in args.assignments:
|
||||
if "=" not in arg:
|
||||
sys.exit("error: no '=' in assignment: '{}'".format(arg))
|
||||
name, value = arg.split("=", 1)
|
||||
|
||||
if name not in kconf.syms:
|
||||
if not args.check_exists:
|
||||
continue
|
||||
sys.exit("error: no symbol '{}' in configuration".format(name))
|
||||
|
||||
sym = kconf.syms[name]
|
||||
|
||||
if not sym.set_value(value):
|
||||
sys.exit("error: '{}' is an invalid value for the {} symbol {}"
|
||||
.format(value, kconfiglib.TYPE_TO_STR[sym.type], name))
|
||||
|
||||
if args.check_value and sym.str_value != value:
|
||||
sys.exit("error: {} was assigned the value '{}', but got the "
|
||||
"value '{}'. Check the symbol's dependencies, and make "
|
||||
"sure that it has a prompt."
|
||||
.format(name, value, sym.str_value))
|
||||
|
||||
kconf.write_config()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -114,8 +114,13 @@ execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${NUTTX_DEFCONFIG}
|
|||
# copy PX4 board config into nuttx
|
||||
file(STRINGS ${NUTTX_DEFCONFIG} config_expanded REGEX "# Automatically generated file; DO NOT EDIT.")
|
||||
if (NOT config_expanded)
|
||||
execute_process(COMMAND kconfig-tweak --set-str CONFIG_APPS_DIR "../apps" WORKING_DIRECTORY ${NUTTX_DIR})
|
||||
execute_process(COMMAND make --no-print-directory --silent -C ${NUTTX_DIR} CONFIG_ARCH_BOARD_CUSTOM=y olddefconfig WORKING_DIRECTORY ${NUTTX_DIR})
|
||||
set(ENV{PATH} "${PX4_SOURCE_DIR}/platforms/nuttx/NuttX/tools:$ENV{PATH}")
|
||||
execute_process(
|
||||
COMMAND make --no-print-directory --silent -C ${NUTTX_DIR} CONFIG_ARCH_BOARD_CUSTOM=y olddefconfig
|
||||
WORKING_DIRECTORY ${NUTTX_DIR}
|
||||
OUTPUT_FILE nuttx_olddefconfig.log
|
||||
ERROR_FILE nuttx_olddefconfig.log
|
||||
)
|
||||
endif()
|
||||
|
||||
###############################################################################
|
||||
|
|
Loading…
Reference in New Issue