Skip to content

Commit 883cc9f

Browse files
committed
Source config.local before generate_board_config.py for correct BASE_BOARD, related #262
Problem: When a user set BASE_BOARD in their distro's config.local (e.g. BASE_BOARD=raspberrypiarm64), generate_board_config.py never saw it because config.local was only sourced later inside src/config. This caused the Python script to default to raspberrypiarmhf, setting BASE_ARCH=armhf, which picked qemu-arm-static instead of qemu-aarch64-static — resulting in 'Invalid ELF image for this architecture' errors. Changes: 1. src/build: Pre-seed config.local alongside the dist config before generate_board_config.py runs. Also updated the heredoc BASE_BOARD check to look in both config and config.local. 2. src/config: Moved EXTRA_BOARD_CONFIG (generated board defaults from images.yml) sourcing to before variant/flavor config, so the priority order is now: generated defaults < variant < flavor < config.local. Previously config.local was silently overridden by EXTRA_BOARD_CONFIG. 3. tests/test_config_local_board.sh: Added unit tests verifying that config.local BASE_BOARD is correctly picked up by generate_board_config.py (4 test cases: default fallback, config.local override, config.local wins over config, config without config.local).
1 parent 79b77a4 commit 883cc9f

File tree

3 files changed

+273
-15
lines changed

3 files changed

+273
-15
lines changed

src/build

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,35 @@ set -x
88

99
define(){ IFS='\n' read -r -d '' ${1} || true; }
1010

11-
# Source in dist config to seed generate_board_config.py
12-
# but will then be overwritten ${CUSTOM_PI_OS_PATH}/config for
13-
# 'final' configuration
11+
# Pre-seed: source dist config and config.local to seed generate_board_config.py
12+
# with BASE_BOARD. The full/authoritative config sourcing happens later via
13+
# ${CUSTOM_PI_OS_PATH}/config inside the heredoc.
1414
source ${DIST_PATH}/config
15+
if [ -f "${DIST_PATH}/config.local" ]; then
16+
source "${DIST_PATH}/config.local"
17+
fi
1518

1619
define SCRIPT <<'EOF'
1720
BUILD_SCRIPT_PATH=$(dirname $(realpath -s $BASH_SOURCE))
1821
1922
# Config file can override BASE_BOARD from cli
2023
CONFIG_FILE="${DIST_PATH}"/config
2124
25+
CONFIG_LOCAL_FILE="${DIST_PATH}"/config.local
26+
2227
if [ -f "${CONFIG_FILE}" ]; then
23-
echo "Found a dist config file, if BASE_BOARD is set there will source it before generating the extra board config"
24-
BASE_BOARD_FROM_CONFIG=$(bash -c "source \"$CONFIG_FILE\" >/dev/null 2>&1; echo \$BASE_BOARD")
28+
echo "Found a dist config file, checking for BASE_BOARD in config and config.local..."
29+
BASE_BOARD_FROM_CONFIG=$(bash -c "source \"$CONFIG_FILE\" >/dev/null 2>&1; \
30+
[ -f \"$CONFIG_LOCAL_FILE\" ] && source \"$CONFIG_LOCAL_FILE\" >/dev/null 2>&1; \
31+
echo \$BASE_BOARD")
2532
if [ -n "$BASE_BOARD_FROM_CONFIG" ]; then
2633
export BASE_BOARD="$BASE_BOARD_FROM_CONFIG"
27-
echo "BASE_BOARD set to ${BASE_BOARD} from ${CONFIG_FILE} before generating board config."
34+
echo "BASE_BOARD set to ${BASE_BOARD} from dist config/config.local before generating board config."
2835
else
29-
echo "BASE_BOARD not found in ${CONFIG_FILE}. It will be set from the cli or fallback to raspberrypiarmhf"
36+
echo "BASE_BOARD not found in ${CONFIG_FILE} or ${CONFIG_LOCAL_FILE}. It will be set from the cli or fallback to raspberrypiarmhf"
3037
fi
3138
else
32-
echo "Config file ${CONFIG_FILE} does not exist. You probably want to create one for you distrubtion."
39+
echo "Config file ${CONFIG_FILE} does not exist. You probably want to create one for your distribution."
3340
fi
3441
3542

src/config

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ if [ "${BUILD_VARIANT}" != 'default' ]; then
5252
fi
5353
fi
5454

55+
# Import generated board config first (lowest priority, can be overridden by variant and config.local)
56+
if [ -f "${EXTRA_BAORD_CONFIG}" ]; then
57+
source "${EXTRA_BAORD_CONFIG}"
58+
else
59+
echo "Note: Not sourcing board config"
60+
fi
61+
5562
echo Import the variant config if we have one
5663
if [ -n "${VARIANT_CONFIG}" ] && [ -f "${VARIANT_CONFIG}" ]
5764
then
@@ -71,6 +78,9 @@ fi
7178

7279

7380

81+
# config.local is the highest-priority override — it wins over generated board
82+
# config, variant config, and flavor config. (It is also pre-seeded in src/build
83+
# so that generate_board_config.py can see BASE_BOARD early enough.)
7484
if [ -f "${DIST_PATH}/config.local" ]
7585
then
7686
echo "Sourcing distro config.local..."
@@ -88,13 +98,6 @@ MODULES_LIST="${TMP//)/,}"
8898
# [ -n "$BASE_CHROOT_SCRIPT_PATH" ] || BASE_CHROOT_SCRIPT_PATH=$BASE_SCRIPT_PATH/chroot_script
8999
[ -n "$BASE_MOUNT_PATH" ] || BASE_MOUNT_PATH=$BASE_WORKSPACE/mount
90100

91-
# Import remote and submodules config
92-
if [ -f "${EXTRA_BAORD_CONFIG}" ]; then
93-
source "${EXTRA_BAORD_CONFIG}"
94-
else
95-
echo "Note: Not sourceing board config"
96-
fi
97-
98101
export REMOTE_AND_META_CONFIG="$BASE_WORKSPACE"/remote_and_meta_config
99102
# Remote modules and meta modulese go in first if they want to change standard behaviour
100103
if [ -f "${REMOTE_AND_META_CONFIG}" ]; then

tests/test_config_local_board.sh

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
#!/bin/bash
2+
#
3+
# Test that config.local can override BASE_BOARD before generate_board_config.py runs.
4+
# This mimics the pre-seed flow in src/build.
5+
#
6+
7+
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8+
CUSTOMPIOS_ROOT="$(cd "${DIR}/.." && pwd)"
9+
10+
# Colors for output
11+
RED='\033[0;31m'
12+
GREEN='\033[0;32m'
13+
BLUE='\033[0;34m'
14+
NC='\033[0m' # No Color
15+
16+
test_count=0
17+
tests_passed=0
18+
failed_tests=()
19+
20+
print_test_header() {
21+
local test_name="$1"
22+
echo
23+
echo -e "${BLUE}════════════════════════════════════════════════════════════════════════════════"
24+
echo "TEST: $test_name"
25+
echo -e "════════════════════════════════════════════════════════════════════════════════${NC}"
26+
}
27+
28+
print_test_result() {
29+
local test_name="$1"
30+
local is_passed="$2"
31+
local detail="$3"
32+
33+
if $is_passed; then
34+
echo -e "${GREEN}✓ PASSED:${NC} $test_name"
35+
else
36+
echo -e "${RED}✗ FAILED:${NC} $test_name"
37+
echo -e "${BLUE}Detail:${NC} $detail"
38+
fi
39+
}
40+
41+
# Helper: mimic src/build pre-seed flow then run generate_board_config.py
42+
# Arguments:
43+
# $1 - path to dist config file
44+
# $2 - path to dist config.local file (or empty)
45+
# $3 - path to output script
46+
run_build_preseed_flow() {
47+
local config_file="$1"
48+
local config_local_file="$2"
49+
local output_script="$3"
50+
51+
# Run in a subshell to avoid polluting the test environment
52+
(
53+
# Unset BASE_BOARD to start clean
54+
unset BASE_BOARD
55+
56+
# Mimic src/build lines 14-17: source config, then config.local
57+
if [ -f "${config_file}" ]; then
58+
source "${config_file}"
59+
fi
60+
if [ -n "${config_local_file}" ] && [ -f "${config_local_file}" ]; then
61+
source "${config_local_file}"
62+
fi
63+
64+
# Mimic the heredoc bash -c check
65+
BASE_BOARD_FROM_CONFIG=$(bash -c "source \"${config_file}\" >/dev/null 2>&1; \
66+
[ -n \"${config_local_file}\" ] && [ -f \"${config_local_file}\" ] && source \"${config_local_file}\" >/dev/null 2>&1; \
67+
echo \$BASE_BOARD")
68+
if [ -n "$BASE_BOARD_FROM_CONFIG" ]; then
69+
export BASE_BOARD="$BASE_BOARD_FROM_CONFIG"
70+
fi
71+
72+
# Set CUSTOM_PI_OS_PATH so common.py can find images.yml
73+
export CUSTOM_PI_OS_PATH="${CUSTOMPIOS_ROOT}/src"
74+
75+
# Run generate_board_config.py
76+
python3 "${CUSTOMPIOS_ROOT}/src/custompios_core/generate_board_config.py" "${output_script}"
77+
)
78+
}
79+
80+
# Test 1: No config.local → defaults to armhf
81+
test_no_config_local_defaults_to_armhf() {
82+
local test_name="No config.local defaults to BASE_ARCH=armhf"
83+
print_test_header "$test_name"
84+
((test_count++))
85+
86+
local tmpdir=$(mktemp -d)
87+
local config_file="${tmpdir}/config"
88+
local output_script="${tmpdir}/board_config.sh"
89+
90+
# Create a dist config that does NOT set BASE_BOARD
91+
cat > "${config_file}" <<'CONF'
92+
# Dist config without BASE_BOARD
93+
export SOME_OTHER_VAR="hello"
94+
CONF
95+
96+
run_build_preseed_flow "${config_file}" "" "${output_script}"
97+
98+
local is_passed=false
99+
if [ -f "${output_script}" ] && grep -q 'BASE_ARCH="armhf"' "${output_script}"; then
100+
is_passed=true
101+
((tests_passed++))
102+
fi
103+
104+
echo "Generated board config:"
105+
[ -f "${output_script}" ] && cat "${output_script}" || echo "(file not created)"
106+
print_test_result "$test_name" "$is_passed" "Expected BASE_ARCH=\"armhf\" in output"
107+
$is_passed || failed_tests+=("$test_name")
108+
109+
rm -rf "${tmpdir}"
110+
}
111+
112+
# Test 2: config.local sets BASE_BOARD=raspberrypiarm64 → BASE_ARCH=arm64
113+
test_config_local_sets_arm64() {
114+
local test_name="config.local with BASE_BOARD=raspberrypiarm64 produces BASE_ARCH=arm64"
115+
print_test_header "$test_name"
116+
((test_count++))
117+
118+
local tmpdir=$(mktemp -d)
119+
local config_file="${tmpdir}/config"
120+
local config_local_file="${tmpdir}/config.local"
121+
local output_script="${tmpdir}/board_config.sh"
122+
123+
# Create a dist config that does NOT set BASE_BOARD
124+
cat > "${config_file}" <<'CONF'
125+
# Dist config without BASE_BOARD
126+
export SOME_OTHER_VAR="hello"
127+
CONF
128+
129+
# Create config.local that sets BASE_BOARD
130+
cat > "${config_local_file}" <<'CONF'
131+
export BASE_BOARD=raspberrypiarm64
132+
CONF
133+
134+
run_build_preseed_flow "${config_file}" "${config_local_file}" "${output_script}"
135+
136+
local is_passed=false
137+
if [ -f "${output_script}" ] && grep -q 'BASE_ARCH="arm64"' "${output_script}"; then
138+
is_passed=true
139+
((tests_passed++))
140+
fi
141+
142+
echo "Generated board config:"
143+
[ -f "${output_script}" ] && cat "${output_script}" || echo "(file not created)"
144+
print_test_result "$test_name" "$is_passed" "Expected BASE_ARCH=\"arm64\" in output"
145+
$is_passed || failed_tests+=("$test_name")
146+
147+
rm -rf "${tmpdir}"
148+
}
149+
150+
# Test 3: config.local overrides config's BASE_BOARD
151+
test_config_local_overrides_config() {
152+
local test_name="config.local BASE_BOARD overrides config BASE_BOARD"
153+
print_test_header "$test_name"
154+
((test_count++))
155+
156+
local tmpdir=$(mktemp -d)
157+
local config_file="${tmpdir}/config"
158+
local config_local_file="${tmpdir}/config.local"
159+
local output_script="${tmpdir}/board_config.sh"
160+
161+
# Config sets armhf board
162+
cat > "${config_file}" <<'CONF'
163+
export BASE_BOARD=raspberrypiarmhf
164+
CONF
165+
166+
# config.local overrides to arm64
167+
cat > "${config_local_file}" <<'CONF'
168+
export BASE_BOARD=raspberrypiarm64
169+
CONF
170+
171+
run_build_preseed_flow "${config_file}" "${config_local_file}" "${output_script}"
172+
173+
local is_passed=false
174+
if [ -f "${output_script}" ] && grep -q 'BASE_ARCH="arm64"' "${output_script}"; then
175+
is_passed=true
176+
((tests_passed++))
177+
fi
178+
179+
echo "Generated board config:"
180+
[ -f "${output_script}" ] && cat "${output_script}" || echo "(file not created)"
181+
print_test_result "$test_name" "$is_passed" "Expected BASE_ARCH=\"arm64\" (config.local should win)"
182+
$is_passed || failed_tests+=("$test_name")
183+
184+
rm -rf "${tmpdir}"
185+
}
186+
187+
# Test 4: Config sets BASE_BOARD, no config.local → uses config's value
188+
test_config_sets_board_no_local() {
189+
local test_name="Config sets BASE_BOARD=raspberrypiarm64, no config.local"
190+
print_test_header "$test_name"
191+
((test_count++))
192+
193+
local tmpdir=$(mktemp -d)
194+
local config_file="${tmpdir}/config"
195+
local output_script="${tmpdir}/board_config.sh"
196+
197+
# Config sets arm64 board
198+
cat > "${config_file}" <<'CONF'
199+
export BASE_BOARD=raspberrypiarm64
200+
CONF
201+
202+
run_build_preseed_flow "${config_file}" "" "${output_script}"
203+
204+
local is_passed=false
205+
if [ -f "${output_script}" ] && grep -q 'BASE_ARCH="arm64"' "${output_script}"; then
206+
is_passed=true
207+
((tests_passed++))
208+
fi
209+
210+
echo "Generated board config:"
211+
[ -f "${output_script}" ] && cat "${output_script}" || echo "(file not created)"
212+
print_test_result "$test_name" "$is_passed" "Expected BASE_ARCH=\"arm64\" from config"
213+
$is_passed || failed_tests+=("$test_name")
214+
215+
rm -rf "${tmpdir}"
216+
}
217+
218+
# Run all tests
219+
run_tests() {
220+
echo -e "${BLUE}Running config.local BASE_BOARD Tests${NC}"
221+
echo "═══════════════════════════════════════"
222+
223+
test_no_config_local_defaults_to_armhf
224+
test_config_local_sets_arm64
225+
test_config_local_overrides_config
226+
test_config_sets_board_no_local
227+
228+
# Print summary
229+
echo
230+
echo -e "${BLUE}Test Summary${NC}"
231+
echo "═══════════"
232+
echo "Total tests: $test_count"
233+
echo "Tests passed: $tests_passed"
234+
echo "Tests failed: $((test_count - tests_passed))"
235+
236+
if ((${#failed_tests[@]} > 0)); then
237+
echo
238+
echo -e "${RED}Failed Tests:${NC}"
239+
printf ' %s\n' "${failed_tests[@]}"
240+
return 1
241+
fi
242+
return 0
243+
}
244+
245+
# Run tests if script is executed directly
246+
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
247+
run_tests
248+
fi

0 commit comments

Comments
 (0)