From aea0232a56d9a9d2611b79ea9c67e0d9d49b183f Mon Sep 17 00:00:00 2001 From: Roman Date: Tue, 27 Feb 2018 10:04:36 +0200 Subject: Implement 'rsource' statement ('source' with relative path) The 'rsource' statement works like 'source', but looks relative to the Kconfig file that has the 'rsource' rather than relative to the base Kconfig file. Using 'rsource' makes it possible to move subtrees with Kconfig files around without breaking references to other Kconfig files. So far, this is a Kconfiglib-exclusive feature. --- kconfiglib.py | 50 +++++++++++++++++++++++++++++++++++++++++++- tests/Klocation | 22 +++++++++++++------ tests/Klocation_included | 18 ---------------- tests/Klocation_sourced | 18 ++++++++++++++++ tests/sub/Klocation_rsourced | 2 ++ testsuite.py | 19 ++++++++++------- 6 files changed, 96 insertions(+), 33 deletions(-) delete mode 100644 tests/Klocation_included create mode 100644 tests/Klocation_sourced create mode 100644 tests/sub/Klocation_rsourced diff --git a/kconfiglib.py b/kconfiglib.py index fda12c6..c246cdc 100644 --- a/kconfiglib.py +++ b/kconfiglib.py @@ -300,6 +300,40 @@ If a condition is missing (e.g., when the 'if ' is removed from functions just avoid printing 'if y' conditions to give cleaner output. +'source' with relative path +=========================== + +The library implements a custom 'rsource' statement that allows to import +Kconfig file by specifying path relative to directory of the currently parsed +file, instead of path relative to project root. +This extension is not supported by Linux kernel tools (yet). + +Consider following directory tree: + + Project + +--Kconfig + | + +--src + +--Kconfig + | + +--SubSystem1 + +--Kconfig + | + +--ModuleA + +--Kconfig + +In above example, src/SubSystem1/Kconfig imports Kconfig for ModuleA. +With default 'source' it looks like: + + source "src/SubSystem1/ModuleA/Kconfig" + +Using 'rsource' it can be rewritten as: + + rsource "ModuleA/Kconfig" + +If absolute path is given to 'rsource' then it follows behavior of 'source'. + + Feedback ======== @@ -1572,6 +1606,17 @@ class Kconfig(object): prev_node) self._leave_file() + elif t0 == _T_RSOURCE: + self._enter_file(os.path.join( + os.path.dirname(self._filename), + self._expand_syms(self._expect_str_and_eol()) + )) + prev_node = self._parse_block(None, # end_token + parent, + visible_if_deps, + prev_node) + self._leave_file() + elif t0 == end_token: # We have reached the end of the block. Terminate the final # node and return it. @@ -4450,13 +4495,14 @@ STR_TO_TRI = { _T_OR, _T_PROMPT, _T_RANGE, + _T_RSOURCE, _T_SELECT, _T_SOURCE, _T_STRING, _T_TRISTATE, _T_UNEQUAL, _T_VISIBLE, -) = range(44) +) = range(45) # Keyword to token map, with the get() method assigned directly as a small # optimization @@ -4490,6 +4536,7 @@ _get_keyword = { "optional": _T_OPTIONAL, "prompt": _T_PROMPT, "range": _T_RANGE, + "rsource": _T_RSOURCE, "select": _T_SELECT, "source": _T_SOURCE, "string": _T_STRING, @@ -4513,6 +4560,7 @@ _STRING_LEX = frozenset(( _T_MAINMENU, _T_MENU, _T_PROMPT, + _T_RSOURCE, _T_SOURCE, _T_STRING, _T_TRISTATE, diff --git a/tests/Klocation b/tests/Klocation index 00d4f4a..aa176b2 100644 --- a/tests/Klocation +++ b/tests/Klocation @@ -33,15 +33,25 @@ config MULTI_DEF endif endif -config EXPANDED_FROM_ENV +config TESTS_DIR_FROM_ENV string - option env="EXPANDED_FROM_ENV" + option env="TESTS_DIR_FROM_ENV" -config _INCLUDED +config SUB_DIR_FROM_ENV string - default "_included" + option env="SUB_DIR_FROM_ENV" -# Expands to "tests/Klocation_included" -source "$EXPANDED_FROM_ENV/Klocation$_INCLUDED" +config _SOURCED + string + default "_sourced" + +config _RSOURCED + string + default "_rsourced" + +# Expands to "tests/Klocation_sourced" +source "$TESTS_DIR_FROM_ENV/Klocation$_SOURCED" +# Expands to "sub/Klocation_rsourced" +rsource "$SUB_DIR_FROM_ENV/Klocation$_RSOURCED" config MULTI_DEF diff --git a/tests/Klocation_included b/tests/Klocation_included deleted file mode 100644 index 6e19f76..0000000 --- a/tests/Klocation_included +++ /dev/null @@ -1,18 +0,0 @@ - - -config MULTI_DEF - -choice CHOICE - bool "choice" -endchoice - -config MENU_HOOK - bool - -menu "menu" -endmenu - -config COMMENT_HOOK - bool - -comment "comment" diff --git a/tests/Klocation_sourced b/tests/Klocation_sourced new file mode 100644 index 0000000..6e19f76 --- /dev/null +++ b/tests/Klocation_sourced @@ -0,0 +1,18 @@ + + +config MULTI_DEF + +choice CHOICE + bool "choice" +endchoice + +config MENU_HOOK + bool + +menu "menu" +endmenu + +config COMMENT_HOOK + bool + +comment "comment" diff --git a/tests/sub/Klocation_rsourced b/tests/sub/Klocation_rsourced new file mode 100644 index 0000000..c6f185d --- /dev/null +++ b/tests/sub/Klocation_rsourced @@ -0,0 +1,2 @@ + +config MULTI_DEF diff --git a/testsuite.py b/testsuite.py index fba897a..403fb06 100644 --- a/testsuite.py +++ b/testsuite.py @@ -787,7 +787,7 @@ g """) - print("Testing locations and 'source'") + print("Testing locations and 'source', 'rsource'") def verify_locations(nodes, *expected_locs): verify(len(nodes) == len(expected_locs), @@ -800,13 +800,15 @@ g .format(repr(node), expected_loc, node_loc)) # Expanded in the 'source' statement in Klocation - os.environ["EXPANDED_FROM_ENV"] = "tests" + os.environ["TESTS_DIR_FROM_ENV"] = "tests" + os.environ["SUB_DIR_FROM_ENV"] = "sub" os.environ["srctree"] = "Kconfiglib/" # Has symbol with empty help text, so disable warnings c = Kconfig("tests/Klocation", warn=False) - os.environ.pop("EXPANDED_FROM_ENV", None) + os.environ.pop("TESTS_DIR_FROM_ENV", None) + os.environ.pop("SUB_DIR_FROM_ENV", None) os.environ.pop("srctree", None) verify_locations(c.syms["SINGLE_DEF"].nodes, "tests/Klocation:4") @@ -814,17 +816,18 @@ g verify_locations(c.syms["MULTI_DEF"].nodes, "tests/Klocation:7", "tests/Klocation:31", - "tests/Klocation_included:3", - "tests/Klocation:47") + "tests/Klocation_sourced:3", + "tests/sub/Klocation_rsourced:2", + "tests/Klocation:57") verify_locations(c.named_choices["CHOICE"].nodes, - "tests/Klocation_included:5") + "tests/Klocation_sourced:5") verify_locations([c.syms["MENU_HOOK"].nodes[0].next], - "tests/Klocation_included:12") + "tests/Klocation_sourced:12") verify_locations([c.syms["COMMENT_HOOK"].nodes[0].next], - "tests/Klocation_included:18") + "tests/Klocation_sourced:18") # Test recursive 'source' detection -- cgit v1.2.3