diff options
Diffstat (limited to 'scripts/ci-run.sh')
-rwxr-xr-x | scripts/ci-run.sh | 493 |
1 files changed, 493 insertions, 0 deletions
diff --git a/scripts/ci-run.sh b/scripts/ci-run.sh new file mode 100755 index 000000000..cee5d05e2 --- /dev/null +++ b/scripts/ci-run.sh @@ -0,0 +1,493 @@ +#! /bin/bash + +scriptdir=`dirname $0` + +if [ -n "$GITHUB_EVENT_PATH" ]; then + export CI=true +fi + +. "$scriptdir/ansi_color.sh" +disable_color + +print_start() { + COL="$ANSI_YELLOW" + if [ "x$2" != "x" ]; then + COL="$2" + fi + printf "${COL}${1}$ANSI_NOCOLOR\n" +} + +gstart () { + print_start "$@" +} +gend () { + : +} + +if [ -n "$TRAVIS" ]; then + echo "INFO: set 'gstart' and 'gend' for TRAVIS" + # This is a trimmed down copy of https://github.com/travis-ci/travis-build/blob/master/lib/travis/build/bash/* + travis_time_start() { + # `date +%N` returns the date in nanoseconds. It is used as a replacement for $RANDOM, which is only available in bash. + travis_timer_id=`date +%N` + travis_start_time=`travis_nanoseconds` + echo "travis_time:start:$travis_timer_id" + } + travis_time_finish() { + travis_end_time=`travis_nanoseconds` + local duration=$(($travis_end_time-$travis_start_time)) + echo "travis_time:end:$travis_timer_id:start=$travis_start_time,finish=$travis_end_time,duration=$duration" + } + + if [ "$TRAVIS_OS_NAME" = "osx" ]; then + travis_nanoseconds() { + date -u '+%s000000000' + } + else + travis_nanoseconds() { + date -u '+%s%N' + } + fi + + gstart () { + echo "travis_fold:start:group" + travis_time_start + print_start "$@" + } + + gend () { + travis_time_finish + echo "travis_fold:end:group" + } +else + if [ -n "$CI" ]; then + echo "INFO: set 'gstart' and 'gend' for CI" + gstart () { + printf '::group::' + print_start "$@" + SECONDS=0 + } + + gend () { + duration=$SECONDS + echo '::endgroup::' + printf "${ANSI_GRAY}took $(($duration / 60)) min $(($duration % 60)) sec.${ANSI_NOCOLOR}\n" + } + fi +fi + +echo "cliargs: $0 $@" + +# Stop in case of error +set -e + +ISGPL=false +ISSYNTH=true + +# Transform long options to short ones +for arg in "$@"; do + shift + case "$arg" in + "--color"|"-color") set -- "$@" "-c";; + "--backend"|"-backend") set -- "$@" "-b";; + "--pkg"|"-pkg") set -- "$@" "-p";; + "--gpl"|"-gpl") set -- "$@" "-g";; + "--no-synth"|"-no-synth") set -- "$@" "-s";; + *) set -- "$@" "$arg" + esac +done +# Parse args +while getopts ":b:p:cgs" opt; do + case $opt in + c) enable_color;; + b) BACK=$OPTARG ;; + p) PKG_NAME=$OPTARG;; + g) ISGPL=true;; + s) ISSYNTH=false;; + \?) printf "$ANSI_RED[CI - args] Invalid option: -$OPTARG $ANSI_NOCOLOR\n" >&2 + exit 1 ;; + :) printf "$ANSI_RED[CI - args] Option -$OPTARG requires an argument. $ANSI_NOCOLOR\n" >&2 + exit 1 ;; + esac +done +shift $((OPTIND -1)) + +#--- + +# +# Build command options +# + +notag() { + # No tag: use date + commit id + echo "`git log -1 --date=short --pretty=format:%cd | sed 's/-//g'`-$PKG_SHA" +} + +vertag() { + if expr "$1" : 'v[0-9].*' > /dev/null; then + # Check version defined in configure. + cfgver=`grep "^ghdl_version=" configure | sed -e 's/.*"\(.*\)"/\1/'` + if [ "x$1" != "xv$cfgver" ]; then + printf "${ANSI_RED}Tag '$1' does not match configure 'ghdl_version' ($cfgver)!${ANSI_NOCOLOR}\n" 1>&2; + exit 1 + fi + # Remove leading 'v' in tags in the filenames. + echo $1 | cut -c2- + else + # Regular tag (like snapshots), nothing to change. + echo "$1" + fi +} + +buildCmdOpts () { + BUILD_ARG="$1" + + # Get short commit SHA + if [ -n "$TRAVIS_COMMIT" ]; then + GIT_SHA="$TRAVIS_COMMIT" + fi + if [ -n "$GITHUB_SHA" ]; then + GIT_SHA="$GITHUB_SHA" + fi + if [ -z "$GIT_SHA" ]; then + GIT_SHA="`git rev-parse --verify HEAD`" + fi + PKG_SHA="`printf $GIT_SHA | cut -c1-10`" + + echo "TRAVIS_COMMIT: $TRAVIS_COMMIT" + echo "TRAVIS_TAG: $TRAVIS_TAG" + echo "GITHUB_SHA: $GITHUB_SHA" + echo "GITHUB_REF: $GITHUB_REF" + echo "GIT_SHA: $GIT_SHA" + + # Compute package name + case "$GITHUB_REF" in + *tags*) + PKG_TAG="$(vertag "`echo "$GITHUB_REF" | sed 's#^refs/tags/\(.*\)#\1#g'`")" + ;; + *heads*|*pull*) + PKG_TAG="`notag`" + ;; + "") + if [ -z "$TRAVIS_TAG" ]; then + PKG_TAG="`notag`" + else + PKG_TAG="`vertag "$TRAVIS_TAG"`" + fi + ;; + *) + PKG_TAG="$GITHUB_REF" + ;; + esac + + echo "PKG_SHA: $PKG_SHA" + echo "PKG_TAG: $PKG_TAG" + + # Extract from BUILD_ARG + IFS='+' read -ra REFS <<< "$BUILD_ARG" + DDIST=${REFS[0]} # Linux distro (eg: ubuntuXX, fedoraXX) + DBACK=${REFS[1]} # Build/backend (eg: mcode, llvm) + + PKG_NAME="ghdl-${PKG_TAG}-${DDIST}-${DBACK}" + BUILD_CMD_OPTS="$ENABLECOLOR -b $DBACK" + + if [ "x$ISGPL" = "xtrue" ]; then + BUILD_CMD_OPTS="$BUILD_CMD_OPTS --gpl" + PKG_NAME="${PKG_NAME}-gpl" + DEXT="-gpl" + fi + export BUILD_CMD_OPTS="${BUILD_CMD_OPTS} -p $PKG_NAME" + + GHDL_IMAGE_TAG="`echo $BUILD_ARG | sed -e 's/+/-/g'`" + BUILD_IMAGE_TAG="$GHDL_IMAGE_TAG" + + case $BUILD_ARG in + *gcc*) + BUILD_IMAGE_TAG="`echo $GHDL_IMAGE_TAG | sed 's#\(.*\)-gcc.*#\1-gcc#g'`" + ;; + esac + + GHDL_IMAGE_TAG="${GHDL_IMAGE_TAG}$DEXT" +} + +run_cmd() { + echo "$@" + "$@" +} + +# +# Build ghdl +# + +build () { + rm -f build_ok + + #--- Env + + gstart "[GHDL - build] Environment" + env + gend + + #--- GPL: gpl-ize sources + + if [ "$ISGPL" = "true" ]; then + GPLDIR="${PKG_NAME}.src" + gstart "[GHDL - build] create GPL source package (${ANSI_CYAN}${GPLDIR}.tgz${ANSI_NOCOLOR})" + files=`echo *` + make -f Makefile.in srcdir=. clean-pure-gpl + mkdir "$GPLDIR" + cp -pdrl $files "$GPLDIR" + tar -zcf "${GPLDIR}.tgz" "$GPLDIR" + gend + fi + + #--- Configure + + CDIR=`pwd` + INSTALL_DIR="$CDIR/install-$BACK" + mkdir "$INSTALL_DIR" + mkdir "build-$BACK" + cd "build-$BACK" + + if [ "x$ISSYNTH" = "xfalse" ]; then + CONFIG_OPTS+=" --disable-synth" + fi + + case "$BACK" in + gcc*) + gstart "[GHDL - build] Get gcc sources" + gccURL="https://codeload.github.com/gcc-mirror/gcc/tar.gz/releases/${BACK}" + echo "$gccURL" + mkdir gcc-srcs + curl -L "$gccURL" | tar -xz -C gcc-srcs --strip-components=1 + cd gcc-srcs + sed -i.bak s/ftp:/http:/g ./contrib/download_prerequisites + ./contrib/download_prerequisites + cd .. + gend + + gstart "[GHDL - build] Configure ghdl" + run_cmd ../configure --with-gcc=gcc-srcs $CONFIG_OPTS + gend + gstart "[GHDL - build] Copy sources" + make copy-sources + mkdir gcc-objs; cd gcc-objs + gend + gstart "[GHDL - build] Configure gcc" + run_cmd ../gcc-srcs/configure --enable-languages=c,vhdl --disable-bootstrap --disable-lto --disable-multilib --disable-libssp --disable-libgomp --disable-libquadmath "`gcc -v 2>&1 | grep -o -- --enable-default-pie`" + gend + ;; + mcode) + CXX="" + ;; + llvm) + CXX="clang++" + CONFIG_OPTS+=" --with-llvm-config CXX=$CXX" + ;; + llvm-3.5) + CXX="clang++" + CONFIG_OPTS+=" --with-llvm-config=llvm-config-3.5 CXX=$CXX" + ;; + llvm-*) + llvmver=`echo $BACK | sed -e "s/llvm-//"` + CXX="clang++-$llvmver" + CONFIG_OPTS+=" --with-llvm-config=llvm-config-$llvmver CXX=$CXX" + ;; + *) + printf "$ANSI_RED[GHDL - build] Unknown build $BACK $ANSI_NOCOLOR\n" + exit 1;; + esac + + if [ ! "`echo $BACK | grep gcc`" ]; then + gstart "[GHDL - build] Configure" + run_cmd ../configure $CONFIG_OPTS + gend + fi + + #--- make + + gstart "[GHDL - build] Make" + set +e + make LIB_CFLAGS="$LIB_CFLAGS" OPT_FLAGS="$OPT_FLAGS" -j`nproc` 2>make_err.log + tail -1000 make_err.log + set -e + gend + + gstart "[GHDL - build] Install" + make DESTDIR="$INSTALL_DIR" install + cd .. + gend + + if [ "`echo $BACK | grep gcc`" ]; then + gstart "[GHDL - build] Make ghdllib" + make DESTDIR="$INSTALL_DIR" ghdllib + gend + + gstart "[GHDL - build] Install ghdllib" + make DESTDIR="$INSTALL_DIR" install + cd .. + gend + fi + + #--- package + + gstart "[GHDL - build] Create package ${ANSI_DARKCYAN}${PKG_NAME}.tgz" + tar -zcvf "${PKG_NAME}.tgz" -C "$INSTALL_DIR/usr/local" . + gend + + #--- build tools versions + + { + make --version | grep 'Make' + gnatls --version | grep 'GNATLS' + gcc --version | grep 'gcc' + if [ "$CXX" != "" ]; then + $CXX --version | grep 'clang' + fi + } > BUILD_TOOLS + + #--- + + printf "$ANSI_GREEN[GHDL - build] SUCCESSFUL${ANSI_NOCOLOR}\n" + touch build_ok +} + +# +# Build ghdl/ghdl image +# + +build_img_ghdl() { + gstart "[DOCKER - build] ghdl/ghdl:${GHDL_IMAGE_TAG}" "$ANSI_BLUE" + docker build -t ghdl/ghdl:$GHDL_IMAGE_TAG . -f-<<EOF +FROM ghdl/run:$BUILD_IMAGE_TAG +ADD `ls | grep -v '\.src\.' | grep '^ghdl.*\.tgz'` /usr/local +EOF + gend +} + +# +# Full CI run +# + +ci_run () { + if [ "x$TASK" = "x" ]; then + if [ "x$1" = "x" ]; then + printf "${ANSI_RED}TASK not defined${ANSI_NOCOLOR}\n" + exit 1 + else + TASK="$1" + fi + fi + + gstart "[CI] git fetch --unshallow" "$ANSI_BLUE" + # The command 'git describe' (used for version) needs the history. Get it. + # But the following command fails if the repository is complete. + git fetch --unshallow || true + gend + + # Get build command options + gstart "[CI] Get build command options" "$ANSI_BLUE" + buildCmdOpts "$TASK" + echo "build cmd: $BUILD_CMD_OPTS" + gend + + # Build + + RUN="docker run --rm -t -e CI -e TRAVIS -v `pwd`:/work -w /work" + if [ "x$IS_MACOS" = "xtrue" ]; then + export CPATH="$CPATH:`xcrun --show-sdk-path`/usr/include" + CC=clang \ + CONFIG_OPTS="--disable-libghdl" \ + bash -c "${scriptdir}/ci-run.sh $BUILD_CMD_OPTS build" + else + # Assume linux + + gstart "[CI] Docker pull ghdl/build:$BUILD_IMAGE_TAG" "$ANSI_BLUE" + docker pull ghdl/build:$BUILD_IMAGE_TAG + gend + + printf "$ANSI_BLUE[CI] Build ghdl in docker image ghdl/build:$BUILD_IMAGE_TAG\n" + $RUN \ + -e GHDL_VER_DESC="$(git describe --dirty)" \ + -e GHDL_VER_REF="$(git rev-parse --abbrev-ref HEAD)@${BUILD_IMAGE_TAG}" \ + -e GHDL_VER_HASH="$(git rev-parse HEAD)" \ + -e CONFIG_OPTS="$CONFIG_OPTS" \ + ghdl/build:"$BUILD_IMAGE_TAG" \ + bash -c "${scriptdir}/ci-run.sh $BUILD_CMD_OPTS build" + fi + + if [ ! -f build_ok ]; then + printf "${ANSI_RED}[GHDL - build] FAILED${ANSI_NOCOLOR}\n" + exit 1 + fi + + # Test + + if [ "x$IS_MACOS" = "xtrue" ]; then + CC=clang \ + prefix="`cd ./install-mcode; pwd`/usr/local" \ + ./testsuite/testsuite.sh sanity gna vests vpi + else + # Build ghdl/ghdl:$GHDL_IMAGE_TAG image + build_img_ghdl + + tests="sanity" + + case "$GHDL_IMAGE_TAG" in + *ubuntu20*|*buster*) + GHDL_TEST_IMAGE="test:$GHDL_IMAGE_TAG-py" + gstart "[CI] Docker build $GHDL_TEST_IMAGE" "$ANSI_BLUE" + docker build -t "$GHDL_TEST_IMAGE" . -f- <<-EOF +# syntax=docker/dockerfile:experimental +FROM ghdl/ghdl:$GHDL_IMAGE_TAG +RUN apt update -qq && apt install -y python3 python3-pip +RUN --mount=type=bind,src=./,target=/tmp/ghdl/ \ + pip3 install -r /tmp/ghdl/testsuite/requirements.txt +EOF + gend + tests+=" pyunit" + ;; + *) + GHDL_TEST_IMAGE="ghdl/ghdl:$GHDL_IMAGE_TAG" + ;; + esac + + if [ "x$ISGPL" != "xtrue" ]; then + tests+=" gna" + fi + + tests+=" vests" + + if [ "x$ISSYNTH" = "xtrue" ]; then + tests+=" synth" + fi + + tests+=" vpi" + + # Run tests in docker container + $RUN "$GHDL_TEST_IMAGE" bash -c "GHDL=ghdl ./testsuite/testsuite.sh $tests" + fi + + if [ ! -f testsuite/test_ok ]; then + printf "${ANSI_RED}[GHDL - test] FAILED${ANSI_NOCOLOR}\n" + exit 1 + fi +} + +#--- + +echo "command: $0 $@" + +unset IS_MACOS +if [ "$GITHUB_OS" = "macOS" ] || [ "$TRAVIS_OS_NAME" = "osx" ]; then + IS_MACOS="true" +fi + +case "$1" in + build) + build + ;; + *) + ci_run + ;; +esac |