[dpdk-dev] [PATCH] add ABI checks
David Marchand
david.marchand at redhat.com
Fri Dec 20 16:20:58 CET 2019
Starting from Kevin and Bruce idea of using libabigail, here is an
alternate approach to implement ABI checks.
By default, those checks are disabled and enabling them requires a
manual step that generates the ABI dumps on a reference version for a
set of configurations.
Those checks are enabled in the CI by default for the default meson
options on x86 and aarch64 so that proposed patches are validated.
A cache of the ABI is stored in travis jobs.
Checks can be only informational by setting ABI_CHECKS_WARN_ONLY when
breaking the ABI in a future release.
For advanced developers and maintainers, the contributing guide details
the higher level scripts that are quite close to the existing devtools
scripts.
Signed-off-by: David Marchand <david.marchand at redhat.com>
---
.ci/linux-build.sh | 43 +++++++++++++++++++++++++++
.travis.yml | 20 +++++++++++--
devtools/check-abi-dump.sh | 46 +++++++++++++++++++++++++++++
devtools/check-abi-reference.sh | 27 +++++++++++++++++
devtools/dpdk.abignore | 2 ++
devtools/gen-abi-dump.sh | 29 ++++++++++++++++++
devtools/gen-abi-reference.sh | 24 +++++++++++++++
devtools/test-build.sh | 13 ++++++--
devtools/test-meson-builds.sh | 6 ++++
doc/guides/contributing/patches.rst | 25 ++++++++++++++++
10 files changed, 230 insertions(+), 5 deletions(-)
create mode 100755 devtools/check-abi-dump.sh
create mode 100755 devtools/check-abi-reference.sh
create mode 100644 devtools/dpdk.abignore
create mode 100755 devtools/gen-abi-dump.sh
create mode 100755 devtools/gen-abi-reference.sh
diff --git a/.ci/linux-build.sh b/.ci/linux-build.sh
index ccc3a7ccd..345dba264 100755
--- a/.ci/linux-build.sh
+++ b/.ci/linux-build.sh
@@ -30,8 +30,51 @@ fi
OPTS="$OPTS --default-library=$DEF_LIB"
meson build --werror -Dexamples=all $OPTS
+
+if [ "$ABI_CHECKS" = "1" ]; then
+ git remote add ref ${REF_GIT_REPO:-https://dpdk.org/git/dpdk}
+ git fetch --tags ref ${REF_GIT_BRANCH:-master}
+
+ head=$(git describe --all)
+ tag=$(git describe --abbrev=0)
+
+ if [ "$(cat reference/VERSION 2>/dev/null)" != "$tag" ]; then
+ rm -rf reference
+ fi
+
+ if [ ! -d reference ]; then
+ gen_abi_dump=$(mktemp -t gen-abi-dump-XXX.sh)
+ cp -a devtools/gen-abi-dump.sh $gen_abi_dump
+
+ git checkout -qf $tag
+ ninja -C build
+ $gen_abi_dump build reference
+
+ if [ "$AARCH64" != "1" ]; then
+ mkdir -p reference/app
+ cp -a build/app/dpdk-testpmd reference/app/
+
+ export LD_LIBRARY_PATH=$(pwd)/build/lib:$(pwd)/build/drivers
+ devtools/test-null.sh reference/app/dpdk-testpmd
+ unset LD_LIBRARY_PATH
+ fi
+ echo $tag > reference/VERSION
+
+ git checkout -qf $head
+ fi
+fi
+
ninja -C build
+if [ "$ABI_CHECKS" = "1" ]; then
+ devtools/check-abi-dump.sh build reference ${ABI_CHECKS_WARN_ONLY:-}
+ if [ "$AARCH64" != "1" ]; then
+ export LD_LIBRARY_PATH=$(pwd)/build/lib:$(pwd)/build/drivers
+ devtools/test-null.sh reference/app/dpdk-testpmd
+ unset LD_LIBRARY_PATH
+ fi
+fi
+
if [ "$AARCH64" != "1" ]; then
devtools/test-null.sh
fi
diff --git a/.travis.yml b/.travis.yml
index 8f90d06f2..bbb060fa2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,8 @@
language: c
-cache: ccache
+cache:
+ ccache: true
+ directories:
+ - reference
compiler:
- gcc
- clang
@@ -21,7 +24,7 @@ aarch64_packages: &aarch64_packages
extra_packages: &extra_packages
- *required_packages
- - [libbsd-dev, libpcap-dev, libcrypto++-dev, libjansson4]
+ - [libbsd-dev, libpcap-dev, libcrypto++-dev, libjansson4, abigail-tools]
build_32b_packages: &build_32b_packages
- *required_packages
@@ -59,6 +62,13 @@ matrix:
apt:
packages:
- *aarch64_packages
+ - env: DEF_LIB="shared" EXTRA_PACKAGES=1 ABI_CHECKS=1 AARCH64=1
+ compiler: gcc
+ addons:
+ apt:
+ packages:
+ - *aarch64_packages
+ - *extra_packages
- env: DEF_LIB="static" EXTRA_PACKAGES=1
compiler: gcc
addons:
@@ -72,6 +82,12 @@ matrix:
packages:
- *extra_packages
- *doc_packages
+ - env: DEF_LIB="shared" EXTRA_PACKAGES=1 ABI_CHECKS=1
+ compiler: gcc
+ addons:
+ apt:
+ packages:
+ - *extra_packages
- env: DEF_LIB="static" OPTS="-Denable_kmods=false" EXTRA_PACKAGES=1
compiler: gcc
addons:
diff --git a/devtools/check-abi-dump.sh b/devtools/check-abi-dump.sh
new file mode 100755
index 000000000..f48a2ae7e
--- /dev/null
+++ b/devtools/check-abi-dump.sh
@@ -0,0 +1,46 @@
+#!/bin/sh -e
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright (c) 2019 Red Hat, Inc.
+
+if [ $# != 2 ] && [ $# != 3 ]; then
+ echo "Usage: $0 builddir dumpdir [warnonly]"
+ exit 1
+fi
+
+builddir=$1
+dumpdir=$2
+warnonly=${3:-}
+if [ ! -d $builddir ]; then
+ echo "Error: build directory '$builddir' does not exist."
+ exit 1
+fi
+if [ ! -d $dumpdir ]; then
+ echo "Error: dump directory '$dumpdir' does not exist."
+ exit 1
+fi
+
+ABIDIFF_OPTIONS="--suppr $(dirname $0)/dpdk.abignore"
+for dump in $(find $dumpdir -name "*.dump"); do
+ libname=$(basename $dump)
+ libname=${libname%.dump}
+ result=
+ for f in $(find $builddir -name "$libname.so.*"); do
+ if test -L $f || [ "$f" != "${f%%.symbols}" ]; then
+ continue
+ fi
+ result=found
+
+ if ! abidiff $ABIDIFF_OPTIONS $dump $f; then
+ if [ -z "$warnonly" ]; then
+ echo "Error: ABI issue reported for $dump, $f"
+ exit 1
+ fi
+ echo "Warning: ABI issue reported for $dump, $f"
+ fi
+ break
+ done
+ if [ "$result" != "found" ]; then
+ echo "Error: can't find a library for dump file $dump"
+ exit 1
+ fi
+done
diff --git a/devtools/check-abi-reference.sh b/devtools/check-abi-reference.sh
new file mode 100755
index 000000000..7addb094e
--- /dev/null
+++ b/devtools/check-abi-reference.sh
@@ -0,0 +1,27 @@
+#!/bin/sh -e
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright (c) 2019 Red Hat, Inc.
+
+devtools_dir=$(dirname $(readlink -f $0))
+. $devtools_dir/load-devel-config
+
+abi_ref_build_dir=${DPDK_ABI_REF_BUILD_DIR:-reference}
+builds_dir=${DPDK_BUILD_TEST_DIR:-.}
+
+for dir in $abi_ref_build_dir/*; do
+ if [ "$dir" = "$abi_ref_build_dir" ]; then
+ exit 1
+ fi
+ if [ ! -d $dir/dump ]; then
+ echo "Skipping $dir"
+ continue
+ fi
+ target=$(basename $dir)
+ if [ -d $builds_dir/$target/install ]; then
+ libdir=$builds_dir/$target/install
+ else
+ libdir=$builds_dir/$target
+ fi
+ echo "Checking ABI between $libdir and $dir/dump"
+ $devtools_dir/check-abi-dump.sh $libdir $dir/dump
+done
diff --git a/devtools/dpdk.abignore b/devtools/dpdk.abignore
new file mode 100644
index 000000000..b866b7f26
--- /dev/null
+++ b/devtools/dpdk.abignore
@@ -0,0 +1,2 @@
+[suppress_function]
+ symbol_version = EXPERIMENTAL
diff --git a/devtools/gen-abi-dump.sh b/devtools/gen-abi-dump.sh
new file mode 100755
index 000000000..4e38d751f
--- /dev/null
+++ b/devtools/gen-abi-dump.sh
@@ -0,0 +1,29 @@
+#!/bin/sh -e
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright (c) 2019 Red Hat, Inc.
+
+if [ $# != 2 ]; then
+ echo "Usage: $0 builddir dumpdir"
+ exit 1
+fi
+
+builddir=$1
+dumpdir=$2
+if [ ! -d $builddir ]; then
+ echo "Error: build directory '$builddir' does not exist."
+ exit 1
+fi
+if [ -d $dumpdir ]; then
+ echo "Error: dump directory '$dumpdir' already exists."
+ exit 1
+fi
+
+mkdir -p $dumpdir
+for f in $(find $builddir -name "*.so.*"); do
+ if test -L $f || [ "$f" != "${f%%.symbols}" ]; then
+ continue
+ fi
+
+ libname=$(basename $f)
+ abidw --out-file $dumpdir/${libname%.so.*}.dump $f
+done
diff --git a/devtools/gen-abi-reference.sh b/devtools/gen-abi-reference.sh
new file mode 100755
index 000000000..f41d7fadc
--- /dev/null
+++ b/devtools/gen-abi-reference.sh
@@ -0,0 +1,24 @@
+#!/bin/sh -e
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright (c) 2019 Red Hat, Inc.
+
+devtools_dir=$(dirname $(readlink -f $0))
+. $devtools_dir/load-devel-config
+
+abi_ref_build_dir=${DPDK_ABI_REF_BUILD_DIR:-reference}
+for dir in $abi_ref_build_dir/*; do
+ if [ "$dir" = "$abi_ref_build_dir" ]; then
+ exit 1
+ fi
+ if [ -d $dir/dump ]; then
+ echo "Skipping $dir"
+ continue
+ fi
+ if [ -d $dir/install ]; then
+ libdir=$dir/install
+ else
+ libdir=$dir
+ fi
+ echo "Dumping libraries from $libdir in $dir/dump"
+ $devtools_dir/gen-abi-dump.sh $libdir $dir/dump
+done
diff --git a/devtools/test-build.sh b/devtools/test-build.sh
index 52305fbb8..8cb5b56fb 100755
--- a/devtools/test-build.sh
+++ b/devtools/test-build.sh
@@ -30,7 +30,8 @@ default_path=$PATH
# - LIBSSO_SNOW3G_PATH
# - LIBSSO_KASUMI_PATH
# - LIBSSO_ZUC_PATH
-. $(dirname $(readlink -f $0))/load-devel-config
+devtools_dir=$(dirname $(readlink -f $0))
+. $devtools_dir/load-devel-config
print_usage () {
echo "usage: $(basename $0) [-h] [-jX] [-s] [config1 [config2] ...]]"
@@ -64,6 +65,7 @@ print_help () {
[ -z $MAKE ] && echo "Cannot find make or gmake" && exit 1
J=$DPDK_MAKE_JOBS
+abi_ref_build_dir=${DPDK_ABI_REF_BUILD_DIR:-reference}
builds_dir=${DPDK_BUILD_TEST_DIR:-.}
short=false
unset verbose
@@ -97,7 +99,7 @@ trap "signal=INT ; trap - INT ; kill -INT $$" INT
# notify result on exit
trap on_exit EXIT
-cd $(dirname $(readlink -f $0))/..
+cd $devtools_dir/..
reset_env ()
{
@@ -233,7 +235,7 @@ for conf in $configs ; do
# reload config with DPDK_TARGET set
DPDK_TARGET=$target
reset_env
- . $(dirname $(readlink -f $0))/load-devel-config
+ . $devtools_dir/load-devel-config
options=$(echo $conf | sed 's,[^~+]*,,')
dir=$builds_dir/$conf
@@ -246,6 +248,11 @@ for conf in $configs ; do
export RTE_TARGET=$target
rm -rf $dir/install
${MAKE} install O=$dir DESTDIR=$dir/install prefix=
+ if [ -d $abi_ref_build_dir/$conf/dump ]; then
+ echo "================== Check ABI $conf"
+ $devtools_dir/check-abi-dump.sh $dir/install \
+ $abi_ref_build_dir/$conf/dump
+ fi
echo "================== Build examples for $conf"
export RTE_SDK=$(readlink -f $dir)/install/share/dpdk
ln -sTf $(pwd)/lib $RTE_SDK/lib # workaround for vm_power_manager
diff --git a/devtools/test-meson-builds.sh b/devtools/test-meson-builds.sh
index 688567714..aaefa38a2 100755
--- a/devtools/test-meson-builds.sh
+++ b/devtools/test-meson-builds.sh
@@ -16,6 +16,7 @@ srcdir=$(dirname $(readlink -f $0))/..
MESON=${MESON:-meson}
use_shared="--default-library=shared"
+abi_ref_build_dir=${DPDK_ABI_REF_BUILD_DIR:-reference}
builds_dir=${DPDK_BUILD_TEST_DIR:-.}
if command -v gmake >/dev/null 2>&1 ; then
@@ -88,6 +89,11 @@ build () # <directory> <target compiler> <meson options>
echo "$ninja_cmd -C $builddir"
$ninja_cmd -C $builddir
fi
+
+ if [ -d $abi_ref_build_dir/$1/dump ]; then
+ $srcdir/devtools/check-abi-dump.sh $builddir
+ $abi_ref_build_dir/$1/dump
+ fi
}
if [ "$1" = "-vv" ] ; then
diff --git a/doc/guides/contributing/patches.rst b/doc/guides/contributing/patches.rst
index 0686450e4..de3dff145 100644
--- a/doc/guides/contributing/patches.rst
+++ b/doc/guides/contributing/patches.rst
@@ -513,6 +513,31 @@ in a single subfolder called "__builds" created in the current directory.
Setting ``DPDK_BUILD_TEST_DIR`` to an absolute directory path e.g. ``/tmp`` is also supported.
+Checking ABI compatibility
+--------------------------
+
+The first thing is to build reference binaries for the latest release your
+patches are built on top of.
+
+Either you are in a git tree and an easy way to identify this is to run::
+
+ git checkout $(git describe --abbrev=0)
+
+Or you use a tarball and you extract the sources in a director of your choice.
+
+Next is building those sources, refer to the previous paragraph.
+You can set ``DPDK_BUILD_TEST_DIR=reference``, so that the builds occur in this
+directory.
+
+Finally, the ABI dump files are generated with the
+``devtools/gen-abi-reference.sh`` script. This script will look for builds in
+the current sub directory ``reference``. But you can set the environment
+variable ``DPDK_ABI_REF_BUILD_DIR`` to a different location.
+
+Once done, you can check your current binaries ABI with this reference with the
+``devtools/check-abi-reference.sh`` script.
+
+
Sending Patches
---------------
--
2.23.0
More information about the dev
mailing list