build_example 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. #!/usr/bin/env bash
  2. #
  3. # Usage:
  4. #
  5. # build_example -b|--base=<path> - Configurations root folder (e.g., ./.pio/build-BRANCH)
  6. # -c|--config=<rel> - Sub-path of the configs to build (within config/examples)
  7. # [-n|--index=N] - Which environment to build, by index (Based on pins.h comments)
  8. # [-m|--many] - Build all the board's environments listed in pins.h
  9. # [-e|--export=N] - Use CONFIG_EXPORT N to export the config to the export location
  10. # [-a|--archive] - Archive the build (to the export location)
  11. # [-o|--output] - Redirect export / archiving to another location
  12. # (By default export to origin config folder)
  13. # [-f|--nofail] - Don't stop on a failed build
  14. # [-w|--nowarn] - Suppress warnings with extra config options
  15. # [-r|--reveal] - Reveal the config/export folder after the build
  16. # [-h|--help] - Print usage and exit
  17. # [--allow] - Allow this script to run standalone
  18. #
  19. usage() { echo "Usage:
  20. build_example -b|--base=<path> - Configurations root folder (e.g., ./.pio/build-BRANCH)
  21. -c|--config=<rel> - Sub-path of the configs to build (within config/examples)
  22. [-n|--index=N] - Which environment to build, by index (Based on pins.h comments)
  23. [-m|--many] - Build all the board's environments listed in pins.h
  24. [-e|--export=N] - Use CONFIG_EXPORT N to export the config to the export location
  25. [-a|--archive] - Archive the build (to the export location)
  26. [-o|--output] - Redirect export / archiving to another location
  27. (By default export to origin config folder)
  28. [-f|--nofail] - Don't stop on a failed build
  29. [-w|--nowarn] - Suppress warnings with extra config options
  30. [-r|--reveal] - Reveal the config/export folder after the build
  31. [-h|--help] - Print usage and exit
  32. [--allow] - Allow this script to run standalone
  33. "
  34. }
  35. HERE=`dirname $0`
  36. PATH="$HERE:$PATH"
  37. . mfutil
  38. annc() { echo -e "\033[0;32m$1\033[0m" ; }
  39. alrt() { echo -e "\033[0;31m$1\033[0m" ; }
  40. # Get arguments
  41. BUILD=./.pio/build
  42. CLEANER=
  43. ALLOW=
  44. ARCHIVE=
  45. BASE=
  46. CONFIG=
  47. REVEAL=
  48. EXPNUM=
  49. NOFAIL=
  50. OUTBASE=
  51. BUILDINDEX=1
  52. MANY=
  53. while getopts 'ab:c:e:fhmn:o:r-:' OFLAG; do
  54. case "${OFLAG}" in
  55. a) ARCHIVE=1 ;;
  56. b) BASE="${OPTARG%/}" ;;
  57. c) CONFIG="${OPTARG%/}" ;;
  58. e) EXPNUM="$OPTARG" ;;
  59. f) NOFAIL=1 ;;
  60. h) EXIT_USAGE=1 ; break ;;
  61. m) MANY=1 ;;
  62. n) BUILDINDEX="$OPTARG" ;;
  63. o) OUTBASE="${OPTARG%/}" ;;
  64. r) REVEAL=1 ;;
  65. -) ONAM="${OPTARG%%=*}" ; OVAL="${OPTARG#*=}"
  66. case "$ONAM" in
  67. archive) ARCHIVE=1 ;;
  68. allow) ALLOW=1 ;;
  69. base) BASE="${OVAL%/}" ;;
  70. config) CONFIG="${OVAL%/}" ;;
  71. many) MANY=1 ;;
  72. index) BUILDINDEX="$OVAL" ;;
  73. export) EXPNUM="$OVAL" ;;
  74. output) OUTBASE="${OVAL%/}" ;;
  75. help) EXIT_USAGE=1 ; break ;;
  76. nofail) NOFAIL=1 ;;
  77. reveal) REVEAL=1 ;;
  78. *) EXIT_USAGE=2 ; echo "$SELF: unrecognized option \`--$ONAM'" ; break ;;
  79. esac
  80. ;;
  81. *) EXIT_USAGE=2 ; break ;;
  82. esac
  83. done
  84. shift $((OPTIND - 1))
  85. # Must be called from another script (or with --allow)
  86. [[ $ALLOW || $SHLVL -gt 2 ]] || { echo "Don't call this script directly, use build_all_examples instead." ; exit 1 ; }
  87. # Exit with helpful usage information
  88. ((EXIT_USAGE)) && { usage ; let EXIT_USAGE-- ; exit $EXIT_USAGE ; }
  89. # -b|--base and -c|--config are required
  90. [[ -z $BASE ]] && { echo "-b|--base is required" ; exit 1 ; }
  91. [[ -z $CONFIG ]] && { echo "-c|--config is required" ; exit 1 ; }
  92. # Expand ~ to $HOME in provided arguments
  93. BASE=${BASE/#\~/$HOME}
  94. CONFIG=${CONFIG/#\~/$HOME}
  95. # Make sure the examples exist
  96. SUB1="$BASE/config/examples"
  97. [[ -d "$SUB1" ]] || { echo "-b|--base $BASE doesn't contain config/examples" ; exit 1 ; }
  98. # Make sure the specific config folder exists
  99. SUB="$SUB1/$CONFIG"
  100. [[ -d "$SUB" ]] || { echo "-c|--config $CONFIG doesn't exist" ; exit 1 ; }
  101. # ...and contains Configuration.h or Configuration_adv.h
  102. [[ -f "$SUB"/Configuration.h || -f "$SUB"/Configuration_adv.h ]] || { echo "No configuration files found in $SUB" ; exit 1 ; }
  103. # Get the location for exports and archives
  104. if [[ -n $OUTBASE ]]; then
  105. ARCSUB="${OUTBASE/#\~/$HOME}/$CONFIG"
  106. mkdir -p "$ARCSUB"
  107. else
  108. ARCSUB="$SUB"
  109. fi
  110. # Delete any config files from previous builds
  111. rm -f Marlin/_Bootscreen.h Marlin/_Statusscreen.h
  112. # Copy configurations into the Marlin folder
  113. echo "Getting configuration files from $SUB"
  114. cp "$BASE"/config/default/*.h Marlin/
  115. cp "$SUB"/*.h Marlin/
  116. rm -f Marlin/Config.h Marlin/Config-export.h
  117. set -e
  118. # Strip #error lines from Configuration.h using
  119. awk 'NR < 20 || NR > 30 || !/#error/' Marlin/Configuration.h > Marlin/Configuration.h~
  120. mv Marlin/Configuration.h~ Marlin/Configuration.h
  121. # Hide several warnings when not exporting
  122. [[ -z $EXPNUM ]] && CLEANER=1
  123. # Suppress fatal warnings
  124. if ((CLEANER)); then
  125. opt_add NO_CONTROLLER_CUSTOM_WIRING_WARNING
  126. opt_add NO_AUTO_ASSIGN_WARNING
  127. opt_add NO_CREALITY_DRIVER_WARNING
  128. opt_add DIAG_JUMPERS_REMOVED
  129. opt_add DIAG_PINS_REMOVED
  130. opt_add NO_MK3_FAN_PINS_WARNING
  131. opt_add NO_USER_FEEDBACK_WARNING
  132. opt_add NO_Z_SAFE_HOMING_WARNING
  133. opt_add NO_LCD_CONTRAST_WARNING
  134. opt_add NO_MICROPROBE_WARNING
  135. opt_add NO_CONFIGURATION_EMBEDDING_WARNING
  136. opt_add NO_HOMING_CURRENT_WARNING
  137. fi
  138. # Possible exported file names (in the build folder)
  139. ENAME=("-name" "marlin_config.json" \
  140. "-o" "-name" "config.ini" \
  141. "-o" "-name" "schema.json" \
  142. "-o" "-name" "schema.yml")
  143. # Possible built firmware names (in the build folder)
  144. BNAME=("-name" "firmware*.hex" \
  145. "-o" "-name" "firmware*.bin" \
  146. "-o" "-name" "project*.bin" \
  147. "-o" "-name" "Robin*.bin" \
  148. "-o" "-name" "main_*.bin" \
  149. "-o" "-name" "MarlinSimulator*")
  150. mkdir -p "$BUILD"
  151. # If EXPNUM is set then apply to the config before build
  152. if [[ $EXPNUM ]]; then
  153. opt_set CONFIG_EXPORT $EXPNUM
  154. # Clean up old exports
  155. find "$BUILD" -type f \( "${ENAME[@]}" \) -exec rm "{}" \;
  156. fi
  157. ((ARCHIVE)) && find "$BUILD" -type f \( "${BNAME[@]}" \) -exec rm "{}" \;
  158. echo "Building example $CONFIG..."
  159. # If doing many builds get a list of all environment names,
  160. # which also gives us the number of environments.
  161. if ((MANY)); then
  162. ENVLIST=$(mfenvs) # BOARD_NAME_STRING (1234): [ env1 env2 env3 ... ]
  163. ENVLIST=${ENVLIST##*: [ }
  164. ENVARRAY=(${ENVLIST% ]})
  165. ENVCOUNT=${#ENVARRAY[*]}
  166. ((ENVCOUNT)) || { alrt "mfenvs failed for this board." ; exit 1 ; }
  167. echo "Found $ENVCOUNT environment(s): ${ENVARRAY[*]}"
  168. fi
  169. # Run one or more builds based on --many
  170. # Build all from BUILDINDEX onward (usually 1) meaning ALL.
  171. # MANY with a BUILDINDEX may be useful for continuing an interrupted build.
  172. while ((1)); do
  173. set +e
  174. echo "Building example $CONFIG ($BUILDINDEX)..."
  175. # Run a build and record the error number
  176. mftest -s -a -n$BUILDINDEX ; ERR=$?
  177. # "Index out of range" can fail without an error
  178. ((MANY)) && ((ERR == 66)) && ERR=0 && break # "index out of range"
  179. set -e
  180. if [[ $ERR -gt 0 ]]; then
  181. alrt "Failed ($ERR)"
  182. # Error? For --nofail simply log. Otherwise return the error.
  183. if [[ -n $NOFAIL ]]; then
  184. date +"%F %T [FAIL] $CONFIG ($BUILDINDEX)" >>./.pio/error-log.txt
  185. else
  186. exit $ERR
  187. fi
  188. else
  189. annc "Success"
  190. # Copy exports back to the configs
  191. if [[ -n $EXPNUM ]]; then
  192. annc "Exporting $EXPNUM"
  193. [[ -f Marlin/Config-export.h ]] && { cp Marlin/Config-export.h "$ARCSUB"/Config.h ; }
  194. find "$BUILD" -type f \( "${ENAME[@]}" \) -exec cp "{}" "$ARCSUB" \;
  195. fi
  196. # When building many, create sub-folders for each build env name
  197. if [[ -n $MANY && $ENVCOUNT -gt 1 ]]; then
  198. ENV=${ENVARRAY[BUILDINDEX-1]}
  199. ARCENVSUB="$ARCSUB/$ENV"
  200. else
  201. ARCENVSUB="$ARCSUB"
  202. fi
  203. # Copy potential firmware files into the config folder
  204. # TODO: Consider firmware that needs an STM32F4_UPDATE folder.
  205. # Currently only BOARD_CREALITY_F401RE env:STM32F401RE_creality
  206. if ((ARCHIVE)); then
  207. annc "Archiving"
  208. find "$BUILD" -type f \( "${BNAME[@]}" \) -exec sh -c '
  209. ARCDIR="$1" ; CONFIG="$2" ; FILE="$3" ; shift 3
  210. NAME=${FILE##*/} ; SHRT=${NAME%.*} ; DIR=${FILE%/*}
  211. ZIPX=
  212. if [[ $CONFIG == *Simulator* ]]; then
  213. case $(uname | tr '[:upper:]' '[:lower:]') in
  214. darwin) SUB="macOS" ; ZIPX="-X" ;;
  215. *linux) SUB="Linux" ;;
  216. win*) SUB="Windows" ;;
  217. msys*) SUB="Windows" ;;
  218. cygwin*) SUB="Windows" ;;
  219. mingw*) SUB="Windows" ;;
  220. *) SUB='Unix' ;;
  221. esac
  222. ARCH=$(uname -m | tr '[:lower:]' '[:upper:]')
  223. ARCDIR="$ARCDIR/$SUB-$ARCH"
  224. fi
  225. mkdir -p "$ARCDIR"
  226. rm -f "$ARCDIR"/*.zip "$ARCDIR"/*.sha256.txt
  227. cd "$DIR"
  228. SHASUM=$(sha256sum "$NAME" | cut -d" " -f1)
  229. echo "$CONFIG\n$SHASUM" > "$ARCDIR/$NAME.sha256.txt"
  230. zip $ZIPX "$ARCDIR/$SHRT.zip" "$NAME" && rm "$NAME"
  231. cd - >/dev/null
  232. ' sh "$ARCENVSUB" "$CONFIG" {} +
  233. fi
  234. # Reveal the configs after the build, if requested
  235. ((REVEAL)) && { annc "Revealing $ARCENVSUB" ; open "$ARCENVSUB" ; }
  236. fi
  237. ((MANY)) || break # Only one build if not --many
  238. # Set up for the next build, if there is one
  239. ((++BUILDINDEX > ENVCOUNT)) && break
  240. done
  241. exit 0