This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new d0886af95dc cmake: Link a loadable module through the compiler driver
with LTO.
d0886af95dc is described below
commit d0886af95dc1bba6c6db7495a48c68ba9182937f
Author: Marco Casaroli <[email protected]>
AuthorDate: Mon Oct 19 14:21:35 2026 +0200
cmake: Link a loadable module through the compiler driver with LTO.
With LTO, arm, arm64 and risc-v set CMAKE_LD to gcc, and
nuttx_add_application() links a loadable module with it. Two parts of
that link were wrong, so no module could be built or loaded.
The ELF link options of arm64 (--gc-sections, -Bstatic), risc-v
(--oformat) and arm (-Bstatic, and --unresolved-symbols and
--emit-relocs with CONFIG_PIC) are linker options. gcc does not know
them and stops with "unrecognized command-line option '--gc-sections'".
Give them with -Wl, when CMAKE_LD is gcc, as arm already did for
--gc-sections. An FDPIC module of arm is linked by the FDPIC linker, so
its options stay as they are.
The module objects and crt0 were compiled with -flto, and the partial
link (-r) keeps only LTO data, which the loader cannot use. When the
link mixes LTO and other objects, gcc compiles the LTO objects without
the options of the target, and an arm link stops with "uses VFP
register arguments, ... does not". Compile the objects of a loadable
module and STARTUP_OBJS (crt0) with ${NO_LTO} when LTO is on.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <[email protected]>
---
arch/arm/src/cmake/elf.cmake | 23 +++++++++++++----------
arch/arm64/src/cmake/elf.cmake | 11 +++++++++--
arch/risc-v/src/cmake/elf.cmake | 10 ++++++++--
cmake/nuttx_add_application.cmake | 13 +++++++++++++
4 files changed, 43 insertions(+), 14 deletions(-)
diff --git a/arch/arm/src/cmake/elf.cmake b/arch/arm/src/cmake/elf.cmake
index 45fb444a814..7d5febf29a5 100644
--- a/arch/arm/src/cmake/elf.cmake
+++ b/arch/arm/src/cmake/elf.cmake
@@ -27,6 +27,13 @@ nuttx_mod_compile_options(-fvisibility=hidden -mlong-calls)
nuttx_elf_compile_options_ifdef(CONFIG_UNWINDER_ARM -fno-unwind-tables
-fno-asynchronous-unwind-tables)
+# With LTO the compiler driver links the module: a linker option needs the -Wl,
+# prefix. The FDPIC linker links an FDPIC module.
+
+if(NOT CONFIG_FDPIC AND "${CMAKE_LD}" MATCHES "gcc$")
+ set(ELF_LD_OPTION -Wl,)
+endif()
+
if(CONFIG_FDPIC)
# An FDPIC module is a shared object whose two segments the loader places
@@ -86,8 +93,9 @@ elseif(CONFIG_PIC)
nuttx_elf_compile_options(-mpic-register=r9)
- nuttx_elf_link_options(--unresolved-symbols=ignore-in-object-files
- --emit-relocs)
+ nuttx_elf_link_options(
+ ${ELF_LD_OPTION}--unresolved-symbols=ignore-in-object-files
+ ${ELF_LD_OPTION}--emit-relocs)
endif()
@@ -102,14 +110,9 @@ if(NOT CONFIG_FDPIC)
nuttx_mod_link_options(-r)
endif()
-nuttx_elf_link_options_ifdef(CONFIG_BUILD_KERNEL -Bstatic)
+nuttx_elf_link_options_ifdef(CONFIG_BUILD_KERNEL ${ELF_LD_OPTION}-Bstatic)
-if(CONFIG_DEBUG_OPT_UNUSED_SECTIONS)
- if("${CMAKE_LD}" MATCHES "gcc$")
- nuttx_elf_link_options(-Wl,--gc-sections)
- else()
- nuttx_elf_link_options(--gc-sections)
- endif()
-endif()
+nuttx_elf_link_options_ifdef(CONFIG_DEBUG_OPT_UNUSED_SECTIONS
+ ${ELF_LD_OPTION}--gc-sections)
nuttx_elf_link_options(-e _start)
diff --git a/arch/arm64/src/cmake/elf.cmake b/arch/arm64/src/cmake/elf.cmake
index 2c0550f969e..1383f0bb8b0 100644
--- a/arch/arm64/src/cmake/elf.cmake
+++ b/arch/arm64/src/cmake/elf.cmake
@@ -28,8 +28,15 @@ nuttx_elf_link_options_ifdef(CONFIG_BINFMT_ELF_RELOCATABLE
-r)
nuttx_mod_link_options(-r)
-nuttx_elf_link_options_ifdef(CONFIG_BUILD_KERNEL -Bstatic)
+# With LTO the compiler driver links the module: a linker option needs -Wl,
-nuttx_elf_link_options_ifdef(CONFIG_DEBUG_OPT_UNUSED_SECTIONS --gc-sections)
+if("${CMAKE_LD}" MATCHES "gcc$")
+ set(ELF_LD_OPTION -Wl,)
+endif()
+
+nuttx_elf_link_options_ifdef(CONFIG_BUILD_KERNEL ${ELF_LD_OPTION}-Bstatic)
+
+nuttx_elf_link_options_ifdef(CONFIG_DEBUG_OPT_UNUSED_SECTIONS
+ ${ELF_LD_OPTION}--gc-sections)
nuttx_elf_link_options(-e _start)
diff --git a/arch/risc-v/src/cmake/elf.cmake b/arch/risc-v/src/cmake/elf.cmake
index 4ad92f1dd37..8453bb4a264 100644
--- a/arch/risc-v/src/cmake/elf.cmake
+++ b/arch/risc-v/src/cmake/elf.cmake
@@ -31,10 +31,16 @@ nuttx_mod_link_options(-r)
nuttx_elf_link_options_ifdef(CONFIG_BINFMT_ELF_RELOCATABLE -r)
+# With LTO the compiler driver links the module: a linker option needs -Wl,
+
+if("${CMAKE_LD}" MATCHES "gcc$")
+ set(ELF_LD_OPTION -Wl,)
+endif()
+
if(CONFIG_ARCH_RV32)
- nuttx_elf_link_options(--oformat elf32-littleriscv)
+ nuttx_elf_link_options(${ELF_LD_OPTION}--oformat=elf32-littleriscv)
else()
- nuttx_elf_link_options(--oformat elf64-littleriscv)
+ nuttx_elf_link_options(${ELF_LD_OPTION}--oformat=elf64-littleriscv)
endif()
nuttx_elf_link_options(-e _start)
diff --git a/cmake/nuttx_add_application.cmake
b/cmake/nuttx_add_application.cmake
index bf4b626ce93..f6a7e3b5842 100644
--- a/cmake/nuttx_add_application.cmake
+++ b/cmake/nuttx_add_application.cmake
@@ -254,6 +254,19 @@ function(nuttx_add_application)
)
endif()
+ # A partial link (-r) of LTO objects keeps only LTO data, which the
loader
+ # cannot use: compile the module and its crt0 to machine code.
+
+ if(NO_LTO
+ AND (CONFIG_LTO_FULL
+ OR CONFIG_LTO_THIN
+ OR CONFIG_LTO_FAT))
+ target_compile_options(${TARGET} PRIVATE ${NO_LTO})
+ if(TARGET STARTUP_OBJS)
+ target_compile_options(STARTUP_OBJS PRIVATE ${NO_LTO})
+ endif()
+ endif()
+
install(TARGETS ${TARGET})
set_property(
TARGET nuttx