]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/dpdk/devtools/validate-abi.sh
bump version to 15.2.11-pve1
[ceph.git] / ceph / src / spdk / dpdk / devtools / validate-abi.sh
CommitLineData
11fdf7f2
TL
1#!/usr/bin/env bash
2# SPDX-License-Identifier: BSD-3-Clause
3# Copyright(c) 2015 Neil Horman. All rights reserved.
4# Copyright(c) 2017 6WIND S.A.
5# All rights reserved
6
7set -e
8
9abicheck=abi-compliance-checker
10abidump=abi-dumper
11default_dst=abi-check
12default_target=x86_64-native-linuxapp-gcc
13
14# trap on error
15err_report() {
16 echo "$0: error at line $1"
17}
18trap 'err_report $LINENO' ERR
19
20print_usage () {
21 cat <<- END_OF_HELP
22 $(basename $0) [options] <rev1> <rev2>
23
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.
26
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.
30
31 <rev1> and <rev2> are git commit id or tags.
32
33 Options:
34 -h show this help
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
40
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.
44
45 END_OF_HELP
46}
47
48# log in the file, and on stdout if verbose
49# $1: level string
50# $2: string to be logged
51log() {
52 echo "$1: $2"
53 if [ "${verbose}" != "true" ]; then
54 echo "$1: $2" >&3
55 fi
56}
57
58# launch a command and log it, taking care of surrounding spaces with quotes
59cmd() {
60 local i s whitespace ret
61 s=""
62 whitespace="[[:space:]]"
63 for i in "$@"; do
64 if [[ $i =~ $whitespace ]]; then
65 i=\"$i\"
66 fi
67 if [ -z "$s" ]; then
68 s="$i"
69 else
70 s="$s $i"
71 fi
72 done
73
74 ret=0
75 log "CMD" "$s"
76 "$@" || ret=$?
77 if [ "$ret" != "0" ]; then
78 log "CMD" "previous command returned $ret"
79 fi
80
81 return $ret
82}
83
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
87set_log_file() {
88 # save original stdout and stderr in fd 3 and 4
89 exec 3>&1
90 exec 4>&2
91 # create a new fd 5 that send to a file
92 exec 5> >(cat > $1)
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)
97 else
98 exec 1>&5
99 exec 2>&5
100 fi
101}
102
103# Make sure we configure SHARED libraries
104# Also turn off IGB and KNI as those require kernel headers to build
105fixup_config() {
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
112}
113
114# build dpdk for the given tag and dump abi
115# $1: hash of the revision
116gen_abi() {
117 local i
118
119 cmd git clone ${dpdkroot} ${dst}/${1}
120 cmd cd ${dst}/${1}
121
122 log "INFO" "Checking out version ${1} of the dpdk"
123 # Move to the old version of the tree
124 cmd git checkout ${1}
125
126 fixup_config
127
128 # Now configure the build
129 log "INFO" "Configuring DPDK ${1}"
130 cmd make config T=$target O=$target
131
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"
137
138 # Move to the lib directory
139 cmd cd ${PWD}/$target/lib
140 log "INFO" "Collecting ABI information for ${1}"
141 for i in *.so; do
142 [ -e "$i" ] || break
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 \
146 2> /dev/null; then
147 log "INFO" "${i} has no public ABI, remove dump file"
148 cmd rm -f $dst/${1}/${i}.dump
149 fi
150 done
151}
152
153verbose=false
154parallel=1
155dst=${default_dst}
156target=${default_target}
157force=0
158while getopts j:vd:t:fh ARG ; do
159 case $ARG in
160 j ) parallel=$OPTARG ;;
161 v ) verbose=true ;;
162 d ) dst=$OPTARG ;;
163 t ) target=$OPTARG ;;
164 f ) force=1 ;;
165 h ) print_usage ; exit 0 ;;
166 ? ) print_usage ; exit 1 ;;
167 esac
168done
169shift $(($OPTIND - 1))
170
171if [ $# != 2 ]; then
172 print_usage
173 exit 1
174fi
175
176tag1=$1
177tag2=$2
178
179# convert path to absolute
180case "${dst}" in
181 /*) ;;
182 *) dst=${PWD}/${dst} ;;
183esac
184dpdkroot=$(readlink -e $(dirname $0)/..)
185
186if [ -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)"
189 exit 1
190fi
191
192rm -rf ${dst}
193mkdir -p ${dst}
194set_log_file ${dst}/abi-check.log
195log "INFO" "Logs available in ${dst}/abi-check.log"
196
197command -v ${abicheck} || log "INFO" "Can't find ${abicheck} utility"
198command -v ${abidump} || log "INFO" "Can't find ${abidump} utility"
199
200hash1=$(git show -s --format=%h "$tag1" -- 2> /dev/null | tail -1)
201hash2=$(git show -s --format=%h "$tag2" -- 2> /dev/null | tail -1)
202
203# Make hashes available in output for non-local reference
204tag1="$tag1 ($hash1)"
205tag2="$tag2 ($hash2)"
206
207if [ "$hash1" = "$hash2" ]; then
208 log "ERROR" "$tag1 and $tag2 are the same revisions"
209 exit 1
210fi
211
212cmd mkdir -p ${dst}
213
214# dump abi for each revision
215gen_abi ${hash1}
216gen_abi ${hash2}
217
218# compare the abi dumps
219cmd cd ${dst}
220ret=0
221list=""
222for i in ${hash2}/*.dump; do
223 name=`basename $i`
224 libname=${name%.dump}
225
226 if [ ! -f ${hash1}/$name ]; then
227 log "INFO" "$NAME does not exist in $tag1. skipping..."
228 continue
229 fi
230
231 local_ret=0
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"
236 ret=$local_ret
237 list="$list $libname"
238 fi
239done
240
241if [ $ret != 0 ]; then
242 log "NOTICE" "ABI may be incompatible, check reports/logs for details."
243 log "NOTICE" "Incompatible list: $list"
244else
245 log "NOTICE" "No error detected, ABI is compatible."
246fi
247
248log "INFO" "Logs are in ${dst}/abi-check.log"
249log "INFO" "HTML reports are in ${dst}/compat_reports directory"
250
251exit $ret