Mercurial > hg > vamp-build-and-test
view SCRIPTS/process.sh @ 133:4acb5d8d80b6 tip
Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author | Chris Cannam |
---|---|
date | Tue, 30 Jul 2019 12:25:44 +0100 |
parents | 85e84012311b |
children |
line wrap: on
line source
#!/bin/bash # Run this from the top-level vamp-build-and-test directory ## Things to test: ## the plugin builds! ## plugin loads ## passes vamp-plugin-tester tests ## does not export any unnecessary symbols ## has valid .cat and .n3 set -e mydir=$(dirname "$0") case "$mydir" in /*);; *) mydir=$(pwd)/"$mydir";; esac . "$mydir"/include.sh have_all=true for program in make perl git svn hg zip tar ; do if ! $program --version >/dev/null 2>&1; then if ! $program -v 2>&1 | grep -q version; then echo " ** $program program not found" have_all=false fi fi done if [ "$have_all" != "true" ]; then echo "Not all dependencies found, exiting" exit 1 fi do_rebuild="" do_speedy="" speedy_test_pattern="^[ABE]" usage() { echo echo "Usage: $0 <platform> [-c] [-s] [<dir> ...]" echo echo " <platform> one of native, linux32, linux64, mingw32, mingw64, osx32, osx64" echo " -c build from clean" echo " -s speedy build: skip the slower tests" echo " <dir> directory to build (default is all of them)" echo echo "Platform usually should match the platform you are running this" echo "script on, unless you have a cross-compile toolset installed and" echo "this script knows how to run it. The special platform 'native'" echo "tries to guess the currently running platform." echo exit 2 } platform_arg="$1" platform_native="unknown" case `uname -a` in Linux*x86_64*) platform_native=linux64;; Linux*) platform_native=linux32;; Darwin*) platform_native=osx64;; CYG*) platform_native=mingw32;; MINGW*) platform_native=mingw32;; esac if [ "$platform_arg" = "native" ]; then platform_arg="$platform_native" fi platform= platform_defines=("UNUSED_=") # Avoid passing empty arg to make as if target pubtag= bits=32 altbits= toolprefix= pluginext= hostwrapper= hostext= valgrind= archflags= identpattern= sep=":" case "$platform_arg" in linux32) platform=linux pubtag=linux32 if [ "$platform_native" = "linux64" ]; then toolprefix=x86_64-unknown-linux-gnu- platform_defines=("CXX=${toolprefix}g++ -m32" "CC=${toolprefix}gcc -m32" "LD=${toolprefix}g++ -m32") fi pluginext=.so valgrind=valgrind identpattern='ELF 32' ;; linux64) platform=linux bits=64 pubtag=linux64 pluginext=.so valgrind=valgrind identpattern='ELF 64' ;; mingw32) platform=mingw pubtag=win32 toolprefix=i686-w64-mingw32- pluginext=.dll hostwrapper=wine hostext=.exe identpattern='PE32.*386.*Windows' sep=";" ;; mingw64) platform=mingw bits=64 pubtag=win64 altbits=32 # We can usually use a mingw32 Makefile if toolprefix is OK toolprefix=x86_64-w64-mingw32- pluginext=.dll hostwrapper=wine hostext=.exe identpattern='PE32.*x86-64.*Windows' sep=";" ;; osx32) platform=osx pubtag=osx32 pluginext=.dylib archflags="-arch i386" identpattern='Mach-O .*i386' ;; osx64) platform=osx bits=64 pubtag=osx pluginext=.dylib # This is a difficult choice for various reasons... have to ponder archflags="-mmacosx-version-min=10.7 -arch x86_64 -arch i386 -stdlib=libc++" identpattern='Mach-O 64-bit .*x86_64' ;; *) usage ;; esac; shift if [ -z "$platform" ]; then usage else echo "(Platform is $platform, $bits bits, package platform tag $pubtag)" fi if [ -z "$pluginext" ]; then echo "Internal error: pluginext not set for platform $platform" 1>&2 exit 2 fi if [ -z "$identpattern" ]; then echo "Internal error: identpattern not set for platform $platform" 1>&2 exit 2 fi while true; do case "t$1" in t-c) echo "(Building from clean)" do_rebuild=yes shift ;; t-s) echo "(Speedy build)" do_speedy=yes shift ;; *) break;; esac done metadir="$mydir"/../METADATA depincdir="$mydir"/../DEPENDENCIES/$platform$bits/include deplibdir="$mydir"/../DEPENDENCIES/$platform$bits/lib depincdir_generic="$mydir"/../DEPENDENCIES/generic/include pyver=27 pyincdir="$mydir"/../DEPENDENCIES/$platform$bits/Python$pyver/include numpyincdir="$mydir"/../DEPENDENCIES/$platform$bits/Python$pyver/Lib/site-packages/numpy/core/include pylibdir="$mydir"/../DEPENDENCIES/$platform$bits/Python$pyver/libs plugindirs="$@" if [ -z "$plugindirs" ]; then plugindirs=$(cat METADATA/repos.txt | grep -v vamp-plugin-sdk | grep -v vamp-plugin-tester | awk '{ print $1; }') else for dir in $plugindirs ; do if [ ! -d "$dir" ]; then echo "ERROR: Directory $dir not found" usage fi done fi set -u reportdir="REPORTS/$platform$bits" packagedir="PACKAGES/$platform$bits" mkdir -p "$reportdir" "$packagedir" || exit 1 built="/tmp/built.$$.txt" testfailed="/tmp/testfailed.$$.txt" envcheckfailed="/tmp/envcheckfailed.$$.txt" notbuilt="/tmp/notbuilt.$$.txt" trap 'rm -f "$built" "$envcheckfailed" "$testfailed" "$notbuilt"' 0 touch "$built" "$envcheckfailed" "$testfailed" "$notbuilt" target_for() { local dir="$1" if grep -q "^$dir: " ${metadir}/maketarget.txt ; then grep "^$dir: " ${metadir}/maketarget.txt | head -1 | sed 's/^[^:]*: //' fi } custom_plugin_dir_for() { local dir="$1" if grep -q "^$dir: " ${metadir}/plugindir.txt ; then echo "${mydir}/../${dir}"/$(grep "^$dir: " ${metadir}/plugindir.txt | head -1 | sed 's/^[^:]*: //') fi } plugin_dir_for() { local dir="$1" local pdir=$(custom_plugin_dir_for "$dir") if [ -z "$pdir" ]; then case "$dir" in /*) pdir="$dir" ;; *) pdir="${mydir}/../${dir}";; esac fi echo "$pdir" } configure() { local dir="$1" if [ -f "$dir/configure" ] ; then ( cd "$dir" ; ./configure ) 2>&1 | tee "$reportdir/$dir.configure.txt" fi } repoint() { local dir="$1" if [ -f "$dir/repoint-project.json" ] ; then ( cd "$dir" ; ./repoint install ) 2>&1 | tee "$reportdir/$dir.repoint.txt" fi } find_makefile() { local dir="$1" for f in \ build/$platform$bits/Makefile.$platform$bits \ build/$platform/Makefile.$platform$bits \ build/$platform$bits/Makefile.$platform \ build/$platform$bits/Makefile \ build/Makefile.$platform$bits \ Makefile.$platform$bits \ build/$platform/Makefile.$platform \ build/$platform/Makefile \ build/Makefile.$platform \ Makefile.$platform \ build/$platform$altbits/Makefile.$platform$altbits \ build/$platform/Makefile.$platform$altbits \ build/$platform$altbits/Makefile.$platform \ build/$platform$altbits/Makefile \ build/Makefile.$platform$altbits \ Makefile.$platform$altbits \ Makefile ; do if [ -f "$dir/$f" ]; then echo $f break fi done } find_vampy_plugins_in() { local dir="$1" local pdir=$(plugin_dir_for "$dir") find "$pdir" -name \*.py -print0 | xargs -0 grep -l 'import.*\bvampy\b' } have_vampy_plugins() { local dir="$1" local plugs=$(find_vampy_plugins_in "$dir") if [ -z "$plugs" ]; then return 1 else return 0 fi } configure_maybe() { local dir="$1" if [ t"$do_rebuild" = t"yes" ]; then configure "$dir" else mfile=$(find_makefile "$dir") if [ -z "$mfile" ]; then configure "$dir" fi fi } logfile_for() { local activity="$1" local dir="$2" echo "$reportdir/$dir.$activity.txt" } build() { local dir="$1" local log=$(logfile_for build "$dir") repoint "$dir" if configure_maybe "$dir"; then mfile=$(find_makefile "$dir") if [ -n "$mfile" ]; then target=$(target_for "$dir") TOOLPREFIX="$toolprefix" \ CXXFLAGS="-I${depincdir} -I${pyincdir} -I${numpyincdir} -I${depincdir_generic} -I${mydir}/../vamp-plugin-sdk" \ LDFLAGS="-L${deplibdir} -L${pylibdir} -L${mydir}/../vamp-plugin-sdk" \ ARCHFLAGS="$archflags" \ make -C "$dir" -f "$mfile" $target "${platform_defines[@]}" 2>&1 | \ tee "$log" return ${PIPESTATUS[0]} elif have_vampy_plugins "$dir"; then return 0 else echo "*** Failed to find a Makefile in $dir!" | tee "$log" return 1 fi fi } rebuild() { local dir="$1" local log=$(logfile_for build "$dir") repoint "$dir" if configure_maybe "$dir"; then mfile=$(find_makefile "$dir") if [ -n "$mfile" ]; then if make -C "$dir" -f "$mfile" distclean; then build "$dir" elif make -C "$dir" -f "$mfile" clean; then build "$dir" else echo "*** Failed to 'make clean' in $dir!" | tee "$log" return 1 fi elif have_vampy_plugins "$dir"; then return 0 else echo "*** Failed to find a Makefile in $dir!" | tee "$log" return 1 fi fi } build_or_rebuild() { local dir="$1" if [ -n "$do_rebuild" ]; then rebuild "$dir" else build "$dir" fi } have_plugin() { local dir="$1" local log=$(logfile_for build "$dir") for x in "$dir/"*"$pluginext"; do if [ -f "$x" ]; then if file "$x" | grep -q "$identpattern" ; then return 0 else echo "Plugin $x exists, but fails to match file type for correct platform (file type is: `file $x`, expected pattern is: $identpattern)" | tee "$log" return 1 fi fi done have_vampy_plugins "$dir" } is_nondeterministic() { plugin_id="$1" grep -q "^$id\$" ${metadir}/nondeterministic.txt } plugin_ids_in() { local dir="$1" local pdir=$(plugin_dir_for "$dir") local vampydir="" if have_vampy_plugins "$pdir"; then vampydir="./vampy" fi # can't use sed to remove \r from DOS line endings -- BSD and GNU # vary in how they interpret \r escape -- so we use perl for that... VAMP_PATH="$pdir$sep$vampydir" $hostwrapper \ vamp-plugin-sdk/host/vamp-simple-host$hostext --list-ids | \ grep '^vamp:' | \ sed 's/^vamp://' | \ perl -p -e 's/\r//g' } run_tester() { ##!!! todo: timeout if the plugin takes too long and report as failure local dir="$1" local log=$(logfile_for test "$dir") local ids=$(plugin_ids_in "$dir") local pdir=$(plugin_dir_for "$dir") cat /dev/null > "$log" if [ -z "$ids" ]; then echo echo "No plugins reported to test in $dir" | tee -a "$log" echo "$dir" >> "$testfailed" return 1 fi good=yes for id in $ids; do extra="" if is_nondeterministic "$id"; then extra="-n" fi tests=$($hostwrapper vamp-plugin-tester/vamp-plugin-tester$hostext -l | tail -n +6 | sed 's/ *|.*$//' | fmt -1000) for test in $tests; do run_this_test=yes if [ -n "$do_speedy" ]; then if echo "$test" | grep -q "$speedy_test_pattern"; then run_this_test=yes else run_this_test="" fi fi if [ -z "$run_this_test" ]; then continue fi echo "Running command: VAMP_PATH=\"$pdir\" $hostwrapper vamp-plugin-tester/vamp-plugin-tester$hostext \"$extra\" -t \"$test\" \"$id\"" | tee -a "$log" if ( VAMP_PATH="$pdir$sep./vampy" $hostwrapper vamp-plugin-tester/vamp-plugin-tester$hostext "$extra" -t "$test" "$id" 2>&1 | tee -a "$log" ; exit ${PIPESTATUS[0]} ) ; then echo "OK" | tee -a "$log" else if [ -n "$do_speedy" ]; then echo | tee -a "$log" echo "Tester failed for id $id and test $test (not restarting with valgrind, as speedy flag is set)" | tee -a "$log" elif have_vampy_plugins "$pdir"; then # (don't attempt vampy+valgrind) echo | tee -a "$log" echo "Tester failed for id $id and test $test (not restarting with valgrind, as this is a VamPy plugin)" | tee -a "$log" else echo | tee -a "$log" echo "Tester failed for id $id and test $test: running again with valgrind (if available) and verbose for a report..." | tee -a "$log" VAMP_PATH="$pdir$sep./vampy" $valgrind $hostwrapper vamp-plugin-tester/vamp-plugin-tester$hostext -v "$extra" -t "$test" "$id" 2>&1 | tee -a "$log" fi good=no fi done done if [ "$good" != "yes" ]; then echo "$dir" >> "$testfailed" return 1 else return 0 fi } public_symbols_in() { lib="$1" # nm -g prints global symbols in both OS/X and GNU tools, but # printing only global *defined* symbols is harder. In GNU it is # nm -g --defined-only; the OS/X docs suggest nm -gu should work, # but it doesn't. What I think will work with both is simply # grepping out the undefineds: nm="${toolprefix}nm" if ! type -path "$nm" >/dev/null; then nm=nm; fi "$nm" -g "$lib" | grep -v ' U ' | awk '{ print $3; }' } env_test_exports() { local dir="$1" local log=$(logfile_for envtest "$dir") local good=yes for lib in "$dir"/*"$pluginext"; do if [ ! -f "$lib" ]; then # This should only happen if the glob was not expanded at all echo "NOTE: no library found in $dir?" | tee -a "$log" good=no break fi echo echo "Testing for exported symbols in $lib..." if public_symbols_in "$lib" | grep -q vampGetPluginDescriptor; then others=`public_symbols_in "$lib" | grep -v vampGetPluginDescriptor` if [ -n "$others" ]; then count=`echo "$others" | wc -l` echo "ERROR: library $lib exports $count extra symbols in addition to vampGetPluginDescriptor" | tee -a "$log" good=no else echo "GOOD: library $lib only exports vampGetPluginDescriptor" | tee -a "$log" fi else echo "NOTE: found library $lib that is not a Vamp plugin library" | tee -a "$log" fi done [ "$good" = "yes" ] } env_test_stdout() { local dir="$1" local log=$(logfile_for envtest "$dir") local pdir=$(plugin_dir_for "$dir") local good=yes local ids=$(VAMP_PATH="$pdir" $hostwrapper vamp-plugin-sdk/host/vamp-simple-host$hostext --list-ids); echo echo "Testing for any unwanted output to stdout..." for id in $ids; do case "$id" in vamp:*) ;; *) echo "ERROR: plugin in $dir prints to stdout as it runs: found text $id (should use stderr for debug logging to avoid mixing with batch output stream)" | tee -a "$log" good=no ;; esac done [ "$good" = "yes" ] } env_test_cat() { local dir="$1" local log=$(logfile_for envtest "$dir") local pdir=$(custom_plugin_dir_for "$dir") local cdir=$(if test -n "$pdir" ; then echo "$pdir" ; else echo "$dir" ; fi) local good=yes local first=yes echo echo "Testing some details of .cat files..." for catfile in "$cdir"/*".cat"; do if [ ! -f "$catfile" ]; then # This should only happen if the glob was not expanded at all echo "ERROR: no .cat file found in $dir" | tee -a "$log" good=no break fi if [ "$first" = "yes" ]; then first=no else echo "NOTE: multiple .cat files found in $cdir" | tee -a "$log" fi done if [ "$good" = "yes" ]; then excess=$(plugin_ids_in "$dir" | sed 's/^/vamp:/' | \ cat - "$cdir"/*".cat" | \ sed 's/::.*//' | \ sort | \ uniq -u) if [ -n "$excess" ]; then echo "ERROR: excess or missing definitions in .cat file? $excess" | tee -a "$log" good=no else echo "GOOD: no excess or missing definitions in .cat files" | tee -a "$log" fi fi [ "$good" = "yes" ] } env_test_ttl() { local dir="$1" local log=$(logfile_for envtest "$dir") local pdir=$(custom_plugin_dir_for "$dir") local rdir=$(if test -n "$pdir" ; then echo "$pdir" ; else echo "$dir" ; fi) local good=yes local first=yes echo echo "Testing existence of RDF files..." for ttlfile in "$rdir"/*.{n3,ttl}; do if [ ! -f "$ttlfile" ]; then # Because we have two different extensions, this isn't an # error as it is with e.g. .cat (because one or the other # of .n3 and .ttl almost certainly won't exist). But if we # drop out the bottom and first is still true, then we # know neither matched. : elif [ "$first" = "yes" ]; then first=no else echo "NOTE: multiple .ttl or .n3 files found in $rdir" | tee -a "$log" fi done if [ "$first" = "yes" ]; then echo "ERROR: no .ttl or .n3 files found in $rdir" | tee -a "$log" good=no; else echo "GOOD: found one or more .ttl or .n3 files (we don't actually test their validity or content here though)" | tee -a "$log" fi [ "$good" = "yes" ] } env_test_accompaniments() { local dir="$1" local log=$(logfile_for envtest "$dir") local good=yes echo echo "Testing existence of README and accompanying files..." if ! ls -1 "$dir" | egrep -qi "^readme(.txt|.md)?$"; then echo "ERROR: no README file found" | tee -a "$log" good=no fi if ! ls -1 "$dir" | egrep -qi "^(copying|licen[cs]e)(.txt)?$"; then echo "ERROR: no COPYING or LICEN[CS]E file found" | tee -a "$log" good=no fi if ! ls -1 "$dir" | egrep -qi "^citation(.txt)?$"; then echo "NOTE: no CITATION file found" | tee -a "$log" fi [ "$good" = "yes" ] } run_environmental_tests() { local dir="$1" local log=$(logfile_for envtest "$dir") local allgood=yes cat /dev/null > "$log" for test in exports stdout cat ttl accompaniments; do "env_test_$test" "$dir" || allgood=no done if [ "$allgood" != "yes" ]; then echo "$dir" >> "$envcheckfailed" return 1 else return 0 fi } package() { local dir="$1" local id=$(vcs_id "$dir") local pstub="$dir-$pubtag-$id" local pdir="$packagedir/$pstub" mkdir -p "$pdir" ( cd "$dir" ; cp -av \ *"$pluginext" \ *.cat \ *.n3 \ *.ttl \ [Rr][Ee][Aa][Dd][Mm][Ee]* \ [Cc][Oo][Pp][Yy][Ii][Nn][Gg]* \ [Ll][Ii][Cc][Ee][Nn][CcSs][Ee]* \ [Cc][Ii][Tt][Aa][Tt][Ii][Oo][Nn]* \ [Cc][Hh][Aa][Nn][Gg][Ee][Ll][Oo][Gg]* \ ../"$pdir"/ || true if have_vampy_plugins "$dir"; then find_vampy_plugins_in "$dir" | while read p; do cp -av "$p" ../"$pdir"/ done fi ) ( cd "$packagedir"; if [ "$platform" = "mingw" ]; then zip -r "$pstub".zip "$pstub" else tar cvjf "$pstub".tar.bz2 "$pstub" fi; rm -rf "$pstub" ) } if ! build_or_rebuild "vamp-plugin-sdk"; then echo "*** Failed to build Vamp plugin SDK!" exit 1 fi # Ensure we can only link statically against these for x in vamp-hostsdk vamp-sdk; do for y in dylib dll so; do rm -f "vamp-plugin-sdk/lib$x.$y" rm -f "vamp-plugin-sdk/$x.$y" done done if ! build_or_rebuild "vamp-plugin-tester"; then echo "*** Failed to build Vamp plugin tester!" exit 1 fi need_vampy=no for dir in $plugindirs ; do if have_vampy_plugins "$dir"; then need_vampy=yes break fi done if [ "$need_vampy" = "yes" ] && [ "$plugindirs" != "vampy" ]; then if ! build_or_rebuild "vampy"; then echo "*** Failed to build VamPy! (needed for other plugins)" exit 1 fi fi for dir in $plugindirs ; do dir=${dir%/*} echo echo "Processing: $dir" if [ ! -d "$dir" ]; then echo "Directory $dir not found!" echo "$dir" >> "$notbuilt" elif build_or_rebuild "$dir"; then if have_plugin "$dir" ; then echo "$dir" >> "$built" if ! run_tester "$dir"; then echo "Tester failed for $dir" fi if ! run_environmental_tests "$dir"; then echo "Environmental tests failed for $dir" fi else log=$(logfile_for build "$dir") echo "Build apparently succeeded, but no resulting plugin(s) found, or plugin(s) have wrong file type or platform" | tee -a "$log" echo "$dir" >> "$notbuilt" fi else echo "$dir" >> "$notbuilt" fi slog=$(logfile_for summary "$dir") echo "initialising logfile $slog for $dir" cat /dev/null > "$slog" done cat "$built" | while read dir; do package "$dir" done echo echo "** Built, tested, checked, and packaged:" cat "$built" | while read dir; do slog=$(logfile_for summary "$dir") if ! grep -q "^$dir\$" "$testfailed"; then if ! grep -q "^$dir\$" "$envcheckfailed"; then echo "$dir" echo "$dir: OK: Success" >> "$slog" fi fi done | sort echo echo "** Failed tests:" cat "$testfailed" | sort | uniq | while read dir; do slog=$(logfile_for summary "$dir") echo "$dir" echo "$dir: TEST_FAILED: Built successfully, but failed tests" >> "$slog" done echo echo "** Failed environmental checks:" cat "$envcheckfailed" | sort | uniq | while read dir; do slog=$(logfile_for summary "$dir") echo "$dir" echo "$dir: ENV_FAILED: Built successfully, but failed environmental checks" >> "$slog" done echo echo "** Failed to build:" cat "$notbuilt" | sort | while read dir; do slog=$(logfile_for summary "$dir") echo "$dir" echo "$dir: BUILD_FAILED: Failed to compile" >> "$slog" done echo