cross-gcc
Use when compiling for ARM, AArch64, RISC-V, or MIPS from x86-64 with a GCC cross toolchain: triplets, sysroots, pkg-config, CMake toolchain files, QEMU. Not for Zig: use zig-cross.
Install
npx skills add https://github.com/OutlineDriven/outline-driven-development/tree/main/.devin/skills/cross-gcc
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install outlinedriven-outline-driven-development@llmmart
git clone https://github.com/OutlineDriven/outline-driven-development.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole outlinedriven/outline-driven-development collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Cross-compilation with GCC
Contract
| Field | Bound contract |
|---|---|
| Trigger | The user needs to build for a different architecture with a <triplet>-gcc toolchain, gets Exec format error or wrong ELF class, finds host libraries leaking into a cross link, or wants to run and debug a cross-built binary under QEMU. |
| Authority | Read-only. The skill emits install commands, compiler invocations, environment settings, and a toolchain file to chat; the user runs them. Rollback is not needed. No remote mutation. |
| Side effect | Chat output. Confirmation compiles run on scratch files. |
| Done | The triplet, toolchain, sysroot, and build-system wiring are stated for the target, every flag is confirmed against the GCC target-options documentation or the installed cross compiler, and each error in the request has a cause and fix. |
Inputs
- Target: required. Architecture, OS or bare metal, ABI, and CPU when known.
- Host distribution: required for install commands; the package names below are Debian and Ubuntu names.
- Whether the program links target libraries beyond libc: required; decides whether a sysroot is needed.
- Build system: required. Plain compiler, Make, autoconf, or CMake.
- GCC line of the cross compiler, from
<triplet>-gcc --version: required. Current stable is GCC 16.2; distribution cross packages often lag.
Procedure
Choose the triplet
<arch>-<vendor>-<os>-<abi>, three or four parts. Common values:aarch64-linux-gnu(64-bit ARM, glibc),arm-linux-gnueabihf(32-bit ARM, hard float),arm-none-eabi(bare-metal ARM),riscv64-linux-gnu,mipsel-linux-gnu,x86_64-w64-mingw32(Windows from Linux). Done when: one triplet is chosen.Install and confirm the toolchain. Debian and Ubuntu:
apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu binutils-aarch64-linux-gnu; bare-metal ARM:apt install gcc-arm-none-eabi. Confirm withaarch64-linux-gnu-gcc --version. Done when: the compiler prints its version.Compile. Hosted:
aarch64-linux-gnu-gcc -O2 -o hello hello.c,aarch64-linux-gnu-g++ -O2 -std=c++20 -o hello hello.cpp. Bare-metal Cortex-M4:arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -ffreestanding -nostdlib -nostartfiles -T linker.ld -o firmware.elf startup.s main.c. Target flags from the reference:-march,-mcpu,-mthumb,-mfloat-abi=soft|softfp|hard,-mfpu, and for AArch64-moutline-atomics; RISC-V uses-march=rv64gc -mabi=lp64dstyle ISA strings. Done when: the compile command names the CPU and ABI.Add a sysroot when the program links target libraries:
--sysroot=/path/to/sysrooton every compile and link. Sources: a vendor image,debootstrap --arch arm64 <suite> <dir>for Debian, or the Yocto or Buildroot output tree. Confirm withaarch64-linux-gnu-gcc --sysroot=<dir> -v -E - < /dev/null 2>&1 | grep sysroot. Done when: the sysroot path appears in the compiler's verbose output.Redirect pkg-config, which returns host paths by default:
export PKG_CONFIG_SYSROOT_DIR=<sysroot>,export PKG_CONFIG_LIBDIR=$PKG_CONFIG_SYSROOT_DIR/usr/lib/aarch64-linux-gnu/pkgconfig:$PKG_CONFIG_SYSROOT_DIR/usr/share/pkgconfig,export PKG_CONFIG_PATH=. Check withpkg-config --libs <lib>. Done when: the printed paths are under the sysroot.Wire the build system. Environment for Make and autoconf:
CC,CXX,AR,STRIP,OBJDUMPset to the triplet-prefixed tools, and./configure --host=aarch64-linux-gnu. CMake toolchain file:set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR aarch64) set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc) set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++) set(CMAKE_SYSROOT /path/to/sysroot) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)Configure with
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=aarch64.cmake. Done when: the build system resolves the cross compiler and searches only the sysroot for libraries.Run under QEMU user mode:
apt install qemu-user-static, thenqemu-aarch64-static ./hello; with binfmt_misc registered the binary runs directly. Debug:qemu-aarch64-static -g 1234 ./hello &thenaarch64-linux-gnu-gdb -ex "target remote :1234" ./hello. Done when: the binary runs or the debugger attaches.Map errors from the table. Done when: each reported error has a cause and fix.
Error Cause Fix cannot execute binary file: Exec format errorTarget binary run on the host Run under qemu-<arch>-staticwrong ELF class: ELFCLASS64(or 32)Object from another architecture in the link One toolchain for every object; check ARandCCld: cannot find -lfooHost library path used in a cross link Set --sysroot; fixPKG_CONFIG_LIBDIRundefined reference to '__aeabi_*'ARM runtime helpers missing from a -nostdliblinkAdd -lgccrelocation ... out of rangeCode or data too far apart for the relocation -mcmodel=largeor restructureunrecognized opcode-mcpuor-marchdoes not match the sourceSet the CPU flags for the real target
Failure and recovery
| Failure class | Behavior |
|---|---|
| No distribution package for the target | Point to the vendor toolchain download; do not invent a package name. |
| Sysroot lacks a needed library | Report the library as missing from the sysroot; the fix is to install it into the sysroot, not to use the host copy. |
| Windows target requested | Use the x86_64-w64-mingw32 triplet; MSVC-flavored builds: use msvc-cl. |
| No system cross toolchain wanted | zig cc -target cross-compiles C without one: use zig-cross. |
| Assembly-level question | AArch64 or ARM assembly: use assembly-arm. |
Output
A chat report with the triplet, install and confirmation commands, the compile command with target flags, sysroot and pkg-config settings when needed, the build-system wiring, the QEMU run or debug command, and the error table entries that apply. Flag details are in references/arm-flags.md.
Files (outline-driven-development)
-
agents
-
openai.yaml 216 B
interface: display_name: "Cross Gcc" short_description: "Use when compiling for ARM, AArch64, RISC-V, or MIPS from x86-64 with a GCC cross toolchain: triplets, sysroots, pkg-config, CMake toolchain files, QEMU."
-
-
references
-
arm-flags.md 2.3 KB
# ARM, AArch64, and RISC-V GCC target flags Sources: https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html, https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html, https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Options.html. Every flag and value below appears on those pages for GCC 16. ## AArch64 | Flag | Effect | |---|---| | `-march=armv8-a` | ARMv8-A baseline | | `-march=armv8.2-a+fp16` | ARMv8.2-A with the half-precision extension | | `-mcpu=cortex-a72` | Select and tune for Cortex-A72 | | `-mcpu=native` | Detect the host CPU; only for native AArch64 builds | | `-moutline-atomics` | Call runtime helpers that pick LSE atomics when the CPU has them | ## 32-bit ARM | Flag | Effect | |---|---| | `-march=armv7-a` | ARMv7-A (Cortex-A) | | `-march=armv7-m` | ARMv7-M (Cortex-M3) | | `-mcpu=cortex-m4` | Select and tune for Cortex-M4 | | `-mthumb` | Generate Thumb code | | `-mthumb-interwork` | Allow ARM and Thumb code to call each other | | `-mfloat-abi=soft` | Software floating point | | `-mfloat-abi=softfp` | Hardware FPU, floats passed in integer registers | | `-mfloat-abi=hard` | Hardware FPU, floats passed in FP registers | | `-mfpu=fpv4-sp-d16` | Cortex-M4 single-precision FPU | | `-mfpu=fpv5-d16` | Cortex-M7 double-precision FPU | | `-mfpu=neon-vfpv4` | NEON with VFPv4 | `-mfloat-abi` must match the libraries being linked; a hard-float object does not link against a soft-float libc. ## Bare-metal link ```bash arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 \ -ffreestanding -nostdlib -nostartfiles -T linker.ld -o firmware.elf startup.s main.c ``` `-ffreestanding` tells the compiler no hosted C library exists; `-nostdlib` drops the standard libraries from the link; `-nostartfiles` drops `crt0.o` and friends; `-T` selects the linker script. Add `-lgcc` back when the link reports missing `__aeabi_*` helpers. ## RISC-V | Flag | Effect | |---|---| | `-march=rv64gc` | 64-bit, general-purpose extensions plus compressed instructions | | `-march=rv32imc` | 32-bit, integer, multiply, compressed | | `-mabi=lp64d` | 64-bit ABI with double-precision floats in FP registers | | `-mabi=ilp32` | 32-bit ABI, soft float | | `-mcpu=sifive-u74` | SiFive U74 core | The `-march` string is composed from the base ISA and extension letters as the RISC-V options page describes; `rv64gc` and `rv32imc` are two such compositions.
-
-
SKILL.md 6.2 KB
--- name: cross-gcc description: 'Use when compiling for ARM, AArch64, RISC-V, or MIPS from x86-64 with a GCC cross toolchain: triplets, sysroots, pkg-config, CMake toolchain files, QEMU. Not for Zig: use zig-cross.' --- # Cross-compilation with GCC ## Contract | Field | Bound contract | |---|---| | Trigger | The user needs to build for a different architecture with a `<triplet>-gcc` toolchain, gets `Exec format error` or `wrong ELF class`, finds host libraries leaking into a cross link, or wants to run and debug a cross-built binary under QEMU. | | Authority | Read-only. The skill emits install commands, compiler invocations, environment settings, and a toolchain file to chat; the user runs them. Rollback is not needed. No remote mutation. | | Side effect | Chat output. Confirmation compiles run on scratch files. | | Done | The triplet, toolchain, sysroot, and build-system wiring are stated for the target, every flag is confirmed against the GCC target-options documentation or the installed cross compiler, and each error in the request has a cause and fix. | ## Inputs - Target: required. Architecture, OS or bare metal, ABI, and CPU when known. - Host distribution: required for install commands; the package names below are Debian and Ubuntu names. - Whether the program links target libraries beyond libc: required; decides whether a sysroot is needed. - Build system: required. Plain compiler, Make, autoconf, or CMake. - GCC line of the cross compiler, from `<triplet>-gcc --version`: required. Current stable is GCC 16.2; distribution cross packages often lag. ## Procedure 1. Choose the triplet `<arch>-<vendor>-<os>-<abi>`, three or four parts. Common values: `aarch64-linux-gnu` (64-bit ARM, glibc), `arm-linux-gnueabihf` (32-bit ARM, hard float), `arm-none-eabi` (bare-metal ARM), `riscv64-linux-gnu`, `mipsel-linux-gnu`, `x86_64-w64-mingw32` (Windows from Linux). Done when: one triplet is chosen. 2. Install and confirm the toolchain. Debian and Ubuntu: `apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu binutils-aarch64-linux-gnu`; bare-metal ARM: `apt install gcc-arm-none-eabi`. Confirm with `aarch64-linux-gnu-gcc --version`. Done when: the compiler prints its version. 3. Compile. Hosted: `aarch64-linux-gnu-gcc -O2 -o hello hello.c`, `aarch64-linux-gnu-g++ -O2 -std=c++20 -o hello hello.cpp`. Bare-metal Cortex-M4: `arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -ffreestanding -nostdlib -nostartfiles -T linker.ld -o firmware.elf startup.s main.c`. Target flags from the reference: `-march`, `-mcpu`, `-mthumb`, `-mfloat-abi=soft|softfp|hard`, `-mfpu`, and for AArch64 `-moutline-atomics`; RISC-V uses `-march=rv64gc -mabi=lp64d` style ISA strings. Done when: the compile command names the CPU and ABI. 4. Add a sysroot when the program links target libraries: `--sysroot=/path/to/sysroot` on every compile and link. Sources: a vendor image, `debootstrap --arch arm64 <suite> <dir>` for Debian, or the Yocto or Buildroot output tree. Confirm with `aarch64-linux-gnu-gcc --sysroot=<dir> -v -E - < /dev/null 2>&1 | grep sysroot`. Done when: the sysroot path appears in the compiler's verbose output. 5. Redirect pkg-config, which returns host paths by default: `export PKG_CONFIG_SYSROOT_DIR=<sysroot>`, `export PKG_CONFIG_LIBDIR=$PKG_CONFIG_SYSROOT_DIR/usr/lib/aarch64-linux-gnu/pkgconfig:$PKG_CONFIG_SYSROOT_DIR/usr/share/pkgconfig`, `export PKG_CONFIG_PATH=`. Check with `pkg-config --libs <lib>`. Done when: the printed paths are under the sysroot. 6. Wire the build system. Environment for Make and autoconf: `CC`, `CXX`, `AR`, `STRIP`, `OBJDUMP` set to the triplet-prefixed tools, and `./configure --host=aarch64-linux-gnu`. CMake toolchain file: ```cmake set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR aarch64) set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc) set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++) set(CMAKE_SYSROOT /path/to/sysroot) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) ``` Configure with `cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=aarch64.cmake`. Done when: the build system resolves the cross compiler and searches only the sysroot for libraries. 7. Run under QEMU user mode: `apt install qemu-user-static`, then `qemu-aarch64-static ./hello`; with binfmt_misc registered the binary runs directly. Debug: `qemu-aarch64-static -g 1234 ./hello &` then `aarch64-linux-gnu-gdb -ex "target remote :1234" ./hello`. Done when: the binary runs or the debugger attaches. 8. Map errors from the table. Done when: each reported error has a cause and fix. | Error | Cause | Fix | |---|---|---| | `cannot execute binary file: Exec format error` | Target binary run on the host | Run under `qemu-<arch>-static` | | `wrong ELF class: ELFCLASS64` (or 32) | Object from another architecture in the link | One toolchain for every object; check `AR` and `CC` | | `ld: cannot find -lfoo` | Host library path used in a cross link | Set `--sysroot`; fix `PKG_CONFIG_LIBDIR` | | `undefined reference to '__aeabi_*'` | ARM runtime helpers missing from a `-nostdlib` link | Add `-lgcc` | | `relocation ... out of range` | Code or data too far apart for the relocation | `-mcmodel=large` or restructure | | `unrecognized opcode` | `-mcpu` or `-march` does not match the source | Set the CPU flags for the real target | ## Failure and recovery | Failure class | Behavior | |---|---| | No distribution package for the target | Point to the vendor toolchain download; do not invent a package name. | | Sysroot lacks a needed library | Report the library as missing from the sysroot; the fix is to install it into the sysroot, not to use the host copy. | | Windows target requested | Use the `x86_64-w64-mingw32` triplet; MSVC-flavored builds: use msvc-cl. | | No system cross toolchain wanted | `zig cc -target` cross-compiles C without one: use zig-cross. | | Assembly-level question | AArch64 or ARM assembly: use assembly-arm. | ## Output A chat report with the triplet, install and confirmation commands, the compile command with target flags, sysroot and pkg-config settings when needed, the build-system wiring, the QEMU run or debug command, and the error table entries that apply. Flag details are in `references/arm-flags.md`.
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.