Technicolor ARM Toolchain (Cortex-A9 + NEON)
This page documents how to prepare and use the Technicolor/OpenWrt-style cross toolchain located at:
~/firmware/technicolor_toolchain/toolchain-arm_cortex-a9+neon_gcc-4.8-linaro_glibc_eabi/
The toolchain provides binaries such as:
arm-openwrt-linux-gnueabi-gccarm-openwrt-linux-gnueabi-g++arm-openwrt-linux-gnueabi-ldarm-openwrt-linux-gnueabi-striparm-openwrt-linux-gnueabi-objcopyarm-openwrt-linux-gnueabi-objdumparm-openwrt-linux-gnueabi-readelfarm-openwrt-linux-gnueabi-gdb
Goals
- Ensure the toolchain is callable from any shell
- Verify it targets ARM EABI (gnueabi)
- Provide reproducible Makefile / CMake / Autotools patterns
- Avoid host header/library contamination
Directory Layout
~/firmware/technicolor_toolchain/
└── toolchain-arm_cortex-a9+neon_gcc-4.8-linaro_glibc_eabi/
├── bin/
├── lib/
├── include/
└── ...
The bin/ directory must be added to PATH.
1) Environment Setup
One-shot (Current Shell)
export TCROOT="~/firmware/technicolor_toolchain/toolchain-arm_cortex-a9+neon_gcc-4.8-linaro_glibc_eabi"
export PATH="$TCROOT/bin:$PATH"
export TARGET="arm-openwrt-linux-gnueabi"
export CROSS_COMPILE="$TARGET-"
export CC="${CROSS_COMPILE}gcc"
export CXX="${CROSS_COMPILE}g++"
export AR="${CROSS_COMPILE}ar"
export AS="${CROSS_COMPILE}as"
export LD="${CROSS_COMPILE}ld"
export RANLIB="${CROSS_COMPILE}ranlib"
export STRIP="${CROSS_COMPILE}strip"
export OBJCOPY="${CROSS_COMPILE}objcopy"
export OBJDUMP="${CROSS_COMPILE}objdump"
export READELF="${CROSS_COMPILE}readelf"
Persistent Setup (Recommended)
mkdir -p ~/.config/technicolor
nano ~/.config/technicolor/arm-a9-neon.env
Add:
export TCROOT="~/firmware/technicolor_toolchain/toolchain-arm_cortex-a9+neon_gcc-4.8-linaro_glibc_eabi"
export PATH="$TCROOT/bin:$PATH"
export TARGET="arm-openwrt-linux-gnueabi"
export CROSS_COMPILE="$TARGET-"
export CC="${CROSS_COMPILE}gcc"
export CXX="${CROSS_COMPILE}g++"
export AR="${CROSS_COMPILE}ar"
export RANLIB="${CROSS_COMPILE}ranlib"
export STRIP="${CROSS_COMPILE}strip"
Load when needed:
source ~/.config/technicolor/arm-a9-neon.env
2) Sanity Checks
Confirm Toolchain
which arm-openwrt-linux-gnueabi-gcc
arm-openwrt-linux-gnueabi-gcc -v
arm-openwrt-linux-gnueabi-gcc -dumpmachine
Expected output:
arm-openwrt-linux-gnueabi
Compile Test Program
cat > hello.c <<'EOF'
#include <stdio.h>
int main() { puts("hello"); return 0; }
EOF
$CC hello.c -o hello.arm
file hello.arm
$READELF -h hello.arm | sed -n '1,30p'
Expected result:
ELF 32-bit LSB executable, ARM, EABI5 ...
3) Cortex-A9 + NEON Compiler Flags
CFLAGS="-O2 -pipe -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp"
CXXFLAGS="$CFLAGS"
LDFLAGS=""
Warning
Most gnueabi toolchains use a soft-float ABI.
Do not use -mfloat-abi=hard unless the firmware userland is confirmed hard-float.
Optional (if firmware expects ARM mode instead of Thumb):
-marm
4) Sysroot & Preventing Host Contamination
Check sysroot:
$CC -print-sysroot
$CC -print-search-dirs
If valid:
SYSROOT="$($CC -print-sysroot)"
$CC --sysroot="$SYSROOT" $CFLAGS hello.c -o hello.arm
Best Practices
- Avoid
/usr/include - Avoid
/usr/lib - Use
--sysroot - Inspect verbose logs during build
5) Build System Recipes
A) Minimal Makefile
TARGET ?= hello
CC ?= arm-openwrt-linux-gnueabi-gcc
STRIP ?= arm-openwrt-linux-gnueabi-strip
CFLAGS ?= -O2 -pipe -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp
LDFLAGS ?=
all: $(TARGET)
$(TARGET): hello.c
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
$(STRIP) -s $@
clean:
rm -f $(TARGET)
Build:
make CC="$CC" STRIP="$STRIP"
B) Autotools
export CFLAGS="-O2 -pipe -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp"
export CXXFLAGS="$CFLAGS"
./configure \
--host=arm-openwrt-linux-gnueabi \
--build=$(gcc -dumpmachine) \
CC="$CC" CXX="$CXX" AR="$AR" RANLIB="$RANLIB" \
--prefix=/usr
make -j"$(nproc)"
C) CMake Toolchain File
Create toolchain-arm-openwrt.cmake:
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(TOOLCHAIN_PREFIX arm-openwrt-linux-gnueabi)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)
set(CMAKE_AR ${TOOLCHAIN_PREFIX}-ar)
set(CMAKE_RANLIB ${TOOLCHAIN_PREFIX}-ranlib)
set(CMAKE_STRIP ${TOOLCHAIN_PREFIX}-strip)
set(CMAKE_C_FLAGS "-O2 -pipe -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp")
set(CMAKE_CXX_FLAGS "-O2 -pipe -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
Build:
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=toolchain-arm-openwrt.cmake
cmake --build build -j"$(nproc)"
6) Debugging & Inspection
Inspect linked libraries:
$READELF -d yourbinary | grep -E 'NEEDED|RPATH|RUNPATH'
Architecture details:
file yourbinary
$READELF -A yourbinary | sed -n '1,120p'
Strip symbols:
$STRIP -s yourbinary
7) Common Failure Modes
Exec Format Error During Build
Cause: A configure script attempted to run an ARM binary on x86_64.
Fix:
--host=arm-openwrt-linux-gnueabi
--build=$(gcc -dumpmachine)
Disable runtime tests or cache results when necessary.
Header/Library Mismatch
Cause: Host /usr/include or /usr/lib contamination.
Fix:
- Use
--sysroot - Verify verbose logs
- Ensure CMake root path modes are
ONLY
Soft-Float vs Hard-Float Mismatch
Symptoms:
- Loader refusal
- Runtime crashes
Fix:
- Use
-mfloat-abi=softfp - Confirm ABI via:
readelf -A binary
Compare against target firmware libc.
Appendix: Environment Dump (Bug Reports)
echo "TCROOT=$TCROOT"
echo "$PATH" | tr ':' '\n' | head -15
$CC -v
$CC -dumpmachine
$CC -print-sysroot