2022-11-23 15:26:29

by Masahiro Yamada

[permalink] [raw]
Subject: [PATCH v2 1/5] kbuild: add test-{le,ge,lt,gt} macros

Because GNU Make is only able to handle strings, it is very hard to
perform arighmetic in Makefiles.

When we compare two integers, we invokes shell. One example is in the
top Makefile:

ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 130000; echo $$?),0)

This is more expensive than using built-in functions since it forks a
process.

If we know the two have the same number of digits, we can do better.

This commit adds four macros, test-le, test-ge, test-lt, test-gt.

$(call test-lt, A, B) is evaluated to 'y' if A is less than B, or
empty otherwise. This will replace $(call shell test A -lt B).

Again, the limitation is that A and B must have the same number of
digits because these macros are based on $(sort ) function.

$(call test-lt, 1, 9) --> y (Works!)
$(call test-lt, 10, 9) --> y (Not work...)

To make the latter work, you need to add '0' prefix to align the number
of digits:

$(call test-lt, 10, 09) --> empty (Works!)

Actually, we can live with this limitation in many places. As for the
example above, we know $(CONFIG_LLD_VERSION) is 6-digits because the
minimal supported version of LLVM is 11.0.0.

So, the shell invocation can be replaced with more efficient code:

ifeq ($(call test-lt, $(CONFIG_LLD_VERSION), 130000),y)

Of course, this assumption will break when LLVM 100 is released, but it
will be far in the future.

Signed-off-by: Masahiro Yamada <[email protected]>
---

(no changes since v1)

Makefile | 2 +-
arch/riscv/Makefile | 2 +-
arch/x86/Makefile | 2 +-
scripts/Kbuild.include | 10 ++++++++++
4 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile
index 6f846b1f2618..eb80332f7b51 100644
--- a/Makefile
+++ b/Makefile
@@ -986,7 +986,7 @@ KBUILD_LDFLAGS += -mllvm -import-instr-limit=5
# Check for frame size exceeding threshold during prolog/epilog insertion
# when using lld < 13.0.0.
ifneq ($(CONFIG_FRAME_WARN),0)
-ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 130000; echo $$?),0)
+ifeq ($(call test-lt, $(CONFIG_LLD_VERSION), 130000),y)
KBUILD_LDFLAGS += -plugin-opt=-warn-stack-size=$(CONFIG_FRAME_WARN)
endif
endif
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 0d13b597cb55..faf2c2177094 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -37,7 +37,7 @@ else
endif

ifeq ($(CONFIG_LD_IS_LLD),y)
-ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 150000; echo $$?),0)
+ifeq ($(call test-lt, $(CONFIG_LLD_VERSION), 150000),y)
KBUILD_CFLAGS += -mno-relax
KBUILD_AFLAGS += -mno-relax
ifndef CONFIG_AS_IS_LLVM
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 415a5d138de4..e72c7a49cd59 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -211,7 +211,7 @@ endif
KBUILD_LDFLAGS += -m elf_$(UTS_MACHINE)

ifdef CONFIG_LTO_CLANG
-ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 130000; echo $$?),0)
+ifeq ($(call test-lt, $(CONFIG_LLD_VERSION), 130000),y)
KBUILD_LDFLAGS += -plugin-opt=-stack-alignment=$(if $(CONFIG_X86_32),4,8)
endif
endif
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index cbe28744637b..9996f34327cb 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -11,6 +11,16 @@ space := $(empty) $(empty)
space_escape := _-_SPACE_-_
pound := \#

+###
+# Comparison macros.
+# Usage: $(call test-le, A, B)
+# works like shell's "test A -le B", but A and B must have the same number of
+# digits since it is just ASCII sort.
+test-le = $(if $(filter $1, $(firstword $(sort $1 $2))),y)
+test-ge = $(call test-le, $2, $1)
+test-lt = $(if $(filter-out $2, $(firstword $(sort $1 $2))),y)
+test-gt = $(call test-lt, $2, $1)
+
###
# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o
dot-target = $(dir $@).$(notdir $@)
--
2.34.1


2022-11-23 15:26:45

by Masahiro Yamada

[permalink] [raw]
Subject: [PATCH v2 5/5] kbuild: check Make version

This is implemented based on test-le. It will work until GNU Make 10
is released.

Signed-off-by: Masahiro Yamada <[email protected]>
---

(no changes since v1)

Makefile | 3 +++
1 file changed, 3 insertions(+)

diff --git a/Makefile b/Makefile
index 60ce9dcafc72..797fafbc1b45 100644
--- a/Makefile
+++ b/Makefile
@@ -368,6 +368,9 @@ else # !mixed-build

include $(srctree)/scripts/Kbuild.include

+# Check for the minimal Make version
+$(if $(call test-lt, $(MAKE_VERSION), 3.82), $(error Make $(MAKE_VERSION) is too old))
+
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
KERNELRELEASE = $(call read-file, include/config/kernel.release)
KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
--
2.34.1

2022-11-23 15:39:36

by Masahiro Yamada

[permalink] [raw]
Subject: [PATCH v2 2/5] kbuild: implement {gcc,clang}-min-version only with built-in functions

Converting clang-min-version is straightforward because the versions
are always 6-digit.

gcc-min-version is somewhat tricky because the minimal GCC version
is GCC 5.2; prepend '0' to the version that is less than 10 so that
test-ge is always passed with 6-digit versions.

Signed-off-by: Masahiro Yamada <[email protected]>
---

Changes in v2:
- Covert gcc-min-version in a different way

scripts/Makefile.compiler | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/scripts/Makefile.compiler b/scripts/Makefile.compiler
index 20d353dcabfb..cd75f81e88ef 100644
--- a/scripts/Makefile.compiler
+++ b/scripts/Makefile.compiler
@@ -63,11 +63,15 @@ cc-disable-warning = $(call try-run,\

# gcc-min-version
# Usage: cflags-$(call gcc-min-version, 70100) += -foo
-gcc-min-version = $(shell [ $(CONFIG_GCC_VERSION)0 -ge $(1)0 ] && echo y)
+
+# Preprend 0 to the version that is less than 10 so test-ge works.
+gcc-min-version = $(call test-ge, \
+ $(or $(filter 1%, $(CONFIG_GCC_VERSION)), 0$(CONFIG_GCC_VERSION)), \
+ $(or $(filter 1%, $1), 0$(strip $1)))

# clang-min-version
# Usage: cflags-$(call clang-min-version, 110000) += -foo
-clang-min-version = $(shell [ $(CONFIG_CLANG_VERSION)0 -ge $(1)0 ] && echo y)
+clang-min-version = $(call test-ge, $(CONFIG_CLANG_VERSION), $1)

# ld-option
# Usage: KBUILD_LDFLAGS += $(call ld-option, -X, -Y)
--
2.34.1

2022-11-23 15:40:36

by Masahiro Yamada

[permalink] [raw]
Subject: [PATCH v2 3/5] kbuild: add read-file macro

Since GMU Make 4.2, $(file ...) supports the read operater '<', which is
useful to read a file without forking any process. No warning is shown even
if the input file is missing.

For older Make versions, it falls back to the cat command.

Signed-off-by: Masahiro Yamada <[email protected]>
---

(no changes since v1)

Makefile | 2 +-
scripts/Kbuild.include | 12 ++++++++++++
scripts/Makefile.modfinal | 2 +-
scripts/Makefile.modinst | 2 +-
4 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile
index eb80332f7b51..60ce9dcafc72 100644
--- a/Makefile
+++ b/Makefile
@@ -369,7 +369,7 @@ else # !mixed-build
include $(srctree)/scripts/Kbuild.include

# Read KERNELRELEASE from include/config/kernel.release (if it exists)
-KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
+KERNELRELEASE = $(call read-file, include/config/kernel.release)
KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION

diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 9996f34327cb..722846c23264 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -10,6 +10,10 @@ empty :=
space := $(empty) $(empty)
space_escape := _-_SPACE_-_
pound := \#
+define newline
+
+
+endef

###
# Comparison macros.
@@ -55,6 +59,14 @@ stringify = $(squote)$(quote)$1$(quote)$(squote)
kbuild-dir = $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file = $(or $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Makefile)

+###
+# Read a file, replacing newlines with spaces
+ifeq ($(call test-ge, $(MAKE_VERSION), 4.2),y)
+read-file = $(subst $(newline),$(space),$(file < $1))
+else
+read-file = $(shell cat $1 2>/dev/null)
+endif
+
###
# Easy method for doing a status message
kecho := :
diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
index 25bedd83644b..7252f6cf7837 100644
--- a/scripts/Makefile.modfinal
+++ b/scripts/Makefile.modfinal
@@ -13,7 +13,7 @@ include $(srctree)/scripts/Kbuild.include
include $(srctree)/scripts/Makefile.lib

# find all modules listed in modules.order
-modules := $(sort $(shell cat $(MODORDER)))
+modules := $(sort $(call read-file, $(MODORDER)))

__modfinal: $(modules)
@:
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
index a4c987c23750..509d424dbbd2 100644
--- a/scripts/Makefile.modinst
+++ b/scripts/Makefile.modinst
@@ -9,7 +9,7 @@ __modinst:
include include/config/auto.conf
include $(srctree)/scripts/Kbuild.include

-modules := $(sort $(shell cat $(MODORDER)))
+modules := $(sort $(call read-file, $(MODORDER)))

ifeq ($(KBUILD_EXTMOD),)
dst := $(MODLIB)/kernel
--
2.34.1

2022-11-23 16:06:12

by Masahiro Yamada

[permalink] [raw]
Subject: [PATCH v2 4/5] kconfig: refactor Makefile to reduce process forks

Refactor Makefile and use read-file macro. For Make >= 4.2, it can read
out a file by using the built-in function.

Signed-off-by: Masahiro Yamada <[email protected]>
---

(no changes since v1)

scripts/kconfig/.gitignore | 4 +++-
scripts/kconfig/Makefile | 43 +++++++++++++++++++-----------------
scripts/kconfig/gconf-cfg.sh | 7 ++++--
scripts/kconfig/mconf-cfg.sh | 25 ++++++++++++---------
scripts/kconfig/nconf-cfg.sh | 23 ++++++++++---------
scripts/kconfig/qconf-cfg.sh | 10 ++++++---
scripts/remove-stale-files | 2 ++
7 files changed, 67 insertions(+), 47 deletions(-)

diff --git a/scripts/kconfig/.gitignore b/scripts/kconfig/.gitignore
index 500e7424b3ef..c8a3f9cd52f0 100644
--- a/scripts/kconfig/.gitignore
+++ b/scripts/kconfig/.gitignore
@@ -1,5 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
/conf
/[gmnq]conf
-/[gmnq]conf-cfg
+/[gmnq]conf-cflags
+/[gmnq]conf-libs
+/qconf-bin
/qconf-moc.cc
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index b8ef0fb4bbef..da7da9775a4b 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -159,11 +159,12 @@ conf-objs := conf.o $(common-objs)
hostprogs += nconf
nconf-objs := nconf.o nconf.gui.o $(common-objs)

-HOSTLDLIBS_nconf = $(shell . $(obj)/nconf-cfg && echo $$libs)
-HOSTCFLAGS_nconf.o = $(shell . $(obj)/nconf-cfg && echo $$cflags)
-HOSTCFLAGS_nconf.gui.o = $(shell . $(obj)/nconf-cfg && echo $$cflags)
+HOSTLDLIBS_nconf = $(call read-file, $(obj)/nconf-libs)
+HOSTCFLAGS_nconf.o = $(call read-file, $(obj)/nconf-cflags)
+HOSTCFLAGS_nconf.gui.o = $(call read-file, $(obj)/nconf-cflags)

-$(obj)/nconf.o $(obj)/nconf.gui.o: $(obj)/nconf-cfg
+$(obj)/nconf: | $(obj)/nconf-libs
+$(obj)/nconf.o $(obj)/nconf.gui.o: | $(obj)/nconf-cflags

# mconf: Used for the menuconfig target based on lxdialog
hostprogs += mconf
@@ -171,27 +172,28 @@ lxdialog := $(addprefix lxdialog/, \
checklist.o inputbox.o menubox.o textbox.o util.o yesno.o)
mconf-objs := mconf.o $(lxdialog) $(common-objs)

-HOSTLDLIBS_mconf = $(shell . $(obj)/mconf-cfg && echo $$libs)
+HOSTLDLIBS_mconf = $(call read-file, $(obj)/mconf-libs)
$(foreach f, mconf.o $(lxdialog), \
- $(eval HOSTCFLAGS_$f = $$(shell . $(obj)/mconf-cfg && echo $$$$cflags)))
+ $(eval HOSTCFLAGS_$f = $$(call read-file, $(obj)/mconf-cflags)))

-$(addprefix $(obj)/, mconf.o $(lxdialog)): $(obj)/mconf-cfg
+$(obj)/mconf: | $(obj)/mconf-libs
+$(addprefix $(obj)/, mconf.o $(lxdialog)): | $(obj)/mconf-cflags

# qconf: Used for the xconfig target based on Qt
hostprogs += qconf
qconf-cxxobjs := qconf.o qconf-moc.o
qconf-objs := images.o $(common-objs)

-HOSTLDLIBS_qconf = $(shell . $(obj)/qconf-cfg && echo $$libs)
-HOSTCXXFLAGS_qconf.o = $(shell . $(obj)/qconf-cfg && echo $$cflags)
-HOSTCXXFLAGS_qconf-moc.o = $(shell . $(obj)/qconf-cfg && echo $$cflags)
-
-$(obj)/qconf.o: $(obj)/qconf-cfg
+HOSTLDLIBS_qconf = $(call read-file, $(obj)/qconf-libs)
+HOSTCXXFLAGS_qconf.o = -std=c++11 -fPIC $(call read-file, $(obj)/qconf-cflags)
+HOSTCXXFLAGS_qconf-moc.o = -std=c++11 -fPIC $(call read-file, $(obj)/qconf-cflags)
+$(obj)/qconf: | $(obj)/qconf-libs
+$(obj)/qconf.o $(obj)/qconf-moc.o: | $(obj)/qconf-cflags

quiet_cmd_moc = MOC $@
- cmd_moc = $(shell . $(obj)/qconf-cfg && echo $$moc) $< -o $@
+ cmd_moc = $(call read-file, $(obj)/qconf-bin)/moc $< -o $@

-$(obj)/qconf-moc.cc: $(src)/qconf.h $(obj)/qconf-cfg FORCE
+$(obj)/qconf-moc.cc: $(src)/qconf.h FORCE | $(obj)/qconf-bin
$(call if_changed,moc)

targets += qconf-moc.cc
@@ -200,15 +202,16 @@ targets += qconf-moc.cc
hostprogs += gconf
gconf-objs := gconf.o images.o $(common-objs)

-HOSTLDLIBS_gconf = $(shell . $(obj)/gconf-cfg && echo $$libs)
-HOSTCFLAGS_gconf.o = $(shell . $(obj)/gconf-cfg && echo $$cflags)
+HOSTLDLIBS_gconf = $(call read-file, $(obj)/gconf-libs)
+HOSTCFLAGS_gconf.o = $(call read-file, $(obj)/gconf-cflags)

-$(obj)/gconf.o: $(obj)/gconf-cfg
+$(obj)/gconf: | $(obj)/gconf-libs
+$(obj)/gconf.o: | $(obj)/gconf-cflags

# check if necessary packages are available, and configure build flags
-filechk_conf_cfg = $(CONFIG_SHELL) $<
+cmd_conf_cfg = $< $(addprefix $(obj)/$*conf-, cflags libs bin)

-$(obj)/%conf-cfg: $(src)/%conf-cfg.sh FORCE
- $(call filechk,conf_cfg)
+$(obj)/%conf-cflags $(obj)/%conf-libs $(obj)/%conf-bin: $(src)/%conf-cfg.sh
+ $(call cmd,conf_cfg)

clean-files += *conf-cfg
diff --git a/scripts/kconfig/gconf-cfg.sh b/scripts/kconfig/gconf-cfg.sh
index cbd90c28c05f..040d8f338820 100755
--- a/scripts/kconfig/gconf-cfg.sh
+++ b/scripts/kconfig/gconf-cfg.sh
@@ -1,6 +1,9 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0

+cflags=$1
+libs=$2
+
PKG="gtk+-2.0 gmodule-2.0 libglade-2.0"

if [ -z "$(command -v ${HOSTPKG_CONFIG})" ]; then
@@ -26,5 +29,5 @@ if ! ${HOSTPKG_CONFIG} --atleast-version=2.0.0 gtk+-2.0; then
exit 1
fi

-echo cflags=\"$(${HOSTPKG_CONFIG} --cflags $PKG)\"
-echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG)\"
+${HOSTPKG_CONFIG} --cflags ${PKG} > ${cflags}
+${HOSTPKG_CONFIG} --libs ${PKG} > ${libs}
diff --git a/scripts/kconfig/mconf-cfg.sh b/scripts/kconfig/mconf-cfg.sh
index 025b565e0b7c..1e61f50a5905 100755
--- a/scripts/kconfig/mconf-cfg.sh
+++ b/scripts/kconfig/mconf-cfg.sh
@@ -1,19 +1,22 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0

+cflags=$1
+libs=$2
+
PKG="ncursesw"
PKG2="ncurses"

if [ -n "$(command -v ${HOSTPKG_CONFIG})" ]; then
if ${HOSTPKG_CONFIG} --exists $PKG; then
- echo cflags=\"$(${HOSTPKG_CONFIG} --cflags $PKG)\"
- echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG)\"
+ ${HOSTPKG_CONFIG} --cflags ${PKG} > ${cflags}
+ ${HOSTPKG_CONFIG} --libs ${PKG} > ${libs}
exit 0
fi

- if ${HOSTPKG_CONFIG} --exists $PKG2; then
- echo cflags=\"$(${HOSTPKG_CONFIG} --cflags $PKG2)\"
- echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG2)\"
+ if ${HOSTPKG_CONFIG} --exists ${PKG2}; then
+ ${HOSTPKG_CONFIG} --cflags ${PKG2} > ${cflags}
+ ${HOSTPKG_CONFIG} --libs ${PKG2} > ${libs}
exit 0
fi
fi
@@ -22,22 +25,22 @@ fi
# (Even if it is installed, some distributions such as openSUSE cannot
# find ncurses by pkg-config.)
if [ -f /usr/include/ncursesw/ncurses.h ]; then
- echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncursesw\"
- echo libs=\"-lncursesw\"
+ echo -D_GNU_SOURCE -I/usr/include/ncursesw > ${cflags}
+ echo -lncursesw > ${libs}
exit 0
fi

if [ -f /usr/include/ncurses/ncurses.h ]; then
- echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncurses\"
- echo libs=\"-lncurses\"
+ echo -D_GNU_SOURCE -I/usr/include/ncurses > ${cflags}
+ echo -lncurses > ${libs}
exit 0
fi

# As a final fallback before giving up, check if $HOSTCC knows of a default
# ncurses installation (e.g. from a vendor-specific sysroot).
if echo '#include <ncurses.h>' | ${HOSTCC} -E - >/dev/null 2>&1; then
- echo cflags=\"-D_GNU_SOURCE\"
- echo libs=\"-lncurses\"
+ echo -D_GNU_SOURCE > ${cflags}
+ echo -lncurses > ${libs}
exit 0
fi

diff --git a/scripts/kconfig/nconf-cfg.sh b/scripts/kconfig/nconf-cfg.sh
index 3a10bac2adb3..f871a2160e36 100755
--- a/scripts/kconfig/nconf-cfg.sh
+++ b/scripts/kconfig/nconf-cfg.sh
@@ -1,19 +1,22 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0

+cflags=$1
+libs=$2
+
PKG="ncursesw menuw panelw"
PKG2="ncurses menu panel"

if [ -n "$(command -v ${HOSTPKG_CONFIG})" ]; then
if ${HOSTPKG_CONFIG} --exists $PKG; then
- echo cflags=\"$(${HOSTPKG_CONFIG} --cflags $PKG)\"
- echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG)\"
+ ${HOSTPKG_CONFIG} --cflags ${PKG} > ${cflags}
+ ${HOSTPKG_CONFIG} --libs ${PKG} > ${libs}
exit 0
fi

if ${HOSTPKG_CONFIG} --exists $PKG2; then
- echo cflags=\"$(${HOSTPKG_CONFIG} --cflags $PKG2)\"
- echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG2)\"
+ ${HOSTPKG_CONFIG} --cflags ${PKG2} > ${cflags}
+ ${HOSTPKG_CONFIG} --libs ${PKG2} > ${libs}
exit 0
fi
fi
@@ -22,20 +25,20 @@ fi
# (Even if it is installed, some distributions such as openSUSE cannot
# find ncurses by pkg-config.)
if [ -f /usr/include/ncursesw/ncurses.h ]; then
- echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncursesw\"
- echo libs=\"-lncursesw -lmenuw -lpanelw\"
+ echo -D_GNU_SOURCE -I/usr/include/ncursesw > ${cflags}
+ echo -lncursesw -lmenuw -lpanelw > ${libs}
exit 0
fi

if [ -f /usr/include/ncurses/ncurses.h ]; then
- echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncurses\"
- echo libs=\"-lncurses -lmenu -lpanel\"
+ echo -D_GNU_SOURCE -I/usr/include/ncurses > ${cflags}
+ echo -lncurses -lmenu -lpanel > ${libs}
exit 0
fi

if [ -f /usr/include/ncurses.h ]; then
- echo cflags=\"-D_GNU_SOURCE\"
- echo libs=\"-lncurses -lmenu -lpanel\"
+ echo -D_GNU_SOURCE > ${cflags}
+ echo -lncurses -lmenu -lpanel > ${libs}
exit 0
fi

diff --git a/scripts/kconfig/qconf-cfg.sh b/scripts/kconfig/qconf-cfg.sh
index ad652cb53947..117f36e568fc 100755
--- a/scripts/kconfig/qconf-cfg.sh
+++ b/scripts/kconfig/qconf-cfg.sh
@@ -1,6 +1,10 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0

+cflags=$1
+libs=$2
+bin=$3
+
PKG="Qt5Core Qt5Gui Qt5Widgets"

if [ -z "$(command -v ${HOSTPKG_CONFIG})" ]; then
@@ -11,9 +15,9 @@ if [ -z "$(command -v ${HOSTPKG_CONFIG})" ]; then
fi

if ${HOSTPKG_CONFIG} --exists $PKG; then
- echo cflags=\"-std=c++11 -fPIC $(${HOSTPKG_CONFIG} --cflags $PKG)\"
- echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG)\"
- echo moc=\"$(${HOSTPKG_CONFIG} --variable=host_bins Qt5Core)/moc\"
+ ${HOSTPKG_CONFIG} --cflags ${PKG} > ${cflags}
+ ${HOSTPKG_CONFIG} --libs ${PKG} > ${libs}
+ ${HOSTPKG_CONFIG} --variable=host_bins Qt5Core > ${bin}
exit 0
fi

diff --git a/scripts/remove-stale-files b/scripts/remove-stale-files
index ccadfa3afb2b..64b14aa5aebf 100755
--- a/scripts/remove-stale-files
+++ b/scripts/remove-stale-files
@@ -47,3 +47,5 @@ rm -f arch/riscv/purgatory/kexec-purgatory.c
rm -f scripts/extract-cert

rm -f arch/x86/purgatory/kexec-purgatory.c
+
+rm -f scripts/kconfig/[gmnq]conf-cfg
--
2.34.1

2022-11-23 20:34:09

by Nicolas Schier

[permalink] [raw]
Subject: Re: [PATCH v2 1/5] kbuild: add test-{le,ge,lt,gt} macros

On Thu 24 Nov 2022 00:18:24 GMT, Masahiro Yamada wrote:
> Because GNU Make is only able to handle strings, it is very hard to
> perform arighmetic in Makefiles.
>
> When we compare two integers, we invokes shell. One example is in the
> top Makefile:
>
> ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 130000; echo $$?),0)
>
> This is more expensive than using built-in functions since it forks a
> process.
>
> If we know the two have the same number of digits, we can do better.
>
> This commit adds four macros, test-le, test-ge, test-lt, test-gt.
>
> $(call test-lt, A, B) is evaluated to 'y' if A is less than B, or
> empty otherwise. This will replace $(call shell test A -lt B).
>
> Again, the limitation is that A and B must have the same number of
> digits because these macros are based on $(sort ) function.
>
> $(call test-lt, 1, 9) --> y (Works!)
> $(call test-lt, 10, 9) --> y (Not work...)
>
> To make the latter work, you need to add '0' prefix to align the number
> of digits:
>
> $(call test-lt, 10, 09) --> empty (Works!)
>
> Actually, we can live with this limitation in many places. As for the
> example above, we know $(CONFIG_LLD_VERSION) is 6-digits because the
> minimal supported version of LLVM is 11.0.0.
>
> So, the shell invocation can be replaced with more efficient code:
>
> ifeq ($(call test-lt, $(CONFIG_LLD_VERSION), 130000),y)
>
> Of course, this assumption will break when LLVM 100 is released, but it
> will be far in the future.
>
> Signed-off-by: Masahiro Yamada <[email protected]>
> ---
>
> (no changes since v1)
>
> Makefile | 2 +-
> arch/riscv/Makefile | 2 +-
> arch/x86/Makefile | 2 +-
> scripts/Kbuild.include | 10 ++++++++++
> 4 files changed, 13 insertions(+), 3 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index 6f846b1f2618..eb80332f7b51 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -986,7 +986,7 @@ KBUILD_LDFLAGS += -mllvm -import-instr-limit=5
> # Check for frame size exceeding threshold during prolog/epilog insertion
> # when using lld < 13.0.0.
> ifneq ($(CONFIG_FRAME_WARN),0)
> -ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 130000; echo $$?),0)
> +ifeq ($(call test-lt, $(CONFIG_LLD_VERSION), 130000),y)
> KBUILD_LDFLAGS += -plugin-opt=-warn-stack-size=$(CONFIG_FRAME_WARN)
> endif
> endif
> diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
> index 0d13b597cb55..faf2c2177094 100644
> --- a/arch/riscv/Makefile
> +++ b/arch/riscv/Makefile
> @@ -37,7 +37,7 @@ else
> endif
>
> ifeq ($(CONFIG_LD_IS_LLD),y)
> -ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 150000; echo $$?),0)
> +ifeq ($(call test-lt, $(CONFIG_LLD_VERSION), 150000),y)
> KBUILD_CFLAGS += -mno-relax
> KBUILD_AFLAGS += -mno-relax
> ifndef CONFIG_AS_IS_LLVM
> diff --git a/arch/x86/Makefile b/arch/x86/Makefile
> index 415a5d138de4..e72c7a49cd59 100644
> --- a/arch/x86/Makefile
> +++ b/arch/x86/Makefile
> @@ -211,7 +211,7 @@ endif
> KBUILD_LDFLAGS += -m elf_$(UTS_MACHINE)
>
> ifdef CONFIG_LTO_CLANG
> -ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 130000; echo $$?),0)
> +ifeq ($(call test-lt, $(CONFIG_LLD_VERSION), 130000),y)
> KBUILD_LDFLAGS += -plugin-opt=-stack-alignment=$(if $(CONFIG_X86_32),4,8)
> endif
> endif
> diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
> index cbe28744637b..9996f34327cb 100644
> --- a/scripts/Kbuild.include
> +++ b/scripts/Kbuild.include
> @@ -11,6 +11,16 @@ space := $(empty) $(empty)
> space_escape := _-_SPACE_-_
> pound := \#
>
> +###
> +# Comparison macros.
> +# Usage: $(call test-le, A, B)
> +# works like shell's "test A -le B", but A and B must have the same number of
> +# digits since it is just ASCII sort.
> +test-le = $(if $(filter $1, $(firstword $(sort $1 $2))),y)
> +test-ge = $(call test-le, $2, $1)
> +test-lt = $(if $(filter-out $2, $(firstword $(sort $1 $2))),y)
> +test-gt = $(call test-lt, $2, $1)
> +

I like that whole patch set, thanks! A cherry on the cake would be a
sanity check for equal length of A and B ...

Reviewed-by: Nicolas Schier <[email protected]>

> ###
> # Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o
> dot-target = $(dir $@).$(notdir $@)
> --
> 2.34.1

--
epost|xmpp: [email protected] irc://oftc.net/nsc
↳ gpg: 18ed 52db e34f 860e e9fb c82b 7d97 0932 55a0 ce7f
-- frykten for herren er opphav til kunnskap --


Attachments:
(No filename) (4.42 kB)
signature.asc (849.00 B)
Download all attachments

2022-11-23 21:14:39

by Nicolas Schier

[permalink] [raw]
Subject: Re: [PATCH v2 3/5] kbuild: add read-file macro

On Thu 24 Nov 2022 00:18:26 GMT, Masahiro Yamada wrote:
> Since GMU Make 4.2, $(file ...) supports the read operater '<', which is
> useful to read a file without forking any process. No warning is shown even
> if the input file is missing.
>
> For older Make versions, it falls back to the cat command.
>
> Signed-off-by: Masahiro Yamada <[email protected]>
> ---
>
> (no changes since v1)
>
> Makefile | 2 +-
> scripts/Kbuild.include | 12 ++++++++++++
> scripts/Makefile.modfinal | 2 +-
> scripts/Makefile.modinst | 2 +-
> 4 files changed, 15 insertions(+), 3 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index eb80332f7b51..60ce9dcafc72 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -369,7 +369,7 @@ else # !mixed-build
> include $(srctree)/scripts/Kbuild.include
>
> # Read KERNELRELEASE from include/config/kernel.release (if it exists)
> -KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
> +KERNELRELEASE = $(call read-file, include/config/kernel.release)
> KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
> export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
>
> diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
> index 9996f34327cb..722846c23264 100644
> --- a/scripts/Kbuild.include
> +++ b/scripts/Kbuild.include
> @@ -10,6 +10,10 @@ empty :=
> space := $(empty) $(empty)
> space_escape := _-_SPACE_-_
> pound := \#
> +define newline
> +
> +
> +endef
>
> ###
> # Comparison macros.
> @@ -55,6 +59,14 @@ stringify = $(squote)$(quote)$1$(quote)$(squote)
> kbuild-dir = $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
> kbuild-file = $(or $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Makefile)
>
> +###
> +# Read a file, replacing newlines with spaces
> +ifeq ($(call test-ge, $(MAKE_VERSION), 4.2),y)
> +read-file = $(subst $(newline),$(space),$(file < $1))
> +else
> +read-file = $(shell cat $1 2>/dev/null)
> +endif
> +

I like the implementation of read-file, but I am afraid that the
MAKE_VERSION comparison breaks all make versions w/ a minor version
number: 3.99.9x, 4.2.x, 4.3.x.

Not beautiful, but this might possibly work:
ifneq ($(filter 3.% 4.0 4.0.% 4.1 4.1.%,$(MAKE_VERSION)),)
read-file = ...


Kind regards,
Nicolas


> ###
> # Easy method for doing a status message
> kecho := :
> diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
> index 25bedd83644b..7252f6cf7837 100644
> --- a/scripts/Makefile.modfinal
> +++ b/scripts/Makefile.modfinal
> @@ -13,7 +13,7 @@ include $(srctree)/scripts/Kbuild.include
> include $(srctree)/scripts/Makefile.lib
>
> # find all modules listed in modules.order
> -modules := $(sort $(shell cat $(MODORDER)))
> +modules := $(sort $(call read-file, $(MODORDER)))
>
> __modfinal: $(modules)
> @:
> diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
> index a4c987c23750..509d424dbbd2 100644
> --- a/scripts/Makefile.modinst
> +++ b/scripts/Makefile.modinst
> @@ -9,7 +9,7 @@ __modinst:
> include include/config/auto.conf
> include $(srctree)/scripts/Kbuild.include
>
> -modules := $(sort $(shell cat $(MODORDER)))
> +modules := $(sort $(call read-file, $(MODORDER)))
>
> ifeq ($(KBUILD_EXTMOD),)
> dst := $(MODLIB)/kernel
> --
> 2.34.1

--
epost|xmpp: [email protected] irc://oftc.net/nsc
↳ gpg: 18ed 52db e34f 860e e9fb c82b 7d97 0932 55a0 ce7f
-- frykten for herren er opphav til kunnskap --


Attachments:
(No filename) (3.53 kB)
signature.asc (849.00 B)
Download all attachments

2022-11-23 21:36:21

by Nicolas Schier

[permalink] [raw]
Subject: Re: [PATCH v2 2/5] kbuild: implement {gcc,clang}-min-version only with built-in functions

On Thu 24 Nov 2022 00:18:25 GMT, Masahiro Yamada wrote:
> Converting clang-min-version is straightforward because the versions
> are always 6-digit.
>
> gcc-min-version is somewhat tricky because the minimal GCC version
> is GCC 5.2; prepend '0' to the version that is less than 10 so that
> test-ge is always passed with 6-digit versions.
>
> Signed-off-by: Masahiro Yamada <[email protected]>
> ---
>
> Changes in v2:
> - Covert gcc-min-version in a different way
>
> scripts/Makefile.compiler | 8 ++++++--
> 1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/scripts/Makefile.compiler b/scripts/Makefile.compiler
> index 20d353dcabfb..cd75f81e88ef 100644
> --- a/scripts/Makefile.compiler
> +++ b/scripts/Makefile.compiler
> @@ -63,11 +63,15 @@ cc-disable-warning = $(call try-run,\
>
> # gcc-min-version
> # Usage: cflags-$(call gcc-min-version, 70100) += -foo
> -gcc-min-version = $(shell [ $(CONFIG_GCC_VERSION)0 -ge $(1)0 ] && echo y)
> +
> +# Preprend 0 to the version that is less than 10 so test-ge works.
> +gcc-min-version = $(call test-ge, \
> + $(or $(filter 1%, $(CONFIG_GCC_VERSION)), 0$(CONFIG_GCC_VERSION)), \
> + $(or $(filter 1%, $1), 0$(strip $1)))

Hm, this silently expects a gcc version < 20, which we should expect in
about seven-eight years [1]. I am thinking about the possibility of
silent (but unlikely) breaks when someone in far future uses a gcc 20
against a kernel with this line. Probably we should not care about
that today, yet, right?

Reviewed-by: Nicolas Schier <[email protected]>

[1]: https://gcc.gnu.org/develop.html#timeline

>
> # clang-min-version
> # Usage: cflags-$(call clang-min-version, 110000) += -foo
> -clang-min-version = $(shell [ $(CONFIG_CLANG_VERSION)0 -ge $(1)0 ] && echo y)
> +clang-min-version = $(call test-ge, $(CONFIG_CLANG_VERSION), $1)
>
> # ld-option
> # Usage: KBUILD_LDFLAGS += $(call ld-option, -X, -Y)
> --
> 2.34.1

--
epost|xmpp: [email protected] irc://oftc.net/nsc
↳ gpg: 18ed 52db e34f 860e e9fb c82b 7d97 0932 55a0 ce7f
-- frykten for herren er opphav til kunnskap --


Attachments:
(No filename) (2.15 kB)
signature.asc (849.00 B)
Download all attachments

2022-11-23 21:41:41

by Nicolas Schier

[permalink] [raw]
Subject: Re: [PATCH v2 4/5] kconfig: refactor Makefile to reduce process forks

On Thu 24 Nov 2022 00:18:27 GMT, Masahiro Yamada wrote:
> Refactor Makefile and use read-file macro. For Make >= 4.2, it can
> read
> out a file by using the built-in function.
>
> Signed-off-by: Masahiro Yamada <[email protected]>
> ---

Reviewed-by: Nicolas Schier <[email protected]>

>
> (no changes since v1)
>
> scripts/kconfig/.gitignore | 4 +++-
> scripts/kconfig/Makefile | 43 +++++++++++++++++++-----------------
> scripts/kconfig/gconf-cfg.sh | 7 ++++--
> scripts/kconfig/mconf-cfg.sh | 25 ++++++++++++---------
> scripts/kconfig/nconf-cfg.sh | 23 ++++++++++---------
> scripts/kconfig/qconf-cfg.sh | 10 ++++++---
> scripts/remove-stale-files | 2 ++
> 7 files changed, 67 insertions(+), 47 deletions(-)
>
> diff --git a/scripts/kconfig/.gitignore b/scripts/kconfig/.gitignore
> index 500e7424b3ef..c8a3f9cd52f0 100644
> --- a/scripts/kconfig/.gitignore
> +++ b/scripts/kconfig/.gitignore
> @@ -1,5 +1,7 @@
> # SPDX-License-Identifier: GPL-2.0-only
> /conf
> /[gmnq]conf
> -/[gmnq]conf-cfg
> +/[gmnq]conf-cflags
> +/[gmnq]conf-libs
> +/qconf-bin
> /qconf-moc.cc
> diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
> index b8ef0fb4bbef..da7da9775a4b 100644
> --- a/scripts/kconfig/Makefile
> +++ b/scripts/kconfig/Makefile
> @@ -159,11 +159,12 @@ conf-objs := conf.o $(common-objs)
> hostprogs += nconf
> nconf-objs := nconf.o nconf.gui.o $(common-objs)
>
> -HOSTLDLIBS_nconf = $(shell . $(obj)/nconf-cfg && echo $$libs)
> -HOSTCFLAGS_nconf.o = $(shell . $(obj)/nconf-cfg && echo $$cflags)
> -HOSTCFLAGS_nconf.gui.o = $(shell . $(obj)/nconf-cfg && echo $$cflags)
> +HOSTLDLIBS_nconf = $(call read-file, $(obj)/nconf-libs)
> +HOSTCFLAGS_nconf.o = $(call read-file, $(obj)/nconf-cflags)
> +HOSTCFLAGS_nconf.gui.o = $(call read-file, $(obj)/nconf-cflags)
>
> -$(obj)/nconf.o $(obj)/nconf.gui.o: $(obj)/nconf-cfg
> +$(obj)/nconf: | $(obj)/nconf-libs
> +$(obj)/nconf.o $(obj)/nconf.gui.o: | $(obj)/nconf-cflags
>
> # mconf: Used for the menuconfig target based on lxdialog
> hostprogs += mconf
> @@ -171,27 +172,28 @@ lxdialog := $(addprefix lxdialog/, \
> checklist.o inputbox.o menubox.o textbox.o util.o yesno.o)
> mconf-objs := mconf.o $(lxdialog) $(common-objs)
>
> -HOSTLDLIBS_mconf = $(shell . $(obj)/mconf-cfg && echo $$libs)
> +HOSTLDLIBS_mconf = $(call read-file, $(obj)/mconf-libs)
> $(foreach f, mconf.o $(lxdialog), \
> - $(eval HOSTCFLAGS_$f = $$(shell . $(obj)/mconf-cfg && echo $$$$cflags)))
> + $(eval HOSTCFLAGS_$f = $$(call read-file, $(obj)/mconf-cflags)))
>
> -$(addprefix $(obj)/, mconf.o $(lxdialog)): $(obj)/mconf-cfg
> +$(obj)/mconf: | $(obj)/mconf-libs
> +$(addprefix $(obj)/, mconf.o $(lxdialog)): | $(obj)/mconf-cflags
>
> # qconf: Used for the xconfig target based on Qt
> hostprogs += qconf
> qconf-cxxobjs := qconf.o qconf-moc.o
> qconf-objs := images.o $(common-objs)
>
> -HOSTLDLIBS_qconf = $(shell . $(obj)/qconf-cfg && echo $$libs)
> -HOSTCXXFLAGS_qconf.o = $(shell . $(obj)/qconf-cfg && echo $$cflags)
> -HOSTCXXFLAGS_qconf-moc.o = $(shell . $(obj)/qconf-cfg && echo $$cflags)
> -
> -$(obj)/qconf.o: $(obj)/qconf-cfg
> +HOSTLDLIBS_qconf = $(call read-file, $(obj)/qconf-libs)
> +HOSTCXXFLAGS_qconf.o = -std=c++11 -fPIC $(call read-file, $(obj)/qconf-cflags)
> +HOSTCXXFLAGS_qconf-moc.o = -std=c++11 -fPIC $(call read-file, $(obj)/qconf-cflags)
> +$(obj)/qconf: | $(obj)/qconf-libs
> +$(obj)/qconf.o $(obj)/qconf-moc.o: | $(obj)/qconf-cflags
>
> quiet_cmd_moc = MOC $@
> - cmd_moc = $(shell . $(obj)/qconf-cfg && echo $$moc) $< -o $@
> + cmd_moc = $(call read-file, $(obj)/qconf-bin)/moc $< -o $@
>
> -$(obj)/qconf-moc.cc: $(src)/qconf.h $(obj)/qconf-cfg FORCE
> +$(obj)/qconf-moc.cc: $(src)/qconf.h FORCE | $(obj)/qconf-bin
> $(call if_changed,moc)
>
> targets += qconf-moc.cc
> @@ -200,15 +202,16 @@ targets += qconf-moc.cc
> hostprogs += gconf
> gconf-objs := gconf.o images.o $(common-objs)
>
> -HOSTLDLIBS_gconf = $(shell . $(obj)/gconf-cfg && echo $$libs)
> -HOSTCFLAGS_gconf.o = $(shell . $(obj)/gconf-cfg && echo $$cflags)
> +HOSTLDLIBS_gconf = $(call read-file, $(obj)/gconf-libs)
> +HOSTCFLAGS_gconf.o = $(call read-file, $(obj)/gconf-cflags)
>
> -$(obj)/gconf.o: $(obj)/gconf-cfg
> +$(obj)/gconf: | $(obj)/gconf-libs
> +$(obj)/gconf.o: | $(obj)/gconf-cflags
>
> # check if necessary packages are available, and configure build flags
> -filechk_conf_cfg = $(CONFIG_SHELL) $<
> +cmd_conf_cfg = $< $(addprefix $(obj)/$*conf-, cflags libs bin)
>
> -$(obj)/%conf-cfg: $(src)/%conf-cfg.sh FORCE
> - $(call filechk,conf_cfg)
> +$(obj)/%conf-cflags $(obj)/%conf-libs $(obj)/%conf-bin: $(src)/%conf-cfg.sh
> + $(call cmd,conf_cfg)
>
> clean-files += *conf-cfg
> diff --git a/scripts/kconfig/gconf-cfg.sh b/scripts/kconfig/gconf-cfg.sh
> index cbd90c28c05f..040d8f338820 100755
> --- a/scripts/kconfig/gconf-cfg.sh
> +++ b/scripts/kconfig/gconf-cfg.sh
> @@ -1,6 +1,9 @@
> #!/bin/sh
> # SPDX-License-Identifier: GPL-2.0
>
> +cflags=$1
> +libs=$2
> +
> PKG="gtk+-2.0 gmodule-2.0 libglade-2.0"
>
> if [ -z "$(command -v ${HOSTPKG_CONFIG})" ]; then
> @@ -26,5 +29,5 @@ if ! ${HOSTPKG_CONFIG} --atleast-version=2.0.0 gtk+-2.0; then
> exit 1
> fi
>
> -echo cflags=\"$(${HOSTPKG_CONFIG} --cflags $PKG)\"
> -echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG)\"
> +${HOSTPKG_CONFIG} --cflags ${PKG} > ${cflags}
> +${HOSTPKG_CONFIG} --libs ${PKG} > ${libs}
> diff --git a/scripts/kconfig/mconf-cfg.sh b/scripts/kconfig/mconf-cfg.sh
> index 025b565e0b7c..1e61f50a5905 100755
> --- a/scripts/kconfig/mconf-cfg.sh
> +++ b/scripts/kconfig/mconf-cfg.sh
> @@ -1,19 +1,22 @@
> #!/bin/sh
> # SPDX-License-Identifier: GPL-2.0
>
> +cflags=$1
> +libs=$2
> +
> PKG="ncursesw"
> PKG2="ncurses"
>
> if [ -n "$(command -v ${HOSTPKG_CONFIG})" ]; then
> if ${HOSTPKG_CONFIG} --exists $PKG; then
> - echo cflags=\"$(${HOSTPKG_CONFIG} --cflags $PKG)\"
> - echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG)\"
> + ${HOSTPKG_CONFIG} --cflags ${PKG} > ${cflags}
> + ${HOSTPKG_CONFIG} --libs ${PKG} > ${libs}
> exit 0
> fi
>
> - if ${HOSTPKG_CONFIG} --exists $PKG2; then
> - echo cflags=\"$(${HOSTPKG_CONFIG} --cflags $PKG2)\"
> - echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG2)\"
> + if ${HOSTPKG_CONFIG} --exists ${PKG2}; then
> + ${HOSTPKG_CONFIG} --cflags ${PKG2} > ${cflags}
> + ${HOSTPKG_CONFIG} --libs ${PKG2} > ${libs}
> exit 0
> fi
> fi
> @@ -22,22 +25,22 @@ fi
> # (Even if it is installed, some distributions such as openSUSE cannot
> # find ncurses by pkg-config.)
> if [ -f /usr/include/ncursesw/ncurses.h ]; then
> - echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncursesw\"
> - echo libs=\"-lncursesw\"
> + echo -D_GNU_SOURCE -I/usr/include/ncursesw > ${cflags}
> + echo -lncursesw > ${libs}
> exit 0
> fi
>
> if [ -f /usr/include/ncurses/ncurses.h ]; then
> - echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncurses\"
> - echo libs=\"-lncurses\"
> + echo -D_GNU_SOURCE -I/usr/include/ncurses > ${cflags}
> + echo -lncurses > ${libs}
> exit 0
> fi
>
> # As a final fallback before giving up, check if $HOSTCC knows of a default
> # ncurses installation (e.g. from a vendor-specific sysroot).
> if echo '#include <ncurses.h>' | ${HOSTCC} -E - >/dev/null 2>&1; then
> - echo cflags=\"-D_GNU_SOURCE\"
> - echo libs=\"-lncurses\"
> + echo -D_GNU_SOURCE > ${cflags}
> + echo -lncurses > ${libs}
> exit 0
> fi
>
> diff --git a/scripts/kconfig/nconf-cfg.sh b/scripts/kconfig/nconf-cfg.sh
> index 3a10bac2adb3..f871a2160e36 100755
> --- a/scripts/kconfig/nconf-cfg.sh
> +++ b/scripts/kconfig/nconf-cfg.sh
> @@ -1,19 +1,22 @@
> #!/bin/sh
> # SPDX-License-Identifier: GPL-2.0
>
> +cflags=$1
> +libs=$2
> +
> PKG="ncursesw menuw panelw"
> PKG2="ncurses menu panel"
>
> if [ -n "$(command -v ${HOSTPKG_CONFIG})" ]; then
> if ${HOSTPKG_CONFIG} --exists $PKG; then
> - echo cflags=\"$(${HOSTPKG_CONFIG} --cflags $PKG)\"
> - echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG)\"
> + ${HOSTPKG_CONFIG} --cflags ${PKG} > ${cflags}
> + ${HOSTPKG_CONFIG} --libs ${PKG} > ${libs}
> exit 0
> fi
>
> if ${HOSTPKG_CONFIG} --exists $PKG2; then
> - echo cflags=\"$(${HOSTPKG_CONFIG} --cflags $PKG2)\"
> - echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG2)\"
> + ${HOSTPKG_CONFIG} --cflags ${PKG2} > ${cflags}
> + ${HOSTPKG_CONFIG} --libs ${PKG2} > ${libs}
> exit 0
> fi
> fi
> @@ -22,20 +25,20 @@ fi
> # (Even if it is installed, some distributions such as openSUSE cannot
> # find ncurses by pkg-config.)
> if [ -f /usr/include/ncursesw/ncurses.h ]; then
> - echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncursesw\"
> - echo libs=\"-lncursesw -lmenuw -lpanelw\"
> + echo -D_GNU_SOURCE -I/usr/include/ncursesw > ${cflags}
> + echo -lncursesw -lmenuw -lpanelw > ${libs}
> exit 0
> fi
>
> if [ -f /usr/include/ncurses/ncurses.h ]; then
> - echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncurses\"
> - echo libs=\"-lncurses -lmenu -lpanel\"
> + echo -D_GNU_SOURCE -I/usr/include/ncurses > ${cflags}
> + echo -lncurses -lmenu -lpanel > ${libs}
> exit 0
> fi
>
> if [ -f /usr/include/ncurses.h ]; then
> - echo cflags=\"-D_GNU_SOURCE\"
> - echo libs=\"-lncurses -lmenu -lpanel\"
> + echo -D_GNU_SOURCE > ${cflags}
> + echo -lncurses -lmenu -lpanel > ${libs}
> exit 0
> fi
>
> diff --git a/scripts/kconfig/qconf-cfg.sh b/scripts/kconfig/qconf-cfg.sh
> index ad652cb53947..117f36e568fc 100755
> --- a/scripts/kconfig/qconf-cfg.sh
> +++ b/scripts/kconfig/qconf-cfg.sh
> @@ -1,6 +1,10 @@
> #!/bin/sh
> # SPDX-License-Identifier: GPL-2.0
>
> +cflags=$1
> +libs=$2
> +bin=$3
> +
> PKG="Qt5Core Qt5Gui Qt5Widgets"
>
> if [ -z "$(command -v ${HOSTPKG_CONFIG})" ]; then
> @@ -11,9 +15,9 @@ if [ -z "$(command -v ${HOSTPKG_CONFIG})" ]; then
> fi
>
> if ${HOSTPKG_CONFIG} --exists $PKG; then
> - echo cflags=\"-std=c++11 -fPIC $(${HOSTPKG_CONFIG} --cflags $PKG)\"
> - echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG)\"
> - echo moc=\"$(${HOSTPKG_CONFIG} --variable=host_bins Qt5Core)/moc\"
> + ${HOSTPKG_CONFIG} --cflags ${PKG} > ${cflags}
> + ${HOSTPKG_CONFIG} --libs ${PKG} > ${libs}
> + ${HOSTPKG_CONFIG} --variable=host_bins Qt5Core > ${bin}
> exit 0
> fi
>
> diff --git a/scripts/remove-stale-files b/scripts/remove-stale-files
> index ccadfa3afb2b..64b14aa5aebf 100755
> --- a/scripts/remove-stale-files
> +++ b/scripts/remove-stale-files
> @@ -47,3 +47,5 @@ rm -f arch/riscv/purgatory/kexec-purgatory.c
> rm -f scripts/extract-cert
>
> rm -f arch/x86/purgatory/kexec-purgatory.c
> +
> +rm -f scripts/kconfig/[gmnq]conf-cfg
> --
> 2.34.1

--
epost|xmpp: [email protected] irc://oftc.net/nsc
↳ gpg: 18ed 52db e34f 860e e9fb c82b 7d97 0932 55a0 ce7f
-- frykten for herren er opphav til kunnskap --


Attachments:
(No filename) (10.79 kB)
signature.asc (849.00 B)
Download all attachments

2022-11-23 21:42:24

by Masahiro Yamada

[permalink] [raw]
Subject: Re: [PATCH v2 2/5] kbuild: implement {gcc,clang}-min-version only with built-in functions

On Thu, Nov 24, 2022 at 5:37 AM Nicolas Schier <[email protected]> wrote:
>
> On Thu 24 Nov 2022 00:18:25 GMT, Masahiro Yamada wrote:
> > Converting clang-min-version is straightforward because the versions
> > are always 6-digit.
> >
> > gcc-min-version is somewhat tricky because the minimal GCC version
> > is GCC 5.2; prepend '0' to the version that is less than 10 so that
> > test-ge is always passed with 6-digit versions.
> >
> > Signed-off-by: Masahiro Yamada <[email protected]>
> > ---
> >
> > Changes in v2:
> > - Covert gcc-min-version in a different way
> >
> > scripts/Makefile.compiler | 8 ++++++--
> > 1 file changed, 6 insertions(+), 2 deletions(-)
> >
> > diff --git a/scripts/Makefile.compiler b/scripts/Makefile.compiler
> > index 20d353dcabfb..cd75f81e88ef 100644
> > --- a/scripts/Makefile.compiler
> > +++ b/scripts/Makefile.compiler
> > @@ -63,11 +63,15 @@ cc-disable-warning = $(call try-run,\
> >
> > # gcc-min-version
> > # Usage: cflags-$(call gcc-min-version, 70100) += -foo
> > -gcc-min-version = $(shell [ $(CONFIG_GCC_VERSION)0 -ge $(1)0 ] && echo y)
> > +
> > +# Preprend 0 to the version that is less than 10 so test-ge works.
> > +gcc-min-version = $(call test-ge, \
> > + $(or $(filter 1%, $(CONFIG_GCC_VERSION)), 0$(CONFIG_GCC_VERSION)), \
> > + $(or $(filter 1%, $1), 0$(strip $1)))
>
> Hm, this silently expects a gcc version < 20, which we should expect in
> about seven-eight years [1]. I am thinking about the possibility of
> silent (but unlikely) breaks when someone in far future uses a gcc 20
> against a kernel with this line. Probably we should not care about
> that today, yet, right?

Yeah, I thought of it.

It depends on which of the following two will happen first.

(a) We raise the min gcc version to 10.0.0 and remove this hack
(b) GCC 20 is released

I am guessing (a) will occur first, so we do not need to care about (b).


If (b) happens first, we will need to add "2%".
It means that the window of supported GCC versions will get larger than 10.
Presumably, we do not want to support such a wide range of compiler
versions.


GCC 5.1 was released in 2015.
So, the current window of GCC versions is 7 years.
I hope it will not get even larger...





--
Best Regards
Masahiro Yamada

2022-11-23 21:54:38

by Nicolas Schier

[permalink] [raw]
Subject: Re: [PATCH v2 5/5] kbuild: check Make version

On Thu 24 Nov 2022 00:18:28 GMT, Masahiro Yamada wrote:
> This is implemented based on test-le. It will work until GNU Make 10
> is released.

... and as long as nobody uses make versions w/ minor version numbers,
cp. patch 3/5.

Kind regards,
Nicolas

>
> Signed-off-by: Masahiro Yamada <[email protected]>
> ---
>
> (no changes since v1)
>
> Makefile | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/Makefile b/Makefile
> index 60ce9dcafc72..797fafbc1b45 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -368,6 +368,9 @@ else # !mixed-build
>
> include $(srctree)/scripts/Kbuild.include
>
> +# Check for the minimal Make version
> +$(if $(call test-lt, $(MAKE_VERSION), 3.82), $(error Make $(MAKE_VERSION) is too old))
> +
> # Read KERNELRELEASE from include/config/kernel.release (if it exists)
> KERNELRELEASE = $(call read-file, include/config/kernel.release)
> KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
> --
> 2.34.1

--
epost|xmpp: [email protected] irc://oftc.net/nsc
↳ gpg: 18ed 52db e34f 860e e9fb c82b 7d97 0932 55a0 ce7f
-- frykten for herren er opphav til kunnskap --


Attachments:
(No filename) (1.20 kB)
signature.asc (849.00 B)
Download all attachments

2022-11-23 22:14:04

by Masahiro Yamada

[permalink] [raw]
Subject: Re: [PATCH v2 3/5] kbuild: add read-file macro

On Thu, Nov 24, 2022 at 6:02 AM Nicolas Schier <[email protected]> wrote:
>
> On Thu 24 Nov 2022 00:18:26 GMT, Masahiro Yamada wrote:
> > Since GMU Make 4.2, $(file ...) supports the read operater '<', which is
> > useful to read a file without forking any process. No warning is shown even
> > if the input file is missing.
> >
> > For older Make versions, it falls back to the cat command.
> >
> > Signed-off-by: Masahiro Yamada <[email protected]>
> > ---
> >
> > (no changes since v1)
> >
> > Makefile | 2 +-
> > scripts/Kbuild.include | 12 ++++++++++++
> > scripts/Makefile.modfinal | 2 +-
> > scripts/Makefile.modinst | 2 +-
> > 4 files changed, 15 insertions(+), 3 deletions(-)
> >
> > diff --git a/Makefile b/Makefile
> > index eb80332f7b51..60ce9dcafc72 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -369,7 +369,7 @@ else # !mixed-build
> > include $(srctree)/scripts/Kbuild.include
> >
> > # Read KERNELRELEASE from include/config/kernel.release (if it exists)
> > -KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
> > +KERNELRELEASE = $(call read-file, include/config/kernel.release)
> > KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
> > export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
> >
> > diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
> > index 9996f34327cb..722846c23264 100644
> > --- a/scripts/Kbuild.include
> > +++ b/scripts/Kbuild.include
> > @@ -10,6 +10,10 @@ empty :=
> > space := $(empty) $(empty)
> > space_escape := _-_SPACE_-_
> > pound := \#
> > +define newline
> > +
> > +
> > +endef
> >
> > ###
> > # Comparison macros.
> > @@ -55,6 +59,14 @@ stringify = $(squote)$(quote)$1$(quote)$(squote)
> > kbuild-dir = $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
> > kbuild-file = $(or $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Makefile)
> >
> > +###
> > +# Read a file, replacing newlines with spaces
> > +ifeq ($(call test-ge, $(MAKE_VERSION), 4.2),y)
> > +read-file = $(subst $(newline),$(space),$(file < $1))
> > +else
> > +read-file = $(shell cat $1 2>/dev/null)
> > +endif
> > +
>
> I like the implementation of read-file, but I am afraid that the
> MAKE_VERSION comparison breaks all make versions w/ a minor version
> number: 3.99.9x, 4.2.x, 4.3.x.


I think these should work correctly
unless I missed something terribly.


In the ASCII-sorting, they are sorted like this:

3.99.9x 4.2 4.2.x 4.3.x






The bad scenarios I came up with is GNU Make 4.10
and GNU Make 10.0 because $(sort ) will sort

10 4.10 4.2




GNU Make 4.3 was released in Jan 2020
GNU Make 4.4 was released in Oct 2022



If the current release pace continues,
we will have about 10 years until GNU Make hits 4.10

Until then, we can remove this ifeq.




--
Best Regards
Masahiro Yamada

2022-11-24 05:15:26

by Nicolas Schier

[permalink] [raw]
Subject: Re: [PATCH v2 3/5] kbuild: add read-file macro

On Thu 24 Nov 2022 06:52:06 GMT, Masahiro Yamada wrote:
> On Thu, Nov 24, 2022 at 6:02 AM Nicolas Schier <[email protected]> wrote:
> >
> > On Thu 24 Nov 2022 00:18:26 GMT, Masahiro Yamada wrote:
> > > Since GMU Make 4.2, $(file ...) supports the read operater '<', which is
> > > useful to read a file without forking any process. No warning is shown even
> > > if the input file is missing.
> > >
> > > For older Make versions, it falls back to the cat command.
> > >
> > > Signed-off-by: Masahiro Yamada <[email protected]>
> > > ---
> > >
> > > (no changes since v1)
> > >
> > > Makefile | 2 +-
> > > scripts/Kbuild.include | 12 ++++++++++++
> > > scripts/Makefile.modfinal | 2 +-
> > > scripts/Makefile.modinst | 2 +-
> > > 4 files changed, 15 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/Makefile b/Makefile
> > > index eb80332f7b51..60ce9dcafc72 100644
> > > --- a/Makefile
> > > +++ b/Makefile
> > > @@ -369,7 +369,7 @@ else # !mixed-build
> > > include $(srctree)/scripts/Kbuild.include
> > >
> > > # Read KERNELRELEASE from include/config/kernel.release (if it exists)
> > > -KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
> > > +KERNELRELEASE = $(call read-file, include/config/kernel.release)
> > > KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
> > > export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
> > >
> > > diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
> > > index 9996f34327cb..722846c23264 100644
> > > --- a/scripts/Kbuild.include
> > > +++ b/scripts/Kbuild.include
> > > @@ -10,6 +10,10 @@ empty :=
> > > space := $(empty) $(empty)
> > > space_escape := _-_SPACE_-_
> > > pound := \#
> > > +define newline
> > > +
> > > +
> > > +endef
> > >
> > > ###
> > > # Comparison macros.
> > > @@ -55,6 +59,14 @@ stringify = $(squote)$(quote)$1$(quote)$(squote)
> > > kbuild-dir = $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
> > > kbuild-file = $(or $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Makefile)
> > >
> > > +###
> > > +# Read a file, replacing newlines with spaces
> > > +ifeq ($(call test-ge, $(MAKE_VERSION), 4.2),y)
> > > +read-file = $(subst $(newline),$(space),$(file < $1))
> > > +else
> > > +read-file = $(shell cat $1 2>/dev/null)
> > > +endif
> > > +
> >
> > I like the implementation of read-file, but I am afraid that the
> > MAKE_VERSION comparison breaks all make versions w/ a minor version
> > number: 3.99.9x, 4.2.x, 4.3.x.
>
>
> I think these should work correctly
> unless I missed something terribly.
>
>
> In the ASCII-sorting, they are sorted like this:
>
> 3.99.9x 4.2 4.2.x 4.3.x
>
>
>
>
>
>
> The bad scenarios I came up with is GNU Make 4.10
> and GNU Make 10.0 because $(sort ) will sort
>
> 10 4.10 4.2
>
>
>
>
> GNU Make 4.3 was released in Jan 2020
> GNU Make 4.4 was released in Oct 2022
>
>
>
> If the current release pace continues,
> we will have about 10 years until GNU Make hits 4.10
>
> Until then, we can remove this ifeq.
>

yes, you're right. I should have checked my assumption before
bothering you with it.

Reviewed-by: Nicolas Schier <[email protected]>

>
>
> --
> Best Regards
> Masahiro Yamada

--
epost|xmpp: [email protected] irc://oftc.net/nsc
↳ gpg: 18ed 52db e34f 860e e9fb c82b 7d97 0932 55a0 ce7f
-- frykten for herren er opphav til kunnskap --


Attachments:
(No filename) (3.48 kB)
signature.asc (849.00 B)
Download all attachments

2022-11-24 07:24:27

by Nicolas Schier

[permalink] [raw]
Subject: Re: [PATCH v2 5/5] kbuild: check Make version

On Wed 23 Nov 2022 22:19:33 GMT, Nicolas Schier wrote:
> On Thu 24 Nov 2022 00:18:28 GMT, Masahiro Yamada wrote:
> > This is implemented based on test-le. It will work until GNU Make 10
> > is released.
>
> ... and as long as nobody uses make versions w/ minor version numbers,
> cp. patch 3/5.
>

I had a wrong understanding of the ASCII sort and forgot to re-check my
own assumptions.

Thanks for that whole patch set!

Reviewed-by: Nicolas Schier <[email protected]>


>
> >
> > Signed-off-by: Masahiro Yamada <[email protected]>
> > ---
> >
> > (no changes since v1)
> >
> > Makefile | 3 +++
> > 1 file changed, 3 insertions(+)
> >
> > diff --git a/Makefile b/Makefile
> > index 60ce9dcafc72..797fafbc1b45 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -368,6 +368,9 @@ else # !mixed-build
> >
> > include $(srctree)/scripts/Kbuild.include
> >
> > +# Check for the minimal Make version
> > +$(if $(call test-lt, $(MAKE_VERSION), 3.82), $(error Make $(MAKE_VERSION) is too old))
> > +
> > # Read KERNELRELEASE from include/config/kernel.release (if it exists)
> > KERNELRELEASE = $(call read-file, include/config/kernel.release)
> > KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
> > --
> > 2.34.1
>
> --
> epost|xmpp: [email protected] irc://oftc.net/nsc
> ↳ gpg: 18ed 52db e34f 860e e9fb c82b 7d97 0932 55a0 ce7f
> -- frykten for herren er opphav til kunnskap --



--
epost|xmpp: [email protected] irc://oftc.net/nsc
↳ gpg: 18ed 52db e34f 860e e9fb c82b 7d97 0932 55a0 ce7f
-- frykten for herren er opphav til kunnskap --


Attachments:
(No filename) (1.67 kB)
signature.asc (849.00 B)
Download all attachments

2022-12-02 18:55:49

by Palmer Dabbelt

[permalink] [raw]
Subject: Re: [PATCH v2 1/5] kbuild: add test-{le,ge,lt,gt} macros

On Wed, 23 Nov 2022 07:18:24 PST (-0800), [email protected] wrote:
> Because GNU Make is only able to handle strings, it is very hard to
> perform arighmetic in Makefiles.
>
> When we compare two integers, we invokes shell. One example is in the
> top Makefile:
>
> ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 130000; echo $$?),0)
>
> This is more expensive than using built-in functions since it forks a
> process.
>
> If we know the two have the same number of digits, we can do better.
>
> This commit adds four macros, test-le, test-ge, test-lt, test-gt.
>
> $(call test-lt, A, B) is evaluated to 'y' if A is less than B, or
> empty otherwise. This will replace $(call shell test A -lt B).
>
> Again, the limitation is that A and B must have the same number of
> digits because these macros are based on $(sort ) function.
>
> $(call test-lt, 1, 9) --> y (Works!)
> $(call test-lt, 10, 9) --> y (Not work...)
>
> To make the latter work, you need to add '0' prefix to align the number
> of digits:
>
> $(call test-lt, 10, 09) --> empty (Works!)
>
> Actually, we can live with this limitation in many places. As for the
> example above, we know $(CONFIG_LLD_VERSION) is 6-digits because the
> minimal supported version of LLVM is 11.0.0.
>
> So, the shell invocation can be replaced with more efficient code:
>
> ifeq ($(call test-lt, $(CONFIG_LLD_VERSION), 130000),y)
>
> Of course, this assumption will break when LLVM 100 is released, but it
> will be far in the future.
>
> Signed-off-by: Masahiro Yamada <[email protected]>
> ---
>
> (no changes since v1)
>
> Makefile | 2 +-
> arch/riscv/Makefile | 2 +-
> arch/x86/Makefile | 2 +-
> scripts/Kbuild.include | 10 ++++++++++
> 4 files changed, 13 insertions(+), 3 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index 6f846b1f2618..eb80332f7b51 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -986,7 +986,7 @@ KBUILD_LDFLAGS += -mllvm -import-instr-limit=5
> # Check for frame size exceeding threshold during prolog/epilog insertion
> # when using lld < 13.0.0.
> ifneq ($(CONFIG_FRAME_WARN),0)
> -ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 130000; echo $$?),0)
> +ifeq ($(call test-lt, $(CONFIG_LLD_VERSION), 130000),y)
> KBUILD_LDFLAGS += -plugin-opt=-warn-stack-size=$(CONFIG_FRAME_WARN)
> endif
> endif
> diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
> index 0d13b597cb55..faf2c2177094 100644
> --- a/arch/riscv/Makefile
> +++ b/arch/riscv/Makefile
> @@ -37,7 +37,7 @@ else
> endif
>
> ifeq ($(CONFIG_LD_IS_LLD),y)
> -ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 150000; echo $$?),0)
> +ifeq ($(call test-lt, $(CONFIG_LLD_VERSION), 150000),y)
> KBUILD_CFLAGS += -mno-relax
> KBUILD_AFLAGS += -mno-relax
> ifndef CONFIG_AS_IS_LLVM

Acked-by: Palmer Dabbelt <[email protected]> # RISC-V

> diff --git a/arch/x86/Makefile b/arch/x86/Makefile
> index 415a5d138de4..e72c7a49cd59 100644
> --- a/arch/x86/Makefile
> +++ b/arch/x86/Makefile
> @@ -211,7 +211,7 @@ endif
> KBUILD_LDFLAGS += -m elf_$(UTS_MACHINE)
>
> ifdef CONFIG_LTO_CLANG
> -ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 130000; echo $$?),0)
> +ifeq ($(call test-lt, $(CONFIG_LLD_VERSION), 130000),y)
> KBUILD_LDFLAGS += -plugin-opt=-stack-alignment=$(if $(CONFIG_X86_32),4,8)
> endif
> endif
> diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
> index cbe28744637b..9996f34327cb 100644
> --- a/scripts/Kbuild.include
> +++ b/scripts/Kbuild.include
> @@ -11,6 +11,16 @@ space := $(empty) $(empty)
> space_escape := _-_SPACE_-_
> pound := \#
>
> +###
> +# Comparison macros.
> +# Usage: $(call test-le, A, B)
> +# works like shell's "test A -le B", but A and B must have the same number of
> +# digits since it is just ASCII sort.
> +test-le = $(if $(filter $1, $(firstword $(sort $1 $2))),y)
> +test-ge = $(call test-le, $2, $1)
> +test-lt = $(if $(filter-out $2, $(firstword $(sort $1 $2))),y)
> +test-gt = $(call test-lt, $2, $1)
> +
> ###
> # Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o
> dot-target = $(dir $@).$(notdir $@)

2022-12-08 02:21:25

by Masahiro Yamada

[permalink] [raw]
Subject: Re: [PATCH v2 1/5] kbuild: add test-{le,ge,lt,gt} macros

On Thu, Nov 24, 2022 at 12:19 AM Masahiro Yamada <[email protected]> wrote:
>
> Because GNU Make is only able to handle strings, it is very hard to
> perform arighmetic in Makefiles.





I terribly missed that GNU Make 4.4
introduced the $(intcmp ...) function.

https://www.gnu.org/software/make/manual/make.html#Conditional-Functions


I am thinking if we can do better by using it.















>
> When we compare two integers, we invokes shell. One example is in the
> top Makefile:
>
> ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 130000; echo $$?),0)
>
> This is more expensive than using built-in functions since it forks a
> process.
>
> If we know the two have the same number of digits, we can do better.
>
> This commit adds four macros, test-le, test-ge, test-lt, test-gt.
>
> $(call test-lt, A, B) is evaluated to 'y' if A is less than B, or
> empty otherwise. This will replace $(call shell test A -lt B).
>
> Again, the limitation is that A and B must have the same number of
> digits because these macros are based on $(sort ) function.
>
> $(call test-lt, 1, 9) --> y (Works!)
> $(call test-lt, 10, 9) --> y (Not work...)
>
> To make the latter work, you need to add '0' prefix to align the number
> of digits:
>
> $(call test-lt, 10, 09) --> empty (Works!)
>
> Actually, we can live with this limitation in many places. As for the
> example above, we know $(CONFIG_LLD_VERSION) is 6-digits because the
> minimal supported version of LLVM is 11.0.0.
>
> So, the shell invocation can be replaced with more efficient code:
>
> ifeq ($(call test-lt, $(CONFIG_LLD_VERSION), 130000),y)
>
> Of course, this assumption will break when LLVM 100 is released, but it
> will be far in the future.
>
> Signed-off-by: Masahiro Yamada <[email protected]>
> ---
>
> (no changes since v1)
>
> Makefile | 2 +-
> arch/riscv/Makefile | 2 +-
> arch/x86/Makefile | 2 +-
> scripts/Kbuild.include | 10 ++++++++++
> 4 files changed, 13 insertions(+), 3 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index 6f846b1f2618..eb80332f7b51 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -986,7 +986,7 @@ KBUILD_LDFLAGS += -mllvm -import-instr-limit=5
> # Check for frame size exceeding threshold during prolog/epilog insertion
> # when using lld < 13.0.0.
> ifneq ($(CONFIG_FRAME_WARN),0)
> -ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 130000; echo $$?),0)
> +ifeq ($(call test-lt, $(CONFIG_LLD_VERSION), 130000),y)
> KBUILD_LDFLAGS += -plugin-opt=-warn-stack-size=$(CONFIG_FRAME_WARN)
> endif
> endif
> diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
> index 0d13b597cb55..faf2c2177094 100644
> --- a/arch/riscv/Makefile
> +++ b/arch/riscv/Makefile
> @@ -37,7 +37,7 @@ else
> endif
>
> ifeq ($(CONFIG_LD_IS_LLD),y)
> -ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 150000; echo $$?),0)
> +ifeq ($(call test-lt, $(CONFIG_LLD_VERSION), 150000),y)
> KBUILD_CFLAGS += -mno-relax
> KBUILD_AFLAGS += -mno-relax
> ifndef CONFIG_AS_IS_LLVM
> diff --git a/arch/x86/Makefile b/arch/x86/Makefile
> index 415a5d138de4..e72c7a49cd59 100644
> --- a/arch/x86/Makefile
> +++ b/arch/x86/Makefile
> @@ -211,7 +211,7 @@ endif
> KBUILD_LDFLAGS += -m elf_$(UTS_MACHINE)
>
> ifdef CONFIG_LTO_CLANG
> -ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 130000; echo $$?),0)
> +ifeq ($(call test-lt, $(CONFIG_LLD_VERSION), 130000),y)
> KBUILD_LDFLAGS += -plugin-opt=-stack-alignment=$(if $(CONFIG_X86_32),4,8)
> endif
> endif
> diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
> index cbe28744637b..9996f34327cb 100644
> --- a/scripts/Kbuild.include
> +++ b/scripts/Kbuild.include
> @@ -11,6 +11,16 @@ space := $(empty) $(empty)
> space_escape := _-_SPACE_-_
> pound := \#
>
> +###
> +# Comparison macros.
> +# Usage: $(call test-le, A, B)
> +# works like shell's "test A -le B", but A and B must have the same number of
> +# digits since it is just ASCII sort.
> +test-le = $(if $(filter $1, $(firstword $(sort $1 $2))),y)
> +test-ge = $(call test-le, $2, $1)
> +test-lt = $(if $(filter-out $2, $(firstword $(sort $1 $2))),y)
> +test-gt = $(call test-lt, $2, $1)
> +
> ###
> # Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o
> dot-target = $(dir $@).$(notdir $@)
> --
> 2.34.1
>


--
Best Regards
Masahiro Yamada