1335 lines
48 KiB
Bash
Executable File
1335 lines
48 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# EdgeTX Multi-Language Multi-Variant Build Script
|
|
# Written with assistance from GitHub Copilot AI
|
|
#
|
|
# This script automatically builds all languages for all firmware variants
|
|
# with intelligent filtering for character-based languages on B&W screens
|
|
|
|
# Manual override for color screen targets (set this to override auto-detection)
|
|
COLOR_SCREEN_TARGETS_OVERRIDE=""
|
|
|
|
# Function to build targets by screen type and optional processor filter
|
|
build_targets_by_screen_type() {
|
|
local screen_type="$1" # "color" or "bw"
|
|
local processor_filter="$2" # "F2", "F4", "H7", "exclude-F2", etc. (optional)
|
|
local all_targets=$(get_all_targets)
|
|
local filtered_targets=""
|
|
local failed_targets=0
|
|
local overall_start_time=$(date +%s)
|
|
|
|
# Filter by screen type first
|
|
for target in $all_targets; do
|
|
local is_color_target=false
|
|
if is_color_screen_target "$target"; then
|
|
is_color_target=true
|
|
fi
|
|
|
|
if [[ "$screen_type" == "color" && "$is_color_target" == "true" ]]; then
|
|
filtered_targets="$filtered_targets $target"
|
|
elif [[ "$screen_type" == "bw" && "$is_color_target" == "false" ]]; then
|
|
filtered_targets="$filtered_targets $target"
|
|
fi
|
|
done
|
|
|
|
# Apply processor filter if specified
|
|
if [[ -n "$processor_filter" ]]; then
|
|
local processor_filtered_targets=""
|
|
|
|
if [[ "$processor_filter" == exclude-* ]]; then
|
|
# Exclude specific processor
|
|
local exclude_proc="${processor_filter#exclude-}"
|
|
for target in $filtered_targets; do
|
|
local target_processor=$(get_stm32_processor_type "$target")
|
|
if [[ "$target_processor" != "$exclude_proc" && "$target_processor" != "UNKNOWN" ]]; then
|
|
processor_filtered_targets="$processor_filtered_targets $target"
|
|
fi
|
|
done
|
|
else
|
|
# Include only specific processor
|
|
for target in $filtered_targets; do
|
|
local target_processor=$(get_stm32_processor_type "$target")
|
|
if [[ "$target_processor" == "$processor_filter" ]]; then
|
|
processor_filtered_targets="$processor_filtered_targets $target"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
filtered_targets="$processor_filtered_targets"
|
|
fi
|
|
|
|
# Build the filtered targets
|
|
if [[ -z "$filtered_targets" ]]; then
|
|
echo "No targets match the specified criteria."
|
|
return 0
|
|
fi
|
|
|
|
echo "Building $screen_type screen targets$(if [[ -n "$processor_filter" ]]; then echo " with processor filter: $processor_filter"; fi)..."
|
|
echo "Selected targets: $filtered_targets"
|
|
echo
|
|
|
|
for target in $filtered_targets; do
|
|
echo "========================================"
|
|
echo "Processing target: $target ($(get_stm32_processor_type "$target") processor)"
|
|
echo "========================================"
|
|
|
|
if ! build_target_all_languages "$target"; then
|
|
((failed_targets++))
|
|
echo "Failed to build all languages for target $target"
|
|
fi
|
|
|
|
echo
|
|
done
|
|
|
|
# Calculate overall elapsed time
|
|
local overall_end_time=$(date +%s)
|
|
local overall_elapsed=$((overall_end_time - overall_start_time))
|
|
|
|
# Format overall elapsed time
|
|
local overall_elapsed_formatted
|
|
if [[ $overall_elapsed -ge 3600 ]]; then
|
|
overall_elapsed_formatted=$(printf "%dh %dm %ds" $((overall_elapsed / 3600)) $(((overall_elapsed % 3600) / 60)) $((overall_elapsed % 60)))
|
|
elif [[ $overall_elapsed -ge 60 ]]; then
|
|
overall_elapsed_formatted=$(printf "%dm %ds" $((overall_elapsed / 60)) $((overall_elapsed % 60)))
|
|
else
|
|
overall_elapsed_formatted="${overall_elapsed}s"
|
|
fi
|
|
|
|
if [[ $failed_targets -gt 0 && "${CONTINUE_ON_FAILURE:-}" != "1" ]]; then
|
|
echo "========================================="
|
|
echo "BUILD SUMMARY"
|
|
echo "========================================="
|
|
printf "\033[31m✗\033[0m Warning: %d targets had build failures\n" "$failed_targets"
|
|
echo "Total build time: ${overall_elapsed_formatted}"
|
|
return 1
|
|
else
|
|
echo "========================================="
|
|
echo "BUILD SUMMARY"
|
|
echo "========================================="
|
|
if [[ $failed_targets -gt 0 && "${CONTINUE_ON_FAILURE:-}" == "1" ]]; then
|
|
printf "\033[32m✓\033[0m All targets attempted successfully!\n"
|
|
echo " Note: Some language builds failed but were ignored due to --continue-on-failure"
|
|
else
|
|
printf "\033[32m✓\033[0m All targets built successfully!\n"
|
|
fi
|
|
echo "Total build time: ${overall_elapsed_formatted}"
|
|
return 0
|
|
fi
|
|
}
|
|
# with intelligent filtering for character-based languages on B&W screens
|
|
|
|
set -e
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
|
|
# Source the build-common.sh for target definitions
|
|
if [[ -f "$SCRIPT_DIR/tools/build-common.sh" ]]; then
|
|
. "$SCRIPT_DIR/tools/build-common.sh"
|
|
elif [[ -f "$SCRIPT_DIR/build-common.sh" ]]; then
|
|
. "$SCRIPT_DIR/build-common.sh"
|
|
else
|
|
echo "Error: Could not find build-common.sh"
|
|
exit 1
|
|
fi
|
|
|
|
# Auto-discover available languages from radio/src/CMakeLists.txt
|
|
get_radio_languages() {
|
|
local cmake_file=""
|
|
if [[ -f "$SCRIPT_DIR/../radio/src/CMakeLists.txt" ]]; then
|
|
cmake_file="$SCRIPT_DIR/../radio/src/CMakeLists.txt"
|
|
else
|
|
echo "Error: Could not find radio/src/CMakeLists.txt" >&2
|
|
return 1
|
|
fi
|
|
|
|
# Extract languages from: set(RADIO_LANGUAGES CN CZ DA DE EN ES FI FR HE HU IT JP KO NL PL PT RU SE SK TW UA)
|
|
# Strip carriage returns to handle Windows line endings
|
|
grep "^set(RADIO_LANGUAGES" "$cmake_file" | sed 's/set(RADIO_LANGUAGES \(.*\))/\1/' | tr -d '\r'
|
|
}
|
|
|
|
# Define character-based/logographic languages (configurable with auto-detection fallback)
|
|
# These should not be built for B&W screens due to font/display limitations
|
|
LOGOGRAPHIC_LANGUAGES_OVERRIDE="" # Set this to override auto-detection
|
|
|
|
get_logographic_languages() {
|
|
# Use override if set
|
|
if [[ -n "$LOGOGRAPHIC_LANGUAGES_OVERRIDE" ]]; then
|
|
echo "$LOGOGRAPHIC_LANGUAGES_OVERRIDE"
|
|
return 0
|
|
fi
|
|
|
|
# Auto-detect logographic languages based on known character sets
|
|
# These are languages that typically use complex character sets that may not display well on B&W screens
|
|
local known_logographic="CN JP KO TW"
|
|
|
|
# Could be enhanced to check translation files for unicode/multibyte characters
|
|
# For now, use the known list as fallback
|
|
echo "$known_logographic"
|
|
}
|
|
|
|
# Extract all firmware variants from build-common.sh
|
|
get_all_targets() {
|
|
# Extract target names from the get_target_build_options function
|
|
local build_common_path=""
|
|
if [[ -f "$SCRIPT_DIR/tools/build-common.sh" ]]; then
|
|
build_common_path="$SCRIPT_DIR/tools/build-common.sh"
|
|
elif [[ -f "$SCRIPT_DIR/build-common.sh" ]]; then
|
|
build_common_path="$SCRIPT_DIR/build-common.sh"
|
|
else
|
|
echo "Error: Could not find build-common.sh" >&2
|
|
return 1
|
|
fi
|
|
|
|
# Extract target names from case statement in get_target_build_options function
|
|
awk '
|
|
/^get_target_build_options\(\)/ { in_function=1; next }
|
|
in_function && /^}$/ { exit }
|
|
in_function && /^[[:space:]]*[a-z0-9_-]+\)/ {
|
|
gsub(/^[[:space:]]*/, "")
|
|
gsub(/\).*$/, "")
|
|
if ($0 != "*" && $0 != "esac") print $0
|
|
}
|
|
' "$build_common_path" | sort -u
|
|
}
|
|
|
|
# Auto-discover color screen targets by checking target CMakeLists.txt files - fully dynamic implementation
|
|
get_color_screen_targets() {
|
|
local color_targets=""
|
|
local all_targets
|
|
|
|
all_targets=$(get_all_targets)
|
|
|
|
for target in $all_targets; do
|
|
# Get the PCB type for this target from build-common.sh
|
|
local pcb_line
|
|
pcb_line=$(awk -v target="$target" '
|
|
/^get_target_build_options\(\)/ { in_function=1; next }
|
|
in_function && /^}$/ { exit }
|
|
in_function && $0 ~ "^[[:space:]]*" target "\\)" {
|
|
found_target=1; next
|
|
}
|
|
found_target && /BUILD_OPTIONS.*-DPCB=/ {
|
|
print $0; exit
|
|
}
|
|
found_target && /;;/ { exit }
|
|
' "$SCRIPT_DIR/build-common.sh" 2>/dev/null || true)
|
|
|
|
if [[ -n "$pcb_line" ]]; then
|
|
# Extract PCB type (e.g., -DPCB=X10 -> X10)
|
|
local pcb_type
|
|
pcb_type=$(echo "$pcb_line" | grep -o '\-DPCB=[A-Z0-9+]*' | cut -d= -f2)
|
|
|
|
if [[ -n "$pcb_type" ]]; then
|
|
# Dynamically determine target directory by parsing radio/src/CMakeLists.txt
|
|
local radio_cmake_file="../radio/src/CMakeLists.txt"
|
|
local target_dir=""
|
|
|
|
if [[ -f "$SCRIPT_DIR/$radio_cmake_file" ]]; then
|
|
# Parse the if/elseif chain to find which target directory corresponds to our PCB type
|
|
target_dir=$(awk -v pcb="$pcb_type" '
|
|
/^if\(PCB STREQUAL|^elseif\(PCB STREQUAL/ {
|
|
condition_line = $0
|
|
# Extract all PCB types from the condition
|
|
gsub(/^[^(]*\(/, "", condition_line) # Remove everything before first (
|
|
gsub(/\).*$/, "", condition_line) # Remove everything after last )
|
|
gsub(/PCB STREQUAL /, "", condition_line) # Remove "PCB STREQUAL "
|
|
gsub(/ OR /, " ", condition_line) # Replace " OR " with space
|
|
|
|
# Check if our PCB type is in this condition
|
|
if ((" " condition_line " ") ~ (" " pcb " ")) {
|
|
found_pcb = 1
|
|
}
|
|
}
|
|
found_pcb && /include\(targets\/.*\/CMakeLists\.txt\)/ {
|
|
# Extract target directory from include(targets/horus/CMakeLists.txt)
|
|
match($0, /targets\/([^\/]+)\//, arr)
|
|
if (arr[1]) {
|
|
print arr[1]
|
|
exit
|
|
}
|
|
}
|
|
/^else\(\)|^endif\(\)/ { found_pcb = 0 }
|
|
' "$SCRIPT_DIR/$radio_cmake_file")
|
|
fi
|
|
|
|
if [[ -n "$target_dir" ]]; then
|
|
# Check if this target directory has color screen support
|
|
local target_cmake_file="../radio/src/targets/$target_dir/CMakeLists.txt"
|
|
|
|
if [[ -f "$SCRIPT_DIR/$target_cmake_file" ]]; then
|
|
# Look for color screen indicators: GUI_DIR with colorlcd, COLORLCD definitions, etc.
|
|
if grep -q "GUI_DIR.*colorlcd\|COLORLCD\|set(GUI_DIR.*colorlcd" "$SCRIPT_DIR/$target_cmake_file"; then
|
|
color_targets="$color_targets $target"
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
done
|
|
|
|
# Return unique sorted targets
|
|
echo "$color_targets" | tr ' ' '\n' | sort -u | tr '\n' ' '
|
|
}
|
|
|
|
# Auto-discover STM32 processor types for targets - fully dynamic implementation
|
|
get_stm32_processor_type() {
|
|
local target=$1
|
|
|
|
# Hard-coded case for x9dp (will be phased out)
|
|
if [[ "$target" == "x9dp" ]]; then
|
|
echo "F2"
|
|
return 0
|
|
fi
|
|
|
|
# Get the PCB configuration for this target from build-common.sh
|
|
local pcb_line
|
|
pcb_line=$(awk -v target="$target" '
|
|
/^get_target_build_options\(\)/ { in_function=1; next }
|
|
in_function && /^}$/ { exit }
|
|
in_function && $0 ~ "^[[:space:]]*" target "\\)" {
|
|
found_target=1; next
|
|
}
|
|
found_target && /BUILD_OPTIONS.*-DPCB=/ {
|
|
print $0
|
|
exit
|
|
}
|
|
found_target && /;;/ { exit }
|
|
' "$SCRIPT_DIR/build-common.sh" 2>/dev/null || true)
|
|
|
|
if [[ -z "$pcb_line" ]]; then
|
|
echo "UNKNOWN"
|
|
return 1
|
|
fi
|
|
|
|
# Extract PCB type and PCBREV from BUILD_OPTIONS+="-DPCB=X7 -DPCBREV=T8"
|
|
local pcb_type
|
|
local pcb_rev
|
|
pcb_type=$(echo "$pcb_line" | grep -o '\-DPCB=[A-Z0-9+]*' | cut -d= -f2)
|
|
pcb_rev=$(echo "$pcb_line" | grep -o '\-DPCBREV=[A-Z0-9+]*' | cut -d= -f2 || true)
|
|
|
|
if [[ -z "$pcb_type" ]]; then
|
|
echo "UNKNOWN"
|
|
return 1
|
|
fi
|
|
|
|
# Dynamically determine target directory by parsing radio/src/CMakeLists.txt
|
|
local radio_cmake_file="../radio/src/CMakeLists.txt"
|
|
local target_dir=""
|
|
|
|
if [[ -f "$SCRIPT_DIR/$radio_cmake_file" ]]; then
|
|
# Parse the if/elseif chain to find which target directory corresponds to our PCB type
|
|
target_dir=$(awk -v pcb="$pcb_type" '
|
|
/^if\(PCB STREQUAL|^elseif\(PCB STREQUAL/ {
|
|
condition_line = $0
|
|
# Extract all PCB types from the condition
|
|
gsub(/^[^(]*\(/, "", condition_line) # Remove everything before first (
|
|
gsub(/\).*$/, "", condition_line) # Remove everything after last )
|
|
gsub(/PCB STREQUAL /, "", condition_line) # Remove "PCB STREQUAL "
|
|
gsub(/ OR /, " ", condition_line) # Replace " OR " with space
|
|
|
|
# Check if our PCB type is in this condition
|
|
if ((" " condition_line " ") ~ (" " pcb " ")) {
|
|
found_pcb = 1
|
|
}
|
|
}
|
|
found_pcb && /include\(targets\/.*\/CMakeLists\.txt\)/ {
|
|
# Extract target directory from include(targets/horus/CMakeLists.txt)
|
|
match($0, /targets\/([^\/]+)\//, arr)
|
|
if (arr[1]) {
|
|
print arr[1]
|
|
exit
|
|
}
|
|
}
|
|
/^else\(\)|^endif\(\)/ { found_pcb = 0 }
|
|
' "$SCRIPT_DIR/$radio_cmake_file")
|
|
fi
|
|
|
|
if [[ -z "$target_dir" ]]; then
|
|
echo "UNKNOWN"
|
|
return 1
|
|
fi
|
|
|
|
# Simulate the CMake logic to determine CPU_TYPE_FULL based on PCB and PCBREV
|
|
local target_cmake_file="../radio/src/targets/$target_dir/CMakeLists.txt"
|
|
|
|
if [[ -f "$SCRIPT_DIR/$target_cmake_file" ]]; then
|
|
# Parse the target CMakeLists.txt to determine CPU_TYPE_FULL
|
|
# We need to simulate the if/elseif logic for PCB and PCBREV
|
|
local cpu_type_full
|
|
|
|
# First, try to find CPU_TYPE_FULL within the specific PCBREV block if PCBREV is specified
|
|
if [[ -n "$pcb_rev" ]]; then
|
|
cpu_type_full=$(awk -v pcb="$pcb_type" -v pcbrev="$pcb_rev" '
|
|
BEGIN { in_pcb_block = 0; in_pcbrev_block = 0; cpu_found = 0 }
|
|
|
|
# Look for PCB conditions
|
|
/^if\(PCB STREQUAL|^elseif\(PCB STREQUAL/ {
|
|
condition_line = $0
|
|
gsub(/^[^(]*\(/, "", condition_line)
|
|
gsub(/\).*$/, "", condition_line)
|
|
gsub(/PCB STREQUAL /, "", condition_line)
|
|
gsub(/ OR /, " ", condition_line)
|
|
|
|
# Check if our PCB type is in this condition (use index for exact matching)
|
|
if (index(" " condition_line " ", " " pcb " ") > 0) {
|
|
in_pcb_block = 1
|
|
} else {
|
|
in_pcb_block = 0
|
|
}
|
|
in_pcbrev_block = 0
|
|
}
|
|
|
|
# Look for PCBREV conditions within PCB block
|
|
in_pcb_block && /\$\{PCBREV\} STREQUAL/ {
|
|
condition_line = $0
|
|
gsub(/.*\$\{PCBREV\} STREQUAL /, "", condition_line)
|
|
gsub(/\).*$/, "", condition_line)
|
|
gsub(/ .*$/, "", condition_line)
|
|
|
|
if (condition_line == pcbrev) {
|
|
in_pcbrev_block = 1
|
|
} else {
|
|
in_pcbrev_block = 0
|
|
}
|
|
}
|
|
|
|
# Accept CPU_TYPE_FULL within PCBREV block
|
|
in_pcbrev_block && /set\(CPU_TYPE_FULL STM32/ {
|
|
match($0, /STM32[FH][0-9RSx]+[A-Z]*/, arr)
|
|
if (arr[0] && !cpu_found) {
|
|
print arr[0]
|
|
cpu_found = 1
|
|
exit
|
|
}
|
|
}
|
|
|
|
# Reset PCBREV block when we hit another condition or endif
|
|
/^[[:space:]]*if\(|^[[:space:]]*elseif\(|^[[:space:]]*else\(|^[[:space:]]*endif\(/ && !/PCBREV/ {
|
|
if (in_pcb_block && in_pcbrev_block) {
|
|
in_pcbrev_block = 0
|
|
}
|
|
}
|
|
|
|
# Reset everything when we exit the PCB block
|
|
/^else\(\)|^endif\(\)/ && !(/PCBREV/) {
|
|
in_pcb_block = 0
|
|
in_pcbrev_block = 0
|
|
}
|
|
' "$SCRIPT_DIR/$target_cmake_file")
|
|
fi
|
|
|
|
# If no CPU_TYPE_FULL found in PCBREV block, or no PCBREV specified,
|
|
# look for CPU_TYPE_FULL within the specific PCB block
|
|
if [[ -z "$cpu_type_full" ]]; then
|
|
# Use sed to extract the specific PCB block, then look for CPU_TYPE_FULL
|
|
# For targets without PCBREV, we want the "else()" case, not the PCBREV-specific ones
|
|
local pcb_block_start_pattern="^elseif(PCB STREQUAL $pcb_type)\|^if(PCB STREQUAL.*$pcb_type"
|
|
local pcb_block_end_pattern="^elseif(PCB STREQUAL\|^else()\|^endif()"
|
|
|
|
if [[ -z "$pcb_rev" ]]; then
|
|
# No PCBREV specified, first try to find CPU_TYPE_FULL in else() block for complex targets
|
|
cpu_type_full=$(sed -n "/$pcb_block_start_pattern/,/$pcb_block_end_pattern/p" "$SCRIPT_DIR/$target_cmake_file" | \
|
|
awk '
|
|
BEGIN { in_else_block = 0 }
|
|
/else\(\)/ { in_else_block = 1; next }
|
|
/endif\(\)/ { in_else_block = 0; next }
|
|
/\$\{PCBREV\} STREQUAL/ { in_else_block = 0; next }
|
|
in_else_block && /set\(CPU_TYPE_FULL STM32/ {
|
|
match($0, /STM32[FH][0-9RSx]+[A-Z]*/, arr)
|
|
if (arr[0]) { print arr[0]; exit }
|
|
}
|
|
# If no else() block, take any CPU_TYPE_FULL not in a PCBREV block
|
|
!in_else_block && /set\(CPU_TYPE_FULL STM32/ && (prev_line !~ /\$\{PCBREV\} STREQUAL/) {
|
|
match($0, /STM32[FH][0-9RSx]+[A-Z]*/, arr)
|
|
if (arr[0] && !found_any) { found_any=1; print arr[0]; exit }
|
|
}
|
|
{ prev_line = $0 }
|
|
')
|
|
|
|
# If still not found (simple targets), use global CPU_TYPE_FULL
|
|
if [[ -z "$cpu_type_full" ]]; then
|
|
cpu_type_full=$(grep "set(CPU_TYPE_FULL STM32" "$SCRIPT_DIR/$target_cmake_file" | head -1 | grep -o "STM32[FH][0-9RSx]*[A-Z]*")
|
|
fi
|
|
else
|
|
# PCBREV specified but no CPU_TYPE_FULL found in PCBREV block, use global CPU_TYPE_FULL
|
|
cpu_type_full=$(grep "set(CPU_TYPE_FULL STM32" "$SCRIPT_DIR/$target_cmake_file" | head -1 | grep -o "STM32[FH][0-9RSx]*[A-Z]*")
|
|
fi
|
|
fi
|
|
|
|
if [[ -n "$cpu_type_full" ]]; then
|
|
# Convert CPU_TYPE_FULL to CPU_TYPE (F2, F4, H7, etc.)
|
|
local cpu_type
|
|
case "$cpu_type_full" in
|
|
STM32F2*) cpu_type="F2" ;;
|
|
STM32F4*) cpu_type="F4" ;;
|
|
STM32H7*) cpu_type="H7" ;;
|
|
*) cpu_type="UNKNOWN" ;;
|
|
esac
|
|
echo "$cpu_type"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
echo "UNKNOWN"
|
|
return 1
|
|
}
|
|
|
|
# Function to get targets by STM32 processor type
|
|
get_targets_by_processor() {
|
|
local processor_filter="$1"
|
|
local all_targets=$(get_all_targets)
|
|
local filtered_targets=""
|
|
|
|
for target in $all_targets; do
|
|
local target_processor=$(get_stm32_processor_type "$target")
|
|
if [[ "$target_processor" == "$processor_filter" ]]; then
|
|
filtered_targets="$filtered_targets $target"
|
|
fi
|
|
done
|
|
|
|
echo "$filtered_targets"
|
|
}
|
|
|
|
# Function to get targets by processor exclusion
|
|
get_targets_excluding_processor() {
|
|
local exclude_processor="$1"
|
|
local all_targets=$(get_all_targets)
|
|
local filtered_targets=""
|
|
|
|
for target in $all_targets; do
|
|
local target_processor=$(get_stm32_processor_type "$target")
|
|
if [[ "$target_processor" != "$exclude_processor" && "$target_processor" != "UNKNOWN" ]]; then
|
|
filtered_targets="$filtered_targets $target"
|
|
fi
|
|
done
|
|
|
|
echo "$filtered_targets"
|
|
}
|
|
|
|
# Function to check if a target uses color screen
|
|
is_color_screen_target() {
|
|
local target=$1
|
|
local color_targets
|
|
|
|
# Use override if set, otherwise auto-detect
|
|
if [[ -n "$COLOR_SCREEN_TARGETS_OVERRIDE" ]]; then
|
|
color_targets="$COLOR_SCREEN_TARGETS_OVERRIDE"
|
|
else
|
|
color_targets=$(get_color_screen_targets)
|
|
fi
|
|
|
|
# Check if target is in the color targets list
|
|
for color_target in $color_targets; do
|
|
if [[ "$target" == "$color_target" ]]; then
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# Function to check if a language is logographic
|
|
is_logographic_language() {
|
|
local lang=$1
|
|
local logographic_langs
|
|
|
|
logographic_langs=$(get_logographic_languages)
|
|
|
|
for logo_lang in $logographic_langs; do
|
|
if [[ "$lang" == "$logo_lang" ]]; then
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# Function to get valid languages for a target
|
|
get_valid_languages_for_target() {
|
|
local target=$1
|
|
local valid_languages=""
|
|
local radio_languages
|
|
|
|
radio_languages=$(get_radio_languages)
|
|
|
|
# Check if force all languages flag is set
|
|
if [[ "${FORCE_ALL_LANGUAGES:-}" == "1" ]]; then
|
|
# Force all languages mode: build all languages regardless of screen type
|
|
valid_languages="$radio_languages"
|
|
else
|
|
# Normal mode: filter based on screen type
|
|
for lang in $radio_languages; do
|
|
if is_color_screen_target "$target"; then
|
|
# Color screen: all languages allowed
|
|
valid_languages="$valid_languages $lang"
|
|
else
|
|
# B&W screen: exclude logographic languages
|
|
if ! is_logographic_language "$lang"; then
|
|
valid_languages="$valid_languages $lang"
|
|
fi
|
|
fi
|
|
done
|
|
fi
|
|
|
|
echo "$valid_languages"
|
|
}
|
|
|
|
# Function to build a specific target with a specific language
|
|
build_target_language() {
|
|
local target=$1
|
|
local language=$2
|
|
|
|
# Show building message without newline
|
|
printf "Building %s with language %s... " "$target" "$language"
|
|
|
|
# Dry run mode - just simulate the build
|
|
if [[ "${DRY_RUN:-}" == "1" ]]; then
|
|
printf "\033[32m✓\033[0m [DRY-RUN]\n"
|
|
printf " → Would build: TRANSLATIONS=%s FLAVOR=%s\n" "$language" "$target"
|
|
return 0
|
|
fi
|
|
|
|
# Use build-gh.sh with the target and set the TRANSLATIONS environment variable
|
|
# build-gh.sh expects FLAVOR environment variable with the target name
|
|
local build_script=""
|
|
if [[ -f "$SCRIPT_DIR/tools/build-gh.sh" ]]; then
|
|
build_script="$SCRIPT_DIR/tools/build-gh.sh"
|
|
elif [[ -f "$SCRIPT_DIR/build-gh.sh" ]]; then
|
|
build_script="$SCRIPT_DIR/build-gh.sh"
|
|
else
|
|
echo "Error: Could not find build-gh.sh"
|
|
return 1
|
|
fi
|
|
|
|
export FLAVOR="$target"
|
|
export SRCDIR="/workspaces/edgetx"
|
|
export EXTRA_OPTIONS="-DTRANSLATIONS=$language "
|
|
|
|
# Create build directory if it doesn't exist and change to it
|
|
local build_dir="$SCRIPT_DIR/../build"
|
|
mkdir -p "$build_dir"
|
|
local original_pwd="$PWD"
|
|
cd "$build_dir"
|
|
|
|
# Create a unique log file for this build
|
|
local log_file="/tmp/edgetx-build-${target}-${language}-$$.log"
|
|
|
|
# Run build script and capture all output to log file
|
|
"$build_script" > "$log_file" 2>&1
|
|
|
|
local exit_code=$?
|
|
|
|
# Return to original directory
|
|
cd "$original_pwd"
|
|
|
|
if [[ $exit_code -eq 0 ]]; then
|
|
printf "\033[32m✓\033[0m Success!\n"
|
|
|
|
# Rename firmware files to include language code
|
|
local git_sha=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
|
|
local base_name="${target}-${git_sha}"
|
|
local lang_suffix="-${language,,}" # Convert language to lowercase
|
|
|
|
# Check for and rename .bin file
|
|
if [[ -f "${base_name}.bin" ]]; then
|
|
mv "${base_name}.bin" "${base_name}${lang_suffix}.bin"
|
|
fi
|
|
|
|
# Check for and rename .uf2 file
|
|
if [[ -f "${base_name}.uf2" ]]; then
|
|
mv "${base_name}.uf2" "${base_name}${lang_suffix}.uf2"
|
|
fi
|
|
|
|
# Clean up log file on success
|
|
rm -f "$log_file"
|
|
else
|
|
printf "\033[31m✗\033[0m Failed!\n"
|
|
printf " Build log saved to: %s\n" "$log_file"
|
|
if [[ "${CONTINUE_ON_FAILURE:-0}" != "1" ]]; then
|
|
printf " Terminating current batch due to build failure\n"
|
|
fi
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Function to build all languages for a target
|
|
build_target_all_languages() {
|
|
local target=$1
|
|
local languages
|
|
local failed_builds=0
|
|
local start_time=$(date +%s)
|
|
|
|
languages=$(get_valid_languages_for_target "$target")
|
|
|
|
if [[ "${FORCE_ALL_LANGUAGES:-}" == "1" ]]; then
|
|
echo "Building target '$target' with ALL languages (forced): $languages"
|
|
echo " → Force mode - building all languages including logographic for B&W screens"
|
|
else
|
|
echo "Building target '$target' with languages: $languages"
|
|
|
|
if is_color_screen_target "$target"; then
|
|
echo " → Color screen target - building all languages"
|
|
else
|
|
echo " → B&W screen target - excluding logographic languages ($(get_logographic_languages))"
|
|
fi
|
|
fi
|
|
|
|
for language in $languages; do
|
|
if ! build_target_language "$target" "$language"; then
|
|
((failed_builds++))
|
|
# Stop building more languages for this target after first failure unless --continue-on-failure is set
|
|
if [[ "${CONTINUE_ON_FAILURE:-}" != "1" ]]; then
|
|
break
|
|
fi
|
|
fi
|
|
done
|
|
|
|
local end_time=$(date +%s)
|
|
local elapsed=$((end_time - start_time))
|
|
local elapsed_formatted
|
|
|
|
# Format elapsed time nicely
|
|
if [[ $elapsed -ge 3600 ]]; then
|
|
# Hours, minutes, seconds
|
|
elapsed_formatted=$(printf "%dh %dm %ds" $((elapsed / 3600)) $(((elapsed % 3600) / 60)) $((elapsed % 60)))
|
|
elif [[ $elapsed -ge 60 ]]; then
|
|
# Minutes and seconds
|
|
elapsed_formatted=$(printf "%dm %ds" $((elapsed / 60)) $((elapsed % 60)))
|
|
else
|
|
# Just seconds
|
|
elapsed_formatted="${elapsed}s"
|
|
fi
|
|
|
|
if [[ $failed_builds -gt 0 ]]; then
|
|
echo "Warning: $failed_builds language builds failed for target $target (${elapsed_formatted})"
|
|
return 1
|
|
else
|
|
echo "Target $target completed successfully (${elapsed_formatted})"
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Function to build all targets with all valid languages
|
|
build_all_targets() {
|
|
local all_targets
|
|
local failed_targets=0
|
|
local overall_start_time=$(date +%s)
|
|
|
|
all_targets=$(get_all_targets)
|
|
|
|
echo "Building all firmware variants with appropriate languages..."
|
|
echo
|
|
echo "Detected targets: $(echo $all_targets | tr ' ' ',')"
|
|
echo
|
|
|
|
for target in $all_targets; do
|
|
echo "========================================"
|
|
echo "Processing target: $target"
|
|
echo "========================================"
|
|
|
|
if ! build_target_all_languages "$target"; then
|
|
((failed_targets++))
|
|
echo "Failed to build all languages for target $target"
|
|
fi
|
|
|
|
echo
|
|
done
|
|
|
|
# Calculate overall elapsed time
|
|
local overall_end_time=$(date +%s)
|
|
local overall_elapsed=$((overall_end_time - overall_start_time))
|
|
|
|
# Format overall elapsed time
|
|
local overall_elapsed_formatted
|
|
if [[ $overall_elapsed -ge 3600 ]]; then
|
|
overall_elapsed_formatted=$(printf "%dh %dm %ds" $((overall_elapsed / 3600)) $(((overall_elapsed % 3600) / 60)) $((overall_elapsed % 60)))
|
|
elif [[ $overall_elapsed -ge 60 ]]; then
|
|
overall_elapsed_formatted=$(printf "%dm %ds" $((overall_elapsed / 60)) $((overall_elapsed % 60)))
|
|
else
|
|
overall_elapsed_formatted="${overall_elapsed}s"
|
|
fi
|
|
|
|
if [[ $failed_targets -gt 0 && "${CONTINUE_ON_FAILURE:-}" != "1" ]]; then
|
|
echo "========================================="
|
|
echo "BUILD SUMMARY"
|
|
echo "========================================="
|
|
printf "\033[31m✗\033[0m Warning: %d targets had build failures\n" "$failed_targets"
|
|
echo "Total build time: ${overall_elapsed_formatted}"
|
|
return 1
|
|
else
|
|
echo "========================================="
|
|
echo "BUILD SUMMARY"
|
|
echo "========================================="
|
|
if [[ $failed_targets -gt 0 && "${CONTINUE_ON_FAILURE:-}" == "1" ]]; then
|
|
printf "\033[32m✓\033[0m All targets attempted successfully!\n"
|
|
echo " Note: Some language builds failed but were ignored due to --continue-on-failure"
|
|
else
|
|
printf "\033[32m✓\033[0m All targets built successfully!\n"
|
|
fi
|
|
echo "Total build time: ${overall_elapsed_formatted}"
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
show_usage() {
|
|
echo "EdgeTX Multi-Language Multi-Variant Build Script"
|
|
echo
|
|
echo "Usage: $0 [OPTIONS] [TARGET]"
|
|
echo
|
|
echo "Options:"
|
|
echo " -h, --help Show this help message"
|
|
echo " -l, --list-targets List all available firmware targets"
|
|
echo " -c, --list-color List color screen targets"
|
|
echo " -b, --list-bw List black & white screen targets"
|
|
echo " -L, --list-languages List all available languages (auto-detected)"
|
|
echo " --list-logographic List logographic/character-based languages"
|
|
echo " --list-color-targets-detected Show auto-detected color screen targets"
|
|
echo " --list-processors List targets grouped by STM32 processor type"
|
|
echo " -n, --dry-run Show what would be built without building"
|
|
echo " -f, --force-all Force build all languages for target (ignores screen type)"
|
|
echo " --continue-on-failure Continue building other languages/targets even after failures"
|
|
echo " --color-only Build all color screen targets only"
|
|
echo " --bw-only Build all black & white screen targets only"
|
|
echo " --processor PROC Build targets with specific STM32 processor (F2|F4|H7)"
|
|
echo " --exclude-processor PROC Build targets excluding specific processor"
|
|
echo " --filter-processor PROC Filter list commands by processor (F2|F4|H7|exclude-F2|etc.)"
|
|
echo
|
|
echo "Arguments:"
|
|
echo " TARGET [TARGET...] Build all valid languages for specific target(s)"
|
|
echo " (if not specified, builds all targets with screen type rules)"
|
|
echo
|
|
echo "Examples:"
|
|
echo " $0 # Build all languages for all targets"
|
|
echo " $0 tx16s # Build all languages for TX16S"
|
|
echo " $0 tx16s gx12 x9d # Build all languages for multiple targets"
|
|
echo " $0 x7 # Build non-logographic languages for X7 (B&W)"
|
|
echo " $0 -f x7 # Force build ALL languages for X7 (including CN,JP,KO,TW)"
|
|
echo " $0 -f tx16s st16 x9d # Force build ALL languages for multiple targets"
|
|
echo " $0 --color-only # Build all color screen targets with appropriate languages"
|
|
echo " $0 --bw-only # Build all B&W screen targets (excluding logographic)"
|
|
echo " $0 --bw-only -f # Build all B&W screen targets with ALL languages"
|
|
echo " $0 --processor F2 # Build all F2 processor targets"
|
|
echo " $0 --bw-only --processor F2 # Build F2 B&W targets only"
|
|
echo " $0 --exclude-processor F2 # Build all targets except F2"
|
|
echo " $0 -l # List all available targets"
|
|
echo " $0 -l --filter-processor F4 # List only F4 targets"
|
|
echo " $0 -c --filter-processor H7 # List only H7 color screen targets"
|
|
echo " $0 -b --filter-processor exclude-F2 # List B&W targets excluding F2"
|
|
echo " $0 --list-processors # Show all targets grouped by processor type"
|
|
echo " $0 -n x7 # Show what languages would be built for X7"
|
|
echo " $0 -n tx16s gx12 # Show what would be built for multiple targets"
|
|
echo " $0 --continue-on-failure x7 # Build all languages for X7 even if some fail"
|
|
echo " $0 --continue-on-failure --color-only # Build all color targets, continue on failures"
|
|
echo
|
|
echo "Language Rules:"
|
|
echo " - Color screen radios: All languages ($(get_radio_languages))"
|
|
echo " - B&W screen radios: All languages except logographic ($(get_logographic_languages))"
|
|
echo " - Force mode (-f): All languages regardless of screen type"
|
|
echo
|
|
echo "Auto-Detection:"
|
|
echo " - Languages: Parsed from radio/src/CMakeLists.txt"
|
|
echo " - Color targets: Detected from radio/src/targets/*/CMakeLists.txt"
|
|
echo " - Logographic languages: Configurable (override with LOGOGRAPHIC_LANGUAGES_OVERRIDE)"
|
|
}
|
|
|
|
# Function to list targets by screen type with optional processor filtering
|
|
list_targets_by_type() {
|
|
local screen_filter="$1" # "color", "bw", or "all"
|
|
local processor_filter="$2" # Optional: "F2", "F4", "H7", "exclude-F2", etc.
|
|
|
|
echo "Scanning for available targets..." >&2
|
|
local all_targets
|
|
local color_targets=""
|
|
local bw_targets=""
|
|
|
|
all_targets=$(get_all_targets)
|
|
|
|
# First, categorize by screen type
|
|
for target in $all_targets; do
|
|
if is_color_screen_target "$target"; then
|
|
color_targets="$color_targets $target"
|
|
else
|
|
bw_targets="$bw_targets $target"
|
|
fi
|
|
done
|
|
|
|
# Apply processor filter if specified
|
|
if [[ -n "$processor_filter" ]]; then
|
|
local filtered_color_targets=""
|
|
local filtered_bw_targets=""
|
|
|
|
if [[ "$processor_filter" == exclude-* ]]; then
|
|
# Exclude specific processor
|
|
local exclude_proc="${processor_filter#exclude-}"
|
|
for target in $color_targets; do
|
|
local target_processor=$(get_stm32_processor_type "$target")
|
|
if [[ "$target_processor" != "$exclude_proc" && "$target_processor" != "UNKNOWN" ]]; then
|
|
filtered_color_targets="$filtered_color_targets $target"
|
|
fi
|
|
done
|
|
for target in $bw_targets; do
|
|
local target_processor=$(get_stm32_processor_type "$target")
|
|
if [[ "$target_processor" != "$exclude_proc" && "$target_processor" != "UNKNOWN" ]]; then
|
|
filtered_bw_targets="$filtered_bw_targets $target"
|
|
fi
|
|
done
|
|
else
|
|
# Include only specific processor
|
|
for target in $color_targets; do
|
|
local target_processor=$(get_stm32_processor_type "$target")
|
|
if [[ "$target_processor" == "$processor_filter" ]]; then
|
|
filtered_color_targets="$filtered_color_targets $target"
|
|
fi
|
|
done
|
|
for target in $bw_targets; do
|
|
local target_processor=$(get_stm32_processor_type "$target")
|
|
if [[ "$target_processor" == "$processor_filter" ]]; then
|
|
filtered_bw_targets="$filtered_bw_targets $target"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
color_targets="$filtered_color_targets"
|
|
bw_targets="$filtered_bw_targets"
|
|
fi
|
|
|
|
# Display results based on screen filter
|
|
case "$screen_filter" in
|
|
"color")
|
|
if [[ -n "$processor_filter" ]]; then
|
|
echo "Color screen targets with processor filter ($processor_filter):"
|
|
else
|
|
echo "Color screen targets:"
|
|
fi
|
|
for target in $color_targets; do
|
|
echo " $target ($(get_stm32_processor_type "$target"))"
|
|
done
|
|
;;
|
|
"bw")
|
|
if [[ -n "$processor_filter" ]]; then
|
|
echo "Black & white screen targets with processor filter ($processor_filter):"
|
|
else
|
|
echo "Black & white screen targets:"
|
|
fi
|
|
for target in $bw_targets; do
|
|
echo " $target ($(get_stm32_processor_type "$target"))"
|
|
done
|
|
;;
|
|
"all")
|
|
if [[ -n "$processor_filter" ]]; then
|
|
echo "Color screen targets with processor filter ($processor_filter):"
|
|
else
|
|
echo "Color screen targets:"
|
|
fi
|
|
for target in $color_targets; do
|
|
echo " $target ($(get_stm32_processor_type "$target"))"
|
|
done
|
|
echo
|
|
if [[ -n "$processor_filter" ]]; then
|
|
echo "Black & white screen targets with processor filter ($processor_filter):"
|
|
else
|
|
echo "Black & white screen targets:"
|
|
fi
|
|
for target in $bw_targets; do
|
|
echo " $target ($(get_stm32_processor_type "$target"))"
|
|
done
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Function to list targets by processor type
|
|
list_targets_by_processor() {
|
|
local all_targets=$(get_all_targets)
|
|
local f2_targets=""
|
|
local f4_targets=""
|
|
local h7_targets=""
|
|
local unknown_targets=""
|
|
|
|
for target in $all_targets; do
|
|
local processor=$(get_stm32_processor_type "$target")
|
|
case "$processor" in
|
|
F2) f2_targets="$f2_targets $target" ;;
|
|
F4) f4_targets="$f4_targets $target" ;;
|
|
H7) h7_targets="$h7_targets $target" ;;
|
|
*) unknown_targets="$unknown_targets $target" ;;
|
|
esac
|
|
done
|
|
|
|
echo "Targets grouped by STM32 processor type:"
|
|
echo
|
|
echo "STM32F2 targets:"
|
|
for target in $f2_targets; do
|
|
echo " $target"
|
|
done
|
|
echo
|
|
echo "STM32F4 targets:"
|
|
for target in $f4_targets; do
|
|
echo " $target"
|
|
done
|
|
echo
|
|
echo "STM32H7 targets:"
|
|
for target in $h7_targets; do
|
|
echo " $target"
|
|
done
|
|
|
|
if [[ -n "$unknown_targets" ]]; then
|
|
echo
|
|
echo "Unknown processor targets:"
|
|
for target in $unknown_targets; do
|
|
echo " $target"
|
|
done
|
|
fi
|
|
}
|
|
|
|
# Main script logic
|
|
# Parse force flag first
|
|
FORCE_ALL_LANGUAGES=0
|
|
DRY_RUN=0
|
|
CONTINUE_ON_FAILURE=0
|
|
TARGET=""
|
|
SCREEN_TYPE_FILTER=""
|
|
PROCESSOR_FILTER=""
|
|
LIST_PROCESSOR_FILTER=""
|
|
ACTION=""
|
|
|
|
# Parse arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-h|--help)
|
|
show_usage
|
|
exit 0
|
|
;;
|
|
-l|--list-targets)
|
|
ACTION="list-all"
|
|
shift
|
|
;;
|
|
-c|--list-color)
|
|
ACTION="list-color"
|
|
shift
|
|
;;
|
|
-b|--list-bw)
|
|
ACTION="list-bw"
|
|
shift
|
|
;;
|
|
-L|--list-languages)
|
|
ACTION="list-languages"
|
|
shift
|
|
;;
|
|
--list-logographic)
|
|
ACTION="list-logographic"
|
|
shift
|
|
;;
|
|
--list-color-targets-detected)
|
|
ACTION="list-color-detected"
|
|
shift
|
|
;;
|
|
--list-processors)
|
|
ACTION="list-processors"
|
|
shift
|
|
;;
|
|
-n|--dry-run)
|
|
DRY_RUN=1
|
|
shift
|
|
;;
|
|
-f|--force-all)
|
|
FORCE_ALL_LANGUAGES=1
|
|
shift
|
|
;;
|
|
--continue-on-failure)
|
|
CONTINUE_ON_FAILURE=1
|
|
shift
|
|
;;
|
|
--color-only)
|
|
SCREEN_TYPE_FILTER="color"
|
|
shift
|
|
;;
|
|
--bw-only)
|
|
SCREEN_TYPE_FILTER="bw"
|
|
shift
|
|
;;
|
|
--processor)
|
|
if [[ -n "${2:-}" && ! "$2" =~ ^- ]]; then
|
|
PROCESSOR_FILTER="$2"
|
|
shift 2
|
|
else
|
|
echo "Error: --processor requires a processor type (F2|F4|H7)"
|
|
exit 1
|
|
fi
|
|
;;
|
|
--exclude-processor)
|
|
if [[ -n "${2:-}" && ! "$2" =~ ^- ]]; then
|
|
PROCESSOR_FILTER="exclude-$2"
|
|
shift 2
|
|
else
|
|
echo "Error: --exclude-processor requires a processor type (F2|F4|H7)"
|
|
exit 1
|
|
fi
|
|
;;
|
|
--filter-processor)
|
|
if [[ -n "${2:-}" && ! "$2" =~ ^- ]]; then
|
|
LIST_PROCESSOR_FILTER="$2"
|
|
shift 2
|
|
else
|
|
echo "Error: --filter-processor requires a processor type (F2|F4|H7|exclude-F2|etc.)"
|
|
exit 1
|
|
fi
|
|
;;
|
|
-*)
|
|
echo "Unknown option: $1"
|
|
show_usage
|
|
exit 1
|
|
;;
|
|
*)
|
|
if [[ -z "$TARGET" ]]; then
|
|
TARGET="$1"
|
|
else
|
|
# Support multiple targets - append to TARGET with space separator
|
|
TARGET="$TARGET $1"
|
|
fi
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Execute actions after all arguments are parsed
|
|
case "$ACTION" in
|
|
"list-all")
|
|
list_targets_by_type "all" "$LIST_PROCESSOR_FILTER"
|
|
exit 0
|
|
;;
|
|
"list-color")
|
|
list_targets_by_type "color" "$LIST_PROCESSOR_FILTER"
|
|
exit 0
|
|
;;
|
|
"list-bw")
|
|
list_targets_by_type "bw" "$LIST_PROCESSOR_FILTER"
|
|
exit 0
|
|
;;
|
|
"list-languages")
|
|
echo "All available languages:"
|
|
for lang in $(get_radio_languages); do
|
|
echo " $lang"
|
|
done
|
|
exit 0
|
|
;;
|
|
"list-logographic")
|
|
echo "Logographic/character-based languages:"
|
|
for lang in $(get_logographic_languages); do
|
|
echo " $lang"
|
|
done
|
|
echo
|
|
echo "These languages are not built for B&W screen radios (unless --force-all is used)."
|
|
exit 0
|
|
;;
|
|
"list-color-detected")
|
|
echo "Auto-detected color screen targets:"
|
|
for target in $(get_color_screen_targets); do
|
|
echo " $target"
|
|
done
|
|
exit 0
|
|
;;
|
|
"list-processors")
|
|
list_targets_by_processor
|
|
exit 0
|
|
;;
|
|
esac
|
|
|
|
# Export flags for use in functions
|
|
export FORCE_ALL_LANGUAGES
|
|
export DRY_RUN
|
|
export CONTINUE_ON_FAILURE
|
|
|
|
# Validate processor filter if specified
|
|
if [[ -n "$PROCESSOR_FILTER" ]]; then
|
|
proc="${PROCESSOR_FILTER#exclude-}"
|
|
if [[ "$proc" != "F2" && "$proc" != "F4" && "$proc" != "H7" ]]; then
|
|
echo "Error: Invalid processor type '$proc'. Valid options: F2, F4, H7"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Validate list processor filter if specified
|
|
if [[ -n "$LIST_PROCESSOR_FILTER" ]]; then
|
|
proc="${LIST_PROCESSOR_FILTER#exclude-}"
|
|
if [[ "$proc" != "F2" && "$proc" != "F4" && "$proc" != "H7" ]]; then
|
|
echo "Error: Invalid filter processor type '$proc'. Valid options: F2, F4, H7, exclude-F2, exclude-F4, exclude-H7"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Handle screen type filtering (--color-only or --bw-only)
|
|
if [[ -n "$SCREEN_TYPE_FILTER" ]]; then
|
|
if [[ -n "$TARGET" ]]; then
|
|
echo "Error: Cannot specify both screen type filter and individual target"
|
|
show_usage
|
|
exit 1
|
|
fi
|
|
|
|
build_targets_by_screen_type "$SCREEN_TYPE_FILTER" "$PROCESSOR_FILTER"
|
|
exit $?
|
|
fi
|
|
|
|
# Handle processor-only filtering (--processor or --exclude-processor without screen filter)
|
|
if [[ -n "$PROCESSOR_FILTER" && -z "$SCREEN_TYPE_FILTER" ]]; then
|
|
if [[ -n "$TARGET" ]]; then
|
|
echo "Error: Cannot specify both processor filter and individual target"
|
|
show_usage
|
|
exit 1
|
|
fi
|
|
|
|
# Build all targets (both color and B&W) with processor filter
|
|
filtered_targets=""
|
|
if [[ "$PROCESSOR_FILTER" == exclude-* ]]; then
|
|
filtered_targets=$(get_targets_excluding_processor "${PROCESSOR_FILTER#exclude-}")
|
|
else
|
|
filtered_targets=$(get_targets_by_processor "$PROCESSOR_FILTER")
|
|
fi
|
|
|
|
if [[ -z "$filtered_targets" ]]; then
|
|
echo "No targets match the processor filter: $PROCESSOR_FILTER"
|
|
exit 0
|
|
fi
|
|
|
|
echo "Building targets with processor filter: $PROCESSOR_FILTER"
|
|
echo "Selected targets: $filtered_targets"
|
|
echo
|
|
|
|
failed_targets=0
|
|
for target in $filtered_targets; do
|
|
echo "========================================"
|
|
echo "Processing target: $target ($(get_stm32_processor_type "$target") processor)"
|
|
echo "========================================"
|
|
|
|
if ! build_target_all_languages "$target"; then
|
|
((failed_targets++))
|
|
echo "Failed to build all languages for target $target"
|
|
fi
|
|
|
|
echo
|
|
done
|
|
|
|
if [[ $failed_targets -gt 0 ]]; then
|
|
echo "Warning: $failed_targets targets had build failures"
|
|
exit 1
|
|
else
|
|
echo "All targets built successfully!"
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
# Handle dry-run mode
|
|
if [[ $DRY_RUN -eq 1 ]]; then
|
|
if [[ -n "$TARGET" ]]; then
|
|
all_targets=$(get_all_targets)
|
|
|
|
# Convert TARGET string to array and validate all targets exist
|
|
read -ra target_array <<< "$TARGET"
|
|
for target in "${target_array[@]}"; do
|
|
if ! echo "$all_targets" | grep -q "^$target$"; then
|
|
echo "Error: Unknown target '$target'"
|
|
echo
|
|
echo "Available targets:"
|
|
list_targets_by_type "all"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# Build all specified targets in dry-run mode
|
|
echo "DRY-RUN: Building specified targets: ${target_array[*]}"
|
|
echo
|
|
|
|
for target in "${target_array[@]}"; do
|
|
echo "========================================"
|
|
echo "Processing target: $target"
|
|
echo "========================================"
|
|
|
|
build_target_all_languages "$target"
|
|
echo
|
|
done
|
|
exit 0
|
|
fi
|
|
# If no specific target, let it fall through to the default behavior below
|
|
# The dry-run logic is handled in build_single_target function
|
|
fi
|
|
|
|
# Handle target building
|
|
if [[ -n "$TARGET" ]]; then
|
|
all_targets=$(get_all_targets)
|
|
|
|
# Convert TARGET string to array and validate all targets exist
|
|
read -ra target_array <<< "$TARGET"
|
|
for target in "${target_array[@]}"; do
|
|
if ! echo "$all_targets" | grep -q "^$target$"; then
|
|
echo "Error: Unknown target '$target'"
|
|
echo
|
|
echo "Available targets:"
|
|
list_targets_by_type "all"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# Build all specified targets
|
|
failed_targets=0
|
|
overall_start_time=$(date +%s)
|
|
echo "Building specified targets: ${target_array[*]}"
|
|
echo
|
|
|
|
# Temporarily disable exit on error for target building
|
|
set +e
|
|
|
|
for target in "${target_array[@]}"; do
|
|
echo "========================================"
|
|
echo "Processing target: $target"
|
|
echo "========================================"
|
|
|
|
if ! build_target_all_languages "$target"; then
|
|
((failed_targets++))
|
|
echo "Failed to build all languages for target $target"
|
|
fi
|
|
|
|
echo
|
|
done
|
|
|
|
# Re-enable exit on error
|
|
set -e
|
|
|
|
# Calculate overall elapsed time
|
|
overall_end_time=$(date +%s)
|
|
overall_elapsed=$((overall_end_time - overall_start_time))
|
|
|
|
# Format overall elapsed time
|
|
if [[ $overall_elapsed -ge 3600 ]]; then
|
|
overall_elapsed_formatted=$(printf "%dh %dm %ds" $((overall_elapsed / 3600)) $(((overall_elapsed % 3600) / 60)) $((overall_elapsed % 60)))
|
|
elif [[ $overall_elapsed -ge 60 ]]; then
|
|
overall_elapsed_formatted=$(printf "%dm %ds" $((overall_elapsed / 60)) $((overall_elapsed % 60)))
|
|
else
|
|
overall_elapsed_formatted="${overall_elapsed}s"
|
|
fi
|
|
|
|
if [[ $failed_targets -gt 0 && "${CONTINUE_ON_FAILURE:-}" != "1" ]]; then
|
|
echo "========================================="
|
|
echo "BUILD SUMMARY"
|
|
echo "========================================="
|
|
printf "\033[31m✗\033[0m Warning: %d targets had build failures\n" "$failed_targets"
|
|
echo "Total build time: ${overall_elapsed_formatted}"
|
|
exit 1
|
|
else
|
|
echo "========================================="
|
|
echo "BUILD SUMMARY"
|
|
echo "========================================="
|
|
if [[ $failed_targets -gt 0 && "${CONTINUE_ON_FAILURE:-}" == "1" ]]; then
|
|
printf "\033[32m✓\033[0m All targets attempted successfully!\n"
|
|
echo " Note: Some language builds failed but were ignored due to --continue-on-failure"
|
|
else
|
|
printf "\033[32m✓\033[0m All targets built successfully!\n"
|
|
fi
|
|
echo "Total build time: ${overall_elapsed_formatted}"
|
|
exit 0
|
|
fi
|
|
else
|
|
# No target specified - build all targets
|
|
build_all_targets
|
|
exit $?
|
|
fi
|