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.
The names NSX accepts
Section titled “The names NSX accepts”| 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, gccThe 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.
Selecting one
Section titled “Selecting one”Per app, in nsx.yml:
toolchain: arm-none-eabi-gccPer run, on the command line:
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.
What differs between them
Section titled “What differs between them”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.
Checking what you have installed
Section titled “Checking what you have installed”nsx doctorThe 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.
Switching an existing app
Section titled “Switching an existing app”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:
nsx clean --fullnsx build --toolchain armclangRe-running configure with a different --toolchain against an existing build directory
is the case worth avoiding, because CMake caches the compiler. Clean first.