#!/bin/bash set -o errexit -o pipefail -o noclobber -o nounset # Test if getopt exists command -v getopt >/dev/null 2>&1 || { echo "can't execute getopt"; exit 1; } # Test if getopt works ! getopt --test 2> /dev/null [[ ${PIPESTATUS[0]} -ne 4 ]] && { exit 2; } # List of available options OPTIONS=g:t:qcfs:b:o: LONGOPTS=generator:,type:,qtcreator,cmake,force,source-dir:,build-dir:,output-dir: # Parse options ! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@") [[ ${PIPESTATUS[0]} -ne 0 ]] && exit 3 # Read getopt's output to handle the quoting right eval set -- "$PARSED" # Default generator GENERATOR="Unix Makefiles" # Generate single build type SINGLE_TYPE="n" # Generate QtCreator build types QTCREATOR="n" # Generate CMake build types CMAKE="n" # Force destructive actions FORCE="n" # Default source directory is two levels upper SOURCE_DIR="$(dirname -- "$(dirname -- "$(pwd)")")" # Default build directory is _build BUILD_DIR="${SOURCE_DIR}/_build" # Default output directory is _output OUTPUT_DIR="${SOURCE_DIR}/_output" while true; do case "$1" in -g|--generator) GENERATOR="$2" shift 2 ;; -t|--type) SINGLE_TYPE="$2" shift 2 ;; -q|--qtcreator) QTCREATOR="y" shift ;; -c|--cmake) CMAKE="y" shift ;; -f|--force) FORCE="y" shift ;; -s|--source-dir) SOURCE_DIR="$2" shift 2 ;; -b|--build-dir) BUILD_DIR="$2" shift 2 ;; -o|--output-dir) OUTPUT_DIR="$2" shift 2 ;; --) shift break ;; *) echo "Programming error" exit 3 ;; esac done CMAKE_ARGS=() [ ${#@} -gt 0 ] && CMAKE_ARGS=("${@}") [ ! -f "${SOURCE_DIR}/CMakeLists.txt" ] && { echo "Source directory does not contain CMakeLists.txt"; exit 4; } if [ "x${SINGLE_TYPE}" != "xn" ]; then case "${SINGLE_TYPE}" in None|Debug|Release|Profile|RelWithDebInfo|MinSizeRel) true ;; *) echo "Wrong CMake build type" exit 6 ;; esac fi export CMAKE export QTCREATOR export GENERATOR export SOURCE_DIR export BUILD_DIR export OUTPUT_DIR export CMAKE_ARGS export SINGLE_TYPE export FORCE CMAKE_BUILD_TYPES=(None Debug Release Profile RelWithDebInfo MinSizeRel) QTCREATOR_BUILD_TYPES=(qtNone qtDebug qtRelease qtProfile) generate_configuration() { local BUILD_TYPE="${!#}" local BUILD="$BUILD_TYPE" if [ "x$QTCREATOR" == "xy" ]; then case "$BUILD_TYPE" in qtNone) BUILD="unknown" BUILD_TYPE="None" ;; qtDebug) BUILD="debug" BUILD_TYPE="Debug" ;; qtRelease) BUILD="release" BUILD_TYPE="Release" ;; qtProfile) BUILD="profile" BUILD_TYPE="Profile" ;; esac fi GEN_DIR="${BUILD_DIR}" if [ "x${SINGLE_TYPE}" == "xn" ]; then GEN_DIR="${BUILD_DIR}/${BUILD}" else GEN_DIR="${BUILD_DIR}/${SINGLE_TYPE}" fi if [ -d "${GEN_DIR}" ]; then if [ "x${FORCE}" == "xy" ]; then rm -rf "${GEN_DIR}" else echo "Build directory '${GEN_DIR}' already exists. Use --force to remove this directory or do it manually" return fi fi mkdir -p "${GEN_DIR}" pushd "${GEN_DIR}" 2>/dev/null cmake -G "${GENERATOR}" -DCMAKE_INSTALL_PREFIX="${OUTPUT_DIR}" -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" "${CMAKE_ARGS[@]}" "${SOURCE_DIR}" if [ "x$GENERATOR" == "xNinja" ]; then # Generate fake Makefile, so make can run ninja build cat > Makefile </dev/null } export -f generate_configuration BUILD_TYPES=() if [ "x$SINGLE_TYPE" != "xn" ]; then BUILD_TYPES=("${SINGLE_TYPE}") else [ "x$QTCREATOR" == "xy" ] && BUILD_TYPES=("${BUILD_TYPES[@]}" "${QTCREATOR_BUILD_TYPES[@]}") [ "x$CMAKE" == "xy" ] && BUILD_TYPES=("${BUILD_TYPES[@]}" "${CMAKE_BUILD_TYPES[@]}") fi if [ ${#BUILD_TYPES[@]} -eq 0 ]; then echo "No build type selected." echo "Use -c for default CMake build types" echo "Use -q for build types for QtCreator" echo "Use -t name for build with type 'name'" exit 0 fi # Try to work in parallel if [ -x "$(command -v parallel)" ]; then PV=$(parallel --version | head -n 1 | awk '{ print $3; }') if [ "$PV" -lt "20131121" ]; then parallel --delay 2 -r generate_configuration ::: "${BUILD_TYPES[@]}" elif [ "$PV" -lt "20141023" ]; then parallel --delay 2 -r --no-notice generate_configuration ::: "${BUILD_TYPES[@]}" else parallel --delay 2 -r --will-cite generate_configuration ::: "${BUILD_TYPES[@]}" fi else for T in "${BUILD_TYPES[@]}"; do generate_configuration "${T}"; done fi