diff mbox series

[16/16,v2] Makefile: introduce show-vars, a json-formatted equivalent to printvars

Message ID dac8f92abae72426b9b1c19f1a3ee5e173d101e3.1636810092.git.yann.morin.1998@free.fr
State Accepted
Headers show
Series core: add show-vars, a json-formatted equivalent to printvars (branch yem/show-vars) | expand

Commit Message

Yann E. MORIN Nov. 13, 2021, 1:28 p.m. UTC
The current printvars output suffers from a serious design flaw:
variables are not delimited, which makes it impossible to reliably
retrieve the value of variables; only variables that are known to
not contain a \n can be relatively safely extracted.

However, in some cases, it is important to be able to retrieve the
multi-line value of a variable, notably the CMDS or the hooks. One
such use-case (to follow in an unscheduled future) would be to hash
the variables that make up a package "configuration", and cache or
extract the files for that package to speed up the build.

Modeled after printvars and show-info, we introduce show-vars (what a
lack of imagination here) that outputs a json dictionary which keys are
the variable names, and for each variable, provides the raw and expanded
values.

Unlike printvars, we do not provide a way to get either the raw or
expanded value; both are systematically printed; a user will get just
the one is needs. Additionally, strings in JSON are quoted, so there is
no need to provide a way to quote variables; that would not make sense.

Note: for printvars, we require that the user provides an explicit
pattern to filter variables on. This is historical (see fd5bd12379dc,
Makefile: printvars: don't print anything when VARS is not set). The
underlying reasoning was that printvars is too "raw", and variables are
not well delimited, so printvars was mostly used to extract a few values
here and there, from scripts, or to quickly inspect a specific package's
variables during debugging.

But show-vars, although technically plain-text, being JSON, is not very
human-readable, and is mostly aimed at tools that will parse it with a
real JSON parser, and which will want to have a complete view of a lot
of variables at once. As such, and contrary to printvars, it makes sense
to report on all variables by default, unless the user explicitly
requested a subset.

As a final note: a lot of our variables only make sense in the context
of an actual make target. For example, a variable of package foo, that
contains $(@D)/bar, would expand to .../build/FOO-VERSION/bar. This is
because our CMDS and hooks are expanded as the recipe of a stamp file
that lies in the package build directory.

But for show-info, this falls flat on its face: it is not the stamp file
of a package, so there is no package directory, and show-info itself has
not directory part, so $(@D) expands to '.' (dot).

Additionally, some variables may contain calls to $(shell) (e.g. to call
pkg-config), and this also does not work with show-info.

These two issues make it impossible to emit the correct expanded value
of variables. To be noted: printvars has the exact same limitations for
the exact same reasons.

Signed-off-by: Yann E. MORIN <yann.morin.1998@free.fr>
---
 Makefile | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

Comments

Thomas Petazzoni Dec. 30, 2021, 8:47 p.m. UTC | #1
On Sat, 13 Nov 2021 14:28:27 +0100
"Yann E. MORIN" <yann.morin.1998@free.fr> wrote:

> The current printvars output suffers from a serious design flaw:
> variables are not delimited, which makes it impossible to reliably
> retrieve the value of variables; only variables that are known to
> not contain a \n can be relatively safely extracted.
> 
> However, in some cases, it is important to be able to retrieve the
> multi-line value of a variable, notably the CMDS or the hooks. One
> such use-case (to follow in an unscheduled future) would be to hash
> the variables that make up a package "configuration", and cache or
> extract the files for that package to speed up the build.
> 
> Modeled after printvars and show-info, we introduce show-vars (what a
> lack of imagination here) that outputs a json dictionary which keys are
> the variable names, and for each variable, provides the raw and expanded
> values.
> 
> Unlike printvars, we do not provide a way to get either the raw or
> expanded value; both are systematically printed; a user will get just
> the one is needs. Additionally, strings in JSON are quoted, so there is
> no need to provide a way to quote variables; that would not make sense.
> 
> Note: for printvars, we require that the user provides an explicit
> pattern to filter variables on. This is historical (see fd5bd12379dc,
> Makefile: printvars: don't print anything when VARS is not set). The
> underlying reasoning was that printvars is too "raw", and variables are
> not well delimited, so printvars was mostly used to extract a few values
> here and there, from scripts, or to quickly inspect a specific package's
> variables during debugging.
> 
> But show-vars, although technically plain-text, being JSON, is not very
> human-readable, and is mostly aimed at tools that will parse it with a
> real JSON parser, and which will want to have a complete view of a lot
> of variables at once. As such, and contrary to printvars, it makes sense
> to report on all variables by default, unless the user explicitly
> requested a subset.
> 
> As a final note: a lot of our variables only make sense in the context
> of an actual make target. For example, a variable of package foo, that
> contains $(@D)/bar, would expand to .../build/FOO-VERSION/bar. This is
> because our CMDS and hooks are expanded as the recipe of a stamp file
> that lies in the package build directory.
> 
> But for show-info, this falls flat on its face: it is not the stamp file
> of a package, so there is no package directory, and show-info itself has
> not directory part, so $(@D) expands to '.' (dot).
> 
> Additionally, some variables may contain calls to $(shell) (e.g. to call
> pkg-config), and this also does not work with show-info.
> 
> These two issues make it impossible to emit the correct expanded value
> of variables. To be noted: printvars has the exact same limitations for
> the exact same reasons.
> 
> Signed-off-by: Yann E. MORIN <yann.morin.1998@free.fr>
> ---
>  Makefile | 21 ++++++++++++++++++++-
>  1 file changed, 20 insertions(+), 1 deletion(-)

Applied to master, thanks.

However, there are two things that are missing:

 (1) Update to the Buildroot manual

 (2) At least one test case in supporting/testing/

Thanks!

Thomas
diff mbox series

Patch

diff --git a/Makefile b/Makefile
index 6f6bb72de3..0a24f7c5be 100644
--- a/Makefile
+++ b/Makefile
@@ -141,7 +141,7 @@  nobuild_targets := source %-source \
 	clean distclean help show-targets graph-depends \
 	%-graph-depends %-show-depends %-show-version \
 	graph-build graph-size list-defconfigs \
-	savedefconfig update-defconfig printvars
+	savedefconfig update-defconfig printvars show-vars
 ifeq ($(MAKECMDGOALS),)
 BR_BUILDING = y
 else ifneq ($(filter-out $(nobuild_targets),$(MAKECMDGOALS)),)
@@ -1058,6 +1058,7 @@  endif
 # Makefiles. Alternatively, if a non-empty VARS variable is passed,
 # only the variables matching the make pattern passed in VARS are
 # displayed.
+# show-vars does the same, but as a JSON dictionnary.
 .PHONY: printvars
 printvars:
 	@:
@@ -1070,6 +1071,22 @@  printvars:
 			$(info $V=$(if $(RAW_VARS),$(value $V),$($V))))))
 # ')))) # Syntax colouring...
 
+.PHONY: show-vars
+show-vars: VARS?=%
+show-vars:
+	@:
+	$(info $(call clean-json, { \
+			$(foreach V, \
+				$(sort $(filter $(VARS),$(.VARIABLES))), \
+				$(if $(filter-out environment% default automatic, $(origin $V)), \
+					"$V": { \
+						"expanded": $(call mk-json-str,$($V))$(comma) \
+						"raw": $(call mk-json-str,$(value $V)) \
+					}$(comma) \
+				) \
+			) \
+	} ))
+
 .PHONY: clean
 clean:
 	rm -rf $(BASE_TARGET_DIR) $(BINARIES_DIR) $(HOST_DIR) $(HOST_DIR_SYMLINK) \
@@ -1162,6 +1179,8 @@  help:
 	@echo '  pkg-stats              - generate info about packages as JSON and HTML'
 	@echo '  missing-cpe            - generate XML snippets for missing CPE identifiers'
 	@echo '  printvars              - dump internal variables selected with VARS=...'
+	@echo '  show-vars              - dump all internal variables as a JSON blurb; use VARS=...'
+	@echo '                             to limit the list to variables names matching that pattern'
 	@echo
 	@echo '  make V=0|1             - 0 => quiet build (default), 1 => verbose build'
 	@echo '  make O=dir             - Locate all output files in "dir", including .config'