commit 2be62ace11edcab46d608527ce5bdecfe56b2749
Author: Thomas Schöpping <tschoepp@cit-ec.uni-bielefeld.de>
Date:   Mon May 25 20:59:00 2020 +0200

    QtCreator setup script completely reworked

diff --git a/os/AMiRo-OS b/os/AMiRo-OS
index a93a101..cacd990 160000
--- a/os/AMiRo-OS
+++ b/os/AMiRo-OS
@@ -1 +1 @@
-Subproject commit a93a1019de6cb332cf4a1fc72451410f65077503
+Subproject commit cacd990cefab7167a7cac1ea1f5a8ec8e87687d7
diff --git a/os/os.mk b/os/os.mk
index 8281772..c698b4f 100644
--- a/os/os.mk
+++ b/os/os.mk
@@ -33,5 +33,5 @@ UDEFS += -DAMIRO_APPS=true
 # make all variables that have been set so far available to all other makefiles
 export
 
-OS_MODULES_DIR := $(realpath $(OS_DIR)/AMiRo-OS/modules)
+OS_MODULES_DIR := $(OS_DIR)/AMiRo-OS/modules
 
diff --git a/tools/ide/QtCreator/QtCreatorSetup.sh b/tools/ide/QtCreator/QtCreatorSetup.sh
index 75e1cff..1dcc890 100755
--- a/tools/ide/QtCreator/QtCreatorSetup.sh
+++ b/tools/ide/QtCreator/QtCreatorSetup.sh
@@ -62,12 +62,14 @@ function printWelcomeText {
 #
 function printHelp {
   printInfo "printing help text\n"
-  printf "usage:    $(basename ${BASH_SOURCE[0]}) [-h|--help] [-c|--clean] [-w|--wipe] [-q|--quit] [--log=<file>]\n"
+  printf "usage:    $(basename ${BASH_SOURCE[0]}) [-h|--help] [-p|--project=<project>] [-a|--all] [-c|--clean] [-w|--wipe] [-q|--quit] [--log=<file>]\n"
   printf "\n"
   printf "options:  -h, --help\n"
   printf "              Print this help text.\n"
-  printf "          -i, --initialize\n"
-  printf "              Initialize project files.\n"
+  printf "          -p, --project <project>\n"
+  printf "              Create projects for a single configuration.\n"
+  printf "          -a, --all\n"
+  printf "              Create projects for all configurations.\n"
   printf "          -c, --clean\n"
   printf "              Delete project files.\n"
   printf "          -w, --wipe\n"
@@ -81,12 +83,12 @@ function printHelp {
 ### read directory where to create/delete projects #############################
 # Read the directory where to create/delete project files from user.
 #
-# usage:      getProjectDir <pathvar>
+# usage:      getProjectsDir <pathvar>
 # arguments:  <pathvar>
 #                 Variable to store the selected path to.
 # return:     n/a
 #
-function getProjectDir {
+function getProjectsDir {
   printLog "reading path for project files from user...\n"
   local amiroappsdir=$(realpath $(dirname $(realpath ${BASH_SOURCE[0]}))/../../../)
   local input=""
@@ -105,10 +107,13 @@ function getProjectDir {
 #                 No error or warning occurred.
 #            -1
 #                 Error: Command 'arm-none-eabi-gcc' not found.
+#            -2
+#                 Error: include directory could not be resolved.
 #
 function retrieveGccIncludeDir {
   # retrieve binary path or link
   local binpath=$(which arm-none-eabi-gcc)
+  local gccincpath=""
   if [ -z "$binpath" ]; then
     printError "command 'arm-none-eabi-gcc' not found\n"
     return -1
@@ -116,22 +121,52 @@ function retrieveGccIncludeDir {
 
     # traverse any links
     while [ -L "$binpath" ]; do
-      binpath=$(readlink $binpath)
+      binpath=$(realpath $(dirname $binpath)/$(readlink $binpath))
     done
     printInfo "gcc-arm-none-eabi detected: $binpath\n"
 
     # return include path
-    eval $1=$(realpath $(dirname ${binpath})/../arm-none-eabi/include/)
-
-    return 0
+    gccincpath=$(realpath $(dirname ${binpath})/../arm-none-eabi/include/)
+    if [ ! -d "$gccincpath" ]; then
+      printWarning "$gccincpath does not exist\n"
+      return -2
+    else
+      eval $1="$gccincpath"
+      return 0
+    fi
   fi
 }
 
-### intialize project files ####################################################
-# Initailizes all project files.
+### detect available configurations ############################################
+# Detect all avalable configurations.
 #
-# usage:      initProject [-p|--path=<path>] [--gcc=<path>] [-o|--out=<var>] [--gccout=<var>]
-# arguments:  -p, --path <path>
+# usage:      detectConfigurations <configurationsarray>
+# arguments:  <configurationsarray>
+#                 Array variable to store all detected configurations to.
+# return:     n/a
+#
+function detectConfigurations {
+  local configsdir=$(realpath $(dirname $(realpath ${BASH_SOURCE[0]}))/../../../configurations)
+  local configs_detected=()
+
+  # detect all available modules (via directories)
+  for dir in $(ls -d ${configsdir}/*/); do
+    configs_detected[${#configs_detected[@]}]=$(basename $dir)
+  done
+
+  # set the output variable
+  eval "$1=(${configs_detected[*]})"
+}
+
+### create project files for a single configuration ############################
+# Create project files for all modules of a configuration.
+#
+# usage:      createConfigProjects <configurations> [-c|--config=<configuration>] [-p|--path=<path>] [--gcc=<path>] [-o|--out=<var>] [--gccout=<var>]
+# arguments:  <configurations>
+#                 Array containing all configurations available.
+#             -c, --config <configuration>
+#                 Name (folder name) of the configuration for which project files shall be generated.
+#             -p, --path <path>
 #                 Path where to create the project files.
 #             --gcc=<path>
 #                 Path to the GCC include directory.
@@ -139,25 +174,53 @@ function retrieveGccIncludeDir {
 #                 Variable to store the path to.
 #             --gccout=<var>
 #                 Variable to store the path to the GCC include directory to.
+#                 If this optional arguments is absent, ths function will ask for user input.
 # return:     0
 #                 No error or warning occurred.
+#             1
+#                 Aborted by user.
+#             2
+#                 The selected configuration does not contain any modules.
+#             -1
+#                 No configurations available.
+#             -2
+#                 The specified <configuration> could not be found.
+#             -3
+#                 Parsing the project for the specified configuration failed.
+#             -4
+#                 Missing dependencies.
 #
-function initProject {
+function createConfigProjects {
   local userdir=$(pwd)
-  local projectdir=""
+  local configsdir=$(realpath $(dirname $(realpath ${BASH_SOURCE[0]}))/../../../configurations)
+  local configs=("${!1}")
+  local config=""
+  local configidx=""
+  local projectsdir=""
   local gccincludedir=""
   local outvar=""
   local gccoutvar=""
 
+  # check dependencies
+  checkCommands make
+  if [ $? -ne 0 ]; then
+    printError "Missing dependencies detected.\n"
+    return -4
+  fi
+
   # parse arguments
   local otherargs=()
   while [ $# -gt 0 ]; do
     if ( parseIsOption $1 ); then
       case "$1" in
+        -c=*|--config=*)
+          config="${1#*=}"; shift 1;;
+        -c|--config)
+          config="$2"; shift 2;;
         -p=*|--path=*)
-          projectdir=$(realpath "${1#*=}"); shift 1;;
+          projectsdir=$(realpath "${1#*=}"); shift 1;;
         -p|--path)
-          projectdir=$(realpath "$2"); shift 2;;
+          projectsdir=$(realpath "$2"); shift 2;;
         --gcc=*)
           gccincludedir=$(realpath "${1#*=}"); shift 1;;
         --gcc)
@@ -179,72 +242,218 @@ function initProject {
     fi
   done
 
-  # print message
-  printInfo "creating QtCreator project files...\n"
+  # sanity check for the configs variable
+  if [ -z "${configs[*]}" ]; then
+    printError "no configurations available\n"
+    return -1
+  fi
+
+  # select configuration
+  if [ -z $config ]; then
+    # list all available configurations
+    printInfo "choose a configuration or type 'A' to abort:\n"
+    for (( idx=0; idx<${#configs[@]}; ++idx )); do
+      printf "%4u: %s\n" $(($idx + 1)) "${configs[$idx]}"
+    done
+    # read user input
+    printLog "read user selection\n"
+    local userinput=""
+    while [[ ! "$userinput" =~ ^[0-9]+$ ]] || [ ! "$userinput" -gt 0 ] || [ ! "$userinput" -le ${#configs[@]} ] && [[ ! "$userinput" =~ ^[Aa]$ ]]; do
+      read -p "your selection: " -e userinput
+      printLog "user selection: $userinput\n"
+      if [[ ! "$userinput" =~ ^[0-9]+$ ]] || [ ! "$userinput" -gt 0 ] || [ ! "$userinput" -le ${#configs[@]} ] && [[ ! "$userinput" =~ ^[Aa]$ ]]; then
+        printWarning "Please enter an integer between 1 and ${#configs[@]} or 'A' to abort.\n"
+      fi
+    done
+    if [[ "$userinput" =~ ^[Aa]$ ]]; then
+      printWarning "aborted by user\n"
+      return 1
+    fi
+    # store selection
+    configidx=$(($userinput - 1))
+    config="${configs[$configidx]}"
+    printf "\n"
+  else
+    # search all configurations for the selected one
+    for (( idx=0; idx<${#configs[@]}; ++idx )); do
+      if [ "${configs[$idx]}" = "$config" ]; then
+        configidx=$idx
+        break
+      fi
+    done
+    # error if the configurations could not be found
+    if [ -z $configidx ]; then
+      printError "configuration ($config) not available\n"
+      return -2
+    fi
+  fi
+
+  # retrieve modules in the configuration
+  local modules=()
+  if [ -d ${configsdir}/${config}/modules ]; then
+    for dir in $(ls -d ${configsdir}/${config}/modules/*/); do
+      modules[${#modules[@]}]=$(basename $dir)
+    done
+    if [ ${#modules[@]} -eq 0 ]; then
+      printWarning "configuration ${config} does not contain any modules\n"
+      return 2
+    fi
+  else
+    printWarning "'module/' folder does not exist in configuration ${config}\n"
+    return 2
+  fi
 
   # read absolute project directory if required
-  if [ -z "$projectdir" ]; then
-    getProjectDir projectdir
+  if [ -z "$projectsdir" ]; then
+    getProjectsDir projectsdir
+    printf "\n"
+  fi
+
+  # check for existing project files
+  local projectfiles=""
+  for module in ${modules[@]}; do
+    projectfiles+="$(find ${projectsdir} -maxdepth 1 -type f | grep -E "${config}_${module}\.(includes|files|config|creator)$")"
+  done
+  IFS=$'\n'; projectfiles=($projectfiles); unset IFS
+  if [ ! -z "${projectfiles[*]}" ]; then
+    printWarning "The following files will be overwritten:\n"
+    for pfile in ${projectfiles[@]}; do
+      printWarning "\t$(basename $pfile)\n"
+    done
+    local userinput=""
+    printInfo "Continue and overwrite? [y/n]\n"
+    readUserInput "YyNn" userinput
+    case "$userinput" in
+      Y|y)
+        ;;
+      N|n)
+        printWarning "Project generation for ${config} configuration aborted by user\n"
+        return 1
+        ;;
+      *)
+        printError "unexpected input: ${userinput}\n"; return -999;;
+    esac
+    printf "\n"
   fi
 
-  # retrieve absolute GCC include dir
+  # print message
+  printInfo "generating QtCreator project files for the $config configuration...\n"
+
+  # retrieve absolute GCC include path
   if [ -z "$gccincludedir" ]; then
     retrieveGccIncludeDir gccincludedir
   fi
 
-  # move to project directory
-  cd $projectdir
-
-  # AMiRo-OS, ChibiOS, AMiRo-BLT, AMiRo-LLD and uRtWare relative root directories
-  local amiroappsrootdir=$(realpath --relative-base=$projectdir $(dirname ${BASH_SOURCE[0]})/../../..)
-  local amiroosrootdir=$(realpath --relative-base=$projectdir ${amiroappsrootdir}/os/AMiRo-OS/os)
-  local chibiosrootdir=$(realpath --relative-base=$projectdir ${amiroosrootdir}/../kernel/ChibiOS)
-  local amirobltrootdir=$(realpath --relative-base=$projectdir ${amiroosrootdir}/../bootloader/AMiRo-BLT)
-  local amirolldrootdir=$(realpath --relative-base=$projectdir ${amiroosrootdir}/../periphery-lld/AMiRo-LLD)
-  local urtwarerootdir=$(realpath --relative-base=$projectdir $(dirname ${BASH_SOURCE[0]})/../../../middleware/uRtWare/)
-
-  # generate a file that contains all subdirectories as includes (but ignore hidden and documentation directories)
-  find $gccincludedir -type d > ${projectdir}/AMiRo-Apps.includes
-  find $amiroappsrootdir -type d | grep -E "/(apps|configurations)/.+" >> ${projectdir}/AMiRo-Apps.includes
-  find $amiroosrootdir -type d | grep -v "/doc\|/build\|/.dep\|/hal\|/ports" >> ${projectdir}/AMiRo-Apps.includes
-  find $amiroosrootdir -type d | grep -E "/os/hal/(include|src)" >> ${projectdir}/AMiRo-Apps.includes
-  find $chibiosrootdir -type d | grep -E "/os/common/abstractions/cmsis_os$" >> ${projectdir}/AMiRo-Apps.includes
-  find $chibiosrootdir -type d | grep -E "/os/common/oslib/(include|src)$" >> ${projectdir}/AMiRo-Apps.includes
-  find $chibiosrootdir -type d | grep -E "/os/hal/(include|src)$" >> ${projectdir}/AMiRo-Apps.includes
-  find $chibiosrootdir -type d | grep -E "/os/hal/lib/streams" >> ${projectdir}/AMiRo-Apps.includes
-  find $chibiosrootdir -type d | grep -E "/os/hal/osal/(lib|rt)$" >> ${projectdir}/AMiRo-Apps.includes
-  find $chibiosrootdir -type d | grep -E "/os/license$" >> ${projectdir}/AMiRo-Apps.includes
-  find $chibiosrootdir -type d | grep -E "/os/rt/(include|src)$" >> ${projectdir}/AMiRo-Apps.includes
-  find $chibiosrootdir -type d | grep -E "/os/various/(shell|cpp_wrappers)" >> ${projectdir}/AMiRo-Apps.includes
-  find $chibiosrootdir -type d | grep -E "/test/(lib|rt/source/test)$" >> ${projectdir}/AMiRo-Apps.includes
-  find $amirobltrootdir -type d | grep -E "/Target/Source/AMiRo$" >> ${projectdir}/AMiRo-Apps.includes
-  echo "$(realpath --relative-base=$projectdir ${amirolldrootdir}/..)" >> ${projectdir}/AMiRo-Apps.includes
-  find $amirolldrootdir -type d | grep -v "/doc" >> ${projectdir}/AMiRo-Apps.includes
-  find $urtwarerootdir -type d | grep -v "/doc" >> ${projectdir}/AMiRo-Apps.includes
-  # generate a file that specifies all files
-  echo -n "" > ${projectdir}/AMiRo-Apps.files
-  for path in `cat ${projectdir}/AMiRo-Apps.includes`; do
-    find $path -maxdepth 1 -type f \( ! -iname ".*" \) |
-      grep -Ev "^.*/arm-none-eabi/.*$" |
-      grep -E  "^.*(\.s|\.S|\.h|\.c|\.hpp|\.cpp|\.tpp|\.ld)$" |
-      grep -Ev "^${amirobltrootdir}/Target/Source/AMiRo/helper.*$" >> ${projectdir}/AMiRo-Apps.files;
+  # change to project directory
+  cd "$projectsdir"
+
+  # create project files for each module of the selected configuration
+  for module in ${modules[@]}; do
+    # run make, but only run the GCC preprocessor and produce no binaries
+    local sourcefiles=()
+    local sourcefile=""
+    local parse_state="WAIT_FOR_INCLUDE_COMPILE_MAKE"
+    local makedirs=()
+    # capture all output from make and GCC and append the return value of make as last line
+    printInfo "processing module ${module} (this may take a while)...\n"
+    local rawout=$(make --directory ${configsdir}/${config}/modules/${module} --always-make USE_OPT="-v -E -H" USE_VERBOSE_COMPILE="no" OUTFILES="" 2>&1 && echo $?)
+    # check whether the make call was successfull
+    if [[ $(echo "${rawout}" | tail -n 1) != "0" ]]; then
+      printError "executing 'make' in configuration directory failed\n"
+      cd "$userdir"
+      return -3
+    else
+      # cleanup
+      make --directory ${configsdir}/${config}/modules/${module} clean &>/dev/null
+    fi
+    # extract file names from raw output
+    IFS=$'\n'; rawout=($rawout); unset IFS
+    for line in "${rawout[@]}"; do
+      case $parse_state in
+        WAIT_FOR_INCLUDE_COMPILE_MAKE)
+          # lines stating include files look like:
+          # ... <../relative/path/to/file>
+          if [[ "$line" =~ ^\.+[[:blank:]].+\..+$ ]]; then
+            sourcefile=${line##* }
+            if [[ ! "$sourcefile" =~ ^/ ]]; then
+              sourcefile=$(realpath ${makedirs[-1]}/${sourcefile})
+            fi
+            sourcefiles[${#sourcefiles[@]}]="$sourcefile"
+          # whenever the next source file is processed, a message appears like:
+          # Compiling <filename>
+          elif [[ "$line" =~ ^Compiling[[:blank:]](.+\..+)$ ]]; then
+            printf "."
+            sourcefile=${BASH_REMATCH[1]}
+            parse_state="WAIT_FOR_COMPILERCALL"
+          # if make is called again in another directory, a message appears like:
+          # make[1]: Entering directory 'directory'
+          elif [[ "$line" =~ ^make(\[[0-9]+\])?:\ Entering\ directory\ \'.+\'$ ]]; then
+            makedirs+=($(echo "$line" | (cut -d "'" -f 2)))
+          # if make is leaving a directory, a message appears like:
+          # make[1]: Leaving directory 'directory'
+          elif [[ "$line" =~ ^make(\[[0-9]+\])?:\ Leaving\ directory\ \'.+\'$ ]]; then
+            unset makedirs[-1]
+          fi;;
+        WAIT_FOR_COMPILERCALL)
+          # wait for the actual call of the compiler to retrieve the full path to the source file
+          if [[ "$line" == *${sourcefile}* ]]; then
+            line="${line%%${sourcefile}*}${sourcefile}"
+            line="${line##* }"
+            if [[ "$line" =~ ^/ ]]; then
+              # aboslute path
+              sourcefile=$line
+            else
+              # relative path
+              sourcefile=$(realpath ${makedirs[-1]}/${line##* })
+            fi
+            sourcefiles[${#sourcefiles[@]}]="$sourcefile"
+            parse_state="WAIT_FOR_INCLUDE_COMPILE_MAKE"
+          fi;;
+      esac
+    done
+    unset rawout
+    printf "\n"
+    # sort and remove duplicates
+    IFS=$'\n'; sourcefiles=($(sort --unique <<< "${sourcefiles[*]}")); unset IFS
+
+    # extract include paths
+    local includes=()
+    for source in ${sourcefiles[*]}; do
+      includes[${#includes[@]}]="$(dirname ${source})"
+    done
+    # sort and remove duplicates
+    IFS=$'\n'; includes=($(sort --unique <<< "${includes[*]}")); unset IFS
+
+    # generate the .incldues file, containing all include paths
+    echo "" > ${projectsdir}/${config}_${module}.includes
+    for inc in ${includes[*]}; do
+      echo "$inc" >> ${projectsdir}/${config}_${module}.includes
+    done
+    # generate the .files file, containing all source files
+    echo "" > ${projectsdir}/${config}_${module}.files
+    for source in ${sourcefiles[*]}; do
+      # skip GCC files
+      if [[ ! "$source" =~ .*/gcc.* ]]; then
+        echo "$source" >> ${projectsdir}/${config}_${module}.files
+      fi
+    done
+    # generate a default project configuration file if it doesn't exits yet
+    if [ ! -f ${projectsdir}/${config}_${module}.config ]; then
+      echo "// Add predefined macros for your project here. For example:" > ${projectsdir}/${config}_${module}.config
+      echo "// #define YOUR_CONFIGURATION belongs here" >> ${projectsdir}/${config}_${module}.config
+    fi
+    # generate a default .creator file if it doesn't exist yet
+    if [ ! -f ${projectsdir}/${config}_${module}.creator ]; then
+      echo "[general]" > ${projectsdir}/${config}_${module}.creator
+    fi
   done
-  # generate a default project configuration file if none exists so far
-  if [ ! -f ${projectdir}/AMiRo-Apps.config ]; then
-    echo "// Add predefined macros for your project here. For example:" > ${projectdir}/AMiRo-Apps.config
-    echo "// #define YOUR_CONFIGURATION belongs here" >> ${projectdir}/AMiRo-Apps.config
-  fi
-  # generate a default .creator file if none exists so far
-  if [ ! -f ${projectdir}/AMiRo-Apps}.creator ]; then
-    echo "[general]" > ${projectdir}/AMiRo-Apps.creator
-  fi
 
   # go back to user directory
   cd $userdir
 
   # fill the output variables
   if [ ! -z "$outvar" ]; then
-    eval $outvar="$projectdir"
+    eval $outvar="$projectsdir"
   fi
   if [ ! -z "$gccoutvar" ]; then
     eval $gccoutvar="$gccincludedir"
@@ -253,24 +462,152 @@ function initProject {
   return 0
 }
 
+### create project files for all configurations ################################
+# Create project files for all configurations.
+#
+# usage:      createAllProjects <configurations> [-p|--path=<path>] [--gcc=<path>] [-o|--out=<var>] [--gccout=<var>]
+# arguments:  <configurations>
+#                 Array containing all configurations available.
+#             -p, --path <path>
+#                 Path where to create the project files.
+#             --gcc=<path>
+#                 Path to the GCC include directory.
+#             -o, --out <var>
+#                 Variable to store the path to.
+#             --gccout=<var>
+#                 Variable to store the path to the GCC include directory to.
+#                 If this optional arguments is absent, ths function will ask for user input.
+# return:     0
+#                 No error or warning occurred.
+#             1
+#                 Aborted by user.
+#             -1
+#                 No configurations available.
+#
+function createAllProjects {
+  local configs=("${!1}")
+  local projectsdir=""
+  local gccincludedir=""
+  local outvar=""
+  local gccoutvar=""
+
+  # parse arguments
+  local otherargs=()
+  while [ $# -gt 0 ]; do
+    if ( parseIsOption $1 ); then
+      case "$1" in
+        -p=*|--path=*)
+          projectsdir=$(realpath "${1#*=}"); shift 1;;
+        -p|--path)
+          projectsdir=$(realpath "$2"); shift 2;;
+        --gcc=*)
+          gccincludedir=$(realpath "${1#*=}"); shift 1;;
+        --gcc)
+          gccincludedir=$(realpath "$2"); shift 2;;
+        -o=*|--out=*)
+          outvar=${1#*=}; shift 1;;
+        -o|--out)
+          outvar=$2; shift 2;;
+        --gccout=*)
+          gccoutvar=$(realpath "${1#*=}"); shift 1;;
+        --gccout)
+          gccoutvar=$(realpath "$2"); shift 2;;
+        *)
+          printError "invalid option: $1\n"; shift 1;;
+      esac
+    else
+      otherargs+=("$1")
+      shift 1
+    fi
+  done
+
+  # sanity check for the configurations variable
+  if [ -z "${configs[*]}" ]; then
+    printError "no configurations available\n"
+    return -1
+  fi
+
+  # read absolute project directory if required
+  if [ -z "$projectsdir" ]; then
+    getProjectsDir projectsdir
+  fi
+
+  # check for existing project files
+  local projectfiles=""
+  for config in ${configs[@]}; do
+    for module in ${modules[@]}; do
+      projectfiles+="$(find ${projectsdir} -maxdepth 1 -type f | grep -E "${config}_${module}\.(includes|files|config|creator)$")"
+    done
+  done
+  IFS=$'\n'; projectfiles=($projectfiles); unset IFS
+  if [ ! -z "${projectfiles[*]}" ]; then
+    printWarning "The following files will be removed:\n"
+    for pfile in ${projectfiles[@]}; do
+      printWarning "\t$(basename $pfile)\n"
+    done
+    local userinput=""
+    printInfo "Continue and overwrite? [y/n]\n"
+    readUserInput "YyNn" userinput
+    case "${userinput}" in
+      Y|y)
+        for pfile in ${projectfiles[*]}; do
+          rm "$pfile"
+        done
+        ;;
+      N|n)
+        printWarning "Project generation aborted by user\n"
+        return 1
+        ;;
+      *)
+        printError "unexpected input: ${userinput}\n"
+        return 999
+        ;;
+    esac
+  fi
+
+  # print message
+  printf "\n"
+  printInfo "generating QtCreator project files for all configurations...\n"
+
+  # retrieve absolute GCC include path
+  if [ -z "$gccincludedir" ]; then
+    retrieveGccIncludeDir gccincludedir
+  fi
+
+  # iterate over all configurations
+  local retval=1
+  for config in ${configs[@]}; do
+    if [ $retval != 0 ]; then
+      printf "\n"
+    fi
+    createConfigProjects configs[@] --config="$config" --path="$projectsdir" --gcc="$gccincludedir"
+    retval=$?
+  done
+
+  return 0
+}
+
 ### delete project files #######################################################
 # Deletes all project files and optionally .user files, too.
 #
-# usage:      deleteProject [-p|--path=<path>] [-o|--out=<var>] [-w|-wipe]
+# usage:      deleteProjects [-p|--path=<path>] [-c|--config=<configuration>] [-o|--out=<var>] [-w|-wipe]
 # arguments:  -p, --path <path>
 #                 Path where to delete the project files.
+#             -c, --config <configuration>
+#                 Configuration name for which the project files shall be deleted.
 #             -o, --out <var>
 #                 Variable to store the path to.
 #             -w, --wipe
 #                 Delete .user files as well.
 # return:
 #  -  0: no error
-#  -  1: warning: function aborted by user
-#  - -1: error: unexpected user input
-function deleteProject {
-  local projectdir=""
+#
+function deleteProjects {
+  local config=""
+  local projectsdir=""
   local outvar=""
   local wipe=false
+  local files=""
 
   # parse arguments
   local otherargs=()
@@ -278,9 +615,13 @@ function deleteProject {
     if ( parseIsOption $1 ); then
       case "$1" in
         -p=*|--path=*)
-          projectdir=$(realpath "${1#*=}"); shift 1;;
+          projectsdir=$(realpath "${1#*=}"); shift 1;;
         -p|--path)
-          projectdir=$(realpath "$2"); shift 2;;
+          projectsdir=$(realpath "$2"); shift 2;;
+        -c=*|--config=*)
+          config="${1#*=}"; shift 1;;
+        -c|--config)
+          config="${2}"; shift 2;;
         -o=*|--out=*)
           outvar=${1#*=}; shift 1;;
         -o|--out)
@@ -296,39 +637,45 @@ function deleteProject {
     fi
   done
 
-  # print message
-  if [ $wipe != true ]; then
-    printInfo "deleting all QtCreator project files (*.includes, *.files, *.config, and *.creator)\n"
-  else
-    printInfo "deleting all QtCreator project files (*.includes, *.files, *.config, *.creator, and *.user)\n"
+  # read absolute project directory if required
+  if [ -z "$projectsdir" ]; then
+    getProjectsDir projectsdir
   fi
 
-  # read project directory if required
-  if [ -z "$projectdir" ]; then
-    getProjectDir projectdir
+  # list all files to be deleted
+  if [ -z "$config" ]; then
+    if [ $wipe != true ]; then
+      files=$(find "${projectsdir}" -maxdepth 1 -type f | grep -E "^.+\.(includes|files|config|creator|cflags|cxxflags)$")
+    else
+      files=$(find "${projectsdir}" -maxdepth 1 -type f | grep -E "^.+\.(includes|files|config|creator|cflags|cxxflags|creator(\.user(\..+)?)?)$")
+    fi
+  else
+    if [ $wipe != true ]; then
+      files=$(find "${projectsdir}" -maxdepth 1 -type f | grep -E "^${config}_.+\.(includes|files|config|creator|cflags|cxxflags)$")
+    else
+      files=$(find "${projectsdir}" -maxdepth 1 -type f | grep -E "^${config}_.+\.(includes|files|config|creator|cflags|cxxflags|creator(\.user(\..+)?)?)$")
+    fi
   fi
-
-  # remove all project files
-  rm ${projectdir}/AMiRo-Apps.includes 2>&1 | tee -a $LOG_FILE
-  rm ${projectdir}/AMiRo-Apps.files 2>&1 | tee -a $LOG_FILE
-  rm ${projectdir}/AMiRo-Apps.config 2>&1 | tee -a $LOG_FILE
-  rm ${projectdir}/AMiRo-Apps.creator 2>&1 | tee -a $LOG_FILE
-
-  if [ $wipe == true ]; then
-    rm ${projectdir}/AMiRo-Apps.creator.user 2>&1 | tee -a $LOG_FILE
+  if [ ! -z "$files" ]; then
+    printInfo "Deleting the following files:\n"
+    while read line; do
+      printInfo "\t$(basename ${line})\n"
+      rm ${line} 2>&1 | tee -a $LOG_FILE
+    done <<< "${files}"
+  else
+    printInfo "No project files found\n"
   fi
 
   # store the path to the output variable, if required
   if [ ! -z "$outvar" ]; then
-    eval $outvar="$projectdir"
+    eval $outvar="$projectsdir"
   fi
 
   return 0
-
 }
 
 ### main function of this script ###############################################
-# Creates, deletes and wipes QtCreator project files for the three AMiRo base modules.
+# Creates, deletes and wipes QtCreator project files.
 #
 # usage:      see function printHelp
 # arguments:  see function printHelp
@@ -377,6 +724,22 @@ function main {
   # log script name
   printLog "this is $(realpath ${BASH_SOURCE[0]})\n"
 
+  # detect available configurations and inform user
+  local configurations=()
+  detectConfigurations configurations
+  case "${#configurations[@]}" in
+    0)
+      printInfo "no configuration has been detected\n";;
+    1)
+      printInfo "1 configuration has been detected:\n";;
+    *)
+      printInfo "${#configurations[@]} configurations have been detected:\n";;
+  esac
+  for (( idx=0; idx<${#configurations[@]}; ++idx )); do
+    printInfo "  - ${configurations[$idx]}\n"
+  done
+  printf "\n"
+
   # parse arguments
   local otherargs=()
   while [ $# -gt 0 ]; do
@@ -384,6 +747,12 @@ function main {
       case "$1" in
         -h|--help) # already handled; ignore
           shift 1;;
+        -p=*|--project=*)
+          createConfigProjects configurations[@] --configuration="${1#*=}"; printf "\n"; shift 1;;
+        -p|--project)
+          createConfigProjects configurations[@] --configuration="${2}"; printf "\n"; shift 2;;
+        -a|--all)
+          createAllProjects configurations[@]; shift 1;;
         -c|--clean)
           deleteProjects; printf "\n"; shift 1;;
         -w|--wipe)
@@ -410,22 +779,25 @@ function main {
     # main menu info prompt and selection
     printInfo "QtCreator setup main menu\n"
     printf "Please select one of the following actions:\n"
-    printf "  [I] - initialize project files\n"
+    printf "  [P] - create projects for a single configuration\n"
+    printf "  [A] - create projects for all configurations\n"
     printf "  [C] - clean project files\n"
     printf "  [W] - wipe project and .user files\n"
     printf "  [Q] - quit this setup\n"
     local userinput=""
-    readUserInput "IiCcWwQq" userinput
+    readUserInput "PpAaCcWwQq" userinput
     printf "\n"
 
     # evaluate user selection
     case "$userinput" in
-      I|i)
-        initProject; printf "\n";;
+      P|p)
+        createConfigProjects configurations[@]; printf "\n";;
+      A|a)
+        createAllProjects configurations[@]; printf "\n";;
       C|c)
-        deleteProject; printf "\n";;
+        deleteProjects; printf "\n";;
       W|w)
-        deleteProject --wipe; printf "\n";;
+        deleteProjects --wipe; printf "\n";;
       Q|q)
         quitScript;;
       *) # sanity check (exit with error)
@@ -441,3 +813,4 @@ function main {
 ################################################################################
 
 main "$@"
+
