123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- #!/usr/bin/env bash
- #
- # Usage:
- #
- # build_example -b|--base=<path> - Configurations root folder (e.g., ./.pio/build-BRANCH)
- # -c|--config=<rel> - Sub-path of the configs to build (within config/examples)
- # [-n|--index=N] - Which environment to build, by index (Based on pins.h comments)
- # [-m|--many] - Build all the board's environments listed in pins.h
- # [-e|--export=N] - Use CONFIG_EXPORT N to export the config to the export location
- # [-a|--archive] - Archive the build (to the export location)
- # [-o|--output] - Redirect export / archiving to another location
- # (By default export to origin config folder)
- # [-f|--nofail] - Don't stop on a failed build
- # [-w|--nowarn] - Suppress warnings with extra config options
- # [-r|--reveal] - Reveal the config/export folder after the build
- # [-h|--help] - Print usage and exit
- # [--allow] - Allow this script to run standalone
- #
- usage() { echo "Usage:
- build_example -b|--base=<path> - Configurations root folder (e.g., ./.pio/build-BRANCH)
- -c|--config=<rel> - Sub-path of the configs to build (within config/examples)
- [-n|--index=N] - Which environment to build, by index (Based on pins.h comments)
- [-m|--many] - Build all the board's environments listed in pins.h
- [-e|--export=N] - Use CONFIG_EXPORT N to export the config to the export location
- [-a|--archive] - Archive the build (to the export location)
- [-o|--output] - Redirect export / archiving to another location
- (By default export to origin config folder)
- [-f|--nofail] - Don't stop on a failed build
- [-w|--nowarn] - Suppress warnings with extra config options
- [-r|--reveal] - Reveal the config/export folder after the build
- [-h|--help] - Print usage and exit
- [--allow] - Allow this script to run standalone
- "
- }
- HERE=`dirname $0`
- PATH="$HERE:$PATH"
- . mfutil
- annc() { echo -e "\033[0;32m$1\033[0m" ; }
- alrt() { echo -e "\033[0;31m$1\033[0m" ; }
- # Get arguments
- BUILD=./.pio/build
- CLEANER=
- ALLOW=
- ARCHIVE=
- BASE=
- CONFIG=
- REVEAL=
- EXPNUM=
- NOFAIL=
- OUTBASE=
- BUILDINDEX=1
- MANY=
- while getopts 'ab:c:e:fhmn:o:r-:' OFLAG; do
- case "${OFLAG}" in
- a) ARCHIVE=1 ;;
- b) BASE="${OPTARG%/}" ;;
- c) CONFIG="${OPTARG%/}" ;;
- e) EXPNUM="$OPTARG" ;;
- f) NOFAIL=1 ;;
- h) EXIT_USAGE=1 ; break ;;
- m) MANY=1 ;;
- n) BUILDINDEX="$OPTARG" ;;
- o) OUTBASE="${OPTARG%/}" ;;
- r) REVEAL=1 ;;
- -) ONAM="${OPTARG%%=*}" ; OVAL="${OPTARG#*=}"
- case "$ONAM" in
- archive) ARCHIVE=1 ;;
- allow) ALLOW=1 ;;
- base) BASE="${OVAL%/}" ;;
- config) CONFIG="${OVAL%/}" ;;
- many) MANY=1 ;;
- index) BUILDINDEX="$OVAL" ;;
- export) EXPNUM="$OVAL" ;;
- output) OUTBASE="${OVAL%/}" ;;
- help) EXIT_USAGE=1 ; break ;;
- nofail) NOFAIL=1 ;;
- reveal) REVEAL=1 ;;
- *) EXIT_USAGE=2 ; echo "$SELF: unrecognized option \`--$ONAM'" ; break ;;
- esac
- ;;
- *) EXIT_USAGE=2 ; break ;;
- esac
- done
- shift $((OPTIND - 1))
- # Must be called from another script (or with --allow)
- [[ $ALLOW || $SHLVL -gt 2 ]] || { echo "Don't call this script directly, use build_all_examples instead." ; exit 1 ; }
- # Exit with helpful usage information
- ((EXIT_USAGE)) && { usage ; let EXIT_USAGE-- ; exit $EXIT_USAGE ; }
- # -b|--base and -c|--config are required
- [[ -z $BASE ]] && { echo "-b|--base is required" ; exit 1 ; }
- [[ -z $CONFIG ]] && { echo "-c|--config is required" ; exit 1 ; }
- # Expand ~ to $HOME in provided arguments
- BASE=${BASE/#\~/$HOME}
- CONFIG=${CONFIG/#\~/$HOME}
- # Make sure the examples exist
- SUB1="$BASE/config/examples"
- [[ -d "$SUB1" ]] || { echo "-b|--base $BASE doesn't contain config/examples" ; exit 1 ; }
- # Make sure the specific config folder exists
- SUB="$SUB1/$CONFIG"
- [[ -d "$SUB" ]] || { echo "-c|--config $CONFIG doesn't exist" ; exit 1 ; }
- # ...and contains Configuration.h or Configuration_adv.h
- [[ -f "$SUB"/Configuration.h || -f "$SUB"/Configuration_adv.h ]] || { echo "No configuration files found in $SUB" ; exit 1 ; }
- # Get the location for exports and archives
- if [[ -n $OUTBASE ]]; then
- ARCSUB="${OUTBASE/#\~/$HOME}/$CONFIG"
- mkdir -p "$ARCSUB"
- else
- ARCSUB="$SUB"
- fi
- # Delete any config files from previous builds
- rm -f Marlin/_Bootscreen.h Marlin/_Statusscreen.h
- # Copy configurations into the Marlin folder
- echo "Getting configuration files from $SUB"
- cp "$BASE"/config/default/*.h Marlin/
- cp "$SUB"/*.h Marlin/
- rm -f Marlin/Config.h Marlin/Config-export.h
- set -e
- # Strip #error lines from Configuration.h using
- awk 'NR < 20 || NR > 30 || !/#error/' Marlin/Configuration.h > Marlin/Configuration.h~
- mv Marlin/Configuration.h~ Marlin/Configuration.h
- # Hide several warnings when not exporting
- [[ -z $EXPNUM ]] && CLEANER=1
- # Suppress fatal warnings
- if ((CLEANER)); then
- opt_add NO_CONTROLLER_CUSTOM_WIRING_WARNING
- opt_add NO_AUTO_ASSIGN_WARNING
- opt_add NO_CREALITY_DRIVER_WARNING
- opt_add DIAG_JUMPERS_REMOVED
- opt_add DIAG_PINS_REMOVED
- opt_add NO_MK3_FAN_PINS_WARNING
- opt_add NO_USER_FEEDBACK_WARNING
- opt_add NO_Z_SAFE_HOMING_WARNING
- opt_add NO_LCD_CONTRAST_WARNING
- opt_add NO_MICROPROBE_WARNING
- opt_add NO_CONFIGURATION_EMBEDDING_WARNING
- opt_add NO_HOMING_CURRENT_WARNING
- fi
- # Possible exported file names (in the build folder)
- ENAME=("-name" "marlin_config.json" \
- "-o" "-name" "config.ini" \
- "-o" "-name" "schema.json" \
- "-o" "-name" "schema.yml")
- # Possible built firmware names (in the build folder)
- BNAME=("-name" "firmware*.hex" \
- "-o" "-name" "firmware*.bin" \
- "-o" "-name" "project*.bin" \
- "-o" "-name" "Robin*.bin" \
- "-o" "-name" "main_*.bin" \
- "-o" "-name" "MarlinSimulator*")
- mkdir -p "$BUILD"
- # If EXPNUM is set then apply to the config before build
- if [[ $EXPNUM ]]; then
- opt_set CONFIG_EXPORT $EXPNUM
- # Clean up old exports
- find "$BUILD" -type f \( "${ENAME[@]}" \) -exec rm "{}" \;
- fi
- ((ARCHIVE)) && find "$BUILD" -type f \( "${BNAME[@]}" \) -exec rm "{}" \;
- echo "Building example $CONFIG..."
- # If doing many builds get a list of all environment names,
- # which also gives us the number of environments.
- if ((MANY)); then
- ENVLIST=$(mfenvs) # BOARD_NAME_STRING (1234): [ env1 env2 env3 ... ]
- ENVLIST=${ENVLIST##*: [ }
- ENVARRAY=(${ENVLIST% ]})
- ENVCOUNT=${#ENVARRAY[*]}
- ((ENVCOUNT)) || { alrt "mfenvs failed for this board." ; exit 1 ; }
- echo "Found $ENVCOUNT environment(s): ${ENVARRAY[*]}"
- fi
- # Run one or more builds based on --many
- # Build all from BUILDINDEX onward (usually 1) meaning ALL.
- # MANY with a BUILDINDEX may be useful for continuing an interrupted build.
- while ((1)); do
- set +e
- echo "Building example $CONFIG ($BUILDINDEX)..."
- # Run a build and record the error number
- mftest -s -a -n$BUILDINDEX ; ERR=$?
- # "Index out of range" can fail without an error
- ((MANY)) && ((ERR == 66)) && ERR=0 && break # "index out of range"
- set -e
- if [[ $ERR -gt 0 ]]; then
- alrt "Failed ($ERR)"
- # Error? For --nofail simply log. Otherwise return the error.
- if [[ -n $NOFAIL ]]; then
- date +"%F %T [FAIL] $CONFIG ($BUILDINDEX)" >>./.pio/error-log.txt
- else
- exit $ERR
- fi
- else
- annc "Success"
- # Copy exports back to the configs
- if [[ -n $EXPNUM ]]; then
- annc "Exporting $EXPNUM"
- [[ -f Marlin/Config-export.h ]] && { cp Marlin/Config-export.h "$ARCSUB"/Config.h ; }
- find "$BUILD" -type f \( "${ENAME[@]}" \) -exec cp "{}" "$ARCSUB" \;
- fi
- # When building many, create sub-folders for each build env name
- if [[ -n $MANY && $ENVCOUNT -gt 1 ]]; then
- ENV=${ENVARRAY[BUILDINDEX-1]}
- ARCENVSUB="$ARCSUB/$ENV"
- else
- ARCENVSUB="$ARCSUB"
- fi
- # Copy potential firmware files into the config folder
- # TODO: Consider firmware that needs an STM32F4_UPDATE folder.
- # Currently only BOARD_CREALITY_F401RE env:STM32F401RE_creality
- if ((ARCHIVE)); then
- annc "Archiving"
- find "$BUILD" -type f \( "${BNAME[@]}" \) -exec sh -c '
- ARCDIR="$1" ; CONFIG="$2" ; FILE="$3" ; shift 3
- NAME=${FILE##*/} ; SHRT=${NAME%.*} ; DIR=${FILE%/*}
- ZIPX=
- if [[ $CONFIG == *Simulator* ]]; then
- case $(uname | tr '[:upper:]' '[:lower:]') in
- darwin) SUB="macOS" ; ZIPX="-X" ;;
- *linux) SUB="Linux" ;;
- win*) SUB="Windows" ;;
- msys*) SUB="Windows" ;;
- cygwin*) SUB="Windows" ;;
- mingw*) SUB="Windows" ;;
- *) SUB='Unix' ;;
- esac
- ARCH=$(uname -m | tr '[:lower:]' '[:upper:]')
- ARCDIR="$ARCDIR/$SUB-$ARCH"
- fi
- mkdir -p "$ARCDIR"
- rm -f "$ARCDIR"/*.zip "$ARCDIR"/*.sha256.txt
- cd "$DIR"
- SHASUM=$(sha256sum "$NAME" | cut -d" " -f1)
- echo "$CONFIG\n$SHASUM" > "$ARCDIR/$NAME.sha256.txt"
- zip $ZIPX "$ARCDIR/$SHRT.zip" "$NAME" && rm "$NAME"
- cd - >/dev/null
- ' sh "$ARCENVSUB" "$CONFIG" {} +
- fi
- # Reveal the configs after the build, if requested
- ((REVEAL)) && { annc "Revealing $ARCENVSUB" ; open "$ARCENVSUB" ; }
- fi
- ((MANY)) || break # Only one build if not --many
- # Set up for the next build, if there is one
- ((++BUILDINDEX > ENVCOUNT)) && break
- done
- exit 0
|