Statistics
| Branch: | Revision:

amiro-apps / tools / ide / QtCreator / QtCreatorSetup.sh @ 7f26dc6b

History | View | Annotate | Download (27.968 KB)

1
################################################################################
2
# AMiRo-Apps is a collection of applications and configurations for the        #
3
# Autonomous Mini Robot (AMiRo).                                               #
4
# Copyright (C) 2018..2020  Thomas Schöpping et al.                            #
5
#                                                                              #
6
# This program is free software: you can redistribute it and/or modify         #
7
# it under the terms of the GNU General Public License as published by         #
8
# the Free Software Foundation, either version 3 of the License, or            #
9
# (at your option) any later version.                                          #
10
#                                                                              #
11
# This program is distributed in the hope that it will be useful,              #
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of               #
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                #
14
# GNU General Public License for more details.                                 #
15
#                                                                              #
16
# You should have received a copy of the GNU General Public License            #
17
# along with this program.  If not, see <http://www.gnu.org/licenses/>.        #
18
#                                                                              #
19
# This research/work was supported by the Cluster of Excellence Cognitive      #
20
# Interaction Technology 'CITEC' (EXC 277) at Bielefeld University, which is   #
21
# funded by the German Research Foundation (DFG).                              #
22
################################################################################
23

    
24
#!/bin/bash
25

    
26
# load library
27
source "$(dirname ${BASH_SOURCE[0]})/../../bash/setuplib.sh"
28

    
29
### print welcome text #########################################################
30
# Prints a welcome message to standard out.
31
#
32
# usage:      printWelcomeText
33
# arguments:  n/a
34
# return:     n/a
35
#
36
function printWelcomeText {
37
  printf "######################################################################\n"
38
  printf "#                                                                    #\n"
39
  printf "#                  Welcome to the QtCreator setup!                   #\n"
40
  printf "#                                                                    #\n"
41
  printf "######################################################################\n"
42
  printf "#                                                                    #\n"
43
  printf "# Copyright (c) 2018..2020  Thomas Schöpping                         #\n"
44
  printf "#                                                                    #\n"
45
  printf "# This is free software; see the source for copying conditions.      #\n"
46
  printf "# There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR  #\n"
47
  printf "# A PARTICULAR PURPOSE. The development of this software was         #\n"
48
  printf "# supported by the Excellence Cluster EXC 227 Cognitive Interaction  #\n"
49
  printf "# Technology. The Excellence Cluster EXC 227 is a grant of the       #\n"
50
  printf "# Deutsche Forschungsgemeinschaft (DFG) in the context of the German #\n"
51
  printf "# Excellence Initiative.                                             #\n"
52
  printf "#                                                                    #\n"
53
  printf "######################################################################\n"
54
}
55

    
56
### print help #################################################################
57
# Prints a help text to standard out.
58
#
59
# usage:      printHelp
60
# arguments:  n/a
61
# return:     n/a
62
#
63
function printHelp {
64
  printInfo "printing help text\n"
65
  printf "usage:    $(basename ${BASH_SOURCE[0]}) [-h|--help] [-p|--project=<project>] [-a|--all] [-c|--clean] [-w|--wipe] [-q|--quit] [--log=<file>]\n"
66
  printf "\n"
67
  printf "options:  -h, --help\n"
68
  printf "              Print this help text.\n"
69
  printf "          -p, --project <project>\n"
70
  printf "              Create projects for a single configuration.\n"
71
  printf "          -a, --all\n"
72
  printf "              Create projects for all configurations.\n"
73
  printf "          -c, --clean\n"
74
  printf "              Delete project files.\n"
75
  printf "          -w, --wipe\n"
76
  printf "              Delete project and .user files.\n"
77
  printf "          -q, --quit\n"
78
  printf "              Quit the script.\n"
79
  printf "          --log=<file>\n"
80
  printf "              Specify a log file.\n"
81
}
82

    
83
### read directory where to create/delete projects #############################
84
# Read the directory where to create/delete project files from user.
85
#
86
# usage:      getProjectsDir <pathvar>
87
# arguments:  <pathvar>
88
#                 Variable to store the selected path to.
89
# return:     n/a
90
#
91
function getProjectsDir {
92
  printLog "reading path for project files from user...\n"
93
  local amiroappsdir=$(realpath $(dirname $(realpath ${BASH_SOURCE[0]}))/../../../)
94
  local input=""
95
  read -p "Path where to create/delete project files: " -i $amiroappsdir -e input
96
  printLog "user selected path $(realpath $input)\n"
97
  eval $1="$(realpath $input)"
98
}
99

    
100
### retrieves the ARM-NONE-EABI-GCC include directory ##########################
101
# Retrieves the include directory of the currently set arm-none-eabi-gcc.
102
#
103
# usage:      retrieveGccIncludeDir <path>
104
# arguments:  <path>
105
#                 Variable to store the path to.
106
# return:    0
107
#                 No error or warning occurred.
108
#            -1
109
#                 Error: Command 'arm-none-eabi-gcc' not found.
110
#            -2
111
#                 Error: include directory could not be resolved.
112
#
113
function retrieveGccIncludeDir {
114
  # retrieve binary path or link
115
  local binpath=$(which arm-none-eabi-gcc)
116
  local gccincpath=""
117
  if [ -z "$binpath" ]; then
118
    printError "command 'arm-none-eabi-gcc' not found\n"
119
    return -1
120
  else 
121

    
122
    # traverse any links
123
    while [ -L "$binpath" ]; do
124
      binpath=$(realpath $(dirname $binpath)/$(readlink $binpath))
125
    done
126
    printInfo "gcc-arm-none-eabi detected: $binpath\n"
127

    
128
    # return include path
129
    gccincpath=$(realpath $(dirname ${binpath})/../arm-none-eabi/include/)
130
    if [ ! -d "$gccincpath" ]; then
131
      printWarning "$gccincpath does not exist\n"
132
      return -2
133
    else
134
      eval $1="$gccincpath"
135
      return 0
136
    fi
137
  fi
138
}
139

    
140
### detect available configurations ############################################
141
# Detect all avalable configurations.
142
#
143
# usage:      detectConfigurations <configurationsarray>
144
# arguments:  <configurationsarray>
145
#                 Array variable to store all detected configurations to.
146
# return:     n/a
147
#
148
function detectConfigurations {
149
  local configsdir=$(realpath $(dirname $(realpath ${BASH_SOURCE[0]}))/../../../configurations)
150
  local configs_detected=()
151

    
152
  # detect all available modules (via directories)
153
  for dir in $(ls -d ${configsdir}/*/); do
154
    configs_detected[${#configs_detected[@]}]=$(basename $dir)
155
  done
156

    
157
  # set the output variable
158
  eval "$1=(${configs_detected[*]})"
159
}
160

    
161
### create project files for a single configuration ############################
162
# Create project files for all modules of a configuration.
163
#
164
# usage:      createConfigProjects <configurations> [-c|--config=<configuration>] [-p|--path=<path>] [--gcc=<path>] [-o|--out=<var>] [--gccout=<var>]
165
# arguments:  <configurations>
166
#                 Array containing all configurations available.
167
#             -c, --config <configuration>
168
#                 Name (folder name) of the configuration for which project files shall be generated.
169
#             -p, --path <path>
170
#                 Path where to create the project files.
171
#             --gcc=<path>
172
#                 Path to the GCC include directory.
173
#             -o, --out <var>
174
#                 Variable to store the path to.
175
#             --gccout=<var>
176
#                 Variable to store the path to the GCC include directory to.
177
#                 If this optional arguments is absent, ths function will ask for user input.
178
# return:     0
179
#                 No error or warning occurred.
180
#             1
181
#                 Aborted by user.
182
#             2
183
#                 The selected configuration does not contain any modules.
184
#             -1
185
#                 No configurations available.
186
#             -2
187
#                 The specified <configuration> could not be found.
188
#             -3
189
#                 Parsing the project for the specified configuration failed.
190
#             -4
191
#                 Missing dependencies.
192
#
193
function createConfigProjects {
194
  local userdir=$(pwd)
195
  local configsdir=$(realpath $(dirname $(realpath ${BASH_SOURCE[0]}))/../../../configurations)
196
  local configs=("${!1}")
197
  local config=""
198
  local configidx=""
199
  local projectsdir=""
200
  local gccincludedir=""
201
  local outvar=""
202
  local gccoutvar=""
203

    
204
  # check dependencies
205
  checkCommands make
206
  if [ $? -ne 0 ]; then
207
    printError "Missing dependencies detected.\n"
208
    return -4
209
  fi
210

    
211
  # parse arguments
212
  local otherargs=()
213
  while [ $# -gt 0 ]; do
214
    if ( parseIsOption $1 ); then
215
      case "$1" in
216
        -c=*|--config=*)
217
          config="${1#*=}"; shift 1;;
218
        -c|--config)
219
          config="$2"; shift 2;;
220
        -p=*|--path=*)
221
          projectsdir=$(realpath "${1#*=}"); shift 1;;
222
        -p|--path)
223
          projectsdir=$(realpath "$2"); shift 2;;
224
        --gcc=*)
225
          gccincludedir=$(realpath "${1#*=}"); shift 1;;
226
        --gcc)
227
          gccincludedir=$(realpath "$2"); shift 2;;
228
        -o=*|--out=*)
229
          outvar=${1#*=}; shift 1;;
230
        -o|--out)
231
          outvar=$2; shift 2;;
232
        --gccout=*)
233
          gccoutvar=$(realpath "${1#*=}"); shift 1;;
234
        --gccout)
235
          gccoutvar=$(realpath "$2"); shift 2;;
236
        *)
237
          printError "invalid option: $1\n"; shift 1;;
238
      esac
239
    else
240
      otherargs+=("$1")
241
      shift 1
242
    fi
243
  done
244

    
245
  # sanity check for the configs variable
246
  if [ -z "${configs[*]}" ]; then
247
    printError "no configurations available\n"
248
    return -1
249
  fi
250

    
251
  # select configuration
252
  if [ -z $config ]; then
253
    # list all available configurations
254
    printInfo "choose a configuration or type 'A' to abort:\n"
255
    for (( idx=0; idx<${#configs[@]}; ++idx )); do
256
      printf "%4u: %s\n" $(($idx + 1)) "${configs[$idx]}"
257
    done
258
    # read user input
259
    printLog "read user selection\n"
260
    local userinput=""
261
    while [[ ! "$userinput" =~ ^[0-9]+$ ]] || [ ! "$userinput" -gt 0 ] || [ ! "$userinput" -le ${#configs[@]} ] && [[ ! "$userinput" =~ ^[Aa]$ ]]; do
262
      read -p "your selection: " -e userinput
263
      printLog "user selection: $userinput\n"
264
      if [[ ! "$userinput" =~ ^[0-9]+$ ]] || [ ! "$userinput" -gt 0 ] || [ ! "$userinput" -le ${#configs[@]} ] && [[ ! "$userinput" =~ ^[Aa]$ ]]; then
265
        printWarning "Please enter an integer between 1 and ${#configs[@]} or 'A' to abort.\n"
266
      fi
267
    done
268
    if [[ "$userinput" =~ ^[Aa]$ ]]; then
269
      printWarning "aborted by user\n"
270
      return 1
271
    fi
272
    # store selection
273
    configidx=$(($userinput - 1))
274
    config="${configs[$configidx]}"
275
    printf "\n"
276
  else
277
    # search all configurations for the selected one
278
    for (( idx=0; idx<${#configs[@]}; ++idx )); do
279
      if [ "${configs[$idx]}" = "$config" ]; then
280
        configidx=$idx
281
        break
282
      fi
283
    done
284
    # error if the configurations could not be found
285
    if [ -z $configidx ]; then
286
      printError "configuration ($config) not available\n"
287
      return -2
288
    fi
289
  fi
290

    
291
  # retrieve modules in the configuration
292
  local modules=()
293
  if [ -d ${configsdir}/${config}/modules ]; then
294
    for dir in $(ls -d ${configsdir}/${config}/modules/*/); do
295
      modules[${#modules[@]}]=$(basename $dir)
296
    done
297
    if [ ${#modules[@]} -eq 0 ]; then
298
      printWarning "configuration ${config} does not contain any modules\n"
299
      return 2
300
    fi
301
  else
302
    printWarning "'module/' folder does not exist in configuration ${config}\n"
303
    return 2
304
  fi
305

    
306
  # read absolute project directory if required
307
  if [ -z "$projectsdir" ]; then
308
    getProjectsDir projectsdir
309
    printf "\n"
310
  fi
311

    
312
  # check for existing project files
313
  local projectfiles=""
314
  for module in ${modules[@]}; do
315
    projectfiles+="$(find ${projectsdir} -maxdepth 1 -type f | grep -E "${config}_${module}\.(includes|files|config|creator)$")"
316
  done
317
  IFS=$'\n'; projectfiles=($projectfiles); unset IFS
318
  if [ ! -z "${projectfiles[*]}" ]; then
319
    printWarning "The following files will be overwritten:\n"
320
    for pfile in ${projectfiles[@]}; do
321
      printWarning "\t$(basename $pfile)\n"
322
    done
323
    local userinput=""
324
    printInfo "Continue and overwrite? [y/n]\n"
325
    readUserInput "YyNn" userinput
326
    case "$userinput" in
327
      Y|y)
328
        ;;
329
      N|n)
330
        printWarning "Project generation for ${config} configuration aborted by user\n"
331
        return 1
332
        ;;
333
      *)
334
        printError "unexpected input: ${userinput}\n"; return -999;;
335
    esac
336
    printf "\n"
337
  fi
338

    
339
  # print message
340
  printInfo "generating QtCreator project files for the $config configuration...\n"
341

    
342
  # retrieve absolute GCC include path
343
  if [ -z "$gccincludedir" ]; then
344
    retrieveGccIncludeDir gccincludedir
345
  fi
346

    
347
  # change to project directory
348
  cd "$projectsdir"
349

    
350
  # create project files for each module of the selected configuration
351
  for module in ${modules[@]}; do
352
    # run make, but only run the GCC preprocessor and produce no binaries
353
    local sourcefiles=()
354
    local sourcefile=""
355
    local parse_state="WAIT_FOR_INCLUDE_COMPILE_MAKE"
356
    local makedirs=()
357
    # capture all output from make and GCC and append the return value of make as last line
358
    printInfo "processing module ${module} (this may take a while)...\n"
359
    local rawout=$(make --directory ${configsdir}/${config}/modules/${module} --always-make USE_OPT="-v -E -H" USE_VERBOSE_COMPILE="no" OUTFILES="" 2>&1 && echo $?)
360
    # check whether the make call was successfull
361
    if [[ $(echo "${rawout}" | tail -n 1) != "0" ]]; then
362
      printError "executing 'make' in configuration directory failed\n"
363
      cd "$userdir"
364
      return -3
365
    else
366
      # cleanup
367
      make --directory ${configsdir}/${config}/modules/${module} clean &>/dev/null
368
    fi
369
    # extract file names from raw output
370
    IFS=$'\n'; rawout=($rawout); unset IFS
371
    for line in "${rawout[@]}"; do
372
      case $parse_state in
373
        WAIT_FOR_INCLUDE_COMPILE_MAKE)
374
          # lines stating include files look like:
375
          # ... <../relative/path/to/file>
376
          if [[ "$line" =~ ^\.+[[:blank:]].+\..+$ ]]; then
377
            sourcefile=${line##* }
378
            if [[ ! "$sourcefile" =~ ^/ ]]; then
379
              sourcefile=$(realpath ${makedirs[-1]}/${sourcefile})
380
            fi
381
            sourcefiles[${#sourcefiles[@]}]="$sourcefile"
382
          # whenever the next source file is processed, a message appears like:
383
          # Compiling <filename>
384
          elif [[ "$line" =~ ^Compiling[[:blank:]](.+\..+)$ ]]; then
385
            printf "."
386
            sourcefile=${BASH_REMATCH[1]}
387
            parse_state="WAIT_FOR_COMPILERCALL"
388
          # if make is called again in another directory, a message appears like:
389
          # make[1]: Entering directory 'directory'
390
          elif [[ "$line" =~ ^make(\[[0-9]+\])?:\ Entering\ directory\ \'.+\'$ ]]; then
391
            makedirs+=($(echo "$line" | (cut -d "'" -f 2)))
392
          # if make is leaving a directory, a message appears like:
393
          # make[1]: Leaving directory 'directory'
394
          elif [[ "$line" =~ ^make(\[[0-9]+\])?:\ Leaving\ directory\ \'.+\'$ ]]; then
395
            unset makedirs[-1]
396
          fi;;
397
        WAIT_FOR_COMPILERCALL)
398
          # wait for the actual call of the compiler to retrieve the full path to the source file
399
          if [[ "$line" == *${sourcefile}* ]]; then
400
            line="${line%%${sourcefile}*}${sourcefile}"
401
            line="${line##* }"
402
            if [[ "$line" =~ ^/ ]]; then
403
              # aboslute path
404
              sourcefile=$line
405
            else
406
              # relative path
407
              sourcefile=$(realpath ${makedirs[-1]}/${line##* })
408
            fi
409
            sourcefiles[${#sourcefiles[@]}]="$sourcefile"
410
            parse_state="WAIT_FOR_INCLUDE_COMPILE_MAKE"
411
          fi;;
412
      esac
413
    done
414
    unset rawout
415
    printf "\n"
416
    # sort and remove duplicates
417
    IFS=$'\n'; sourcefiles=($(sort --unique <<< "${sourcefiles[*]}")); unset IFS
418

    
419
    # extract include paths
420
    local includes=()
421
    for source in ${sourcefiles[*]}; do
422
      includes[${#includes[@]}]="$(dirname ${source})"
423
    done
424
    # sort and remove duplicates
425
    IFS=$'\n'; includes=($(sort --unique <<< "${includes[*]}")); unset IFS
426

    
427
    # generate the .incldues file, containing all include paths
428
    echo "" > ${projectsdir}/${config}_${module}.includes
429
    for inc in ${includes[*]}; do
430
      echo "$inc" >> ${projectsdir}/${config}_${module}.includes
431
    done
432
    # generate the .files file, containing all source files
433
    echo "" > ${projectsdir}/${config}_${module}.files
434
    for source in ${sourcefiles[*]}; do
435
      # skip GCC files
436
      if [[ ! "$source" =~ .*/gcc.* ]]; then
437
        echo "$source" >> ${projectsdir}/${config}_${module}.files
438
      fi
439
    done
440
    # generate a default project configuration file if it doesn't exits yet
441
    if [ ! -f ${projectsdir}/${config}_${module}.config ]; then
442
      echo "// Add predefined macros for your project here. For example:" > ${projectsdir}/${config}_${module}.config
443
      echo "// #define YOUR_CONFIGURATION belongs here" >> ${projectsdir}/${config}_${module}.config
444
    fi
445
    # generate a default .creator file if it doesn't exist yet
446
    if [ ! -f ${projectsdir}/${config}_${module}.creator ]; then
447
      echo "[general]" > ${projectsdir}/${config}_${module}.creator
448
    fi
449
  done
450

    
451
  # go back to user directory
452
  cd $userdir
453

    
454
  # fill the output variables
455
  if [ ! -z "$outvar" ]; then
456
    eval $outvar="$projectsdir"
457
  fi
458
  if [ ! -z "$gccoutvar" ]; then
459
    eval $gccoutvar="$gccincludedir"
460
  fi
461

    
462
  return 0
463
}
464

    
465
### create project files for all configurations ################################
466
# Create project files for all configurations.
467
#
468
# usage:      createAllProjects <configurations> [-p|--path=<path>] [--gcc=<path>] [-o|--out=<var>] [--gccout=<var>]
469
# arguments:  <configurations>
470
#                 Array containing all configurations available.
471
#             -p, --path <path>
472
#                 Path where to create the project files.
473
#             --gcc=<path>
474
#                 Path to the GCC include directory.
475
#             -o, --out <var>
476
#                 Variable to store the path to.
477
#             --gccout=<var>
478
#                 Variable to store the path to the GCC include directory to.
479
#                 If this optional arguments is absent, ths function will ask for user input.
480
# return:     0
481
#                 No error or warning occurred.
482
#             1
483
#                 Aborted by user.
484
#             -1
485
#                 No configurations available.
486
#
487
function createAllProjects {
488
  local configs=("${!1}")
489
  local projectsdir=""
490
  local gccincludedir=""
491
  local outvar=""
492
  local gccoutvar=""
493

    
494
  # parse arguments
495
  local otherargs=()
496
  while [ $# -gt 0 ]; do
497
    if ( parseIsOption $1 ); then
498
      case "$1" in
499
        -p=*|--path=*)
500
          projectsdir=$(realpath "${1#*=}"); shift 1;;
501
        -p|--path)
502
          projectsdir=$(realpath "$2"); shift 2;;
503
        --gcc=*)
504
          gccincludedir=$(realpath "${1#*=}"); shift 1;;
505
        --gcc)
506
          gccincludedir=$(realpath "$2"); shift 2;;
507
        -o=*|--out=*)
508
          outvar=${1#*=}; shift 1;;
509
        -o|--out)
510
          outvar=$2; shift 2;;
511
        --gccout=*)
512
          gccoutvar=$(realpath "${1#*=}"); shift 1;;
513
        --gccout)
514
          gccoutvar=$(realpath "$2"); shift 2;;
515
        *)
516
          printError "invalid option: $1\n"; shift 1;;
517
      esac
518
    else
519
      otherargs+=("$1")
520
      shift 1
521
    fi
522
  done
523

    
524
  # sanity check for the configurations variable
525
  if [ -z "${configs[*]}" ]; then
526
    printError "no configurations available\n"
527
    return -1
528
  fi
529

    
530
  # read absolute project directory if required
531
  if [ -z "$projectsdir" ]; then
532
    getProjectsDir projectsdir
533
  fi
534

    
535
  # check for existing project files
536
  local projectfiles=""
537
  for config in ${configs[@]}; do
538
    for module in ${modules[@]}; do
539
      projectfiles+="$(find ${projectsdir} -maxdepth 1 -type f | grep -E "${config}_${module}\.(includes|files|config|creator)$")"
540
    done
541
  done
542
  IFS=$'\n'; projectfiles=($projectfiles); unset IFS
543
  if [ ! -z "${projectfiles[*]}" ]; then
544
    printWarning "The following files will be removed:\n"
545
    for pfile in ${projectfiles[@]}; do
546
      printWarning "\t$(basename $pfile)\n"
547
    done
548
    local userinput=""
549
    printInfo "Continue and overwrite? [y/n]\n"
550
    readUserInput "YyNn" userinput
551
    case "${userinput}" in
552
      Y|y)
553
        for pfile in ${projectfiles[*]}; do
554
          rm "$pfile"
555
        done
556
        ;;
557
      N|n)
558
        printWarning "Project generation aborted by user\n"
559
        return 1
560
        ;;
561
      *)
562
        printError "unexpected input: ${userinput}\n"
563
        return 999
564
        ;;
565
    esac
566
  fi
567

    
568
  # print message
569
  printf "\n"
570
  printInfo "generating QtCreator project files for all configurations...\n"
571

    
572
  # retrieve absolute GCC include path
573
  if [ -z "$gccincludedir" ]; then
574
    retrieveGccIncludeDir gccincludedir
575
  fi
576

    
577
  # iterate over all configurations
578
  local retval=1
579
  for config in ${configs[@]}; do
580
    if [ $retval != 0 ]; then
581
      printf "\n"
582
    fi
583
    createConfigProjects configs[@] --config="$config" --path="$projectsdir" --gcc="$gccincludedir"
584
    retval=$?
585
  done
586

    
587
  return 0
588
}
589

    
590
### delete project files #######################################################
591
# Deletes all project files and optionally .user files, too.
592
#
593
# usage:      deleteProjects [-p|--path=<path>] [-c|--config=<configuration>] [-o|--out=<var>] [-w|-wipe]
594
# arguments:  -p, --path <path>
595
#                 Path where to delete the project files.
596
#             -c, --config <configuration>
597
#                 Configuration name for which the project files shall be deleted.
598
#             -o, --out <var>
599
#                 Variable to store the path to.
600
#             -w, --wipe
601
#                 Delete .user files as well.
602
# return:
603
#  -  0: no error
604
#
605
function deleteProjects {
606
  local config=""
607
  local projectsdir=""
608
  local outvar=""
609
  local wipe=false
610
  local files=""
611

    
612
  # parse arguments
613
  local otherargs=()
614
  while [ $# -gt 0 ]; do
615
    if ( parseIsOption $1 ); then
616
      case "$1" in
617
        -p=*|--path=*)
618
          projectsdir=$(realpath "${1#*=}"); shift 1;;
619
        -p|--path)
620
          projectsdir=$(realpath "$2"); shift 2;;
621
        -c=*|--config=*)
622
          config="${1#*=}"; shift 1;;
623
        -c|--config)
624
          config="${2}"; shift 2;;
625
        -o=*|--out=*)
626
          outvar=${1#*=}; shift 1;;
627
        -o|--out)
628
          outvar=$2; shift 2;;
629
        -w|--wipe)
630
          wipe=true; shift 1;;
631
        *)
632
          printError "invalid option: $1\n"; shift 1;;
633
      esac
634
    else
635
      otherargs+=("$1")
636
      shift 1
637
    fi
638
  done
639

    
640
  # read absolute project directory if required
641
  if [ -z "$projectsdir" ]; then
642
    getProjectsDir projectsdir
643
  fi
644

    
645
  # list all files to be deleted
646
  if [ -z "$config" ]; then
647
    if [ $wipe != true ]; then
648
      files=$(find "${projectsdir}" -maxdepth 1 -type f | grep -E "^.+\.(includes|files|config|creator|cflags|cxxflags)$")
649
    else
650
      files=$(find "${projectsdir}" -maxdepth 1 -type f | grep -E "^.+\.(includes|files|config|creator|cflags|cxxflags|creator(\.user(\..+)?)?)$")
651
    fi
652
  else
653
    if [ $wipe != true ]; then
654
      files=$(find "${projectsdir}" -maxdepth 1 -type f | grep -E "^${config}_.+\.(includes|files|config|creator|cflags|cxxflags)$")
655
    else
656
      files=$(find "${projectsdir}" -maxdepth 1 -type f | grep -E "^${config}_.+\.(includes|files|config|creator|cflags|cxxflags|creator(\.user(\..+)?)?)$")
657
    fi
658
  fi
659
  if [ ! -z "$files" ]; then
660
    printInfo "Deleting the following files:\n"
661
    while read line; do
662
      printInfo "\t$(basename ${line})\n"
663
      rm ${line} 2>&1 | tee -a $LOG_FILE
664
    done <<< "${files}"
665
  else
666
    printInfo "No project files found\n"
667
  fi
668

    
669
  # store the path to the output variable, if required
670
  if [ ! -z "$outvar" ]; then
671
    eval $outvar="$projectsdir"
672
  fi
673

    
674
  return 0
675
}
676

    
677
### main function of this script ###############################################
678
# Creates, deletes and wipes QtCreator project files.
679
#
680
# usage:      see function printHelp
681
# arguments:  see function printHelp
682
# return:     0
683
#                 No error or warning ocurred.
684
#
685
function main {
686
# print welcome/info text if not suppressed
687
  if [[ $@ != *"--noinfo"* ]]; then
688
    printWelcomeText
689
  else
690
    printf "######################################################################\n"
691
  fi
692
  printf "\n"
693

    
694
  # if --help or -h was specified, print the help text and exit
695
  if [[ $@ == *"--help"* || $@ == *"-h"* ]]; then
696
    printHelp
697
    printf "\n"
698
    quitScript
699
  fi
700

    
701
  # set log file if specified
702
  if [[ $@ == *"--log"* ]] || [[ $@ == *"--LOG"* ]]; then
703
    # get the parameter (file name)
704
    local cmdidx=1
705
    while [[ ! "${!cmdidx}" = "--log"* ]] && [[ ! "${!cmdidx}" = "--LOG"* ]]; do
706
      cmdidx=$[cmdidx + 1]
707
    done
708
    local cmd="${!cmdidx}"
709
    local logfile=""
710
    if [[ "$cmd" = "--log="* ]] || [[ "$cmd" = "--LOG="* ]]; then
711
      logfile=${cmd#*=}
712
    else
713
      local filenameidx=$((cmdidx + 1))
714
      logfile="${!filenameidx}"
715
    fi
716
    # optionally force silent appending
717
    if [[ "$cmd" = "--LOG"* ]]; then
718
      setLogFile --option=c --quiet "$logfile" LOG_FILE
719
    else
720
      setLogFile "$logfile" LOG_FILE
721
      printf "\n"
722
    fi
723
  fi
724
  # log script name
725
  printLog "this is $(realpath ${BASH_SOURCE[0]})\n"
726

    
727
  # detect available configurations and inform user
728
  local configurations=()
729
  detectConfigurations configurations
730
  case "${#configurations[@]}" in
731
    0)
732
      printInfo "no configuration has been detected\n";;
733
    1)
734
      printInfo "1 configuration has been detected:\n";;
735
    *)
736
      printInfo "${#configurations[@]} configurations have been detected:\n";;
737
  esac
738
  for (( idx=0; idx<${#configurations[@]}; ++idx )); do
739
    printInfo "  - ${configurations[$idx]}\n"
740
  done
741
  printf "\n"
742

    
743
  # parse arguments
744
  local otherargs=()
745
  while [ $# -gt 0 ]; do
746
    if ( parseIsOption $1 ); then
747
      case "$1" in
748
        -h|--help) # already handled; ignore
749
          shift 1;;
750
        -p=*|--project=*)
751
          createConfigProjects configurations[@] --configuration="${1#*=}"; printf "\n"; shift 1;;
752
        -p|--project)
753
          createConfigProjects configurations[@] --configuration="${2}"; printf "\n"; shift 2;;
754
        -a|--all)
755
          createAllProjects configurations[@]; shift 1;;
756
        -c|--clean)
757
          deleteProjects; printf "\n"; shift 1;;
758
        -w|--wipe)
759
          deleteProjects --wipe; printf "\n"; shift 1;;
760
        -q|--quit)
761
          quitScript; shift 1;;
762
        --log=*|--LOG=*) # already handled; ignore
763
          shift 1;;
764
        --log|--LOG) # already handled; ignore
765
          shift 2;;
766
        --noinfo) # already handled; ignore
767
          shift 1;;
768
        *)
769
          printError "invalid option: $1\n"; shift 1;;
770
      esac
771
    else
772
      otherargs+=("$1")
773
      shift 1
774
    fi
775
  done
776

    
777
  # interactive menu
778
  while ( true ); do
779
    # main menu info prompt and selection
780
    printInfo "QtCreator setup main menu\n"
781
    printf "Please select one of the following actions:\n"
782
    printf "  [P] - create projects for a single configuration\n"
783
    printf "  [A] - create projects for all configurations\n"
784
    printf "  [C] - clean project files\n"
785
    printf "  [W] - wipe project and .user files\n"
786
    printf "  [Q] - quit this setup\n"
787
    local userinput=""
788
    readUserInput "PpAaCcWwQq" userinput
789
    printf "\n"
790

    
791
    # evaluate user selection
792
    case "$userinput" in
793
      P|p)
794
        createConfigProjects configurations[@]; printf "\n";;
795
      A|a)
796
        createAllProjects configurations[@]; printf "\n";;
797
      C|c)
798
        deleteProjects; printf "\n";;
799
      W|w)
800
        deleteProjects --wipe; printf "\n";;
801
      Q|q)
802
        quitScript;;
803
      *) # sanity check (exit with error)
804
        printError "unexpected argument: $userinput\n";;
805
    esac
806
  done
807

    
808
  exit 0
809
}
810

    
811
################################################################################
812
# SCRIPT ENTRY POINT                                                           #
813
################################################################################
814

    
815
main "$@"
816