Skip to content
neuralSPOT-X
User guide
HELIA HUB

Toolchain support

NSX generates a CMake toolchain file per build and points CMake at it. Three cross compilers are wired, and which one you get is a per-app setting you can override per run.

Name Toolchain file Compiler
arm-none-eabi-gcc arm-none-eabi-gcc.cmake Arm GNU Toolchain. The default.
gcc arm-none-eabi-gcc.cmake An alias for the above.
armclang armclang.cmake Arm Compiler for Embedded.
atfe atfe.cmake Arm Toolchain for Embedded.

arm-none-eabi-gcc is the default, it builds every packaged example, and it is the only one you need installed to get started. Anything else is rejected with the list:

Unknown toolchain 'clang'. Supported: arm-none-eabi-gcc, armclang, atfe, gcc

The toolchain files themselves are vendored into your app at cmake/nsx/toolchains/, so the exact flags any of them sets are readable in the app rather than hidden in the tool.

Per app, in nsx.yml:

toolchain: arm-none-eabi-gcc

Per run, on the command line:

Terminal window
nsx build --toolchain armclang

--toolchain is accepted by configure, build, flash, view and clean. Boards also declare which toolchains they support in board.yaml, and that list is what the board matrix shows. As everywhere else in NSX, a declared toolchain is a claim by the board’s author, not a record of a build that was run.

A board declares its toolchains in two places. board.yaml is the descriptor the board matrix and nsx board show present. The board module’s nsx-module.yaml carries a compatibility.toolchains list, and that is what nsx lock enforces: a target whose toolchain the module omits is refused at lock time, before anything is built. A descriptor may therefore not advertise a toolchain its module refuses; tests/test_packaged_board_toolchains.py pins the two lists to each other for every registered board.

Generated apps also ship cmake/presets/CMakePresets.json with a preset per toolchain, gcc-ninja, armclang-ninja and atfe-ninja, so an IDE can open the project and pick one without going through the CLI.

Most of a build is the same either way. Three things are not.

The compile definitions. Portable code that needs to know what compiled it can test for NSX_TOOLCHAIN_GCC, NSX_TOOLCHAIN_ARMCLANG or NSX_TOOLCHAIN_ATFE. GCC and ATfE additionally define gcc, because both present a GCC-compatible surface to SDK code that predates ATfE existing.

The linker input. GCC and ATfE take a linker script with -T; Arm Compiler for Embedded takes a scatter file with --scatter. That is why every board names both a .ld and a .sct variant. See Startup and linker.

The startup source. Arm Compiler for Embedded uses startup_keil6.c; GCC and ATfE use startup_gcc.c.

Source that needs to differ per compiler should test the NSX_TOOLCHAIN_* definitions rather than the compiler’s own macros, because __GNUC__ is true under ATfE as well. Attribute-level differences are already abstracted: NSX_SECTION, NSX_ALIGNED, NSX_WEAK and the rest in nsx_compiler.h expand correctly under all three. See Memory placement.

Terminal window
nsx doctor

The Arm GNU Toolchain is a required check. Arm Compiler for Embedded and ATfE are reported only when they are present, so a clean report does not mean you have all three. See Check your environment.

The default build directory is per board, not per toolchain. CMake caches the selected compiler there, so remove the generated build tree before switching compilers:

Terminal window
nsx clean --full
nsx build --toolchain armclang

Re-running configure with a different --toolchain against an existing build directory is the case worth avoiding, because CMake caches the compiler. Clean first.