Skip to contentSkip to conversation

selftests: add build/cross-build dependency check script

PATCH In review Shuah Khan 3 participants 5 messages Apr 14, 2020 – Apr 24, 2020

Subsystems (3)
lore
Share & tools
lore

Shuah Khan

author maintainer
#0 lore raw

PATCH 1/1 selftests: add build/cross-build dependency check script

Add build/cross-build dependency check script kselftest_deps.sh This script does the following:

Usage: ./kselftest_deps.sh -[p] <compiler> [test_name]

kselftest_deps.sh [-p] gcc kselftest_deps.sh [-p] gcc vm kselftest_deps.sh [-p] aarch64-linux-gnu-gcc kselftest_deps.sh [-p] aarch64-linux-gnu-gcc vm

- Should be run in selftests directory in the kernel repo.
- Checks if Kselftests can be built/cross-built on a system.
- Parses all test/sub-test Makefile to find library dependencies.
- Runs compile test on a trivial C file with LDLIBS specified in the test Makefiles to identify missing library dependencies.
- Prints suggested target list for a system filtering out tests failed the build dependency check from the TARGETS in Selftests the main Makefile when optional -p is specified.
- Prints pass/fail dependency check for each tests/sub-test.
- Prints pass/fail targets and libraries.
- Default: runs dependency checks on all tests.
- Optional test name can be specified to check dependencies for it.

To make LDLIBS parsing easier
- change gpio and memfd Makefiles to use the same temporary variable used to find and add libraries to LDLIBS.
- simlify LDLIBS append logic in intel_pstate/Makefile.

Results from run on x86_64 system (trimmed detailed pass/fail list):
========================================================
Kselftest Dependency Check for [./kselftest_deps.sh gcc ] results...
========================================================
Checked tests defining LDLIBS dependencies
--------------------------------------------------------
Total tests with Dependencies:
55 Pass: 53 Fail: 2
--------------------------------------------------------
Targets passed build dependency check on system:
bpf capabilities filesystems futex gpio intel_pstate membarrier memfd mqueue net powerpc ptp rseq rtc safesetid timens timers vDSO vm
--------------------------------------------------------
FAIL: netfilter/Makefile dependency check: -lmnl
FAIL: gpio/Makefile dependency check: -lmount
--------------------------------------------------------
Targets failed build dependency check on system:
gpio netfilter
--------------------------------------------------------
Missing libraries system
-lmnl -lmount
--------------------------------------------------------
========================================================

Results from run on x86_64 system with aarch64-linux-gnu-gcc:
(trimmed detailed pass/fail list):
========================================================
Kselftest Dependency Check for [./kselftest_deps.sh aarch64-linux-gnu-gcc ] results...
========================================================
Checked tests defining LDLIBS dependencies
--------------------------------------------------------
Total tests with Dependencies:
55 Pass: 41 Fail: 14
--------------------------------------------------------
Targets failed build dependency check on system:
bpf capabilities filesystems futex gpio intel_pstate membarrier memfd mqueue net powerpc ptp rseq rtc timens timers vDSO vm
--------------------------------------------------------
--------------------------------------------------------
Targets failed build dependency check on system:
bpf capabilities gpio memfd mqueue net netfilter safesetid vm
--------------------------------------------------------
Missing libraries system
-lcap -lcap-ng -lelf -lfuse -lmnl -lmount -lnuma -lpopt -lz
--------------------------------------------------------
========================================================

---
 tools/testing/selftests/gpio/Makefile         |  12 +-
 tools/testing/selftests/intel_pstate/Makefile |   2 +-
 tools/testing/selftests/kselftest_deps.sh     | 272 ++++++++++++++++++
 tools/testing/selftests/memfd/Makefile        |  14 +-
 4 files changed, 291 insertions(+), 9 deletions(-)
 create mode 100755 tools/testing/selftests/kselftest_deps.sh
tools/testing/selftests/gpio/Makefile +6 -6
index 0bb80619db58..32bdc978a711 100644
@@ -1,13 +1,13 @@
 # SPDX-License-Identifier: GPL-2.0
 
-MOUNT_CFLAGS := $(shell pkg-config --cflags mount 2>/dev/null)
-MOUNT_LDLIBS := $(shell pkg-config --libs mount 2>/dev/null)
-ifeq ($(MOUNT_LDLIBS),)
-MOUNT_LDLIBS := -lmount -I/usr/include/libmount
+VAR_CFLAGS := $(shell pkg-config --cflags mount 2>/dev/null)
+VAR_LDLIBS := $(shell pkg-config --libs mount 2>/dev/null)
+ifeq ($(VAR_LDLIBS),)
+VAR_LDLIBS := -lmount -I/usr/include/libmount
 endif
 
-CFLAGS += -O2 -g -std=gnu99 -Wall -I../../../../usr/include/ $(MOUNT_CFLAGS)
-LDLIBS += $(MOUNT_LDLIBS)
+CFLAGS += -O2 -g -std=gnu99 -Wall -I../../../../usr/include/ $(VAR_CFLAGS)
+LDLIBS += $(VAR_LDLIBS)
 
 TEST_PROGS := gpio-mockup.sh
 TEST_FILES := gpio-mockup-sysfs.sh
tools/testing/selftests/intel_pstate/Makefile +1 -1
index 7340fd6a9a9f..39f0fa2a8fd6 100644
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 CFLAGS := $(CFLAGS) -Wall -D_GNU_SOURCE
-LDLIBS := $(LDLIBS) -lm
+LDLIBS += -lm
 
 uname_M := $(shell uname -m 2>/dev/null || echo not)
 ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
tools/testing/selftests/kselftest_deps.sh new file +272 -0

272 lines not on this page · raw message

tools/testing/selftests/memfd/Makefile +12 -2
index 187b14cad00c..4da8b565fa32 100644
@@ -8,11 +8,21 @@ TEST_GEN_PROGS := memfd_test
 TEST_PROGS := run_fuse_test.sh run_hugetlbfs_test.sh
 TEST_GEN_FILES := fuse_test fuse_mnt
 
-fuse_mnt.o: CFLAGS += $(shell pkg-config fuse --cflags)
+VAR_CFLAGS := $(shell pkg-config fuse --cflags 2>/dev/null)
+ifeq ($(VAR_CFLAGS),)
+VAR_CFLAGS := -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse
+endif
+
+VAR_LDLIBS := $(shell pkg-config fuse --libs 2>/dev/null)
+ifeq ($(VAR_LDLIBS),)
+VAR_LDLIBS := -lfuse -pthread
+endif
+
+fuse_mnt.o: CFLAGS += $(VAR_CFLAGS)
 
 include ../lib.mk
 
-$(OUTPUT)/fuse_mnt: LDLIBS += $(shell pkg-config fuse --libs)
+$(OUTPUT)/fuse_mnt: LDLIBS += $(VAR_LDLIBS)
 
 $(OUTPUT)/memfd_test: memfd_test.c common.c
 $(OUTPUT)/fuse_test: fuse_test.c common.c
Signature · 1 line
2.20.1
#1 lore raw

Hi,

tools/testing/selftests/gpio/Makefile line 10

Quoted 4 lines · Shuah Khan
tools/testing/selftests/gpio/Makefile +2 -2
-CFLAGS += -O2 -g -std=gnu99 -Wall -I../../../../usr/include/ $(MOUNT_CFLAGS)
-LDLIBS += $(MOUNT_LDLIBS)
+CFLAGS += -O2 -g -std=gnu99 -Wall -I../../../../usr/include/ $(VAR_CFLAGS)
+LDLIBS += $(VAR_LDLIBS)

(1) Can that series of ../../../.. be replaced by $(objtree)? If so, that would be much cleaner IMO.

(2) I can't find anything that checks that ../../../../usr/include exists (or has been installed via 'make headers_install'). Or anything that requires that CONFIG_HEADERS_INSTALL be set/enabled. Well, other than a Makefile error, but that's not a nice way to find out.

Preferably we would have some Kconfig check/enforcement or at least some documentation.

Thoughts?

thanks.

Signature · 1 line
~Randy
author maintainer
#2 lore raw
Quoted 12 lines · Randy Dunlap

Hi,

tools/testing/selftests/gpio/Makefile line 10

Quoted 4 lines · Shuah Khan
tools/testing/selftests/gpio/Makefile +2 -2
-CFLAGS += -O2 -g -std=gnu99 -Wall -I../../../../usr/include/ $(MOUNT_CFLAGS)
-LDLIBS += $(MOUNT_LDLIBS)
+CFLAGS += -O2 -g -std=gnu99 -Wall -I../../../../usr/include/ $(VAR_CFLAGS)
+LDLIBS += $(VAR_LDLIBS)

(1) Can that series of ../../../.. be replaced by $(objtree)? If so, that would be much cleaner IMO.

Agreed. It can be done in a separate patch. We have other tests that do similar hard coded header paths.

Quoted 5 lines

(2) I can't find anything that checks that ../../../../usr/include exists (or has been installed via 'make headers_install'). Or anything that requires that CONFIG_HEADERS_INSTALL be set/enabled. Well, other than a Makefile error, but that's not a nice way to find out.

At the moment no. When this Makefile is fixed, that is another check to add. It is addressed by headers install during selftest make.

Headers are installed as part of selftests make since selftests are often dependent on recent headers and headers install is a necessary step.

You are right. There are several tests that need cleanup for such hard coded values and this dependency check script in this patch currently does libs check. My plan is to extend this to check for headers installed or not and flag headers as missing dependency.

I can do that in my next version of this dependency check script.

thanks,
-- Shuah

#3 lore raw
In reply to Randy Dunlap
Quoted 4 lines

-----Original Message-----
From: [email protected] <[email protected]> On Behalf Of Randy Dunlap

On 4/14/20 2:22 PM, Shuah Khan wrote:

Quoted 8 lines

Review

Quoted 4 lines
(quoted diff) +2 -2
-CFLAGS += -O2 -g -std=gnu99 -Wall -I../../../../usr/include/ $(MOUNT_CFLAGS)
-LDLIBS += $(MOUNT_LDLIBS)
+CFLAGS += -O2 -g -std=gnu99 -Wall -I../../../../usr/include/ $(VAR_CFLAGS)
+LDLIBS += $(VAR_LDLIBS)

(1) Can that series of ../../../.. be replaced by $(objtree)? If so, that would be much cleaner IMO.

kselftests doesn't set $(objtree) when it is run directly (ie make -C tools/testing/selftests)

I had my own solution which was to use KBUILD_OUTPUT, like so:
This was a patch in my queue, that I didn't send in because I wasn't very happy with it. I was still considering alternatives.

---------------- (patch)
Subject: [PATCH] selftests/vm: use includes from KBUILD_OUTPUT directory

The Makefile for the vm tests was specifying a relative path (in the source directory) for accessing include files. This doesn't work when the headers files are placed in another directory (with O= or KBUILD_OUTPUT). It may appear to work, but ends up using includes from the host machine, which may not match the kernel source being compiled against.

Without this change, when the program userfaultfd.c was compiled, it generated errors like the following:

userfaultfd.c:267:21: error: 'UFFD_API_RANGE_IOCTLS_BASIC' undeclared here (not in a function)
.expected_ioctls = UFFD_API_RANGE_IOCTLS_BASIC,
^~~~~~~~~~~~~~~~~~~~~~~~~~~
userfaultfd.c: In function 'uffd_poll_thread':
userfaultfd.c:529:8: error: 'UFFD_EVENT_FORK' undeclared (first use in this function)
case UFFD_EVENT_FORK:
^~~~~~~~~~~~~~~
userfaultfd.c:529:8: note: each undeclared identifier is reported only once for each function it appears in
userfaultfd.c:531:18: error: 'union <anonymous>' has no member named 'fork'
uffd = msg.arg.fork.ufd;
^

Change the CFLAGS definition in the Makefile to reference KBUILD_OUTPUT.

---
 tools/testing/selftests/vm/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/vm/Makefile +1 -1
index 7f9a8a8..0208659 100644
@@ -3,7 +3,7 @@
 uname_M := $(shell uname -m 2>/dev/null || echo not)
 ARCH ?= $(shell echo $(uname_M) | sed -e 's/aarch64.*/arm64/')
 
-CFLAGS = -Wall -I ../../../../usr/include $(EXTRA_CFLAGS)
+CFLAGS = -Wall -I $(KBUILD_OUTPUT)/usr/include $(EXTRA_CFLAGS)
 LDLIBS = -lrt
 TEST_GEN_FILES = compaction_test
 TEST_GEN_FILES += gup_benchmark
Signature · 7 lines
2.1.4
-------- (end patch)

The reason I wasn't happy is that this required another patch to
tools/testing/Makefile to make sure KBUILD_OUTPUT was always
set.  I got sidetracked on the make headers_install issue, and didn't
finish this up.  Sorry about that. (See below for the headers_install issue).
Quoted 5 lines

(2) I can't find anything that checks that ../../../../usr/include exists (or has been installed via 'make headers_install'). Or anything that requires that CONFIG_HEADERS_INSTALL be set/enabled. Well, other than a Makefile error, but that's not a nice way to find out.

The kselftest handling of headers_install is quite confusing. There is a dependency in the top-level Makefile that ends up causing a vmlinux build, even if you just finished doing a headers_install recently (at least the way that it is called by kselftest, and in certain build configurations that I am seeing with my testing.)

I suspect that we don't have clean separation of kernel headers for the kernel under test, from the host machine's kernel header files, for builds of kselftest programs. But I ran out of time to tease this out.
-- Tim

Quoted 9 lines

Preferably we would have some Kconfig check/enforcement or at least some documentation.

Thoughts?

thanks.
--
~Randy

author maintainer
#4 lore raw
Quoted 63 lines · Tim
Quoted 4 lines

-----Original Message-----
From: [email protected] <[email protected]> On Behalf Of Randy Dunlap

On 4/14/20 2:22 PM, Shuah Khan wrote:

Quoted 8 lines

Review

Quoted 4 lines
(quoted diff) +2 -2
-CFLAGS += -O2 -g -std=gnu99 -Wall -I../../../../usr/include/ $(MOUNT_CFLAGS)
-LDLIBS += $(MOUNT_LDLIBS)
+CFLAGS += -O2 -g -std=gnu99 -Wall -I../../../../usr/include/ $(VAR_CFLAGS)
+LDLIBS += $(VAR_LDLIBS)

(1) Can that series of ../../../.. be replaced by $(objtree)? If so, that would be much cleaner IMO.

kselftests doesn't set $(objtree) when it is run directly (ie make -C tools/testing/selftests)

I had my own solution which was to use KBUILD_OUTPUT, like so:
This was a patch in my queue, that I didn't send in because I wasn't very happy with it. I was still considering alternatives.

---------------- (patch)
Subject: [PATCH] selftests/vm: use includes from KBUILD_OUTPUT directory

The Makefile for the vm tests was specifying a relative path (in the source directory) for accessing include files. This doesn't work when the headers files are placed in another directory (with O= or KBUILD_OUTPUT). It may appear to work, but ends up using includes from the host machine, which may not match the kernel source being compiled against.

Without this change, when the program userfaultfd.c was compiled, it generated errors like the following:

userfaultfd.c:267:21: error: 'UFFD_API_RANGE_IOCTLS_BASIC' undeclared here (not in a function)
.expected_ioctls = UFFD_API_RANGE_IOCTLS_BASIC,
^~~~~~~~~~~~~~~~~~~~~~~~~~~
userfaultfd.c: In function 'uffd_poll_thread':
userfaultfd.c:529:8: error: 'UFFD_EVENT_FORK' undeclared (first use in this function)
case UFFD_EVENT_FORK:
^~~~~~~~~~~~~~~
userfaultfd.c:529:8: note: each undeclared identifier is reported only once for each function it appears in
userfaultfd.c:531:18: error: 'union <anonymous>' has no member named 'fork'
uffd = msg.arg.fork.ufd;
^

Change the CFLAGS definition in the Makefile to reference KBUILD_OUTPUT.

---
  tools/testing/selftests/vm/Makefile | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/vm/Makefile +0 -0
index 7f9a8a8..0208659 100644

tools/testing/selftests/vm/Makefile line 9

Quoted 8 lines
tools/testing/selftests/vm/Makefile +1 -1
@@ -3,7 +3,7 @@
  uname_M := $(shell uname -m 2>/dev/null || echo not)
  ARCH ?= $(shell echo $(uname_M) | sed -e 's/aarch64.*/arm64/')
 
-CFLAGS = -Wall -I ../../../../usr/include $(EXTRA_CFLAGS)
+CFLAGS = -Wall -I $(KBUILD_OUTPUT)/usr/include $(EXTRA_CFLAGS)
  LDLIBS = -lrt
  TEST_GEN_FILES = compaction_test
  TEST_GEN_FILES += gup_benchmark

This should be $(OUTPUT) instead of $(KBUILD_OUTPUT). OUTPUT is set by selftests Makefile and lib.mk which is common for all tests even when make -C is used for compile.

Using KBUILD_OUTPUT will break other use-cases.

Send me the patch when you are ready.

kselftest Makefile invokes headers_install from the main Makefile.

This sequence doesn't install headers again when kselftest make is done:

Main directory:

# make headers_install
[headers_install runs]
# make headers_install
INSTALL ./usr/include
[does nothing - headers are there]

make kselftest-all
make --no-builtin-rules ARCH=x86 -C ../../.. headers_install make[2]: Entering directory '/home/shuah/lkml/linux_5.7'
INSTALL ./usr/include

[Same here - headers aren't installed]

I didn't check O= and KBUILD_OUTPUT cases though.

thanks,
-- Shuah