Skip to content

arch/arm/cmake: do not link an executable to detect the compiler#19507

Open
casaroli wants to merge 1 commit into
apache:masterfrom
casaroli:fix-cmake-try-compile
Open

arch/arm/cmake: do not link an executable to detect the compiler#19507
casaroli wants to merge 1 commit into
apache:masterfrom
casaroli:fix-cmake-try-compile

Conversation

@casaroli

@casaroli casaroli commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

CMake validates a compiler by building and linking a small test program.
For a bare-metal cross toolchain that link cannot succeed on its own terms — no
start files, no default linker script, no libc — and the flags NuttX supplies
for it assume a toolchain shipped with newlib. arch/arm/src/cmake/gcc.cmake
sets:

set(CMAKE_EXE_LINKER_FLAGS_INIT "--specs=nosys.specs")

A perfectly usable arm-none-eabi-gcc built without those specs therefore
fails configuration before a single NuttX source file is considered.

Setting CMAKE_TRY_COMPILE_TARGET_TYPE to STATIC_LIBRARY in the ARM
toolchain file makes the detection step compile without linking. This is the
approach CMake documents for cross-compiling to bare metal, and NuttX does not
currently set it anywhere in the tree.

Impact

  • Users: the CMake build becomes usable with any ARM toolchain that lacks
    nosys.specs, including the Homebrew arm-none-eabi-gcc and other
    newlib-less builds. Previously it could not configure at all.
  • Toolchains that do ship nosys.specs: unaffected. The setting applies
    only to CMake's own compiler-detection step, not to the NuttX link.
  • Build process: no change to any produced artifact.
  • Documentation / hardware / security / compatibility: unaffected.

Testing

Board: mps3-an547:picostest, CMake + Ninja generator.

Before (master 7df7c6ee):

$ cmake -B build -DBOARD_CONFIG=mps3-an547:picostest -GNinja
    arm-none-eabi-gcc: fatal error: cannot read spec file 'nosys.specs': No such file or directory
    compilation terminated.
    ninja: build stopped: subcommand failed.

  CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
  CMakeLists.txt:481 (project)

-- Configuring incomplete, errors occurred!

After this patch, configuration succeeds:

$ cmake -B build -DBOARD_CONFIG=mps3-an547:picostest -GNinja
-- Check for working CXX compiler: /opt/homebrew/bin/arm-none-eabi-g++ - skipped
-- Detecting CXX compile features - done
-- Configuring done (2.5s)
-- Generating done (0.1s)
-- Build files have been written to: build

and the tree then compiles — 1248 objects built:

$ ninja -k 0
...
$ grep -c "Building C object" ninja.log
1248

The build stops at the final link, for a reason this patch does not address and
does not introduce:

FAILED: [code=1] nuttx
arm-none-eabi-g++: fatal error: cannot read spec file 'nosys.specs': No such file or directory

That is the NuttX link itself passing --specs=nosys.specs
(gcc.cmake:277), not CMake's detection step. With this patch the compile
phase is fully exercised on a newlib-less toolchain, where before nothing could
be configured.

(CONFIG_LIBM=y / CONFIG_LIBM_TOOLCHAIN=n was set for the run above, for the
same missing-newlib reason.)

Regression check on a toolchain that does ship newlib

The obvious question is whether this weakens compiler detection where it
currently works. Repeating the configure step with the Arm GNU Toolchain
15.2.Rel1:

Toolchain master with this patch
Arm GNU 15.2.Rel1 (has nosys.specs) configure OK configure OK
Homebrew 16.1.0 (no nosys.specs) configure FAILS configure OK

So the patch strictly widens the set of usable toolchains.

With the newlib toolchain the build then proceeds through 1120 objects and
stops at the final link — again identically with and without this patch:

ld: libs/libc/builtin/lib_builtin_forindex.c:62: undefined reference to `g_builtins'
sched/init/nx_bringup.c:391: undefined reference to `nsh_main'

That is this board config not linking its applications, which reproduces on
unmodified master and is unrelated to this change. I mention it only so the
absence of a nuttx binary in these logs is not mistaken for a regression.

@github-actions github-actions Bot added Arch: arm Issues related to ARM (32-bit) architecture Size: S The size of the change in this PR is small labels Jul 23, 2026
@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown

MemBrowse Memory Report

No memory changes detected for:

@casaroli
casaroli force-pushed the fix-cmake-try-compile branch from bc70a9f to 6cfd507 Compare July 23, 2026 06:47
CMake validates a compiler by building and linking a test program.  For a
bare metal cross toolchain that link cannot succeed on its own terms, and
the flags NuttX supplies for it assume a toolchain shipped with newlib:
gcc.cmake sets

  set(CMAKE_EXE_LINKER_FLAGS_INIT "--specs=nosys.specs")

A perfectly usable arm-none-eabi-gcc built without those specs therefore
fails configuration before a single NuttX source file is considered:

  arm-none-eabi-gcc: fatal error: cannot read spec file 'nosys.specs':
  No such file or directory
  CMake Error: ... CMake will not be able to correctly generate this
  project.

Setting CMAKE_TRY_COMPILE_TARGET_TYPE to STATIC_LIBRARY makes the
detection step compile without linking, which is the documented approach
for cross compiling to a bare metal target.  Toolchains that do ship
nosys.specs are unaffected: the flag only applies to CMake's own
detection, not to the NuttX link.

Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
@casaroli
casaroli force-pushed the fix-cmake-try-compile branch from 6cfd507 to 22f8bf8 Compare July 23, 2026 06:55
# Building a static library instead exercises the compiler and stops short of
# the link, which is the documented approach for this case.

set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we move to a more common places? since it isn't specific to arm.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe this is valid for x86 as well, on bare-metal only architectures I think it might not make sense.

I am ok with moving this to somewhere more generic. Where do you suggest?

I think we would need to make sure this is not included in the sim target. Right? WDYT?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arch: arm Issues related to ARM (32-bit) architecture Size: S The size of the change in this PR is small

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants