diff options
Diffstat (limited to 'src/spdk/dpdk/devtools')
-rwxr-xr-x | src/spdk/dpdk/devtools/build-tags.sh | 209 | ||||
-rwxr-xr-x | src/spdk/dpdk/devtools/check-dup-includes.sh | 18 | ||||
-rwxr-xr-x | src/spdk/dpdk/devtools/check-git-log.sh | 181 | ||||
-rwxr-xr-x | src/spdk/dpdk/devtools/check-includes.sh | 261 | ||||
-rwxr-xr-x | src/spdk/dpdk/devtools/check-maintainers.sh | 132 | ||||
-rwxr-xr-x | src/spdk/dpdk/devtools/check-symbol-change.sh | 159 | ||||
-rwxr-xr-x | src/spdk/dpdk/devtools/check-symbol-maps.sh | 30 | ||||
-rwxr-xr-x | src/spdk/dpdk/devtools/checkpatches.sh | 226 | ||||
-rwxr-xr-x | src/spdk/dpdk/devtools/cocci.sh | 64 | ||||
-rw-r--r-- | src/spdk/dpdk/devtools/cocci/mtod-offset.cocci | 76 | ||||
-rw-r--r-- | src/spdk/dpdk/devtools/cocci/strlcpy.cocci | 8 | ||||
-rwxr-xr-x | src/spdk/dpdk/devtools/get-maintainer.sh | 58 | ||||
-rwxr-xr-x | src/spdk/dpdk/devtools/git-log-fixes.sh | 112 | ||||
-rw-r--r-- | src/spdk/dpdk/devtools/load-devel-config | 12 | ||||
-rwxr-xr-x | src/spdk/dpdk/devtools/test-build.sh | 244 | ||||
-rwxr-xr-x | src/spdk/dpdk/devtools/test-meson-builds.sh | 60 | ||||
-rwxr-xr-x | src/spdk/dpdk/devtools/test-null.sh | 17 | ||||
-rwxr-xr-x | src/spdk/dpdk/devtools/validate-abi.sh | 251 |
18 files changed, 2118 insertions, 0 deletions
diff --git a/src/spdk/dpdk/devtools/build-tags.sh b/src/spdk/dpdk/devtools/build-tags.sh new file mode 100755 index 00000000..78001f04 --- /dev/null +++ b/src/spdk/dpdk/devtools/build-tags.sh @@ -0,0 +1,209 @@ +#!/bin/sh -e +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2017 Cavium, Inc +# + +# +# Generate tags or gtags or cscope or etags files +# + +verbose=false +linux=true +bsd=true +x86_32=true +x86_64=true +ppc_64=true +arm_32=true +arm_64=true + +print_usage() +{ + echo "Usage: $(basename $0) [-h] [-v] tags|cscope|gtags|etags [config]" + echo "Valid configs are:" + make showconfigs | sed 's,^,\t,' +} + +# Move to the root of the git tree +cd $(dirname $0)/.. + +while getopts hv ARG ; do + case $ARG in + v ) verbose=true ;; + h ) print_usage; exit 0 ;; + ? ) print_usage; exit 1 ;; + esac +done +shift $(($OPTIND - 1)) + +#ignore version control files +ignore="( -name .svn -o -name CVS -o -name .hg -o -name .git ) -prune -o" + +source_dirs="test app buildtools drivers examples lib" + +skip_bsd="( -name bsdapp ) -prune -o" +skip_linux="( -name linuxapp ) -prune -o" +skip_arch="( -name arch ) -prune -o" +skip_sse="( -name *_sse*.[chS] ) -prune -o" +skip_avx="( -name *_avx*.[chS] ) -prune -o" +skip_neon="( -name *_neon*.[chS] ) -prune -o" +skip_altivec="( -name *_altivec*.[chS] ) -prune -o" +skip_arm64="( -name *arm64*.[chS] ) -prune -o" +skip_x86="( -name *x86*.[chS] ) -prune -o" +skip_32b_files="( -name *_32.h ) -prune -o" +skip_64b_files="( -name *_64.h ) -prune -o" + +skiplist="$skip_bsd $skip_linux $skip_arch $skip_sse $skip_avx \ + $skip_neon $skip_altivec $skip_x86 $skip_arm64" + +find_sources() +{ + find $1 $ignore $3 -name $2 -not -type l -print +} + +common_sources() +{ + find_sources "$source_dirs" '*.[chS]' "$skiplist" +} + +linux_sources() +{ + find_sources "lib/librte_eal/linuxapp" '*.[chS]' +} + +bsd_sources() +{ + find_sources "lib/librte_eal/bsdapp" '*.[chS]' +} + +arm_common() +{ + find_sources "lib/librte_eal/common/arch/arm" '*.[chS]' + find_sources "$source_dirs" '*neon*.[chS]' +} + +arm_32_sources() +{ + arm_common + find_sources "lib/librte_eal/common/include/arch/arm" '*.[chS]' \ + "$skip_64b_files" +} + +arm_64_sources() +{ + arm_common + find_sources "lib/librte_eal/common/include/arch/arm" '*.[chS]' \ + "$skip_32b_files" + find_sources "$source_dirs" '*arm64.[chS]' +} + +x86_common() +{ + find_sources "lib/librte_eal/common/arch/x86" '*.[chS]' + + find_sources "examples/performance-thread/common/arch/x86" '*.[chS]' + find_sources "$source_dirs" '*_sse*.[chS]' + find_sources "$source_dirs" '*_avx*.[chS]' + find_sources "$source_dirs" '*x86.[chS]' +} + +x86_32_sources() +{ + x86_common + find_sources "lib/librte_eal/common/include/arch/x86" '*.[chS]' \ + "$skip_64b_files" +} + +x86_64_sources() +{ + x86_common + find_sources "lib/librte_eal/common/include/arch/x86" '*.[chS]' \ + "$skip_32b_files" +} + +ppc_64_sources() +{ + find_sources "lib/librte_eal/common/arch/ppc_64" '*.[chS]' + find_sources "lib/librte_eal/common/include/arch/ppc_64" '*.[chS]' + find_sources "$source_dirs" '*altivec*.[chS]' +} + +check_valid_target() +{ + cfgfound=false + allconfigs=$(make showconfigs) + for cfg in $allconfigs ; do + if [ "$cfg" = "$1" ] ; then + cfgfound=true + fi + done + if ! $cfgfound ; then + echo "Invalid config: $1" + print_usage + exit 0 + fi +} + +if [ -n "$2" ]; then + check_valid_target $2 + + echo $2 | grep -q "linuxapp-" || linux=false + echo $2 | grep -q "bsdapp-" || bsd=false + echo $2 | grep -q "x86_64-" || x86_64=false + echo $2 | grep -q "arm-" || arm_32=false + echo $2 | grep -q "arm64-" || arm_64=false + echo $2 | grep -q "ppc_64-" || ppc_64=false + echo $2 | grep -q -e "i686-" -e "x32-" || x86_32=false +fi + +all_sources() +{ + common_sources + if $linux ; then linux_sources ; fi + if $bsd ; then bsd_sources ; fi + if $x86_64 ; then x86_64_sources ; fi + if $x86_32 ; then x86_32_sources ; fi + if $ppc_64 ; then ppc_64_sources ; fi + if $arm_32 ; then arm_32_sources ; fi + if $arm_64 ; then arm_64_sources ; fi +} + +show_flags() +{ + if $verbose ; then + echo "mode: $1" + echo "config: $2" + echo "linux: $linux" + echo "bsd: $bsd" + echo "x86_32: $x86_32" + echo "x86_64: $x86_64" + echo "ppc_64: $ppc_64" + echo "arm_32: $arm_32" + echo "arm_64: $arm_64" + fi +} + +case "$1" in + "cscope") + show_flags $1 $2 + all_sources > cscope.files + cscope -q -b -f cscope.out + ;; + "gtags") + show_flags $1 $2 + all_sources | gtags -i -f - + ;; + "tags") + show_flags $1 $2 + rm -f tags + all_sources | xargs ctags -a + ;; + "etags") + show_flags $1 $2 + rm -f TAGS + all_sources | xargs etags -a + ;; + *) + echo "Invalid mode: $1" + print_usage + ;; +esac diff --git a/src/spdk/dpdk/devtools/check-dup-includes.sh b/src/spdk/dpdk/devtools/check-dup-includes.sh new file mode 100755 index 00000000..e4c2748c --- /dev/null +++ b/src/spdk/dpdk/devtools/check-dup-includes.sh @@ -0,0 +1,18 @@ +#! /bin/sh -e +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2017 Mellanox Technologies, Ltd + +# Check C files in git repository for duplicated includes. +# Usage: devtools/check-dup-includes.sh [directory] + +dir=${1:-$(dirname $(readlink -m $0))/..} +cd $dir + +# speed up by ignoring Unicode details +export LC_ALL=C + +for file in $(git ls-files '*.[ch]') ; do + sed -rn 's,^[[:space:]]*#include[[:space:]]*[<"](.*)[>"].*,\1,p' $file | + sort | uniq -d | + sed "s,^,$file: duplicated include: ," +done diff --git a/src/spdk/dpdk/devtools/check-git-log.sh b/src/spdk/dpdk/devtools/check-git-log.sh new file mode 100755 index 00000000..97dae4be --- /dev/null +++ b/src/spdk/dpdk/devtools/check-git-log.sh @@ -0,0 +1,181 @@ +#! /bin/sh +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2016 6WIND S.A. + +# Check commit logs (headlines and references) +# +# If any doubt about the formatting, please check in the most recent history: +# git log --format='%>|(15)%cr %s' --reverse | grep -i <pattern> + +if [ "$1" = '-h' -o "$1" = '--help' ] ; then + cat <<- END_OF_HELP + usage: $(basename $0) [-h] [range] + + Check commit log formatting. + The git range can be specified as a "git log" option, + e.g. -1 to check only the latest commit. + The default range starts from origin/master to HEAD. + END_OF_HELP + exit +fi + +selfdir=$(dirname $(readlink -f $0)) +range=${1:-origin/master..} +# convert -N to HEAD~N.. in order to comply with git-log-fixes.sh getopts +if printf -- $range | grep -q '^-[0-9]\+' ; then + range="HEAD$(printf -- $range | sed 's,^-,~,').." +fi + +commits=$(git log --format='%h' --reverse $range) +headlines=$(git log --format='%s' --reverse $range) +bodylines=$(git log --format='%b' --reverse $range) +fixes=$(git log --format='%h %s' --reverse $range | grep -i ': *fix' | cut -d' ' -f1) +stablefixes=$($selfdir/git-log-fixes.sh $range | sed '/(N\/A)$/d' | cut -d' ' -f2) +tags=$(git log --format='%b' --reverse $range | grep -i -e 'by *:' -e 'fix.*:') +bytag='\(Reported\|Suggested\|Signed-off\|Acked\|Reviewed\|Tested\)-by:' + +# check headline format (spacing, no punctuation, no code) +bad=$(echo "$headlines" | grep --color=always \ + -e ' ' \ + -e '^ ' \ + -e ' $' \ + -e '\.$' \ + -e '[,;!?&|]' \ + -e ':.*_' \ + -e '^[^:]\+$' \ + -e ':[^ ]' \ + -e ' :' \ + | sed 's,^,\t,') +[ -z "$bad" ] || printf "Wrong headline format:\n$bad\n" + +# check headline prefix when touching only drivers, e.g. net/<driver name> +bad=$(for commit in $commits ; do + headline=$(git log --format='%s' -1 $commit) + files=$(git diff-tree --no-commit-id --name-only -r $commit) + [ -z "$(echo "$files" | grep -v '^\(drivers\|doc\|config\)/')" ] || + continue + drv=$(echo "$files" | grep '^drivers/' | cut -d "/" -f 2,3 | sort -u) + drvgrp=$(echo "$drv" | cut -d "/" -f 1 | uniq) + if [ $(echo "$drvgrp" | wc -l) -gt 1 ] ; then + echo "$headline" | grep -v '^drivers:' + elif [ $(echo "$drv" | wc -l) -gt 1 ] ; then + echo "$headline" | grep -v "^drivers/$drvgrp" + else + echo "$headline" | grep -v "^$drv" + fi +done | sed 's,^,\t,') +[ -z "$bad" ] || printf "Wrong headline prefix:\n$bad\n" + +# check headline label for common typos +bad=$(echo "$headlines" | grep --color=always \ + -e '^example[:/]' \ + -e '^apps/' \ + -e '^testpmd' \ + -e 'test-pmd' \ + -e '^bond:' \ + | sed 's,^,\t,') +[ -z "$bad" ] || printf "Wrong headline label:\n$bad\n" + +# check headline lowercase for first words +bad=$(echo "$headlines" | grep --color=always \ + -e '^.*[[:upper:]].*:' \ + -e ': *[[:upper:]]' \ + | sed 's,^,\t,') +[ -z "$bad" ] || printf "Wrong headline uppercase:\n$bad\n" + +# check headline uppercase (Rx/Tx, VF, L2, MAC, Linux, ARM...) +bad=$(echo "$headlines" | grep -E --color=always \ + -e ':.*\<(rx|tx|RX|TX)\>' \ + -e ':.*\<[pv]f\>' \ + -e ':.*\<[hsf]w\>' \ + -e ':.*\<l[234]\>' \ + -e ':.*\<api\>' \ + -e ':.*\<arm\>' \ + -e ':.*\<armv7\>' \ + -e ':.*\<armv8\>' \ + -e ':.*\<crc\>' \ + -e ':.*\<dma\>' \ + -e ':.*\<eeprom\>' \ + -e ':.*\<freebsd\>' \ + -e ':.*\<iova\>' \ + -e ':.*\<linux\>' \ + -e ':.*\<lro\>' \ + -e ':.*\<lsc\>' \ + -e ':.*\<mac\>' \ + -e ':.*\<mss\>' \ + -e ':.*\<mtu\>' \ + -e ':.*\<nic\>' \ + -e ':.*\<nvm\>' \ + -e ':.*\<numa\>' \ + -e ':.*\<pci\>' \ + -e ':.*\<pmd\>' \ + -e ':.*\<rss\>' \ + -e ':.*\<sctp\>' \ + -e ':.*\<tso\>' \ + -e ':.*\<udp\>' \ + -e ':.*\<[Vv]lan\>' \ + -e ':.*\<vdpa\>' \ + -e ':.*\<vsi\>' \ + | sed 's,^,\t,') +[ -z "$bad" ] || printf "Wrong headline lowercase:\n$bad\n" + +# special case check for VMDq to give good error message +bad=$(echo "$headlines" | grep -E --color=always \ + -e '\<(vmdq|VMDQ)\>' \ + | sed 's,^,\t,') +[ -z "$bad" ] || printf "Wrong headline capitalization, use 'VMDq':\n$bad\n" + +# check headline length (60 max) +bad=$(echo "$headlines" | + awk 'length>60 {print}' | + sed 's,^,\t,') +[ -z "$bad" ] || printf "Headline too long:\n$bad\n" + +# check body lines length (75 max) +bad=$(echo "$bodylines" | grep -v '^Fixes:' | + awk 'length>75 {print}' | + sed 's,^,\t,') +[ -z "$bad" ] || printf "Line too long:\n$bad\n" + +# check starting commit message with "It" +bad=$(for commit in $commits ; do + firstbodyline=$(git log --format='%b' -1 $commit | head -n1) + echo "$firstbodyline" | grep --color=always -ie '^It ' +done | sed 's,^,\t,') +[ -z "$bad" ] || printf "Wrong beginning of commit message:\n$bad\n" + +# check tags spelling +bad=$(echo "$tags" | + grep -v "^$bytag [^,]* <.*@.*>$" | + grep -v '^Fixes: [0-9a-f]\{7\}[0-9a-f]* (".*")$' | + sed 's,^.,\t&,') +[ -z "$bad" ] || printf "Wrong tag:\n$bad\n" + +# check missing Fixes: tag +bad=$(for fix in $fixes ; do + git log --format='%b' -1 $fix | grep -q '^Fixes: ' || + git log --format='\t%s' -1 $fix +done) +[ -z "$bad" ] || printf "Missing 'Fixes' tag:\n$bad\n" + +# check Fixes: reference +IFS=' +' +fixtags=$(echo "$tags" | grep '^Fixes: ') +bad=$(for fixtag in $fixtags ; do + hash=$(echo "$fixtag" | sed 's,^Fixes: \([0-9a-f]*\).*,\1,') + if git branch --contains $hash 2>&- | grep -q '^\*' ; then + good="Fixes: $hash "$(git log --format='("%s")' -1 $hash 2>&-) + else + good="reference not in current branch" + fi + printf "$fixtag" | grep -v "^$good$" +done | sed 's,^,\t,') +[ -z "$bad" ] || printf "Wrong 'Fixes' reference:\n$bad\n" + +# check Cc: stable@dpdk.org for fixes +bad=$(for fix in $stablefixes ; do + git log --format='%b' -1 $fix | grep -qi '^Cc: *stable@dpdk.org' || + git log --format='\t%s' -1 $fix +done) +[ -z "$bad" ] || printf "Is it candidate for Cc: stable@dpdk.org backport?\n$bad\n" diff --git a/src/spdk/dpdk/devtools/check-includes.sh b/src/spdk/dpdk/devtools/check-includes.sh new file mode 100755 index 00000000..9057633e --- /dev/null +++ b/src/spdk/dpdk/devtools/check-includes.sh @@ -0,0 +1,261 @@ +#!/bin/sh -e +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2016 6WIND S.A. + +# This script checks that header files in a given directory do not miss +# dependencies when included on their own, do not conflict and accept being +# compiled with the strictest possible flags. +# +# Files are looked up in the directory provided as the first argument, +# otherwise build/include by default. +# +# Recognized environment variables: +# +# VERBOSE=1 is the same as -v. +# +# QUIET=1 is the same as -q. +# +# SUMMARY=1 is the same as -s. +# +# CC, CPPFLAGS, CFLAGS, EXTRA_CPPFLAGS, EXTRA_CFLAGS, CXX, CXXFLAGS and +# EXTRA_CXXFLAGS are taken into account. +# +# PEDANTIC_CFLAGS, PEDANTIC_CXXFLAGS and PEDANTIC_CPPFLAGS provide strict +# C/C++ compilation flags. +# +# IGNORE contains a list of shell patterns matching files (relative to the +# include directory) to avoid. It is set by default to known DPDK headers +# which must not be included on their own. +# +# IGNORE_CXX provides additional files for C++. + +while getopts hqvs arg; do + case $arg in + h) + cat <<EOF +usage: $0 [-h] [-q] [-v] [-s] [DIR] + +This script checks that header files in a given directory do not miss +dependencies when included on their own, do not conflict and accept being +compiled with the strictest possible flags. + + -h display this help and exit + -q quiet mode, disable normal output + -v show command lines being executed + -s show summary + +With no DIR, default to build/include. + +Any failed header check yields a nonzero exit status. +EOF + exit + ;; + q) + QUIET=1 + ;; + v) + VERBOSE=1 + ;; + s) + SUMMARY=1 + ;; + *) + exit 1 + ;; + esac +done + +shift $(($OPTIND - 1)) + +include_dir=${1:-build/include} + +: ${PEDANTIC_CFLAGS=-std=c99 -pedantic -Wall -Wextra -Werror} +: ${PEDANTIC_CXXFLAGS=} +: ${PEDANTIC_CPPFLAGS=-D_XOPEN_SOURCE=600} +: ${CC:=cc} +: ${CXX:=c++} +: ${IGNORE= \ + 'rte_atomic_32.h' \ + 'rte_atomic_64.h' \ + 'rte_byteorder_32.h' \ + 'rte_byteorder_64.h' \ + 'generic/*' \ + 'exec-env/*' \ + 'rte_vhost.h' \ + 'rte_eth_vhost.h' \ + 'rte_eal_interrupts.h' \ +} +: ${IGNORE_CXX= \ + 'rte_vhost.h' \ + 'rte_eth_vhost.h' \ +} + +temp_cc=/tmp/${0##*/}.$$.c +pass_cc= +failures_cc=0 + +temp_cxx=/tmp/${0##*/}.$$.cc +pass_cxx= +failures_cxx=0 + +# Process output parameters. + +[ "$QUIET" = 1 ] && +exec 1> /dev/null + +[ "$VERBOSE" = 1 ] && +output () +{ + local CCV + local CXXV + + shift + CCV=$CC + CXXV=$CXX + CC="echo $CC" CXX="echo $CXX" "$@" + CC=$CCV + CXX=$CXXV + + "$@" +} || +output () +{ + + printf ' %s\n' "$1" + shift + "$@" +} + +trap 'rm -f "$temp_cc" "$temp_cxx"' EXIT + +compile_cc () +{ + ${CC} -I"$include_dir" \ + ${PEDANTIC_CPPFLAGS} ${CPPFLAGS} ${EXTRA_CPPFLAGS} \ + ${PEDANTIC_CFLAGS} ${CFLAGS} ${EXTRA_CFLAGS} \ + -c -o /dev/null "${temp_cc}" +} + +compile_cxx () +{ + ${CXX} -I"$include_dir" \ + ${PEDANTIC_CPPFLAGS} ${CPPFLAGS} ${EXTRA_CPPFLAGS} \ + ${PEDANTIC_CXXFLAGS} ${CXXFLAGS} ${EXTRA_CXXFLAGS} \ + -c -o /dev/null "${temp_cxx}" +} + +ignore () +{ + file="$1" + shift + while [ $# -ne 0 ]; do + case "$file" in + $1) + return 0 + ;; + esac + shift + done + return 1 +} + +# Check C/C++ compilation for each header file. + +while read -r path +do + file=${path#$include_dir} + file=${file##/} + if ignore "$file" $IGNORE; then + output "SKIP $file" : + continue + fi + if printf "\ +#include <%s> + +int main(void) +{ + return 0; +} +" "$file" > "$temp_cc" && + output "CC $file" compile_cc + then + pass_cc="$pass_cc $file" + else + failures_cc=$(($failures_cc + 1)) + fi + if ignore "$file" $IGNORE_CXX; then + output "SKIP CXX $file" : + continue + fi + if printf "\ +#include <%s> + +int main() +{ +} +" "$file" > "$temp_cxx" && + output "CXX $file" compile_cxx + then + pass_cxx="$pass_cxx $file" + else + failures_cxx=$(($failures_cxx + 1)) + fi +done <<EOF +$(find "$include_dir" -name '*.h') +EOF + +# Check C compilation with all includes. + +: > "$temp_cc" && +for file in $pass_cc; do + printf "\ +#include <%s> +" "$file" >> $temp_cc +done +if printf "\ +int main(void) +{ + return 0; +} +" >> "$temp_cc" && + output "CC (all includes that did not fail)" compile_cc +then + : +else + failures_cc=$(($failures_cc + 1)) +fi + +# Check C++ compilation with all includes. + +: > "$temp_cxx" && +for file in $pass_cxx; do + printf "\ +#include <%s> +" "$file" >> $temp_cxx +done +if printf "\ +int main() +{ +} +" >> "$temp_cxx" && + output "CXX (all includes that did not fail)" compile_cxx +then + : +else + failures_cxx=$(($failures_cxx + 1)) +fi + +# Report results. + +if [ "$SUMMARY" = 1 ]; then + printf "\ +Summary: + %u failure(s) for C using '%s'. + %u failure(s) for C++ using '%s'. +" $failures_cc "$CC" $failures_cxx "$CXX" 1>&2 +fi + +# Exit with nonzero status if there are failures. + +[ $failures_cc -eq 0 ] && +[ $failures_cxx -eq 0 ] diff --git a/src/spdk/dpdk/devtools/check-maintainers.sh b/src/spdk/dpdk/devtools/check-maintainers.sh new file mode 100755 index 00000000..85a300f0 --- /dev/null +++ b/src/spdk/dpdk/devtools/check-maintainers.sh @@ -0,0 +1,132 @@ +#! /bin/sh +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2015 6WIND S.A. + +# Do some basic checks in MAINTAINERS file + +cd $(dirname $0)/.. + +# speed up by ignoring Unicode details +export LC_ALL=C + +# Get files matching paths with wildcards and / meaning recursing +files () # <path> [<path> ...] +{ + if [ -z "$1" ] ; then + return + fi + if [ -d .git ] ; then + git ls-files "$1" + else + find "$1" -type f | + sed 's,^\./,,' + fi | + # if not ended by / + if ! echo "$1" | grep -q '/[[:space:]]*$' ; then + # filter out deeper directories + sed "/\(\/[^/]*\)\{$(($(echo "$1" | grep -o / | wc -l) + 1))\}/d" + else + cat + fi + # next path + shift + files "$@" +} + +# Get all files matching F: and X: fields +parse_fx () # <index file> +{ + IFS=' +' + # parse each line excepted underlining + for line in $( (sed '/^-\+$/d' $1 ; echo) | sed 's,^$,§,') ; do + if echo "$line" | grep -q '^§$' ; then + # empty line delimit end of section + whitelist=$(files $flines) + blacklist=$(files $xlines) + match=$(aminusb "$whitelist" "$blacklist") + if [ -n "$whitelist" ] ; then + printf "# $title " + maintainers=$(echo "$maintainers" | sed -r 's,.*<(.*)>.*,\1,') + maintainers=$(printf "$maintainers" | sed -e 's,^,<,' -e 's,$,>,') + echo $maintainers + fi + if [ -n "$match" ] ; then + echo "$match" + fi + # flush section + unset maintainers + unset flines + unset xlines + elif echo "$line" | grep -q '^[A-Z]: ' ; then + # maintainer + maintainers=$(add_line_to_if "$line" "$maintainers" 'M: ') + # file matching pattern + flines=$(add_line_to_if "$line" "$flines" 'F: ') + # file exclusion pattern + xlines=$(add_line_to_if "$line" "$xlines" 'X: ') + else # assume it is a title + title="$line" + fi + done +} + +# Check patterns in F: and X: +check_fx () # <index file> +{ + IFS=' +' + for line in $(sed -n 's,^[FX]: ,,p' $1 | tr '*' '#') ; do + line=$(printf "$line" | tr '#' '*') + match=$(files "$line") + if [ -z "$match" ] ; then + echo "$line" + fi + done +} + +# Add a line to a set of lines if it begins with right pattern +add_line_to_if () # <new line> <lines> <head pattern> +{ + ( + echo "$2" + echo "$1" | sed -rn "s,^$3(.*),\1,p" + ) | + sed '/^$/d' +} + +# Subtract two sets of lines +aminusb () # <lines a> <lines b> +{ + printf "$1\n$2\n$2" | sort | uniq -u | sed '/^$/d' +} + +printf 'sections: ' +parsed=$(parse_fx MAINTAINERS) +echo "$parsed" | grep -c '^#' +printf 'with maintainer: ' +echo "$parsed" | grep -c '^#.*@' +printf 'maintainers: ' +grep '^M:.*<' MAINTAINERS | sort -u | wc -l + +echo +echo '##########' +echo '# orphan areas' +echo '##########' +echo "$parsed" | sed -rn 's,^#([^@]*)$,\1,p' | uniq + +echo +echo '##########' +echo '# files not listed' +echo '##########' +all=$(files ./) +listed=$(echo "$parsed" | sed '/^#/d' | sort -u) +aminusb "$all" "$listed" + +echo +echo '##########' +echo '# wrong patterns' +echo '##########' +check_fx MAINTAINERS + +# TODO: check overlaps diff --git a/src/spdk/dpdk/devtools/check-symbol-change.sh b/src/spdk/dpdk/devtools/check-symbol-change.sh new file mode 100755 index 00000000..daaf45e1 --- /dev/null +++ b/src/spdk/dpdk/devtools/check-symbol-change.sh @@ -0,0 +1,159 @@ +#!/bin/sh +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2018 Neil Horman <nhorman@tuxdriver.com> + +build_map_changes() +{ + local fname="$1" + local mapdb="$2" + + cat "$fname" | awk ' + # Initialize our variables + BEGIN {map="";sym="";ar="";sec=""; in_sec=0; in_map=0} + + # Anything that starts with + or -, followed by an a + # and ends in the string .map is the name of our map file + # This may appear multiple times in a patch if multiple + # map files are altered, and all section/symbol names + # appearing between a triggering of this rule and the + # next trigger of this rule are associated with this file + /[-+] a\/.*\.map/ {map=$2; in_map=1} + + # Same pattern as above, only it matches on anything that + # does not end in 'map', indicating we have left the map chunk. + # When we hit this, turn off the in_map variable, which + # supresses the subordonate rules below + /[-+] a\/.*\.^(map)/ {in_map=0} + + # Triggering this rule, which starts a line with a + and ends it + # with a { identifies a versioned section. The section name is + # the rest of the line with the + and { symbols remvoed. + # Triggering this rule sets in_sec to 1, which actives the + # symbol rule below + /+.*{/ {gsub("+",""); + if (in_map == 1) { + sec=$1; in_sec=1; + } + } + + # This rule idenfies the end of a section, and disables the + # symbol rule + /.*}/ {in_sec=0} + + # This rule matches on a + followed by any characters except a : + # (which denotes a global vs local segment), and ends with a ;. + # The semicolon is removed and the symbol is printed with its + # association file name and version section, along with an + # indicator that the symbol is a new addition. Note this rule + # only works if we have found a version section in the rule + # above (hence the in_sec check) And found a map file (the + # in_map check). If we are not in a map chunk, do nothing. If + # we are in a map chunk but not a section chunk, record it as + # unknown. + /^+[^}].*[^:*];/ {gsub(";","");sym=$2; + if (in_map == 1) { + if (in_sec == 1) { + print map " " sym " " sec " add" + } else { + print map " " sym " unknown add" + } + } + } + + # This is the same rule as above, but the rule matches on a + # leading - rather than a +, denoting that the symbol is being + # removed. + /^-[^}].*[^:*];/ {gsub(";","");sym=$2; + if (in_map == 1) { + if (in_sec == 1) { + print map " " sym " " sec " del" + } else { + print map " " sym " unknown del" + } + } + }' > "$mapdb" + + sort -u "$mapdb" > "$mapdb.2" + mv -f "$mapdb.2" "$mapdb" + +} + +check_for_rule_violations() +{ + local mapdb="$1" + local mname + local symname + local secname + local ar + local ret=0 + + while read mname symname secname ar + do + if [ "$ar" = "add" ] + then + + if [ "$secname" = "unknown" ] + then + # Just inform the user of this occurrence, but + # don't flag it as an error + echo -n "INFO: symbol $syname is added but " + echo -n "patch has insuficient context " + echo -n "to determine the section name " + echo -n "please ensure the version is " + echo "EXPERIMENTAL" + continue + fi + + if [ "$secname" != "EXPERIMENTAL" ] + then + # Symbols that are getting added in a section + # other than the experimental section + # to be moving from an already supported + # section or its a violation + grep -q \ + "$mname $symname [^EXPERIMENTAL] del" "$mapdb" + if [ $? -ne 0 ] + then + echo -n "ERROR: symbol $symname " + echo -n "is added in a section " + echo -n "other than the EXPERIMENTAL " + echo "section of the version map" + ret=1 + fi + fi + else + + if [ "$secname" != "EXPERIMENTAL" ] + then + # Just inform users that non-experimenal + # symbols need to go through a deprecation + # process + echo -n "INFO: symbol $symname is being " + echo -n "removed, ensure that it has " + echo "gone through the deprecation process" + fi + fi + done < "$mapdb" + + return $ret +} + +trap clean_and_exit_on_sig EXIT + +mapfile=`mktemp mapdb.XXXXXX` +patch=$1 +exit_code=1 + +clean_and_exit_on_sig() +{ + rm -f "$mapfile" + exit $exit_code +} + +build_map_changes "$patch" "$mapfile" +check_for_rule_violations "$mapfile" +exit_code=$? + +rm -f "$mapfile" + +exit $exit_code diff --git a/src/spdk/dpdk/devtools/check-symbol-maps.sh b/src/spdk/dpdk/devtools/check-symbol-maps.sh new file mode 100755 index 00000000..e137d48a --- /dev/null +++ b/src/spdk/dpdk/devtools/check-symbol-maps.sh @@ -0,0 +1,30 @@ +#! /bin/sh -e +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2018 Mellanox Technologies, Ltd + +cd $(dirname $0)/.. + +# speed up by ignoring Unicode details +export LC_ALL=C + +find_orphan_symbols () +{ + for map in $(find lib drivers -name '*.map') ; do + for sym in $(sed -rn 's,^([^}]*_.*);,\1,p' $map) ; do + if echo $sym | grep -q '^per_lcore_' ; then + continue + fi + if ! grep -q -r --exclude=$(basename $map) \ + -w $sym $(dirname $map) ; then + echo "$map: $sym" + fi + done + done +} + +orphan_symbols=$(find_orphan_symbols) +if [ -n "$orphan_symbols" ] ; then + echo "Found only in symbol map file:" + echo "$orphan_symbols" | sed 's,^,\t,' + exit 1 +fi diff --git a/src/spdk/dpdk/devtools/checkpatches.sh b/src/spdk/dpdk/devtools/checkpatches.sh new file mode 100755 index 00000000..ba795ad1 --- /dev/null +++ b/src/spdk/dpdk/devtools/checkpatches.sh @@ -0,0 +1,226 @@ +#! /bin/sh +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2015 6WIND S.A. + +# Load config options: +# - DPDK_CHECKPATCH_PATH +# - DPDK_CHECKPATCH_LINE_LENGTH +. $(dirname $(readlink -e $0))/load-devel-config + +VALIDATE_NEW_API=$(dirname $(readlink -e $0))/check-symbol-change.sh + +length=${DPDK_CHECKPATCH_LINE_LENGTH:-80} + +# override default Linux options +options="--no-tree" +options="$options --max-line-length=$length" +options="$options --show-types" +options="$options --ignore=LINUX_VERSION_CODE,\ +FILE_PATH_CHANGES,MAINTAINERS_STYLE,SPDX_LICENSE_TAG,\ +VOLATILE,PREFER_PACKED,PREFER_ALIGNED,PREFER_PRINTF,\ +PREFER_KERNEL_TYPES,BIT_MACRO,CONST_STRUCT,\ +SPLIT_STRING,LONG_LINE_STRING,\ +LINE_SPACING,PARENTHESIS_ALIGNMENT,NETWORKING_BLOCK_COMMENT_STYLE,\ +NEW_TYPEDEFS,COMPARISON_TO_NULL" + +clean_tmp_files() { + if echo $tmpinput | grep -q '^checkpatches\.' ; then + rm -f "$tmpinput" + fi +} + +trap "clean_tmp_files" INT + +print_usage () { + cat <<- END_OF_HELP + usage: $(basename $0) [-q] [-v] [-nX|patch1 [patch2] ...]] + + Run Linux kernel checkpatch.pl with DPDK options. + The environment variable DPDK_CHECKPATCH_PATH must be set. + + The patches to check can be from stdin, files specified on the command line, + or latest git commits limited with -n option (default limit: origin/master). + END_OF_HELP +} + +check_forbidden_additions() { + # This awk script receives a list of expressions to monitor + # and a list of folders to search these expressions in + # - No search is done inside comments + # - Both additions and removals of the expressions are checked + # A positive balance of additions fails the check + read -d '' awk_script << 'EOF' + BEGIN { + split(FOLDERS,deny_folders," "); + split(EXPRESSIONS,deny_expr," "); + in_file=0; + in_comment=0; + count=0; + comment_start="/*" + comment_end="*/" + } + # search for add/remove instances in current file + # state machine assumes the comments structure is enforced by + # checkpatches.pl + (in_file) { + # comment start + if (index($0,comment_start) > 0) { + in_comment = 1 + } + # non comment code + if (in_comment == 0) { + for (i in deny_expr) { + forbidden_added = "^\+.*" deny_expr[i]; + forbidden_removed="^-.*" deny_expr[i]; + current = expressions[deny_expr[i]] + if ($0 ~ forbidden_added) { + count = count + 1; + expressions[deny_expr[i]] = current + 1 + } + if ($0 ~ forbidden_removed) { + count = count - 1; + expressions[deny_expr[i]] = current - 1 + } + } + } + # comment end + if (index($0,comment_end) > 0) { + in_comment = 0 + } + } + # switch to next file , check if the balance of add/remove + # of previous filehad new additions + ($0 ~ "^\+\+\+ b/") { + in_file = 0; + if (count > 0) { + exit; + } + for (i in deny_folders) { + re = "^\+\+\+ b/" deny_folders[i]; + if ($0 ~ deny_folders[i]) { + in_file = 1 + last_file = $0 + } + } + } + END { + if (count > 0) { + print "Warning in " substr(last_file,6) ":" + print "are you sure you want to add the following:" + for (key in expressions) { + if (expressions[key] > 0) { + print key + } + } + exit RET_ON_FAIL + } + } +EOF + # --------------------------------- + # refrain from new additions of rte_panic() and rte_exit() + # multiple folders and expressions are separated by spaces + awk -v FOLDERS="lib drivers" \ + -v EXPRESSIONS="rte_panic\\\( rte_exit\\\(" \ + -v RET_ON_FAIL=1 \ + "$awk_script" - +} + +number=0 +quiet=false +verbose=false +while getopts hn:qv ARG ; do + case $ARG in + n ) number=$OPTARG ;; + q ) quiet=true ;; + v ) verbose=true ;; + h ) print_usage ; exit 0 ;; + ? ) print_usage ; exit 1 ;; + esac +done +shift $(($OPTIND - 1)) + +if [ ! -f "$DPDK_CHECKPATCH_PATH" ] || [ ! -x "$DPDK_CHECKPATCH_PATH" ] ; then + print_usage >&2 + echo + echo 'Cannot execute DPDK_CHECKPATCH_PATH' >&2 + exit 1 +fi + +total=0 +status=0 + +check () { # <patch> <commit> <title> + local ret=0 + + total=$(($total + 1)) + ! $verbose || printf '\n### %s\n\n' "$3" + if [ -n "$1" ] ; then + tmpinput=$1 + elif [ -n "$2" ] ; then + tmpinput=$(mktemp checkpatches.XXXXXX) + git format-patch --find-renames \ + --no-stat --stdout -1 $commit > "$tmpinput" + else + tmpinput=$(mktemp checkpatches.XXXXXX) + cat > "$tmpinput" + fi + + report=$($DPDK_CHECKPATCH_PATH $options "$tmpinput" 2>/dev/null) + if [ $? -ne 0 ] ; then + $verbose || printf '\n### %s\n\n' "$3" + printf '%s\n' "$report" | sed -n '1,/^total:.*lines checked$/p' + ret=1 + fi + + ! $verbose || printf '\nChecking API additions/removals:\n' + report=$($VALIDATE_NEW_API "$tmpinput") + if [ $? -ne 0 ] ; then + printf '%s\n' "$report" + ret=1 + fi + + ! $verbose || printf '\nChecking forbidden tokens additions:\n' + report=$(check_forbidden_additions <"$tmpinput") + if [ $? -ne 0 ] ; then + printf '%s\n' "$report" + ret=1 + fi + + clean_tmp_files + [ $ret -eq 0 ] && return 0 + + status=$(($status + 1)) +} + +if [ -n "$1" ] ; then + for patch in "$@" ; do + # Subject can be on 2 lines + subject=$(sed '/^Subject: */!d;s///;N;s,\n[[:space:]]\+, ,;s,\n.*,,;q' "$patch") + check "$patch" '' "$subject" + done +elif [ ! -t 0 ] ; then # stdin + subject=$(while read header value ; do + if [ "$header" = 'Subject:' ] ; then + IFS= read next + continuation=$(echo "$next" | sed -n 's,^[[:space:]]\+, ,p') + echo $value$continuation + break + fi + done) + check '' '' "$subject" +else + if [ $number -eq 0 ] ; then + commits=$(git rev-list --reverse origin/master..) + else + commits=$(git rev-list --reverse --max-count=$number HEAD) + fi + for commit in $commits ; do + subject=$(git log --format='%s' -1 $commit) + check '' $commit "$subject" + done +fi +pass=$(($total - $status)) +$quiet || printf '\n%d/%d valid patch' $pass $total +$quiet || [ $pass -le 1 ] || printf 'es' +$quiet || printf '\n' +exit $status diff --git a/src/spdk/dpdk/devtools/cocci.sh b/src/spdk/dpdk/devtools/cocci.sh new file mode 100755 index 00000000..4ca5025f --- /dev/null +++ b/src/spdk/dpdk/devtools/cocci.sh @@ -0,0 +1,64 @@ +#! /bin/sh + +# BSD LICENSE +# +# Copyright 2015 EZchip Semiconductor Ltd. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of EZchip Semiconductor nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Apply coccinelle transforms. + +SRCTREE=$(readlink -f $(dirname $0)/..) +COCCI=$SRCTREE/devtools/cocci +[ -n "$SPATCH" ] || SPATCH=$(which spatch) + +PATCH_LIST="$@" +[ -n "$PATCH_LIST" ] || PATCH_LIST=$(echo $COCCI/*.cocci) + +[ -x "$SPATCH" ] || ( + echo "Coccinelle tools not installed." + exit 1 +) + +tmp=$(mktemp) + +for c in $PATCH_LIST; do + while true; do + echo -n "Applying $c..." + $SPATCH --sp-file $c -c --linux-spacing --very-quiet \ + --include-headers --preprocess \ + --in-place --dir $SRCTREE > $tmp + if [ -s $tmp ]; then + echo " changes applied, retrying." + else + echo " no change." + break; + fi + done +done + +rm -f $tmp diff --git a/src/spdk/dpdk/devtools/cocci/mtod-offset.cocci b/src/spdk/dpdk/devtools/cocci/mtod-offset.cocci new file mode 100644 index 00000000..3f83f322 --- /dev/null +++ b/src/spdk/dpdk/devtools/cocci/mtod-offset.cocci @@ -0,0 +1,76 @@ +// +// Replace explicit packet offset computations with rte_pktmbuf_mtod_offset(). +// +@disable paren@ +typedef uint8_t; +expression M, O; +@@ +( +- rte_pktmbuf_mtod(M, char *) + O ++ rte_pktmbuf_mtod_offset(M, char *, O) +| +- rte_pktmbuf_mtod(M, char *) - O ++ rte_pktmbuf_mtod_offset(M, char *, -O) +| +- rte_pktmbuf_mtod(M, unsigned char *) + O ++ rte_pktmbuf_mtod_offset(M, unsigned char *, O) +| +- rte_pktmbuf_mtod(M, unsigned char *) - O ++ rte_pktmbuf_mtod_offset(M, unsigned char *, -O) +| +- rte_pktmbuf_mtod(M, uint8_t *) + O ++ rte_pktmbuf_mtod_offset(M, uint8_t *, O) +| +- rte_pktmbuf_mtod(M, uint8_t *) - O ++ rte_pktmbuf_mtod_offset(M, uint8_t *, -O) +) + + +// +// Fold subsequent offset terms into pre-existing offset used in +// rte_pktmbuf_mtod_offset(). +// +@disable paren@ +expression M, O1, O2; +@@ +( +- rte_pktmbuf_mtod_offset(M, char *, O1) + O2 ++ rte_pktmbuf_mtod_offset(M, char *, O1 + O2) +| +- rte_pktmbuf_mtod_offset(M, char *, O1) - O2 ++ rte_pktmbuf_mtod_offset(M, char *, O1 - O2) +| +- rte_pktmbuf_mtod_offset(M, unsigned char *, O1) + O2 ++ rte_pktmbuf_mtod_offset(M, unsigned char *, O1 + O2) +| +- rte_pktmbuf_mtod_offset(M, unsigned char *, O1) - O2 ++ rte_pktmbuf_mtod_offset(M, unsigned char *, O1 - O2) +| +- rte_pktmbuf_mtod_offset(M, uint8_t *, O1) + O2 ++ rte_pktmbuf_mtod_offset(M, uint8_t *, O1 + O2) +| +- rte_pktmbuf_mtod_offset(M, uint8_t *, O1) - O2 ++ rte_pktmbuf_mtod_offset(M, uint8_t *, O1 - O2) +) + + +// +// Cleanup rules. Fold in double casts, remove unnecessary parenthesis, etc. +// +@disable paren@ +expression M, O; +type C, T; +@@ +( +- (C)rte_pktmbuf_mtod_offset(M, T, O) ++ rte_pktmbuf_mtod_offset(M, C, O) +| +- (rte_pktmbuf_mtod_offset(M, T, O)) ++ rte_pktmbuf_mtod_offset(M, T, O) +| +- (C)rte_pktmbuf_mtod(M, T) ++ rte_pktmbuf_mtod(M, C) +| +- (rte_pktmbuf_mtod(M, T)) ++ rte_pktmbuf_mtod(M, T) +) diff --git a/src/spdk/dpdk/devtools/cocci/strlcpy.cocci b/src/spdk/dpdk/devtools/cocci/strlcpy.cocci new file mode 100644 index 00000000..335e2712 --- /dev/null +++ b/src/spdk/dpdk/devtools/cocci/strlcpy.cocci @@ -0,0 +1,8 @@ +@use_strlcpy@ +identifier src, dst; +expression size; +@@ +( +- snprintf(dst, size, "%s", src) ++ strlcpy(dst, src, size) +) diff --git a/src/spdk/dpdk/devtools/get-maintainer.sh b/src/spdk/dpdk/devtools/get-maintainer.sh new file mode 100755 index 00000000..b9160486 --- /dev/null +++ b/src/spdk/dpdk/devtools/get-maintainer.sh @@ -0,0 +1,58 @@ +#!/bin/sh +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2017 Intel Corporation + + +# Load config options: +# - DPDK_GETMAINTAINER_PATH +. $(dirname $(readlink -e $0))/load-devel-config + +options="--no-git-fallback" +options="$options --no-rolestats" + +print_usage () { + cat <<- END_OF_HELP + usage: $(basename $0) <patch> + + The DPDK_GETMAINTAINER_PATH variable should be set to the full path to + the get_maintainer.pl script located in Linux kernel sources. Example: + DPDK_GETMAINTAINER_PATH=~/linux/scripts/get_maintainer.pl + + Also refer to devtools/load-devel-config to store your configuration. + END_OF_HELP +} + +# Requires DPDK_GETMAINTAINER_PATH devel config option set +if [ ! -f "$DPDK_GETMAINTAINER_PATH" ] || + [ ! -x "$DPDK_GETMAINTAINER_PATH" ] ; then + print_usage >&2 + echo + echo 'Cannot execute DPDK_GETMAINTAINER_PATH' >&2 + exit 1 +fi + +FILES="COPYING CREDITS Kbuild" +FOLDERS="Documentation arch include fs init ipc scripts" + +# Kernel script checks for some files and folders to run +workaround () { + for f in $FILES; do + if [ ! -f $f ]; then touch $f; fi + done + + for d in $FOLDERS; do + if [ ! -d $d ]; then mkdir $d; fi + done +} + +fix_workaround () { + for f in $FILES; do if [ -f $f ]; then rm -f $f; fi; done + for d in $FOLDERS; do if [ -d $d ]; then rmdir $d; fi; done +} + +# clean workaround on exit +trap fix_workaround EXIT + +workaround +$DPDK_GETMAINTAINER_PATH $options $@ +# fix_workaround called on exit by trap diff --git a/src/spdk/dpdk/devtools/git-log-fixes.sh b/src/spdk/dpdk/devtools/git-log-fixes.sh new file mode 100755 index 00000000..e37ee226 --- /dev/null +++ b/src/spdk/dpdk/devtools/git-log-fixes.sh @@ -0,0 +1,112 @@ +#! /bin/sh -e +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2016 6WIND S.A. + +print_usage () +{ + echo "usage: $(basename $0) [-h] <git_range>" +} + +print_help () +{ + print_usage + cat <<- END_OF_HELP + + Find fixes to backport on previous versions. + It looks for the word "fix" in the headline or a tag "Fixes" or "Reverts". + The oldest bug origin is printed as well as partially fixed versions. + END_OF_HELP +} + +usage_error () # <message> +{ + echo "$*" >&2 + print_usage >&2 + exit 1 +} + +while getopts h ARG ; do + case $ARG in + h ) print_help ; exit 0 ;; + ? ) print_usage >&2 ; exit 1 ;; + esac +done +shift $(($OPTIND - 1)) +[ $# -ge 1 ] || usage_error 'range argument required' +range="$*" + +# get major release version of a commit +commit_version () # <hash> +{ + # use current branch as history reference + local refbranch=$(git rev-parse --abbrev-ref HEAD) + local tag=$( (git tag -l --contains $1 --merged $refbranch 2>&- || + # tag --merged option has been introduced in git 2.7.0 + # below is a fallback in case of old git version + for t in $(git tag -l --contains $1) ; do + git branch $refbranch --contains $t | + sed "s,.\+,$t," + done) | + head -n1) + if [ -z "$tag" ] ; then + # before -rc1 tag of release in progress + make showversion | cut -d'.' -f-2 + else + echo $tag | sed 's,^v,,' | sed 's,-rc.*,,' + fi +} + +# get bug origin hashes of a fix +origin_filter () # <hash> +{ + git log --format='%b' -1 $1 | + sed -n 's,^ *\([Ff]ixes\|[Rr]everts\): *\([0-9a-f]*\).*,\2,p' +} + +# get oldest major release version of bug origins +origin_version () # <origin_hash> ... +{ + for origin in $* ; do + # check hash is valid + git rev-parse -q --verify $1 >&- || continue + # get version of this bug origin + local origver=$(commit_version $origin) + local roothashes="$(origin_filter $origin)" + if [ -n "$roothashes" ] ; then + # look chained fix of fix recursively + local rootver="$(origin_version $roothashes)" + [ -n "$rootver" ] || continue + echo "$rootver (partially fixed in $origver)" + else + echo "$origver" + fi + # filter the oldest origin + done | sort -uV | head -n1 +} + +# print a marker for stable tag presence +stable_tag () # <hash> +{ + if git log --format='%b' -1 $1 | grep -qi '^Cc: *stable@dpdk.org' ; then + echo 'S' + else + echo '-' + fi +} + +git log --oneline --reverse $range | +while read id headline ; do + origins=$(origin_filter $id) + stable=$(stable_tag $id) + [ "$stable" = "S" ] || [ -n "$origins" ] || echo "$headline" | grep -q fix || continue + version=$(commit_version $id) + if [ -n "$origins" ] ; then + origver="$(origin_version $origins)" + [ -n "$origver" ] || continue + # ignore fix of bug introduced in the same release + ! echo "$origver" | grep -q "^$version" || continue + else + origver='N/A' + fi + printf '%s %7s %s %s (%s)\n' $version $id $stable "$headline" "$origver" +done diff --git a/src/spdk/dpdk/devtools/load-devel-config b/src/spdk/dpdk/devtools/load-devel-config new file mode 100644 index 00000000..4f43cb35 --- /dev/null +++ b/src/spdk/dpdk/devtools/load-devel-config @@ -0,0 +1,12 @@ +# Load DPDK devel config and allow override +# from system file +test ! -r /etc/dpdk/devel.config || + . /etc/dpdk/devel.config +# from user file +test ! -r ~/.config/dpdk/devel.config || + . ~/.config/dpdk/devel.config +# from local file +test ! -r $(dirname $(readlink -m $0))/../.develconfig || + . $(dirname $(readlink -m $0))/../.develconfig + +# The config files must export variables in the shell style diff --git a/src/spdk/dpdk/devtools/test-build.sh b/src/spdk/dpdk/devtools/test-build.sh new file mode 100755 index 00000000..1eee2417 --- /dev/null +++ b/src/spdk/dpdk/devtools/test-build.sh @@ -0,0 +1,244 @@ +#! /bin/sh -e +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2015 6WIND S.A. + +default_path=$PATH + +# Load config options: +# - ARMV8_CRYPTO_LIB_PATH +# - DPDK_BUILD_TEST_CONFIGS (defconfig1+option1+option2 defconfig2) +# - DPDK_DEP_ARCHIVE +# - DPDK_DEP_CFLAGS +# - DPDK_DEP_ISAL (y/[n]) +# - DPDK_DEP_LDFLAGS +# - DPDK_DEP_MLX (y/[n]) +# - DPDK_DEP_NUMA ([y]/n) +# - DPDK_DEP_PCAP (y/[n]) +# - DPDK_DEP_SSL (y/[n]) +# - DPDK_DEP_IPSEC_MB (y/[n]) +# - DPDK_DEP_SZE (y/[n]) +# - DPDK_DEP_ZLIB (y/[n]) +# - DPDK_MAKE_JOBS (int) +# - DPDK_NOTIFY (notify-send) +# - FLEXRAN_SDK +# - LIBMUSDK_PATH +# - LIBSSO_SNOW3G_PATH +# - LIBSSO_KASUMI_PATH +# - LIBSSO_ZUC_PATH +. $(dirname $(readlink -e $0))/load-devel-config + +print_usage () { + echo "usage: $(basename $0) [-h] [-jX] [-s] [config1 [config2] ...]]" +} + +print_help () { + echo 'Test building several targets with different options' + echo + print_usage + cat <<- END_OF_HELP + + options: + -h this help + -jX use X parallel jobs in "make" + -s short test only first config without tests|examples|doc + -v verbose build + + config: defconfig[[~][+]option1[[~][+]option2...]] + Example: x86_64-native-linuxapp-gcc+debug~RXTX_CALLBACKS + The lowercase options are defined inside $(basename $0). + The uppercase options can be the end of a defconfig option + to enable if prefixed with '+' or to disable if prefixed with '~'. + Default is to automatically enable most of the options. + The external dependencies are setup with DPDK_DEP_* variables. + If no config on command line, DPDK_BUILD_TEST_CONFIGS is used. + END_OF_HELP +} + +J=$DPDK_MAKE_JOBS +short=false +unset verbose +maxerr=-Wfatal-errors +while getopts hj:sv ARG ; do + case $ARG in + j ) J=$OPTARG ;; + s ) short=true ;; + v ) verbose='V=1' ;; + h ) print_help ; exit 0 ;; + ? ) print_usage ; exit 1 ;; + esac +done +shift $(($OPTIND - 1)) +configs=${*:-$DPDK_BUILD_TEST_CONFIGS} + +success=false +on_exit () +{ + if $success ; then + [ "$DPDK_NOTIFY" != notify-send ] || \ + notify-send -u low --icon=dialog-information 'DPDK build' 'finished' + elif [ -z "$signal" ] ; then + [ -z "$dir" ] || echo "failed to build $dir" >&2 + [ "$DPDK_NOTIFY" != notify-send ] || \ + notify-send -u low --icon=dialog-error 'DPDK build' 'failed' + fi +} +# catch manual interrupt to ignore notification +trap "signal=INT ; trap - INT ; kill -INT $$" INT +# notify result on exit +trap on_exit EXIT + +cd $(dirname $(readlink -m $0))/.. + +reset_env () +{ + export PATH=$default_path + unset CROSS + unset DPDK_DEP_ARCHIVE + unset DPDK_DEP_CFLAGS + unset DPDK_DEP_ISAL + unset DPDK_DEP_LDFLAGS + unset DPDK_DEP_MLX + unset DPDK_DEP_NUMA + unset DPDK_DEP_PCAP + unset DPDK_DEP_SSL + unset DPDK_DEP_IPSEC_MB + unset DPDK_DEP_SZE + unset DPDK_DEP_ZLIB + unset ARMV8_CRYPTO_LIB_PATH + unset FLEXRAN_SDK + unset LIBMUSDK_PATH + unset LIBSSO_SNOW3G_PATH + unset LIBSSO_KASUMI_PATH + unset LIBSSO_ZUC_PATH + unset PQOS_INSTALL_PATH +} + +config () # <directory> <target> <options> +{ + reconfig=false + if git rev-parse 2>&- && [ -n "$(git diff HEAD~ -- config)" ] ; then + echo 'Default config may have changed' + reconfig=true + fi + if [ ! -e $1/.config ] || $reconfig ; then + echo "================== Configure $1" + make T=$2 O=$1 config + + echo 'Customize configuration' + # Built-in options (lowercase) + ! echo $3 | grep -q '+default' || \ + sed -ri 's,(RTE_MACHINE=")native,\1default,' $1/.config + echo $3 | grep -q '+next' || \ + sed -ri 's,(NEXT_ABI=)y,\1n,' $1/.config + ! echo $3 | grep -q '+shared' || \ + sed -ri 's,(SHARED_LIB=)n,\1y,' $1/.config + ! echo $3 | grep -q '+debug' || ( \ + sed -ri 's,(RTE_LOG_DP_LEVEL=).*,\1RTE_LOG_DEBUG,' $1/.config + sed -ri 's,(_DEBUG.*=)n,\1y,' $1/.config + sed -ri 's,(_STAT.*=)n,\1y,' $1/.config + sed -ri 's,(TEST_PMD_RECORD_.*=)n,\1y,' $1/.config ) + + # Automatic configuration + test "$DPDK_DEP_NUMA" != n || \ + sed -ri 's,(NUMA.*=)y,\1n,' $1/.config + sed -ri 's,(LIBRTE_IEEE1588=)n,\1y,' $1/.config + sed -ri 's,(BYPASS=)n,\1y,' $1/.config + test "$DPDK_DEP_ARCHIVE" != y || \ + sed -ri 's,(RESOURCE_TAR=)n,\1y,' $1/.config + test "$DPDK_DEP_ISAL" != y || \ + sed -ri 's,(ISAL_PMD=)n,\1y,' $1/.config + test "$DPDK_DEP_MLX" != y || \ + sed -ri 's,(MLX._PMD=)n,\1y,' $1/.config + test "$DPDK_DEP_SZE" != y || \ + sed -ri 's,(PMD_SZEDATA2=)n,\1y,' $1/.config + test "$DPDK_DEP_ZLIB" != y || \ + sed -ri 's,(BNX2X_PMD=)n,\1y,' $1/.config + test "$DPDK_DEP_ZLIB" != y || \ + sed -ri 's,(COMPRESSDEV_TEST=)n,\1y,' $1/.config + test "$DPDK_DEP_PCAP" != y || \ + sed -ri 's,(PCAP=)n,\1y,' $1/.config + test -z "$ARMV8_CRYPTO_LIB_PATH" || \ + sed -ri 's,(PMD_ARMV8_CRYPTO=)n,\1y,' $1/.config + test "$DPDK_DEP_IPSEC_MB" != y || \ + sed -ri 's,(PMD_AESNI_MB=)n,\1y,' $1/.config + test "$DPDK_DEP_IPSEC_MB" != y || \ + sed -ri 's,(PMD_AESNI_GCM=)n,\1y,' $1/.config + test -z "$LIBSSO_SNOW3G_PATH" || \ + sed -ri 's,(PMD_SNOW3G=)n,\1y,' $1/.config + test -z "$LIBSSO_KASUMI_PATH" || \ + sed -ri 's,(PMD_KASUMI=)n,\1y,' $1/.config + test -z "$LIBSSO_ZUC_PATH" || \ + sed -ri 's,(PMD_ZUC=)n,\1y,' $1/.config + test "$DPDK_DEP_SSL" != y || \ + sed -ri 's,(PMD_CCP=)n,\1y,' $1/.config + test "$DPDK_DEP_SSL" != y || \ + sed -ri 's,(PMD_OPENSSL=)n,\1y,' $1/.config + test "$DPDK_DEP_SSL" != y || \ + sed -ri 's,(PMD_QAT=)n,\1y,' $1/.config + test -z "$FLEXRAN_SDK" || \ + sed -ri 's,(BBDEV_TURBO_SW=)n,\1y,' $1/.config + sed -ri 's,(SCHED_.*=)n,\1y,' $1/.config + test -z "$LIBMUSDK_PATH" || \ + sed -ri 's,(PMD_MVSAM_CRYPTO=)n,\1y,' $1/.config + test -z "$LIBMUSDK_PATH" || \ + sed -ri 's,(MVPP2_PMD=)n,\1y,' $1/.config + build_config_hook $1 $2 $3 + + # Explicit enabler/disabler (uppercase) + for option in $(echo $3 | sed 's,[~+], &,g') ; do + pattern=$(echo $option | cut -c2-) + if echo $option | grep -q '^~' ; then + sed -ri "s,($pattern=)y,\1n," $1/.config + elif echo $option | grep -q '^+' ; then + sed -ri "s,($pattern=)n,\1y," $1/.config + fi + done + fi +} + +# default empty hook to override in devel config +build_config_hook () # <directory> <target> <options> +{ + : +} + +for conf in $configs ; do + target=$(echo $conf | sed 's,[~+].*,,') + # reload config with DPDK_TARGET set + DPDK_TARGET=$target + reset_env + . $(dirname $(readlink -e $0))/load-devel-config + + options=$(echo $conf | sed 's,[^~+]*,,') + dir=$conf + config $dir $target $options + + echo "================== Build $dir" + make -j$J EXTRA_CFLAGS="$maxerr $DPDK_DEP_CFLAGS" \ + EXTRA_LDFLAGS="$DPDK_DEP_LDFLAGS" $verbose O=$dir + ! $short || break + echo "================== Build tests for $dir" + make test-build -j$J EXTRA_CFLAGS="$maxerr $DPDK_DEP_CFLAGS" \ + EXTRA_LDFLAGS="$DPDK_DEP_LDFLAGS" $verbose O=$dir + echo "================== Build examples for $dir" + export RTE_SDK=$(pwd) + export RTE_TARGET=$dir + make -j$J -sC examples \ + EXTRA_LDFLAGS="$DPDK_DEP_LDFLAGS" $verbose \ + O=$(readlink -m $dir/examples) + unset RTE_TARGET + echo "################## $dir done." + unset dir +done + +if ! $short ; then + mkdir -p .check + echo "================== Build doxygen HTML API" + make doc-api-html >/dev/null 2>.check/doc.txt + echo "================== Build sphinx HTML guides" + make doc-guides-html >/dev/null 2>>.check/doc.txt + echo "================== Check docs" + diff -u /dev/null .check/doc.txt +fi + +success=true diff --git a/src/spdk/dpdk/devtools/test-meson-builds.sh b/src/spdk/dpdk/devtools/test-meson-builds.sh new file mode 100755 index 00000000..951c9067 --- /dev/null +++ b/src/spdk/dpdk/devtools/test-meson-builds.sh @@ -0,0 +1,60 @@ +#! /bin/sh -e +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2018 Intel Corporation + +# Run meson to auto-configure the various builds. +# * all builds get put in a directory whose name starts with "build-" +# * if a build-directory already exists we assume it was properly configured +# Run ninja after configuration is done. + +srcdir=$(dirname $(readlink -m $0))/.. +MESON=${MESON:-meson} + +if command -v ninja >/dev/null 2>&1 ; then + ninja_cmd=ninja +elif command -v ninja-build >/dev/null 2>&1 ; then + ninja_cmd=ninja-build +else + echo "ERROR: ninja is not found" >&2 + exit 1 +fi + +build () # <directory> <meson options> +{ + builddir=$1 + shift + if [ ! -d "$builddir" ] ; then + options="--werror -Dexamples=all $*" + echo "$MESON $options $srcdir $builddir" + $MESON $options $srcdir $builddir + unset CC + fi + echo "$ninja_cmd -C $builddir" + $ninja_cmd -C $builddir +} + +# shared and static linked builds with gcc and clang +for c in gcc clang ; do + for s in static shared ; do + export CC="ccache $c" + build build-$c-$s --default-library=$s + done +done + +# test compilation with minimal x86 instruction set +build build-x86-default -Dmachine=nehalem + +# enable cross compilation if gcc cross-compiler is found +c=aarch64-linux-gnu-gcc +if command -v $c >/dev/null 2>&1 ; then + # compile the general v8a also for clang to increase coverage + export CC="ccache clang" + build build-arm64-host-clang --cross-file \ + config/arm/arm64_armv8_linuxapp_gcc + + for f in config/arm/arm*gcc ; do + export CC="ccache gcc" + build build-$(basename $f | tr '_' '-' | cut -d'-' -f-2) \ + --cross-file $f + done +fi diff --git a/src/spdk/dpdk/devtools/test-null.sh b/src/spdk/dpdk/devtools/test-null.sh new file mode 100755 index 00000000..61879e3e --- /dev/null +++ b/src/spdk/dpdk/devtools/test-null.sh @@ -0,0 +1,17 @@ +#! /bin/sh -e +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2015 6WIND S.A. + +# Run a quick testpmd forwarding with null PMD without hugepage + +build=${1:-build} +coremask=${2:-3} # default using cores 0 and 1 + +if grep -q SHARED_LIB=y $build/.config; then + pmd='-d librte_pmd_null.so' +fi + +(sleep 1 && echo stop) | +$build/app/testpmd -c $coremask -n 1 --no-huge \ + $pmd --vdev net_null1 --vdev net_null2 -- \ + --total-num-mbufs=2048 -ia diff --git a/src/spdk/dpdk/devtools/validate-abi.sh b/src/spdk/dpdk/devtools/validate-abi.sh new file mode 100755 index 00000000..138436d9 --- /dev/null +++ b/src/spdk/dpdk/devtools/validate-abi.sh @@ -0,0 +1,251 @@ +#!/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-linuxapp-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 |