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

commit d4453654e4a41b53e374803401708bd4aca5c416
Author: Marco Casaroli <[email protected]>
AuthorDate: Wed Oct 21 00:21:34 2026 +0200

    arch: Compile an LTO module to machine code when gcc links it.
    
    With CONFIG_LTO_FULL, the Toolchain.defs of arm, arm64 and risc-v set
    LD to the gcc driver, and a loadable module (and a program of a kernel
    build) is linked with it, because MODULELD defaults to LD.  The partial
    link (-r) of LTO objects keeps only LTO data, which the loader cannot
    use: "Failed to execute program 'hello': -22", and nm says "plugin
    needed to handle lto object".
    
    Where these Toolchain.defs set LD to gcc for LTO, they now also set
    LDMODULELTOFLAGS and LDELFLTOFLAGS: -flinker-output=nolto-rel and the
    compile options of the module.  LDMODULEFLAGS and LDELFFLAGS use them
    next to -r.  The link then compiles the objects to machine code with
    the options of the module (-mthumb, -mlong-calls, ...).  Without these
    options the arm-none-eabi assembler stopped with "invalid constant
    (3e8) after fixup".
    
    crt0.o is now compiled without -flto.  It must be machine code in any
    case, and as LTO data it made LTO warn that crt0 and the program
    declare main() differently, which -Werror makes an error.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 arch/arm/src/Makefile                 |  2 +-
 arch/arm/src/common/Toolchain.defs    | 11 +++++++++--
 arch/arm64/src/Makefile               |  2 +-
 arch/arm64/src/Toolchain.defs         | 12 ++++++++++--
 arch/risc-v/src/Makefile              |  2 +-
 arch/risc-v/src/common/Toolchain.defs | 11 +++++++++--
 6 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/arch/arm/src/Makefile b/arch/arm/src/Makefile
index 3145100bc8b..5bdff52c61c 100644
--- a/arch/arm/src/Makefile
+++ b/arch/arm/src/Makefile
@@ -189,7 +189,7 @@ $(LDEMPTY_OBJ): common$(DELIM)arm_ldempty.c
        $(call COMPILE, $<, $@)
 
 $(STARTUP_OBJS): %$(OBJEXT): %.c
-       $(Q) $(CC) $(CELFFLAGS) -c common$(DELIM)crt0.c -o crt0$(OBJEXT)
+       $(Q) $(CC) $(filter-out -flto%,$(CELFFLAGS)) -c common$(DELIM)crt0.c -o 
crt0$(OBJEXT)
 
 ifeq ($(CONFIG_BUILD_FLAT),y)
 $(BIN): $(STARTUP_OBJS) $(OBJS)
diff --git a/arch/arm/src/common/Toolchain.defs 
b/arch/arm/src/common/Toolchain.defs
index deea8116de3..bec4dfbb971 100644
--- a/arch/arm/src/common/Toolchain.defs
+++ b/arch/arm/src/common/Toolchain.defs
@@ -317,6 +317,12 @@ else
       UNAR := $(CROSSDEV)gcc-ar x
       NM   := $(CROSSDEV)gcc-nm
       ARCHOPTIMIZATION += -fno-builtin
+
+      # gcc links a module.  The loader cannot use LTO data, so a partial link
+      # (-r) compiles the module to machine code with the module options.
+
+      LDMODULELTOFLAGS = -flinker-output=nolto-rel $(CMODULEFLAGS)
+      LDELFLTOFLAGS = -flinker-output=nolto-rel $(CELFFLAGS)
     endif
   endif
 
@@ -634,7 +640,8 @@ endif
 
 CMODULEFLAGS = $(CFLAGS) -fvisibility=hidden -mlong-calls # --target1-abs
 CXXMODULEFLAGS = $(CXXFLAGS) -fvisibility=hidden -mlong-calls
-LDMODULEFLAGS = -r -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/elf/gnu-elf.ld)
+LDMODULEFLAGS = -r $(LDMODULELTOFLAGS) \
+                -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/elf/gnu-elf.ld)
 
 # ELF module definitions
 
@@ -723,7 +730,7 @@ endif
 
 else
   ifneq ($(CONFIG_BINFMT_ELF_EXECUTABLE),y)
-    LDELFFLAGS += -r
+    LDELFFLAGS += -r $(LDELFLTOFLAGS)
   endif
 endif
 
diff --git a/arch/arm64/src/Makefile b/arch/arm64/src/Makefile
index 52bb3d04065..c96178f0ee5 100644
--- a/arch/arm64/src/Makefile
+++ b/arch/arm64/src/Makefile
@@ -143,7 +143,7 @@ $(sort $(COBJS) $(UCOBJS)): %$(OBJEXT): %.c
        $(call COMPILE, $<, $@)
 
 $(STARTUP_OBJS): %$(OBJEXT): %.c
-       $(Q) $(CC) $(CELFFLAGS) -c common$(DELIM)crt0.c -o crt0$(OBJEXT)
+       $(Q) $(CC) $(filter-out -flto%,$(CELFFLAGS)) -c common$(DELIM)crt0.c -o 
crt0$(OBJEXT)
 
 ifeq ($(CONFIG_BUILD_FLAT),y)
 $(BIN): $(OBJS) $(STARTUP_OBJS)
diff --git a/arch/arm64/src/Toolchain.defs b/arch/arm64/src/Toolchain.defs
index dad042310ce..102d19c38ac 100644
--- a/arch/arm64/src/Toolchain.defs
+++ b/arch/arm64/src/Toolchain.defs
@@ -250,6 +250,12 @@ ifeq ($(CONFIG_LTO_FULL),y)
     NM := $(CROSSDEV)gcc-nm
     ARCHOPTIMIZATION += -fuse-linker-plugin
     ARCHOPTIMIZATION += -fno-builtin
+
+    # gcc links a module.  The loader cannot use LTO data, so a partial link
+    # (-r) compiles the module to machine code with the module options.
+
+    LDMODULELTOFLAGS = -flinker-output=nolto-rel $(CMODULEFLAGS)
+    LDELFLTOFLAGS = -flinker-output=nolto-rel $(CELFFLAGS)
   endif
 endif
 
@@ -285,7 +291,8 @@ endif
 # Loadable module definitions
 
 CMODULEFLAGS = $(CFLAGS) -fvisibility=hidden # --target1-abs
-LDMODULEFLAGS = -r -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/elf/gnu-elf.ld)
+LDMODULEFLAGS = -r $(LDMODULELTOFLAGS) \
+                -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/elf/gnu-elf.ld)
 
 # ELF module definitions
 
@@ -296,11 +303,12 @@ CXXELFFLAGS = $(CXXFLAGS) -fvisibility=hidden # 
--target1-abs
 
 CXXELFFLAGS += -fno-use-cxa-atexit
 
-LDELFFLAGS = -r -e _start
+LDELFFLAGS = -r $(LDELFLTOFLAGS) -e _start
 ifneq ($(CONFIG_BUILD_KERNEL),y)
   # Flat build and protected elf entry point use crt0,
   # Kernel build will use apps/import/scripts/crt0
 
   LDELFFLAGS += $(TOPDIR)$(DELIM)arch$(DELIM)arm64$(DELIM)src$(DELIM)crt0.o
 endif
+
 LDELFFLAGS += -T $(call 
CONVERT_PATH,$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)elf$(DELIM)gnu-elf.ld)
diff --git a/arch/risc-v/src/Makefile b/arch/risc-v/src/Makefile
index 3a75dd4d501..055c057f7a2 100644
--- a/arch/risc-v/src/Makefile
+++ b/arch/risc-v/src/Makefile
@@ -144,7 +144,7 @@ $(COBJS) $(UCOBJS): %$(OBJEXT): %.c
        $(call COMPILE, $<, $@)
 
 $(STARTUP_OBJS): %$(OBJEXT): %.c
-       $(Q) $(CC) $(CELFFLAGS) -c common$(DELIM)crt0.c -o crt0$(OBJEXT)
+       $(Q) $(CC) $(filter-out -flto%,$(CELFFLAGS)) -c common$(DELIM)crt0.c -o 
crt0$(OBJEXT)
 
 ifeq ($(CONFIG_BUILD_FLAT),y)
 $(BIN): $(STARTUP_OBJS) $(OBJS)
diff --git a/arch/risc-v/src/common/Toolchain.defs 
b/arch/risc-v/src/common/Toolchain.defs
index f1262238e11..ab8f08ff0e7 100644
--- a/arch/risc-v/src/common/Toolchain.defs
+++ b/arch/risc-v/src/common/Toolchain.defs
@@ -389,6 +389,12 @@ else
       AR := $(CROSSDEV)gcc-ar rcs
       NM := $(CROSSDEV)gcc-nm
       ARCHOPTIMIZATION += -fno-builtin
+
+      # gcc links a module.  The loader cannot use LTO data, so a partial link
+      # (-r) compiles the module to machine code with the module options.
+
+      LDMODULELTOFLAGS = -flinker-output=nolto-rel $(CMODULEFLAGS)
+      LDELFLTOFLAGS = -flinker-output=nolto-rel $(CELFFLAGS)
     endif
   endif
 
@@ -442,7 +448,8 @@ endif
 # Loadable module definitions
 
 CMODULEFLAGS = $(CFLAGS) -fvisibility=hidden
-LDMODULEFLAGS = -r -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/elf/gnu-elf.ld)
+LDMODULEFLAGS = -r $(LDMODULELTOFLAGS) \
+                -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/elf/gnu-elf.ld)
 
 # ELF module definitions
 
@@ -456,7 +463,7 @@ CXXELFFLAGS += -fno-use-cxa-atexit
 LDELFFLAGS = -e _start
 
 ifeq ($(CONFIG_BINFMT_ELF_RELOCATABLE),y)
-  LDELFFLAGS += -r
+  LDELFFLAGS += -r $(LDELFLTOFLAGS)
 endif
 
 ifeq ($(CONFIG_ARCH_RV32),y)

Reply via email to