Skip to content

arch/*/src/Makefile: Avoid uncessary relinking of the nuttx binary.#18704

Draft
liamhickey2 wants to merge 1 commit intoapache:masterfrom
liamhickey2:EMB-59938-avoid-unnecessary-relinking
Draft

arch/*/src/Makefile: Avoid uncessary relinking of the nuttx binary.#18704
liamhickey2 wants to merge 1 commit intoapache:masterfrom
liamhickey2:EMB-59938-avoid-unnecessary-relinking

Conversation

@liamhickey2
Copy link
Copy Markdown

@liamhickey2 liamhickey2 commented Apr 10, 2026

Note: Please adhere to Contributing Guidelines.

Summary

The goal is to only execute recipes when there is an actual change in the prerequisites.

There were several issues which cause the nuttx binary target to be re-made every time the top level make is run, which was hiding some missing prerequisites.

Changes:

  1. vpath nuttx$(EXEEXT) $(TOPDIR) — so Make can find the existing binary
  2. FORCE pattern replaces .PHONY on libboard — sub-make always runs but nuttx only relinks when library content changes
  3. .config added as prerequisite to .tmp linker script rule — config changes trigger re-preprocessing
  4. Staging libs added as prerequisite to nuttx rule — changed libs trigger relink
  5. Stop deleting .tmp after link — preserves timestamps for dependency tracking
  6. use ifeq instead of #if - mistakenly used for conditional in libs/libc/misc/Make.defs
  7. use existing TESTANDREPLACEFILE instead of inplace sed - avoid touching file if there's no changes

Impact

This change ensures that we only run the nuttx recipe (and others) if the prerequisites are meaningfully out of date. In other words, the make should be faster and have a more concise output when there were no changes made by the user.

Testing

Methodology:

Scripts were made to reproduce build/test steps (e.g. make and touching files).

The change has the intended effects:

  • That is, it doesn't run recipes where the intended prerequisites haven't meaningfully changed. To test, I ran make twice with no changes, the second make shouldn't execute the nuttx target recipe (and link).

The change doesn't have unintended effects:

  • That is, when there are meaningful changes, we run the necessary recipes. To test, I made a trivial change in different prerequisites to ensure that the build works correctly.

Results:

  • PR branch off Nuttx main HEAD
  • Build host: Linux x86_64
  • Toolchain: arm-none-eabi-gcc
  • Target: qemu-armv7a:nsh (CONFIG_LIBC_UNAME_DISABLE_TIMESTAMP=y)

Intended effects (script: test-results/test-intended.sh, output: test-results/test-intended.log):

Two consecutive make runs with no changes — neither triggers LD: nuttx:
--- make (no changes, attempt 1) ---
CP: nuttx.bin
--- end ---

--- make (no changes, attempt 2) ---
CP: nuttx.bin
--- end ---

No unintended effects (script: test-results/test-unintended.sh, output: test-results/test-unintended.log):

Touching a source file recompiles and relinks, then stabilizes:
--- make (after touching arch/arm/src/chip/qemu_boot.c) ---
CC: chip/qemu_boot.c IN: libarch.a -> staging/libarch.a LD: nuttx CP: nuttx.bin
--- make (no changes after source touch) ---
CP: nuttx.bin

Touching .config re-preprocesses linker script and relinks, then stabilizes:
--- make (after touching .config) ---
CPP: dramboot.ld -> dramboot.ld.tmp LD: nuttx CP: nuttx.bin
--- make (no changes after .config touch) ---
CP: nuttx.bin

test-results.zip

Sanity Hardware Test:

The changes are only in the build system, but this confirms that everything is still built/linked correctly.

  • PR branch off NuttX master HEAD (4401b49)
  • Build host: Linux x86_64
  • Toolchain: arm-none-eabi-gcc
  • Target: nucleo-h563zi:nsh
$ arm-none-eabi-gdb nuttx
...
Reading symbols from nuttx...
(gdb) tar ext :8132
Remote debugging using :8132
nx_start () at init/nx_start.c:510
510	  g_nx_initstate = OSINIT_BOOT;
(gdb) load
...
(gdb) info breakpoints
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x08003a2a in nx_start at init/nx_start.c:510
(gdb) c
Continuing.

Breakpoint 1, nx_start () at init/nx_start.c:510
510	  g_nx_initstate = OSINIT_BOOT;
(gdb) 

@github-actions github-actions bot added Area: Build system Arch: arm Issues related to ARM (32-bit) architecture Arch: arm64 Issues related to ARM64 (64-bit) architecture Arch: risc-v Issues related to the RISC-V (32-bit or 64-bit) architecture Arch: simulator Issues related to the SIMulator Arch: x86_64 Issues related to the x86_64 architecture Arch: xtensa Issues related to the Xtensa architecture Size: S The size of the change in this PR is small labels Apr 10, 2026
@acassis acassis requested review from lupyuen and simbit18 April 10, 2026 21:11
@acassis
Copy link
Copy Markdown
Contributor

acassis commented Apr 10, 2026

@liamhickey2 thank you very much for this improvement.
I'm curious, how did you notice it was linking many times?

@liamhickey2
Copy link
Copy Markdown
Author

@liamhickey2 thank you very much for this improvement. I'm curious, how did you notice it was linking many times?

Hi Alan, I just noticed it from the make output. It's not a very important issue, but sometimes I run make when I'm not sure if I've compiled my changes already. I thought maybe other people would appreciate it if I upstreamed that, even if the linking is not very time consuming.

I'm looking into the failure in x86 (I can see its caused by the .tmp files being preserved), and I plan on uploading another sanity test since I ran that hardware test with a (patched) older version of nuttx. Sorry for the trouble, I haven't made any contributions to open source before.

@liamhickey2 liamhickey2 force-pushed the EMB-59938-avoid-unnecessary-relinking branch from 7e817cf to 2790c16 Compare April 10, 2026 22:17
The goal is to only execute recipes when there is an actual change in
the prerequisites.

There are several issues which cause the nuttx binary target to be
re-made every time the top level make is run.

1. Previously the target nuttx$(EXEEXT), was used, but make resolved
this in the relative directory make -C $(ARCH_SRC), and couldn’t find
it (need an absolute path: `$(TOPDIR)/..).

2. The .tmp prerequisite for nuttx was always deleted

3. libboard's recipe had a sub-make which may or may not update that
target. This was a phony target, and was therefore always considered out
of date.

These issues were causing the nuttx recipe to be run every make, which
was hiding some missing prerequisites:

1. the .config is a prerequisite for the .tmp target
2. libapps.a (and other linklibs) are pre-requisites for nuttx

Changes:

The changes are only in the build system, and only for arm.

Track nuttx$(EXEEXT) via vpath so Make knows when it's already up to
date without an explicit path. Add $(TOPDIR)/.config as a dependency
to the linker script preprocessing so config changes trigger
re-preprocessing.

Keep the .tmp linker script on disk (clean already removes it) so
timestamp-based dependency checking works across builds.

Use FORCE pattern for board/libboard to ensure it's always checked
but use the actual library file as the link dependency so nuttx is
only re-linked when library content changes. Add staging libs as
dependency to nuttx link rule so changed app libs trigger re-link.

Signed-off-by: Liam Hickey <williamhickey@geotab.com>
@liamhickey2 liamhickey2 force-pushed the EMB-59938-avoid-unnecessary-relinking branch from 2790c16 to a7267b9 Compare April 14, 2026 12:20
@liamhickey2
Copy link
Copy Markdown
Author

I'm not sure this failure is legitimate. Looking at the test output, there were no failing tests. Not sure if there's something I'm missing here:

https://github.com/apache/nuttx/actions/runs/24398561469/job/71303607293?pr=18704

================ 1224 passed, 548 skipped in 3745.46s (1:02:25) ================

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 Arch: arm64 Issues related to ARM64 (64-bit) architecture Arch: risc-v Issues related to the RISC-V (32-bit or 64-bit) architecture Arch: simulator Issues related to the SIMulator Arch: x86_64 Issues related to the x86_64 architecture Arch: xtensa Issues related to the Xtensa architecture Area: Build system 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