218c4e68c1
Rather than using linuxapp and bsdapp everywhere, we can change things to use the, more readable, terms "linux" and "freebsd" in our build configs. Rather than renaming the configs we can just duplicate the existing ones with the new names using symlinks, and use the new names exclusively internally. ["make showconfigs" also only shows the new names to keep the list short] The result is that backward compatibility is kept fully but any new builds or development can be done using the newer names, i.e. both "make config T=x86_64-native-linuxapp-gcc" and "T=x86_64-native-linux-gcc" work. Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
252 lines
6.0 KiB
Bash
Executable File
252 lines
6.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
# Copyright(c) 2015 Neil Horman. All rights reserved.
|
|
# Copyright(c) 2017 6WIND S.A.
|
|
# All rights reserved
|
|
|
|
set -e
|
|
|
|
abicheck=abi-compliance-checker
|
|
abidump=abi-dumper
|
|
default_dst=abi-check
|
|
default_target=x86_64-native-linux-gcc
|
|
|
|
# trap on error
|
|
err_report() {
|
|
echo "$0: error at line $1"
|
|
}
|
|
trap 'err_report $LINENO' ERR
|
|
|
|
print_usage () {
|
|
cat <<- END_OF_HELP
|
|
$(basename $0) [options] <rev1> <rev2>
|
|
|
|
This script compares the ABI of 2 git revisions of the current
|
|
workspace. The output is a html report and a compilation log.
|
|
|
|
The objective is to make sure that applications built against
|
|
DSOs from the first revision can still run when executed using
|
|
the DSOs built from the second revision.
|
|
|
|
<rev1> and <rev2> are git commit id or tags.
|
|
|
|
Options:
|
|
-h show this help
|
|
-j <num> enable parallel compilation with <num> threads
|
|
-v show compilation logs on the console
|
|
-d <dir> change working directory (default is ${default_dst})
|
|
-t <target> the dpdk target to use (default is ${default_target})
|
|
-f overwrite existing files in destination directory
|
|
|
|
The script returns 0 on success, or the value of last failing
|
|
call of ${abicheck} (incompatible abi or the tool has run with errors).
|
|
The errors returned by ${abidump} are ignored.
|
|
|
|
END_OF_HELP
|
|
}
|
|
|
|
# log in the file, and on stdout if verbose
|
|
# $1: level string
|
|
# $2: string to be logged
|
|
log() {
|
|
echo "$1: $2"
|
|
if [ "${verbose}" != "true" ]; then
|
|
echo "$1: $2" >&3
|
|
fi
|
|
}
|
|
|
|
# launch a command and log it, taking care of surrounding spaces with quotes
|
|
cmd() {
|
|
local i s whitespace ret
|
|
s=""
|
|
whitespace="[[:space:]]"
|
|
for i in "$@"; do
|
|
if [[ $i =~ $whitespace ]]; then
|
|
i=\"$i\"
|
|
fi
|
|
if [ -z "$s" ]; then
|
|
s="$i"
|
|
else
|
|
s="$s $i"
|
|
fi
|
|
done
|
|
|
|
ret=0
|
|
log "CMD" "$s"
|
|
"$@" || ret=$?
|
|
if [ "$ret" != "0" ]; then
|
|
log "CMD" "previous command returned $ret"
|
|
fi
|
|
|
|
return $ret
|
|
}
|
|
|
|
# redirect or copy stderr/stdout to a file
|
|
# the syntax is unfamiliar, but it makes the rest of the
|
|
# code easier to read, avoiding the use of pipes
|
|
set_log_file() {
|
|
# save original stdout and stderr in fd 3 and 4
|
|
exec 3>&1
|
|
exec 4>&2
|
|
# create a new fd 5 that send to a file
|
|
exec 5> >(cat > $1)
|
|
# send stdout and stderr to fd 5
|
|
if [ "${verbose}" = "true" ]; then
|
|
exec 1> >(tee /dev/fd/5 >&3)
|
|
exec 2> >(tee /dev/fd/5 >&4)
|
|
else
|
|
exec 1>&5
|
|
exec 2>&5
|
|
fi
|
|
}
|
|
|
|
# Make sure we configure SHARED libraries
|
|
# Also turn off IGB and KNI as those require kernel headers to build
|
|
fixup_config() {
|
|
local conf=config/defconfig_$target
|
|
cmd sed -i -e"$ a\CONFIG_RTE_BUILD_SHARED_LIB=y" $conf
|
|
cmd sed -i -e"$ a\CONFIG_RTE_NEXT_ABI=n" $conf
|
|
cmd sed -i -e"$ a\CONFIG_RTE_EAL_IGB_UIO=n" $conf
|
|
cmd sed -i -e"$ a\CONFIG_RTE_LIBRTE_KNI=n" $conf
|
|
cmd sed -i -e"$ a\CONFIG_RTE_KNI_KMOD=n" $conf
|
|
}
|
|
|
|
# build dpdk for the given tag and dump abi
|
|
# $1: hash of the revision
|
|
gen_abi() {
|
|
local i
|
|
|
|
cmd git clone ${dpdkroot} ${dst}/${1}
|
|
cmd cd ${dst}/${1}
|
|
|
|
log "INFO" "Checking out version ${1} of the dpdk"
|
|
# Move to the old version of the tree
|
|
cmd git checkout ${1}
|
|
|
|
fixup_config
|
|
|
|
# Now configure the build
|
|
log "INFO" "Configuring DPDK ${1}"
|
|
cmd make config T=$target O=$target
|
|
|
|
# Checking abi compliance relies on using the dwarf information in
|
|
# the shared objects. Build with -g to include them.
|
|
log "INFO" "Building DPDK ${1}. This might take a moment"
|
|
cmd make -j$parallel O=$target V=1 EXTRA_CFLAGS="-g -Og -Wno-error" \
|
|
EXTRA_LDFLAGS="-g" || log "INFO" "The build failed"
|
|
|
|
# Move to the lib directory
|
|
cmd cd ${PWD}/$target/lib
|
|
log "INFO" "Collecting ABI information for ${1}"
|
|
for i in *.so; do
|
|
[ -e "$i" ] || break
|
|
cmd $abidump ${i} -o $dst/${1}/${i}.dump -lver ${1} || true
|
|
# hack to ignore empty SymbolsInfo section (no public ABI)
|
|
if grep -q "'SymbolInfo' => {}," $dst/${1}/${i}.dump \
|
|
2> /dev/null; then
|
|
log "INFO" "${i} has no public ABI, remove dump file"
|
|
cmd rm -f $dst/${1}/${i}.dump
|
|
fi
|
|
done
|
|
}
|
|
|
|
verbose=false
|
|
parallel=1
|
|
dst=${default_dst}
|
|
target=${default_target}
|
|
force=0
|
|
while getopts j:vd:t:fh ARG ; do
|
|
case $ARG in
|
|
j ) parallel=$OPTARG ;;
|
|
v ) verbose=true ;;
|
|
d ) dst=$OPTARG ;;
|
|
t ) target=$OPTARG ;;
|
|
f ) force=1 ;;
|
|
h ) print_usage ; exit 0 ;;
|
|
? ) print_usage ; exit 1 ;;
|
|
esac
|
|
done
|
|
shift $(($OPTIND - 1))
|
|
|
|
if [ $# != 2 ]; then
|
|
print_usage
|
|
exit 1
|
|
fi
|
|
|
|
tag1=$1
|
|
tag2=$2
|
|
|
|
# convert path to absolute
|
|
case "${dst}" in
|
|
/*) ;;
|
|
*) dst=${PWD}/${dst} ;;
|
|
esac
|
|
dpdkroot=$(readlink -e $(dirname $0)/..)
|
|
|
|
if [ -e "${dst}" -a "$force" = 0 ]; then
|
|
echo "The ${dst} directory is not empty. Remove it, use another"
|
|
echo "one (-d <dir>), or force overriding (-f)"
|
|
exit 1
|
|
fi
|
|
|
|
rm -rf ${dst}
|
|
mkdir -p ${dst}
|
|
set_log_file ${dst}/abi-check.log
|
|
log "INFO" "Logs available in ${dst}/abi-check.log"
|
|
|
|
command -v ${abicheck} || log "INFO" "Can't find ${abicheck} utility"
|
|
command -v ${abidump} || log "INFO" "Can't find ${abidump} utility"
|
|
|
|
hash1=$(git show -s --format=%h "$tag1" -- 2> /dev/null | tail -1)
|
|
hash2=$(git show -s --format=%h "$tag2" -- 2> /dev/null | tail -1)
|
|
|
|
# Make hashes available in output for non-local reference
|
|
tag1="$tag1 ($hash1)"
|
|
tag2="$tag2 ($hash2)"
|
|
|
|
if [ "$hash1" = "$hash2" ]; then
|
|
log "ERROR" "$tag1 and $tag2 are the same revisions"
|
|
exit 1
|
|
fi
|
|
|
|
cmd mkdir -p ${dst}
|
|
|
|
# dump abi for each revision
|
|
gen_abi ${hash1}
|
|
gen_abi ${hash2}
|
|
|
|
# compare the abi dumps
|
|
cmd cd ${dst}
|
|
ret=0
|
|
list=""
|
|
for i in ${hash2}/*.dump; do
|
|
name=`basename $i`
|
|
libname=${name%.dump}
|
|
|
|
if [ ! -f ${hash1}/$name ]; then
|
|
log "INFO" "$NAME does not exist in $tag1. skipping..."
|
|
continue
|
|
fi
|
|
|
|
local_ret=0
|
|
cmd $abicheck -l $libname \
|
|
-old ${hash1}/$name -new ${hash2}/$name || local_ret=$?
|
|
if [ $local_ret != 0 ]; then
|
|
log "NOTICE" "$abicheck returned $local_ret"
|
|
ret=$local_ret
|
|
list="$list $libname"
|
|
fi
|
|
done
|
|
|
|
if [ $ret != 0 ]; then
|
|
log "NOTICE" "ABI may be incompatible, check reports/logs for details."
|
|
log "NOTICE" "Incompatible list: $list"
|
|
else
|
|
log "NOTICE" "No error detected, ABI is compatible."
|
|
fi
|
|
|
|
log "INFO" "Logs are in ${dst}/abi-check.log"
|
|
log "INFO" "HTML reports are in ${dst}/compat_reports directory"
|
|
|
|
exit $ret
|