cannam@133: #! /usr/bin/env bash cannam@133: cannam@133: set -euo pipefail cannam@133: cannam@133: doit() { cannam@133: echo "@@@@ $@" cannam@133: "$@" cannam@133: } cannam@133: cannam@133: QUICK= cannam@133: cannam@133: while [ $# -gt 0 ]; do cannam@133: case "$1" in cannam@133: test ) cannam@133: ;; # nothing cannam@133: quick ) cannam@133: QUICK=quick cannam@133: ;; cannam@133: caffeinate ) cannam@133: # Re-run preventing sleep. cannam@133: shift cannam@133: exec caffeinate -ims $0 $@ cannam@133: ;; cannam@133: tmpdir ) cannam@133: # Clone to a temp directory. cannam@133: if [ "$#" -lt 2 ]; then cannam@133: echo "usage: $0 tmpdir NAME [COMMAND]" >&2 cannam@133: exit 1 cannam@133: fi cannam@133: DIR=/tmp/$2 cannam@133: shift 2 cannam@133: if [ -e $DIR ]; then cannam@133: if [ "${DIR/*..*}" = "" ]; then cannam@133: echo "NO DO NOT PUT .. IN THERE IT'S GOING TO GO IN /tmp AND I'M GONNA DELETE IT" >&2 cannam@133: exit 1 cannam@133: fi cannam@133: if [ ! -e "$DIR/super-test.sh" ]; then cannam@133: echo "$DIR exists and it doesn't look like one of mine." >&2 cannam@133: exit 1 cannam@133: fi cannam@133: # make distcheck leaves non-writable files when it fails, so we need to chmod to be safe. cannam@133: chmod -R +w $DIR cannam@133: rm -rf $DIR cannam@133: fi cannam@133: git clone . $DIR cannam@133: cd $DIR cannam@133: exec ./super-test.sh "$@" cannam@133: ;; cannam@133: remote ) cannam@133: if [ "$#" -lt 2 ]; then cannam@133: echo "usage: $0 remote HOST [COMMAND]" >&2 cannam@133: exit 1 cannam@133: fi cannam@133: HOST=$2 cannam@133: shift 2 cannam@133: echo "=========================================================================" cannam@133: echo "Pushing code to $HOST..." cannam@133: echo "=========================================================================" cannam@133: BRANCH=$(git rev-parse --abbrev-ref HEAD) cannam@133: ssh $HOST '(chmod -fR +w tmp-test-capnp || true) && rm -rf tmp-test-capnp && mkdir tmp-test-capnp && git init tmp-test-capnp' cannam@133: git push ssh://$HOST/~/tmp-test-capnp "$BRANCH:test" cannam@133: ssh $HOST "cd tmp-test-capnp && git checkout test" cannam@133: exec ssh $HOST "cd tmp-test-capnp && ./super-test.sh $@ && cd .. && rm -rf tmp-test-capnp" cannam@133: ;; cannam@133: clang ) cannam@133: export CXX=clang++ cannam@133: ;; cannam@133: gcc-4.9 ) cannam@133: export CXX=g++-4.9 cannam@133: ;; cannam@133: gcc-4.8 ) cannam@133: export CXX=g++-4.8 cannam@133: ;; cannam@133: gcc-4.7 ) cannam@133: export CXX=g++-4.7 cannam@133: ;; cannam@133: mingw ) cannam@133: if [ "$#" -ne 2 ]; then cannam@133: echo "usage: $0 mingw CROSS_HOST" >&2 cannam@133: exit 1 cannam@133: fi cannam@133: CROSS_HOST=$2 cannam@133: cannam@133: cd c++ cannam@133: test -e configure || doit autoreconf -i cannam@133: test ! -e Makefile || (echo "ERROR: Directory unclean!" >&2 && false) cannam@133: doit ./configure --host="$CROSS_HOST" --disable-shared CXXFLAGS='-static-libgcc -static-libstdc++' cannam@133: doit make -j6 capnp.exe capnpc-c++.exe cannam@133: cannam@133: cp capnp.exe capnp-mingw.exe cannam@133: cp capnpc-c++.exe capnpc-c++-mingw.exe cannam@133: cannam@133: doit make distclean cannam@133: doit ./configure --host="$CROSS_HOST" --with-external-capnp --disable-shared --disable-reflection CXXFLAGS='-static-libgcc -static-libstdc++' CAPNP=./capnp-mingw.exe CAPNPC_CXX=./capnpc-c++-mingw.exe cannam@133: cannam@133: doit make -j6 check cannam@133: doit make distclean cannam@133: rm -f *-mingw.exe cannam@133: exit 0 cannam@133: ;; cannam@133: android ) cannam@133: if [ "$#" -ne 4 ]; then cannam@133: echo "usage: $0 android SDK_HOME TOOLCHAIN_HOME CROSS_HOST" >&2 cannam@133: exit 1 cannam@133: fi cannam@133: SDK_HOME=$2 cannam@133: TOOLCHAIN_HOME=$3 cannam@133: CROSS_HOST=$4 cannam@133: cannam@133: cd c++ cannam@133: test -e configure || doit autoreconf -i cannam@133: test ! -e Makefile || (echo "ERROR: Directory unclean!" >&2 && false) cannam@133: doit ./configure --disable-shared cannam@133: doit make -j6 capnp capnpc-c++ cannam@133: cannam@133: cp capnp capnp-host cannam@133: cp capnpc-c++ capnpc-c++-host cannam@133: cannam@133: export PATH="$TOOLCHAIN_HOME/bin:$PATH" cannam@133: doit make distclean cannam@133: doit ./configure --host="$CROSS_HOST" --with-external-capnp --disable-shared CXXFLAGS='-pie -fPIE' CAPNP=./capnp-host CAPNPC_CXX=./capnpc-c++-host cannam@133: cannam@133: doit make -j6 cannam@133: doit make -j6 capnp-test cannam@133: cannam@133: echo "Starting emulator..." cannam@133: trap 'kill $(jobs -p)' EXIT cannam@133: $SDK_HOME/tools/emulator -avd n6 -no-window & cannam@133: $SDK_HOME/platform-tools/adb wait-for-device cannam@133: echo "Waiting for localhost to be resolvable..." cannam@133: $SDK_HOME/platform-tools/adb shell 'while ! ping -c 1 localhost > /dev/null 2>&1; do sleep 1; done' cannam@133: doit $SDK_HOME/platform-tools/adb push capnp-test /data/capnp-test cannam@133: doit $SDK_HOME/platform-tools/adb shell 'cd /data && /data/capnp-test && echo ANDROID_""TESTS_PASSED' | tee android-test.log cannam@133: grep -q ANDROID_TESTS_PASSED android-test.log cannam@133: cannam@133: doit make distclean cannam@133: rm -f capnp-host capnpc-c++-host cannam@133: exit 0 cannam@133: ;; cannam@133: cmake ) cannam@133: cd c++ cannam@133: rm -rf cmake-build cannam@133: mkdir cmake-build cannam@133: cd cmake-build cannam@133: doit cmake -G "Unix Makefiles" .. cannam@133: doit make -j6 check cannam@133: exit 0 cannam@133: ;; cannam@133: exotic ) cannam@133: echo "=========================================================================" cannam@133: echo "MinGW 64-bit" cannam@133: echo "=========================================================================" cannam@133: "$0" mingw x86_64-w64-mingw32 cannam@133: echo "=========================================================================" cannam@133: echo "MinGW 32-bit" cannam@133: echo "=========================================================================" cannam@133: "$0" mingw i686-w64-mingw32 cannam@133: echo "=========================================================================" cannam@133: echo "Android" cannam@133: echo "=========================================================================" cannam@133: "$0" android /home/kenton/android/android-sdk-linux /home/kenton/android/android-16 arm-linux-androideabi cannam@133: echo "=========================================================================" cannam@133: echo "CMake" cannam@133: echo "=========================================================================" cannam@133: "$0" cmake cannam@133: exit 0 cannam@133: ;; cannam@133: clean ) cannam@133: rm -rf tmp-staging cannam@133: cd c++ cannam@133: if [ -e Makefile ]; then cannam@133: doit make maintainer-clean cannam@133: fi cannam@133: rm -f capnproto-*.tar.gz samples/addressbook samples/addressbook.capnp.c++ \ cannam@133: samples/addressbook.capnp.h cannam@133: exit 0 cannam@133: ;; cannam@133: help ) cannam@133: echo "usage: $0 [COMMAND]" cannam@133: echo "commands:" cannam@133: echo " test Runs tests (the default)." cannam@133: echo " clang Runs tests using Clang compiler." cannam@133: echo " gcc-4.7 Runs tests using gcc-4.7." cannam@133: echo " gcc-4.8 Runs tests using gcc-4.8." cannam@133: echo " gcc-4.9 Runs tests using gcc-4.9." cannam@133: echo " remote HOST Runs tests on HOST via SSH." cannam@133: echo " mingw Cross-compiles to MinGW and runs tests using WINE." cannam@133: echo " android Cross-compiles to Android and runs tests using emulator." cannam@133: echo " clean Delete temporary files that may be left after failure." cannam@133: echo " help Prints this help text." cannam@133: exit 0 cannam@133: ;; cannam@133: * ) cannam@133: echo "unknown command: $1" >&2 cannam@133: echo "try: $0 help" >&2 cannam@133: exit 1 cannam@133: ;; cannam@133: esac cannam@133: shift cannam@133: done cannam@133: cannam@133: # Build optimized builds because they catch more problems, but also enable debugging macros. cannam@133: # Enable lots of warnings and make sure the build breaks if they fire. Disable strict-aliasing cannam@133: # because GCC warns about code that I know is OK. Disable sign-compare because I've fixed more cannam@133: # sign-compare warnings than probably all other warnings combined and I've never seen it flag a cannam@133: # real problem. Disable unused parameters because it's stupidly noisy and never a real problem. cannam@133: export CXXFLAGS="-O2 -DDEBUG -Wall -Wextra -Werror -Wno-strict-aliasing -Wno-sign-compare -Wno-unused-parameter" cannam@133: cannam@133: STAGING=$PWD/tmp-staging cannam@133: cannam@133: rm -rf "$STAGING" cannam@133: mkdir "$STAGING" cannam@133: mkdir "$STAGING/bin" cannam@133: mkdir "$STAGING/lib" cannam@133: export PATH=$STAGING/bin:$PATH cannam@133: export LD_LIBRARY_PATH=$STAGING/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} cannam@133: export PKG_CONFIG_PATH=$STAGING/lib/pkgconfig cannam@133: cannam@133: if [ "$QUICK" = quick ]; then cannam@133: echo "************************** QUICK TEST ***********************************" cannam@133: fi cannam@133: cannam@133: echo "=========================================================================" cannam@133: echo "Building c++" cannam@133: echo "=========================================================================" cannam@133: cannam@133: # Apple now aliases gcc to clang, so probe to find out what compiler we're really using. cannam@133: if (${CXX:-g++} -dM -E -x c++ /dev/null 2>&1 | grep -q '__clang__'); then cannam@133: IS_CLANG=yes cannam@133: else cannam@133: IS_CLANG=no cannam@133: fi cannam@133: cannam@133: if [ $IS_CLANG = yes ]; then cannam@133: # Don't fail out on this ridiculous "argument unused during compilation" warning. cannam@133: export CXXFLAGS="$CXXFLAGS -Wno-error=unused-command-line-argument" cannam@133: else cannam@133: # GCC emits uninitialized warnings all over and they seem bogus. We use valgrind to test for cannam@133: # uninitialized memory usage later on. cannam@133: CXXFLAGS="$CXXFLAGS -Wno-maybe-uninitialized" cannam@133: fi cannam@133: cannam@133: cd c++ cannam@133: doit autoreconf -i cannam@133: doit ./configure --prefix="$STAGING" cannam@133: doit make -j6 check cannam@133: cannam@133: if [ $IS_CLANG = no ]; then cannam@133: # Verify that generated code compiles with pedantic warnings. Make sure to treat capnp headers cannam@133: # as system headers so warnings in them are ignored. cannam@133: doit ${CXX:-g++} -isystem src -std=c++11 -fno-permissive -pedantic -Wall -Wextra -Werror \ cannam@133: -c src/capnp/test.capnp.c++ -o /dev/null cannam@133: fi cannam@133: cannam@133: echo "=========================================================================" cannam@133: echo "Testing c++ install" cannam@133: echo "=========================================================================" cannam@133: cannam@133: doit make install cannam@133: cannam@133: test "x$(which capnp)" = "x$STAGING/bin/capnp" cannam@133: test "x$(which capnpc-c++)" = "x$STAGING/bin/capnpc-c++" cannam@133: cannam@133: cd samples cannam@133: cannam@133: doit capnp compile -oc++ addressbook.capnp -I"$STAGING"/include --no-standard-import cannam@133: doit ${CXX:-g++} -std=c++11 addressbook.c++ addressbook.capnp.c++ -o addressbook \ cannam@133: $CXXFLAGS $(pkg-config --cflags --libs capnp) cannam@133: echo "@@@@ ./addressbook (in various configurations)" cannam@133: ./addressbook write | ./addressbook read cannam@133: ./addressbook dwrite | ./addressbook dread cannam@133: rm addressbook addressbook.capnp.c++ addressbook.capnp.h cannam@133: cannam@133: doit capnp compile -oc++ calculator.capnp -I"$STAGING"/include --no-standard-import cannam@133: doit ${CXX:-g++} -std=c++11 calculator-client.c++ calculator.capnp.c++ -o calculator-client \ cannam@133: $CXXFLAGS $(pkg-config --cflags --libs capnp-rpc) cannam@133: doit ${CXX:-g++} -std=c++11 calculator-server.c++ calculator.capnp.c++ -o calculator-server \ cannam@133: $CXXFLAGS $(pkg-config --cflags --libs capnp-rpc) cannam@133: rm -f /tmp/capnp-calculator-example-$$ cannam@133: ./calculator-server unix:/tmp/capnp-calculator-example-$$ & cannam@133: sleep 0.1 cannam@133: ./calculator-client unix:/tmp/capnp-calculator-example-$$ cannam@133: kill %+ cannam@133: wait %+ || true cannam@133: rm calculator-client calculator-server calculator.capnp.c++ calculator.capnp.h /tmp/capnp-calculator-example-$$ cannam@133: cannam@133: cd .. cannam@133: cannam@133: if [ "$QUICK" = quick ]; then cannam@133: doit make maintainer-clean cannam@133: rm -rf "$STAGING" cannam@133: exit 0 cannam@133: fi cannam@133: cannam@133: echo "=========================================================================" cannam@133: echo "Testing --with-external-capnp" cannam@133: echo "=========================================================================" cannam@133: cannam@133: doit make distclean cannam@133: doit ./configure --prefix="$STAGING" --disable-shared \ cannam@133: --with-external-capnp CAPNP=$STAGING/bin/capnp cannam@133: doit make -j6 check cannam@133: cannam@133: echo "=========================================================================" cannam@133: echo "Testing --disable-reflection" cannam@133: echo "=========================================================================" cannam@133: cannam@133: doit make distclean cannam@133: doit ./configure --prefix="$STAGING" --disable-shared --disable-reflection \ cannam@133: --with-external-capnp CAPNP=$STAGING/bin/capnp cannam@133: doit make -j6 check cannam@133: doit make distclean cannam@133: cannam@133: # Test 32-bit build now while we have $STAGING available for cross-compiling. cannam@133: if [ "x`uname -m`" = "xx86_64" ]; then cannam@133: echo "=========================================================================" cannam@133: echo "Testing 32-bit build" cannam@133: echo "=========================================================================" cannam@133: cannam@133: if [[ "`uname`" =~ CYGWIN ]]; then cannam@133: # It's just not possible to run cygwin32 binaries from within cygwin64. cannam@133: cannam@133: # Build as if we are cross-compiling, using the capnp we installed to $STAGING. cannam@133: doit ./configure --prefix="$STAGING" --disable-shared --host=i686-pc-cygwin \ cannam@133: --with-external-capnp CAPNP=$STAGING/bin/capnp cannam@133: doit make -j6 cannam@133: doit make -j6 capnp-test.exe cannam@133: cannam@133: # Expect a cygwin32 sshd to be listening at localhost port 2222, and use it cannam@133: # to run the tests. cannam@133: doit scp -P 2222 capnp-test.exe localhost:~/tmp-capnp-test.exe cannam@133: doit ssh -p 2222 localhost './tmp-capnp-test.exe && rm tmp-capnp-test.exe' cannam@133: cannam@133: doit make distclean cannam@133: cannam@133: elif [ "x${CXX:-g++}" != "xg++-4.8" ]; then cannam@133: doit ./configure CXX="${CXX:-g++} -m32" --disable-shared cannam@133: doit make -j6 check cannam@133: doit make distclean cannam@133: fi cannam@133: fi cannam@133: cannam@133: echo "=========================================================================" cannam@133: echo "Testing c++ uninstall" cannam@133: echo "=========================================================================" cannam@133: cannam@133: doit ./configure --prefix="$STAGING" cannam@133: doit make uninstall cannam@133: cannam@133: echo "=========================================================================" cannam@133: echo "Testing c++ dist" cannam@133: echo "=========================================================================" cannam@133: cannam@133: doit make -j6 distcheck cannam@133: doit make distclean cannam@133: rm capnproto-*.tar.gz cannam@133: cannam@133: if [ "x`uname`" = xLinux ]; then cannam@133: echo "=========================================================================" cannam@133: echo "Testing generic Unix (no Linux-specific features)" cannam@133: echo "=========================================================================" cannam@133: cannam@133: doit ./configure --disable-shared CXXFLAGS="$CXXFLAGS -DKJ_USE_FUTEX=0 -DKJ_USE_EPOLL=0" cannam@133: doit make -j6 check cannam@133: doit make distclean cannam@133: fi cannam@133: cannam@133: echo "=========================================================================" cannam@133: echo "Testing with -fno-rtti and -fno-exceptions" cannam@133: echo "=========================================================================" cannam@133: cannam@133: doit ./configure --disable-shared CXXFLAGS="$CXXFLAGS -fno-rtti" cannam@133: doit make -j6 check cannam@133: doit make distclean cannam@133: doit ./configure --disable-shared CXXFLAGS="$CXXFLAGS -fno-exceptions" cannam@133: doit make -j6 check cannam@133: doit make distclean cannam@133: doit ./configure --disable-shared CXXFLAGS="$CXXFLAGS -fno-rtti -fno-exceptions" cannam@133: doit make -j6 check cannam@133: cannam@133: # Valgrind is currently "experimental and mostly broken" on OSX and fails to run the full test cannam@133: # suite, but I have it installed because it did manage to help me track down a bug or two. Anyway, cannam@133: # skip it on OSX for now. cannam@133: if [ "x`uname`" != xDarwin ] && which valgrind > /dev/null; then cannam@133: doit make distclean cannam@133: cannam@133: echo "=========================================================================" cannam@133: echo "Testing with valgrind" cannam@133: echo "=========================================================================" cannam@133: cannam@133: doit ./configure --disable-shared CXXFLAGS="-g" cannam@133: doit make -j6 cannam@133: doit make -j6 capnp-test cannam@133: doit valgrind --leak-check=full --track-fds=yes --error-exitcode=1 ./capnp-test cannam@133: fi cannam@133: cannam@133: doit make maintainer-clean cannam@133: cannam@133: rm -rf "$STAGING"