#!/bin/bash # @see https://intoli.com/blog/exit-on-errors-in-bash-scripts/ set -e trap 'LASTRES=$?; LAST=$BASH_COMMAND; if [[ LASTRES -ne 0 ]]; then msg_err "Command: \"$LAST\" exited with exit code: $LASTRES"; else msg_ok "finished";fi' EXIT SRCDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" DIRNAME="${SRCDIR##*/}" main() { setup process_arguments "$@" } function setup() { setup_ascii DEBUG="false" CLEAN="false" BUILDPATH=$SRCDIR"/../build" CMAKE_INSTALL_PREFIX=$SRCDIR"/../build/bin" mkdir -p $BUILDPATH export CTEST_OUTPUT_ON_FAILURE=1 GIT=`git -C "$SRCDIR" describe --tags --always` GITSTATUS=`git status --porcelain` GITMOD="" if [ ! -z "$GITSTATUS" ]; then GITMOD="-modified" fi } function process_arguments() { # Help if no arguments if [[ $# -eq 0 ]] ; then help ; exit 0 ; fi ## # @see https://www.lifewire.com/pass-arguments-to-bash-script-2200571 while getopts cdhxq:i: option; do case "${option}" in c) CLEAN="true";; d) DEBUG="true";; q) QTVER=$OPTARG;; i) CMAKE_INSTALL_PREFIX=$OPTARG;; h) help;; esac done shift $((OPTIND - 1)) # @see https://stackoverflow.com/a/52708357/1917249 # Process arguments if [ ! -z $QTVER ]; then QTDIR=${HOME}/Qt/$QTVER/clang_64; fi export CMAKE_PREFIX_PATH=$QTDIR ## Processing rest of arguments for arg in "$@"; do case "$arg" in check) check;; build) build;; test) test;; testcc) testcc;; opencc) opencc;; deploy) deploy;; cppcheck) cpp-check;; help) help;; esac done } function check() { if [ -z $QTDIR ]; then fail "QTDIR not set"; else pass "QTDIR is set" ; fi if [ ! -d $QTDIR ]; then fail "QTDIR does not exists"; else pass "QTDIR exists:" $QTDIR ; fi if [ -f "/usr/local/bin/cmake" ]; then pass "cmake installed"; else fail "cmake not installed: ${BLUE}brew install cmake${NC}"; fi if [ -f "/usr/local/bin/ccache" ]; then pass "ccache installed"; else fail "ccache not installed: ${BLUE}brew install ccache${NC}"; fi echo "--------------------" echo "Qt ver : $QTVER" echo "Qt : $CMAKE_PREFIX_PATH" echo "GIT : $GIT$GITMOD" echo "Debug : $DEBUG" echo "Clean : $CLEAN" echo "Makeflags : $MAKEFLAGS" echo "Source : $SRCDIR" echo "Basename : $DIRNAME" echo "BuildPath : $BUILDPATH" echo "Install : $CMAKE_INSTALL_PREFIX" echo "--------------------" } function cpp-check() { info "CppCheck" #if ! cppcheck src --enable=all -i build --suppress='*:test' --error-exitcode=1; then msg_warn "CppCheck with some errors"; exit 0 fi cppcheck src --enable=all -i build --suppress='*:test' --error-exitcode=1 } function build() { info "Building: configuration" cd $BUILDPATH mkdir -p $DIRNAME/release cd $DIRNAME/release if [ "$CLEAN" == "true" ]; then rm -f CMakeCache.txt; fi info "Building: cmake generation" cmake $SRCDIR -DA_UNITTESTS=OFF -DCMAKE_INSTALL_PREFIX=$CMAKE_INSTALL_PREFIX info "Building: building"; make install } function test() { info "Testing: configuration" cd $BUILDPATH mkdir -p $DIRNAME/test cd $DIRNAME/test if [ "$CLEAN" == "true" ]; then rm -f CMakeCache.txt; fi info "Testing: cmake generation" cmake $SRCDIR -DCMAKE_INSTALL_PREFIX=$CMAKE_INSTALL_PREFIX info "Testing: building" cmake --build . --target all info "Testing: run" ctest } function testcc() { info "Coverage: configuration" PROJBUILD="$BUILDPATH"/$DIRNAME/testcc cd $BUILDPATH mkdir -p $DIRNAME/testcc echo $PWD cd $DIRNAME/testcc if [ "$CLEAN" == "true" ]; then rm -f CMakeCache.txt; fi info "Coverage: cmake generation" cmake $SRCDIR -DA_COVERAGE=ON -DCMAKE_INSTALL_PREFIX=$CMAKE_INSTALL_PREFIX info "Coverage: Remove previous *.gcda files" echo "Projbuild: $PROJBUILD" find $PROJBUILD -name *.gcda -exec rm "{}" \; info "Coverage: building" cmake --build . --target all info "Coverage: run" ctest CCDIR="$BUILDPATH"/$DIRNAME/testcc-info CODESOURCEDIR=$SRCDIR"/src" HTML_RESULTS_DIR="$BUILDPATH"/$DIRNAME/testcc-html COVERAGE_FILTER="*Qt*.framework* *Xcode.app* *.moc *moc_*.cpp */test/* *qrc_* ui_* */invsdk/* *qt.headers */build/* *main*.*" echo "x--------------------" echo "Qt : $CMAKE_PREFIX_PATH" echo "Source : $SRCDIR" echo "Build : $BUILDPATH" echo "Build proj : $PROJBUILD" echo "Clean : $INVCLEAN" echo "Makeflags : $MAKEFLAGS" echo "CCDIR : $CCDIR" echo "CODESOURCEDIR : $CODESOURCEDIR" echo "HTML_RESULTS_DIR : $HTML_RESULTS_DIR" echo "COVERAGE_FILTER : $COVERAGE_FILTER" echo "--------------------" echo "[ Create dummy files to ensure not tested class are acounted ]" find $PROJBUILD -name "*.gcno" -exec sh -c 'touch -a "${1%.gcno}.gcda"' _ {} \; mkdir -p $CCDIR echo "[ Make dir 'codecoverage' clean ]" rm -f $CCDIR/*.* rm -rf $PROJBUILD/html echo "[ Copy .gc?? file from $PROJBUILD into 'codecoverage' dir ]" find $PROJBUILD -name *.gc?? -exec cp "{}" $CCDIR \; ########################## # RUN LCOV ########################## # ${1} is the directory containing the .gcno files (%{PROJBUILD} in Qt Creator) LCOV=lcov GENHTML=genhtml BROWSER="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" echo "[ Generating initial code coverage info report]" ${LCOV} --base-directory ${CODESOURCEDIR} -d ${CCDIR} -c -o ${CCDIR}/coverage.info echo "[ Filtering code coverage info report ]" ${LCOV} -r ${CCDIR}/coverage.info $COVERAGE_FILTER -o ${CCDIR}/coverage-filtered.info echo "[ Creating html output ]" mkdir -p ${HTML_RESULTS_DIR} "${GENHTML}" -o "${HTML_RESULTS_DIR}" "${CCDIR}/coverage-filtered.info" echo "[ Reseting coverage counts ]" "${LCOV}" -d "${CCDIR}" -z } function opencc() { HTML_RESULTS_DIR="$BUILDPATH"/$DIRNAME/testcc-html info "Open: code coverage index.html" BROWSER="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" open "${HTML_RESULTS_DIR}/index.html" & #open -a "${BROWSER}" "${HTML_RESULTS_DIR}/index.html" & } function deploy() { cd $SRCDIR cd ../build/$DIRNAME CURDIR=$PWD APP_NAME=$DIRNAME INSTALL_ROOT="$CMAKE_INSTALL_PREFIX/$APP_NAME" APP="$INSTALL_ROOT/$APP_NAME.app" APPFW=$APP"/Contents/Frameworks" APP_NEWPATH=$INSTALL_ROOT"/"$APP_NAME"-"$QTVER"-"$GIT$GITMOD".app" APP_LATEST="$INSTALL_ROOT/$APP_NAME-$QTVER-latest.app" QTDIR=$CMAKE_PREFIX_PATH echo "--------------------" echo "INSTALL_ROOT : $INSTALL_ROOT" echo "APP : $APP" echo "APPFW : $APPFW" echo "APP_NEWPATH : $APP_NEWPATH" echo "APP_LATEST : $APP_LATEST" echo "QTDIR : $QTDIR" echo "--------------------" [ -d $APPFW ] || mkdir -p $APPFW echo "[ macdeployqt: deploying ]" $QTDIR"/bin/macdeployqt" $APP -appstore-compliant # remove new path if [ -d $APP_NEWPATH ]; then rm -rf $APP_NEWPATH; fi # remove applatest if [ -d $APP_LATEST ]; then rm -rf $APP_LATEST; fi #copy app to new path cp -r "$APP" "$APP_NEWPATH" # mv app to latest mv "$APP" "$APP_LATEST" } function help() { info "Build script v1.0" echo "check Check configuration" echo "build Building" echo "test Unittesting" echo "testcc Code Coverage" echo "opencc Open Code Coverage index.html"s } # ################ # Output funcitons # ################ function setup_ascii() { RED='\033[0;31m' GREEN='\033[0;32m' BLUE='\033[0;34m' ORANGE='\033[0;33m' NC='\033[0m' # No Color IN="[${BLUE} info ${NC}]" ER="[${RED} ERR ${NC}]" FAIL="[${RED}FAIL${NC}]" OK="[${GREEN} OK ${NC}]" } function msg_err() { echo -e "[${RED} error ${NC}] $@" } function msg_warn() { echo -e "[${ORANGE} warrning ${NC}] $@" } function msg_ok() { echo -e "[${GREEN} ok ${NC}] $@" } function info () { echo -e "[${BLUE} $@ ${NC}]" } function pass() { echo -e "[${GREEN}PASS${NC}] $@" } function fail() { echo -e "[${RED}FAIL${NC}] $@" } # Run main function main "$@"