Script to download & build Configurations (#20992)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
This commit is contained in:
		
							
								
								
									
										62
									
								
								buildroot/bin/build_all_examples
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										62
									
								
								buildroot/bin/build_all_examples
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| echo "This script will attempt to build Marlin for all known configurations." | ||||
| echo "In case of failure, the current configuration remains in your repository." | ||||
| echo "To revert to your current version, run 'git checkout -f'." | ||||
|  | ||||
| self=`basename "$0"` | ||||
| HERE=`dirname "$0"` | ||||
|  | ||||
| # Check dependencies | ||||
| which curl 1>/dev/null 2>&1 || { echo "curl not found, please install it"; exit ; } | ||||
| which git 1>/dev/null 2>&1 || { echo "git not found, please install it"; exit ; } | ||||
| if [ -z "$1" ]; then | ||||
|   echo "" | ||||
|   echo "ERROR: " | ||||
|   echo "  Expected parameter: $self base_branch [resume_point]" | ||||
|   echo "  with:" | ||||
|   echo "         base_branch              The branch in the Configuration repository to use" | ||||
|   echo "         resume_point             If not empty, resume building from this board" | ||||
|  | ||||
|   exit | ||||
| fi | ||||
|  | ||||
| # Check if called in the right folder | ||||
| if [ ! -e "Marlin/src" ]; then | ||||
|   echo "This script must be called from the root folder of a Marlin repository, please navigate to this folder and call:" | ||||
|   echo "buildroot/ci-check/$self $1" | ||||
|   exit | ||||
| fi | ||||
|  | ||||
| # Check if the current repository has unmerged changes | ||||
| if [ -z "$2" ]; then | ||||
|   git diff --quiet || { echo "Your current repository is not clean. Either commit your change or stash them, and re-run this script"; exit ; } | ||||
| else | ||||
|   echo "Resuming from $2" | ||||
| fi | ||||
|  | ||||
| TMPDIR=`mktemp -d` | ||||
|  | ||||
| # Ok, let's do our stuff now | ||||
| # First extract the current temporary folder | ||||
| echo "Fetching configuration repository" | ||||
| if [ ! -e "$TMPDIR/README.md" ]; then | ||||
|   git clone --single-branch --branch "$1" https://github.com/MarlinFirmware/Configurations.git "$TMPDIR" || { echo "Failed to clone the configuration repository"; exit ; } | ||||
|   rm -r $TMPDIR/.git | ||||
| fi | ||||
|  | ||||
| echo | ||||
| echo "Start building now..." | ||||
| echo "=====================" | ||||
| shopt -s nullglob | ||||
| for config in $TMPDIR/config/examples/*/; do | ||||
|   [ -d "${config}" ] || continue | ||||
|   base=`basename "$config"` | ||||
|   if [ ! -z "$2" ] && [ "$2" != "$base" ]; then | ||||
|     echo "Skipping $base..." | ||||
|     continue | ||||
|   fi | ||||
|   "$HERE/build_example" "internal" "$TMPDIR" "$base" || { echo "Failed to build $base"; exit ; } | ||||
| done | ||||
|  | ||||
| rm -r "$TMPDIR" | ||||
							
								
								
									
										35
									
								
								buildroot/bin/build_example
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										35
									
								
								buildroot/bin/build_example
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| if [ "$1" != "internal" ]; then | ||||
|   echo "Don't call this script directly, use build_all_examples instead." | ||||
|   exit 1 | ||||
| fi | ||||
|  | ||||
| SED=$(which gsed || which sed) | ||||
| HERE=`dirname "$0"` | ||||
|  | ||||
| echo "Testing $3:" | ||||
|  | ||||
| shopt -s nullglob | ||||
| for sub in find $2/config/examples/$3 -type d; do | ||||
|   [[ -d $sub ]] || continue | ||||
|   base=`basename "$sub"` | ||||
|  | ||||
|   if [[ ! -f $sub/Configuration.h ]] && [[ ! -f $sub/Configuration_adv.h ]]; then | ||||
|     echo "No configuration files found in $sub" | ||||
|     continue | ||||
|   fi | ||||
|  | ||||
|   echo "Getting configuration files from $sub" | ||||
|   cp "$2/config/default"/*.h    Marlin/ | ||||
|   cp "$sub"/Configuration.h     Marlin/ 2>/dev/null | ||||
|   cp "$sub"/Configuration_adv.h Marlin/ 2>/dev/null | ||||
|   cp "$sub"/_Bootscreen.h       Marlin/ 2>/dev/null | ||||
|   cp "$sub"/_Statusscreen.h     Marlin/ 2>/dev/null | ||||
|  | ||||
|   echo "Building the firmware now..." | ||||
|   echo "$HERE/mftest" -a || exit 1 | ||||
| done | ||||
|  | ||||
| echo "Success" | ||||
| exit 0 | ||||
							
								
								
									
										313
									
								
								buildroot/bin/mftest
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										313
									
								
								buildroot/bin/mftest
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,313 @@ | ||||
| #!/usr/bin/env bash | ||||
| # | ||||
| #  mftest                             Select a test to apply and build | ||||
| #  mftest -b [#]                      Build the auto-detected environment | ||||
| #  mftest -u [#]                      Upload the auto-detected environment | ||||
| #  mftest [name] [index] [-y]         Set config options and optionally build a test | ||||
| # | ||||
|  | ||||
| MFINFO=$(mfinfo) || exit 1 | ||||
| [[ -d Marlin/src ]] || { echo "Please 'cd' to the Marlin repo root." ; exit 1 ; } | ||||
|  | ||||
| perror() { echo -e "$0: \033[0;31m$1 -- $2\033[0m" ; } | ||||
| errout() { echo -e "\033[0;31m$1\033[0m" ; } | ||||
| bugout() { ((DEBUG)) && echo -e "\033[0;32m$1\033[0m" ; } | ||||
|  | ||||
| usage() { | ||||
|   echo " | ||||
| Usage: mftest [-t|--env=<env>] [-n|--num=<num>] [-m|--make] [-y|--build=<Y|n>] | ||||
|        mftest [-a|--autobuild] | ||||
|        mftest [-r|--rebuild] | ||||
|        mftest [-u|--autoupload] [-n|--num=<num>] | ||||
|  | ||||
| OPTIONS | ||||
|   -t --env         The environment of the test to apply / run. (As named in platformio.ini.) | ||||
|   -n --num         The index of the test to run. (In *-tests file order.) | ||||
|   -m --make        Use the make / Docker method for the build. | ||||
|   -y --build       Skip 'Do you want to build this test?' and assume YES. | ||||
|   -h --help        Print this help. | ||||
|   -a --autobuild   PIO Build using the MOTHERBOARD environment. | ||||
|   -u --autoupload  PIO Upload using the MOTHERBOARD environment. | ||||
|   -v --verbose     Extra output for debugging. | ||||
|  | ||||
| env shortcuts: tree due esp lin lpc|lpc8 lpc9 m128 m256|mega stm|f1 f4 f7 s6 teensy|t31|t32 t35|t36 t40|t41 | ||||
|  | ||||
| " | ||||
| } | ||||
|  | ||||
| TESTPATH=buildroot/tests | ||||
|  | ||||
| STATE_FILE=$( echo ./.pio/.mftestrc ) | ||||
| SED=$(which gsed || which sed) | ||||
|  | ||||
| shopt -s extglob nocasematch | ||||
|  | ||||
| # Matching patterns | ||||
| ISNUM='^[0-9]+$' | ||||
| ISCMD='^(restore|opt|exec|use|pins|env)_' | ||||
| ISEXEC='^exec_' | ||||
| ISCONT='\\ *$' | ||||
|  | ||||
| # Get environment, test number, etc. from the command | ||||
| TESTENV='-' | ||||
| CHOICE=0 | ||||
| DEBUG=0 | ||||
|  | ||||
| while getopts 'abhmruvyn:t:-:' OFLAG; do | ||||
|   case "${OFLAG}" in | ||||
|     a) AUTO_BUILD=1 ; bugout "Auto-Build target..." ;; | ||||
|     h) EXIT_USAGE=1 ;; | ||||
|     m) USE_MAKE=1 ; bugout "Using make with Docker..." ;; | ||||
|     n) case "$OPTARG" in | ||||
|          *[!0-9]*) perror "option requires a number" $OFLAG ; EXIT_USAGE=1 ;; | ||||
|                 *) CHOICE="$OPTARG" ; bugout "Got a number: $CHOICE" ;; | ||||
|        esac | ||||
|        ;; | ||||
|     r) REBUILD=1         ; bugout "Rebuilding previous..."    ;; | ||||
|     t) TESTENV="$OPTARG" ; bugout "Got a target: $TESTENV" ;; | ||||
|     u) AUTO_BUILD=2      ; bugout "Auto-Upload target..."  ;; | ||||
|     v) DEBUG=1           ; bugout "Debug ON" ;; | ||||
|     y) BUILD_YES='Y'     ; bugout "Build will initiate..."    ;; | ||||
|     -) IFS="=" read -r ONAM OVAL <<< "$OPTARG" | ||||
|        case "$ONAM" in | ||||
|          help) [[ -z "$OVAL" ]] || perror "option can't take value $OVAL" $ONAM ; EXIT_USAGE=1 ;; | ||||
|     autobuild) AUTO_BUILD=1 ; bugout "Auto-Build target..."  ;; | ||||
|    autoupload) AUTO_BUILD=2 ; bugout "Auto-Upload target..." ;; | ||||
|           env) case "$OVAL" in | ||||
|                  '') perror "option requires a value" $ONAM ; EXIT_USAGE=1 ;; | ||||
|                   *) TESTENV="$OVAL" ; bugout "Got a target: $TESTENV" ;; | ||||
|                esac | ||||
|                ;; | ||||
|           num) case "$OVAL" in | ||||
|                  [0-9]+) CHOICE="$OVAL" ; bugout "Got a number: $CHOICE" ;; | ||||
|                       *) perror "option requires a value" $ONAM ; EXIT_USAGE=1 ;; | ||||
|                esac | ||||
|                ;; | ||||
|       rebuild) REBUILD=1      ; bugout "Rebuilding previous..."    ;; | ||||
|          make) USE_MAKE=1     ; bugout "Using make with Docker..." ;; | ||||
| debug|verbose) DEBUG=1        ; bugout "Debug ON" ;; | ||||
|         build) case "$OVAL" in | ||||
|                  ''|y|yes) BUILD_YES='Y' ;; | ||||
|                      n|no) BUILD_YES='N' ;; | ||||
|                         *) perror "option value must be y, n, yes, or no" $ONAM ; EXIT_USAGE=1 ;; | ||||
|                esac | ||||
|                bugout "Build will initiate? ($BUILD_YES)" | ||||
|                ;; | ||||
|             *) perror "Unknown flag" "$OPTARG" ; EXIT_USAGE=1 ;; | ||||
|        esac | ||||
|        ;; | ||||
|   esac | ||||
| done | ||||
|  | ||||
| ((EXIT_USAGE)) && { usage ; exit 1 ; } | ||||
|  | ||||
| if ((REBUILD)); then | ||||
|   bugout "Rebuilding previous..." | ||||
|   # Build with the last-built env | ||||
|   [[ -f "$STATE_FILE" ]] || { errout "No previous (-r) build state found." ; exit 1 ; } | ||||
|   read TESTENV <"$STATE_FILE" | ||||
|   pio run -d . -e $TESTENV | ||||
|   exit | ||||
| fi | ||||
|  | ||||
| case $TESTENV in | ||||
|     tree) pio run -d . -e include_tree ; exit 1 ;; | ||||
|      due) TESTENV='DUE' ;; | ||||
|      esp) TESTENV='esp32' ;; | ||||
|     lin*) TESTENV='linux_native' ;; | ||||
| lp8|lpc8) TESTENV='LPC1768' ;; | ||||
| lp9|lpc9) TESTENV='LPC1769' ;; | ||||
|     m128) TESTENV='mega1280' ;; | ||||
|     m256) TESTENV='mega2560' ;; | ||||
|     mega) TESTENV='mega2560' ;; | ||||
|      stm) TESTENV='STM32F103RE' ;; | ||||
|       f1) TESTENV='STM32F103RE' ;; | ||||
|       f4) TESTENV='STM32F4' ;; | ||||
|       f7) TESTENV='STM32F7' ;; | ||||
|       s6) TESTENV='FYSETC_S6' ;; | ||||
|   teensy) TESTENV='teensy31' ;; | ||||
|      t31) TESTENV='teensy31' ;; | ||||
|      t32) TESTENV='teensy31' ;; | ||||
|      t35) TESTENV='teensy35' ;; | ||||
|      t36) TESTENV='teensy35' ;; | ||||
|      t40) TESTENV='teensy41' ;; | ||||
|      t41) TESTENV='teensy41' ;; | ||||
| [1-9][1-9]|[1-9]) TESTNUM=$TESTENV ; TESTENV=- ;; | ||||
| esac | ||||
|  | ||||
| if ((AUTO_BUILD)); then | ||||
|   # | ||||
|   # List environments that apply to the current MOTHERBOARD. | ||||
|   # | ||||
|   case $(uname | tr '[:upper:]' '[:lower:]') in | ||||
|     darwin) SYS='mac' ;; | ||||
|     *linux) SYS='lin' ;; | ||||
|       win*) SYS='win' ;; | ||||
|      msys*) SYS='win' ;; | ||||
|    cygwin*) SYS='win' ;; | ||||
|     mingw*) SYS='win' ;; | ||||
|          *) SYS='uni' ;; | ||||
|   esac | ||||
|   echo ; echo -n "Auto " ; ((AUTO_BUILD == 2)) && echo "Upload..." || echo "Build..." | ||||
|   MB=$( grep -E "^\s*#define MOTHERBOARD" Marlin/Configuration.h | awk '{ print $3 }' | $SED 's/BOARD_//' ) | ||||
|   [[ -z $MB ]] && { echo "Error - Can't read MOTHERBOARD setting." ; exit 1 ; } | ||||
|   BLINE=$( grep -E "define\s+BOARD_$MB\b" Marlin/src/core/boards.h ) | ||||
|   BNUM=$( $SED -E 's/^.+BOARD_[^ ]+ +([0-9]+).+$/\1/' <<<"$BLINE" ) | ||||
|   BDESC=$( $SED -E 's/^.+\/\/ *(.+)$/\1/' <<<"$BLINE" ) | ||||
|   [[ -z $BNUM ]] && { echo "Error - Can't find $MB in boards list." ; exit 1 ; } | ||||
|   ENVS=( $( grep -EA1 "MB\(.*\b$MB\b.*\)" Marlin/src/pins/pins.h | grep -E "#include.+//.+(env|$SYS):[^ ]+" | grep -oE "(env|$SYS):[^ ]+" | $SED -E "s/(env|$SYS)://" ) ) | ||||
|   [[ -z $ENVS ]] && { errout "Error - Can't find target(s) for $MB ($BNUM)." ; exit 1 ; } | ||||
|   ECOUNT=${#ENVS[*]} | ||||
|  | ||||
|   if [[ $ECOUNT == 1 ]]; then | ||||
|     TARGET=$ENVS | ||||
|   else | ||||
|     if [[ $CHOICE == 0 ]]; then | ||||
|       # List env names and numbers. Get selection. | ||||
|       echo "Available targets for \"$BDESC\" | $MB ($BNUM):" | ||||
|  | ||||
|       IND=0 ; for ENV in "${ENVS[@]}"; do let IND++ ; echo " $IND) $ENV" ; done | ||||
|  | ||||
|       if [[ $ECOUNT > 1 ]]; then | ||||
|         for (( ; ; )) | ||||
|         do | ||||
|           read -p "Select a target for '$MB' (1-$ECOUNT) : " CHOICE | ||||
|           [[ -z "$CHOICE" ]] && { echo '(canceled)' ; exit 1 ; } | ||||
|           [[ $CHOICE =~ $ISNUM ]] && ((CHOICE >= 1 && CHOICE <= ECOUNT)) && break | ||||
|           errout ">>> Invalid environment choice '$CHOICE'." | ||||
|         done | ||||
|         echo | ||||
|       fi | ||||
|     else | ||||
|       echo "Detected \"$BDESC\" | $MB ($BNUM)." | ||||
|       [[ $CHOICE > $ECOUNT ]] && { echo "Environment selection out of range." ; exit 1 ; } | ||||
|     fi | ||||
|     TARGET="${ENVS[$CHOICE-1]}" | ||||
|     echo "Selected $TARGET" | ||||
|   fi | ||||
|  | ||||
|   echo "$TARGET" >"$STATE_FILE" | ||||
|  | ||||
|   if ((AUTO_BUILD == 2)); then | ||||
|     echo "Uploading environment $TARGET for board $MB ($BNUM)..." ; echo | ||||
|     pio run -t upload -e $TARGET | ||||
|   else | ||||
|     echo "Building environment $TARGET for board $MB ($BNUM)..." ; echo | ||||
|     pio run -e $TARGET | ||||
|   fi | ||||
|   exit | ||||
| fi | ||||
|  | ||||
| # | ||||
| # List available tests and ask for selection | ||||
| # | ||||
|  | ||||
| if [[ $TESTENV == '-' ]]; then | ||||
|   IND=0 | ||||
|   NAMES=() | ||||
|   for FILE in $( ls -1 $TESTPATH/*-tests ) | ||||
|   do | ||||
|     let IND++ | ||||
|     TNAME=${FILE/-tests/} | ||||
|     TNAME=${TNAME/$TESTPATH\//} | ||||
|     NAMES+=($TNAME) | ||||
|     (( IND < 10 )) && echo -n " " | ||||
|     echo " $IND) $TNAME" | ||||
|   done | ||||
|  | ||||
|   echo | ||||
|   for (( ; ; )) | ||||
|   do | ||||
|     if [[ $TESTNUM -gt 0 ]]; then | ||||
|       NAMEIND=$TESTNUM | ||||
|     else | ||||
|       read -p "Select a test to apply (1-$IND) : " NAMEIND | ||||
|     fi | ||||
|     [[ -z $NAMEIND ]] && { errout "(canceled)" ; exit 1 ; } | ||||
|     TESTENV=${NAMES[$NAMEIND-1]} | ||||
|     [[ $TESTNUM -gt 0 ]] && { echo "Preselected test $TESTNUM ... ($TESTENV)" ; TESTNUM='' ; } | ||||
|     [[ $NAMEIND =~ $ISNUM ]] && ((NAMEIND >= 1 && NAMEIND <= IND)) && { TESTENV=${NAMES[$NAMEIND-1]} ; echo ; break ; } | ||||
|     errout "Invalid selection." | ||||
|   done | ||||
| fi | ||||
|  | ||||
| # Get the contents of the test file | ||||
| OUT=$( cat $TESTPATH/$TESTENV-tests 2>/dev/null ) || { errout "Can't find test '$TESTENV'." ; exit 1 ; } | ||||
|  | ||||
| # Count up the number of tests | ||||
| TESTCOUNT=$( awk "/$ISEXEC/{a++}END{print a}" <<<"$OUT" ) | ||||
|  | ||||
| # User entered a number? | ||||
| (( CHOICE && CHOICE > TESTCOUNT )) && { errout "Invalid test selection '$CHOICE' (1-$TESTCOUNT)." ; exit 1 ; } | ||||
|  | ||||
| if [[ $CHOICE == 0 ]]; then | ||||
|   # | ||||
|   # List test descriptions with numbers and get selection | ||||
|   # | ||||
|   echo "Available '$TESTENV' tests:" ; echo "$OUT" | { | ||||
|     IND=0 | ||||
|     while IFS= read -r LINE | ||||
|     do | ||||
|       if [[ $LINE =~ $ISEXEC ]]; then | ||||
|         DESC=$( "$SED" -E 's/^exec_test \$1 \$2 "([^"]+)".*$/\1/g' <<<"$LINE" ) | ||||
|         (( ++IND < 10 )) && echo -n " " | ||||
|         echo " $IND) $DESC" | ||||
|       fi | ||||
|     done | ||||
|   } | ||||
|   CHOICE=1 | ||||
|   if [[ $TESTCOUNT > 1 ]]; then | ||||
|     for (( ; ; )) | ||||
|     do | ||||
|       read -p "Select a '$TESTENV' test (1-$TESTCOUNT) : " CHOICE | ||||
|       [[ -z "$CHOICE" ]] && { errout "(canceled)" ; exit 1 ; } | ||||
|       [[ $CHOICE =~ $ISNUM ]] && ((CHOICE >= 1 && CHOICE <= TESTCOUNT)) && break | ||||
|       errout ">>> Invalid test selection '$CHOICE'." | ||||
|     done | ||||
|   fi | ||||
| fi | ||||
|  | ||||
| # | ||||
| # Run the specified test lines | ||||
| # | ||||
| echo -ne "\033[0;33m" | ||||
| echo "$OUT" | { | ||||
|   IND=0 | ||||
|   GOTX=0 | ||||
|   CMD="" | ||||
|   while IFS= read -r LINE | ||||
|   do | ||||
|     if [[ $LINE =~ $ISCMD || $GOTX == 1 ]]; then | ||||
|       ((!IND)) && let IND++ | ||||
|       if [[ $LINE =~ $ISEXEC ]]; then | ||||
|         ((IND++ > CHOICE)) && break | ||||
|       else | ||||
|         ((!HEADER)) && { | ||||
|           HEADER=1 | ||||
|           echo -e "\n#\n# Test $TESTENV ($CHOICE) $DESC\n#" | ||||
|         } | ||||
|         ((IND == CHOICE)) && { | ||||
|           GOTX=1 | ||||
|           [[ $CMD == "" ]] && CMD="$LINE" || CMD=$( echo -e "$CMD$LINE" | $SED -e 's/\\//g' | $SED -E 's/ +/ /g' ) | ||||
|           [[ $LINE =~ $ISCONT ]] || { echo "$CMD" ; eval "$CMD" ; CMD="" ; } | ||||
|         } | ||||
|       fi | ||||
|     fi | ||||
|   done | ||||
| } | ||||
| echo -ne "\033[0m" | ||||
|  | ||||
| # Make clear it's a TEST | ||||
| opt_set CUSTOM_MACHINE_NAME "\"$TESTENV-tests ($CHOICE)\"" | ||||
|  | ||||
| # Build the test too? | ||||
| if [[ -z "$BUILD_YES" ]]; then | ||||
|   echo | ||||
|   read -p "Build $TESTENV test #$CHOICE (y/N) ? " BUILD_YES | ||||
| fi | ||||
|  | ||||
| [[ $BUILD_YES == 'Y' || $BUILD_YES == 'Yes' ]] && { | ||||
|   ((USE_MAKE)) && make tests-single-local TEST_TARGET=$TESTENV ONLY_TEST=$CHOICE | ||||
|   ((USE_MAKE)) || pio run -d . -e $TESTENV | ||||
|   echo "$TESTENV" >"$STATE_FILE" | ||||
| } | ||||
		Reference in New Issue
	
	Block a user