[RFC,6/6] buildtools: externally check exported headers
Checks
Commit Message
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
@@ -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%%:*}
new file mode 100644
@@ -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
@@ -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