2 # SPDX-License-Identifier: BSD-3-Clause
3 # Copyright(c) 2015 Neil Horman. All rights reserved.
4 # Copyright(c) 2017 6WIND S.A.
9 abicheck=abi-compliance-checker
12 default_target=x86_64-native-linuxapp-gcc
16 echo "$0: error at line $1"
18 trap 'err_report $LINENO' ERR
22 $(basename $0) [options] <rev1> <rev2>
24 This script compares the ABI of 2 git revisions of the current
25 workspace. The output is a html report and a compilation log.
27 The objective is to make sure that applications built against
28 DSOs from the first revision can still run when executed using
29 the DSOs built from the second revision.
31 <rev1> and <rev2> are git commit id or tags.
35 -j <num> enable parallel compilation with <num> threads
36 -v show compilation logs on the console
37 -d <dir> change working directory (default is ${default_dst})
38 -t <target> the dpdk target to use (default is ${default_target})
39 -f overwrite existing files in destination directory
41 The script returns 0 on success, or the value of last failing
42 call of ${abicheck} (incompatible abi or the tool has run with errors).
43 The errors returned by ${abidump} are ignored.
48 # log in the file, and on stdout if verbose
50 # $2: string to be logged
53 if [ "${verbose}" != "true" ]; then
58 # launch a command and log it, taking care of surrounding spaces with quotes
60 local i s whitespace ret
62 whitespace="[[:space:]]"
64 if [[ $i =~ $whitespace ]]; then
77 if [ "$ret" != "0" ]; then
78 log "CMD" "previous command returned $ret"
84 # redirect or copy stderr/stdout to a file
85 # the syntax is unfamiliar, but it makes the rest of the
86 # code easier to read, avoiding the use of pipes
88 # save original stdout and stderr in fd 3 and 4
91 # create a new fd 5 that send to a file
93 # send stdout and stderr to fd 5
94 if [ "${verbose}" = "true" ]; then
95 exec 1> >(tee /dev/fd/5 >&3)
96 exec 2> >(tee /dev/fd/5 >&4)
103 # Make sure we configure SHARED libraries
104 # Also turn off IGB and KNI as those require kernel headers to build
106 local conf=config/defconfig_$target
107 cmd sed -i -e"$ a\CONFIG_RTE_BUILD_SHARED_LIB=y" $conf
108 cmd sed -i -e"$ a\CONFIG_RTE_NEXT_ABI=n" $conf
109 cmd sed -i -e"$ a\CONFIG_RTE_EAL_IGB_UIO=n" $conf
110 cmd sed -i -e"$ a\CONFIG_RTE_LIBRTE_KNI=n" $conf
111 cmd sed -i -e"$ a\CONFIG_RTE_KNI_KMOD=n" $conf
114 # build dpdk for the given tag and dump abi
115 # $1: hash of the revision
119 cmd git clone ${dpdkroot} ${dst}/${1}
122 log "INFO" "Checking out version ${1} of the dpdk"
123 # Move to the old version of the tree
124 cmd git checkout ${1}
128 # Now configure the build
129 log "INFO" "Configuring DPDK ${1}"
130 cmd make config T=$target O=$target
132 # Checking abi compliance relies on using the dwarf information in
133 # the shared objects. Build with -g to include them.
134 log "INFO" "Building DPDK ${1}. This might take a moment"
135 cmd make -j$parallel O=$target V=1 EXTRA_CFLAGS="-g -Og -Wno-error" \
136 EXTRA_LDFLAGS="-g" || log "INFO" "The build failed"
138 # Move to the lib directory
139 cmd cd ${PWD}/$target/lib
140 log "INFO" "Collecting ABI information for ${1}"
143 cmd $abidump ${i} -o $dst/${1}/${i}.dump -lver ${1} || true
144 # hack to ignore empty SymbolsInfo section (no public ABI)
145 if grep -q "'SymbolInfo' => {}," $dst/${1}/${i}.dump \
147 log "INFO" "${i} has no public ABI, remove dump file"
148 cmd rm -f $dst/${1}/${i}.dump
156 target=${default_target}
158 while getopts j:vd:t:fh ARG ; do
160 j ) parallel=$OPTARG ;;
163 t ) target=$OPTARG ;;
165 h ) print_usage ; exit 0 ;;
166 ? ) print_usage ; exit 1 ;;
169 shift $(($OPTIND - 1))
179 # convert path to absolute
182 *) dst=${PWD}/${dst} ;;
184 dpdkroot=$(readlink -e $(dirname $0)/..)
186 if [ -e "${dst}" -a "$force" = 0 ]; then
187 echo "The ${dst} directory is not empty. Remove it, use another"
188 echo "one (-d <dir>), or force overriding (-f)"
194 set_log_file ${dst}/abi-check.log
195 log "INFO" "Logs available in ${dst}/abi-check.log"
197 command -v ${abicheck} || log "INFO" "Can't find ${abicheck} utility"
198 command -v ${abidump} || log "INFO" "Can't find ${abidump} utility"
200 hash1=$(git show -s --format=%h "$tag1" -- 2> /dev/null | tail -1)
201 hash2=$(git show -s --format=%h "$tag2" -- 2> /dev/null | tail -1)
203 # Make hashes available in output for non-local reference
204 tag1="$tag1 ($hash1)"
205 tag2="$tag2 ($hash2)"
207 if [ "$hash1" = "$hash2" ]; then
208 log "ERROR" "$tag1 and $tag2 are the same revisions"
214 # dump abi for each revision
218 # compare the abi dumps
222 for i in ${hash2}/*.dump; do
224 libname=${name%.dump}
226 if [ ! -f ${hash1}/$name ]; then
227 log "INFO" "$NAME does not exist in $tag1. skipping..."
232 cmd $abicheck -l $libname \
233 -old ${hash1}/$name -new ${hash2}/$name || local_ret=$?
234 if [ $local_ret != 0 ]; then
235 log "NOTICE" "$abicheck returned $local_ret"
237 list="$list $libname"
241 if [ $ret != 0 ]; then
242 log "NOTICE" "ABI may be incompatible, check reports/logs for details."
243 log "NOTICE" "Incompatible list: $list"
245 log "NOTICE" "No error detected, ABI is compatible."
248 log "INFO" "Logs are in ${dst}/abi-check.log"
249 log "INFO" "HTML reports are in ${dst}/compat_reports directory"