[RFC,6/6] buildtools: externally check exported headers

Message ID 20241127112617.1331125-7-david.marchand@redhat.com (mailing list archive)
State Superseded
Delegated to: Thomas Monjalon
Headers
Series Add a stricter headers check |

Checks

Context Check Description
ci/Intel-compilation success Compilation OK
ci/intel-Testing success Testing PASS
ci/github-robot: build success github build: passed
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-broadcom-Performance success Performance Testing PASS
ci/iol-unit-amd64-testing success Testing PASS
ci/iol-compile-amd64-testing success Testing PASS
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-sample-apps-testing success Testing PASS
ci/intel-Functional success Functional PASS
ci/iol-unit-arm64-testing success Testing PASS
ci/iol-compile-arm64-testing success Testing PASS
ci/iol-marvell-Functional success Functional Testing PASS
ci/loongarch-compilation success Compilation OK
ci/loongarch-unit-testing success Unit Testing PASS

Commit Message

David Marchand Nov. 27, 2024, 11:26 a.m. UTC
At the moment, the headers check (triggered via the check_includes meson
option) is run "internally", iow with compilation flags and include path
coming from the meson components.

One issue is that both internal and public headers are usually stored
in a single directory in the DPDK components.
If a lib/foo library exports a header rte_foo.h (iow rte_foo.h is part
of the headers list in lib/foo/meson.build) and this rte_foo.h includes
an internal header foo_internal.h, then the headers check won't detect
such an issue as rte_foo.h is compiled with -Ilib/foo.

Reimplement the headers check by inspecting (compiling) all DPDK headers
installed in a staging directory.
To identify the directory where DPDK headers are, this check relies on
pkg-config and skips EAL generic/ and internal/ headers.

The existing headers check (though less accurate) is kept as is,
as it provides a first level of check and may have existing users.

Signed-off-by: David Marchand <david.marchand@redhat.com>
---
 .ci/linux-build.sh            |  7 ++--
 buildtools/chkincs/Makefile   | 77 +++++++++++++++++++++++++++++++++++
 devtools/test-meson-builds.sh |  6 ++-
 3 files changed, 85 insertions(+), 5 deletions(-)
 create mode 100644 buildtools/chkincs/Makefile
  

Patch

diff --git a/.ci/linux-build.sh b/.ci/linux-build.sh
index fdb5787621..3146d9ccd8 100755
--- a/.ci/linux-build.sh
+++ b/.ci/linux-build.sh
@@ -95,8 +95,6 @@  OPTS="$OPTS -Ddefault_library=$DEF_LIB"
 OPTS="$OPTS -Dbuildtype=$buildtype"
 if [ "$STDATOMIC" = "true" ]; then
 	OPTS="$OPTS -Denable_stdatomic=true"
-else
-	OPTS="$OPTS -Dcheck_includes=true"
 fi
 if [ "$MINI" = "true" ]; then
     OPTS="$OPTS -Denable_drivers=net/null"
@@ -176,13 +174,16 @@  if [ "$RUN_TESTS" = "true" ]; then
     [ "$failed" != "true" ]
 fi
 
-# Test examples compilation with an installed dpdk
+# Test headers and examples compilation with an installed dpdk
 if [ "$BUILD_EXAMPLES" = "true" ]; then
     [ -d install ] || DESTDIR=$(pwd)/install meson install -C build
     export LD_LIBRARY_PATH=$(dirname $(find $(pwd)/install -name librte_eal.so)):$LD_LIBRARY_PATH
     export PATH=$(dirname $(find $(pwd)/install -name dpdk-devbind.py)):$PATH
     export PKG_CONFIG_PATH=$(dirname $(find $(pwd)/install -name libdpdk.pc)):$PKG_CONFIG_PATH
     export PKGCONF="pkg-config --define-prefix"
+
+    make -C buildtools/chkincs O=build/buildtools/chkincs
+
     find build/examples -maxdepth 1 -type f -name "dpdk-*" |
     while read target; do
         target=${target%%:*}
diff --git a/buildtools/chkincs/Makefile b/buildtools/chkincs/Makefile
new file mode 100644
index 0000000000..838819c617
--- /dev/null
+++ b/buildtools/chkincs/Makefile
@@ -0,0 +1,77 @@ 
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright (c) 2024 Red Hat, Inc.
+
+ifeq ($(V),)
+Q ?= @
+else
+Q =
+endif
+
+O ?= build
+
+PKGCONF ?= pkg-config
+
+ifneq ($(shell $(PKGCONF) --exists libdpdk && echo 0),0)
+$(error "no installation of DPDK found")
+endif
+
+ifeq ($(I),)
+
+.PHONY: headers_list
+.ONESHELL:
+headers_list:
+	$(Q)for dir in $$($(PKGCONF) --cflags-only-I libdpdk); do
+		dir=$${dir##-I}
+		[ -e $$dir/rte_build_config.h ] || continue
+		$(MAKE) I="$$dir" O="$(O)"
+		break
+	done
+else
+
+HEADERS := $(shell find $(I) -name "*.h" | grep -vE $(I)'/(generic|internal)/')
+SRCS := $(patsubst $(I)/%.h, $(O)/%.c, $(HEADERS))
+.PRECIOUS: $(SRCS)
+
+PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
+CFLAGS = $(shell $(PKGCONF) --cflags libdpdk) -Wall -Wextra -Werror
+LDFLAGS = $(shell $(PKGCONF) --libs libdpdk)
+
+OBJS := $(patsubst $(I)/%.h, $(O)/%.o, $(HEADERS))
+OBJS_EXP := $(patsubst $(I)/%.h, $(O)/%+exp.o, $(HEADERS))
+OBJS_ALL := $(patsubst $(I)/%.h, $(O)/%+all.o, $(HEADERS))
+
+all: $(OBJS) $(OBJS_EXP) $(OBJS_ALL)
+
+$(O):
+	$(Q)mkdir -p $@
+
+$(O)/%.c: $(I)/%.h $(O) gen_c_file_for_header.py Makefile
+	$(Q)python3 gen_c_file_for_header.py $< $@
+
+$(O)/%.o: $(O)/%.c Makefile $(PC_FILE)
+	$(Q)$(CC) $(CFLAGS) -o $@ -c $<
+
+$(O)/%+exp.o: $(O)/%.c Makefile $(PC_FILE)
+	$(Q)$(CC) $(CFLAGS) -DALLOW_EXPERIMENTAL_API -o $@ -c $<
+
+$(O)/%+all.o: $(O)/%.c Makefile $(PC_FILE)
+	$(Q)$(CC) $(CFLAGS) -DALLOW_EXPERIMENTAL_API -DALLOW_INTERNAL_API -o $@ -c $<
+
+CXXFLAGS = $(shell $(PKGCONF) --cflags libdpdk) -Wall -Wextra -Werror
+
+OBJS_CPP := $(patsubst $(I)/%.h, $(O)/%.cpp.o, $(HEADERS))
+OBJS_CPP_EXP := $(patsubst $(I)/%.h, $(O)/%.cpp+exp.o, $(HEADERS))
+OBJS_CPP_ALL := $(patsubst $(I)/%.h, $(O)/%.cpp+all.o, $(HEADERS))
+
+all: $(OBJS_CPP) $(OBJS_CPP_EXP) $(OBJS_CPP_ALL)
+
+$(O)/%.cpp.o: $(O)/%.c Makefile $(PC_FILE)
+	$(Q)$(CXX) $(CXXFLAGS) -o $@ -c $<
+
+$(O)/%.cpp+exp.o: $(O)/%.c Makefile $(PC_FILE)
+	$(Q)$(CXX) $(CXXFLAGS) -DALLOW_EXPERIMENTAL_API -o $@ -c $<
+
+$(O)/%.cpp+all.o: $(O)/%.c Makefile $(PC_FILE)
+	$(Q)$(CXX) $(CXXFLAGS) -DALLOW_EXPERIMENTAL_API -DALLOW_INTERNAL_API -o $@ -c $<
+
+endif
diff --git a/devtools/test-meson-builds.sh b/devtools/test-meson-builds.sh
index 4fff1f7177..c3cebead70 100755
--- a/devtools/test-meson-builds.sh
+++ b/devtools/test-meson-builds.sh
@@ -248,7 +248,7 @@  generic_isa='nehalem'
 if ! check_cc_flags "-march=$generic_isa" ; then
 	generic_isa='corei7'
 fi
-build build-x86-generic cc skipABI -Dcheck_includes=true \
+build build-x86-generic cc skipABI \
 	-Dlibdir=lib -Dcpu_instruction_set=$generic_isa $use_shared
 
 # 32-bit with default compiler
@@ -318,9 +318,11 @@  if [ "$examples" = 'all' ]; then
 	done | sort -u |
 	tr '\n' ' ')
 fi
-# if pkg-config defines the necessary flags, test building some examples
+# if pkg-config defines the necessary flags, check headers and test building some examples
 if pkg-config --define-prefix libdpdk >/dev/null 2>&1; then
 	export PKGCONF="pkg-config --define-prefix"
+	echo "## Checking exported headers"
+	$MAKE -C buildtools/chkincs O=$build_path/buildtools/chkincs -j
 	for example in $examples; do
 		echo "## Building $example"
 		[ $example = helloworld ] && static=static || static= # save disk space