Skip to content

Phase 1: build the NuttX runtime against NuttX 12 headers with GCC 15 - #2

Merged
NevynUK merged 5 commits into
MergeManagedCodefrom
Phase1
Oct 14, 2026
Merged

NevynUK merged 5 commits into
MergeManagedCodefrom
Phase1

Conversation

@NevynUK

@NevynUK NevynUK commented Oct 14, 2026

Copy link
Copy Markdown

Part of bringing the Mono runtime into the NuttX 12-based Meadow.OS (Meadow.OS MergeManagedCode, phase 1). The NuttX target was written against Meadow's old NuttX 7 headers. This makes it build cleanly against NuttX 12.12 with arm-none-eabi-gcc 15.3, keeping the existing -Wno-error=incompatible-pointer-types for HOST_NUTTX as decided.

This branch starts from meadow-3.0 (f980b4c), which is left untouched because Legacy builds it by name.

Commits

  1. Fix type mismatches exposed by NuttX 12 headers; drop the sys/random.h override. NuttX 12 makes int32_t long int (from __INT32_TYPE__), so five definitions written with int no longer matched their gint32/gboolean/int32_t declarations. GCC 14+ makes those hard errors; each definition now matches its declaration. The h_errno static asserts are skipped on NuttX: NuttX numbers those codes differently, and GetHostErrorCodes is never returned to managed code. The getrandom override no longer compiled because NuttX 12 has the POSIX three-argument call.
  2. Retire the NuttX 7 header workarounds.
    • Removed the errno override and -DO_CLOEXEC=0.
    • Cut nuttx-compat.h down to what NuttX 12 still lacks.
    • Fixed a latent bug: the fallback IFF_ALLMULTI (1 << 8) was NuttX's IFF_NAT.
    • pal_config.h now enables O_CLOEXEC, pipe2, chmod, aligned_alloc, pthread_condattr_setclock, utimensat and timespec stat times. Each was checked against the NuttX 12 headers and user-space libraries.
  3. Sentinel handle for dlopen(NULL). NuttX faults on a NULL file name. This replaces the NuttX libc patch the old firmware carried.
  4. Real-time signals SIGRTMIN + 1/2/3 for suspend, restart and abort, instead of 20/21/22, which are SIGTSTP/SIGTTIN/SIGTTOU on NuttX 12. Suspend stays cooperative.
  5. MONO_BUILD_DIR option in build-nuttx.sh, and a prototype for nxsock_close_notify.

Tested

  • Clean Release and Debug builds, 358/358 targets, via Meadow.OS build-mono.sh against the NuttX 12.12 headers. All the archives the OS link needs are produced.
  • All 86 remaining incompatible-pointer-types warnings were reviewed. Each is 32-bit int/long aliasing, which is harmless on ARM.
  • No hardware test: nothing is linked into the OS yet (agreed for phase 1).

Merge this before the Meadow.OS phase 1 PR. Meadow.OS's MONO_RUNTIME_COMMIT will then be moved to the merge commit.

🤖 Generated with Claude Code

NevynUK and others added 5 commits October 14, 2026 14:56
…om.h override

NuttX 12 takes int32_t from the compiler's __INT32_TYPE__, which is
'long int' for arm-none-eabi GCC, where the old NuttX 7 headers used
'int'.  gint32 and gboolean follow int32_t, so definitions written with
'int' no longer match prototypes written with gint32/gboolean/int32_t.
GCC 14 and later report these as hard errors (conflicting types).

Make each definition match its declaration:
- sgen_client_binary_protocol_sweep_begin/end: full_sweep is gboolean,
  as declared by sgen-protocol-def.h.
- ves_icall_RuntimeType_GetFunctionPointerTypeModifiers: position is
  gint32, as declared in icall-def.h.
- mono_regression_test_step: returns int, as declared by the public
  MONO_API prototype in mini-runtime.h.
- SystemNative_Select: maxFd is int32_t, as declared in pal_networking.h.

NuttX also numbers the h_errno codes differently (NO_DATA 2, TRY_AGAIN
4).  The static asserts that require them to match GetHostErrorCodes are
skipped on NuttX; GetHostErrorCodes values are never returned to managed
code, which receives resolver errors through the EAI_* conversion.

Remove the sys/random.h override.  It wrapped NuttX 7's two-argument
void getrandom() in a POSIX-style function; NuttX 12 declares the POSIX
ssize_t getrandom(void *, size_t, unsigned int) itself, so the wrapper's
two-argument call no longer compiles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The NuttX/Cortex-M7 target was first written against Meadow's NuttX 7
headers.  Meadow.OS now builds against NuttX 12, which provides most of
what those workarounds supplied, and some of the workarounds are wrong
there.

- Remove the errno.h override.  NuttX 12 already defines errno as
  (*__errno()), a per-thread lvalue in user space; the override also
  redirected set_errno() to a firmware helper that is no longer used.
- Stop passing -DO_CLOEXEC=0; NuttX 12 supports O_CLOEXEC.
- Reduce nuttx-compat.h to what NuttX 12 still lacks: the INT32_C family
  (now taken from the compiler, so they match __INT32_TYPE__), the dlmalloc
  mallinfo and page-size settings, _POSIX_HOST_NAME_MAX and IFF_ALLMULTI.
  The declarations of realpath, readlink, lstat, mkdtemp, posix_memalign,
  srand48/lrand48 and the math helpers are dropped, as are the SA_RESTART,
  _POSIX_VERSION and stale CONFIG_C99_BOOL8 definitions.  IFF_ALLMULTI is
  now 0: the old Linux value (1 << 8) is IFF_NAT on NuttX, so interfaces
  with NAT enabled were being reported as multicast-capable.  The other
  IFF_* fallbacks are removed; NuttX numbers those flags differently.
- Set HAVE_MKDTEMP for NuttX in configure.cmake instead of forcing it in
  the compat header.
- pal_config.h: NuttX 12 has F_DUPFD_CLOEXEC, O_CLOEXEC, pipe2, chmod,
  fchmod, aligned_alloc, pthread_condattr_setclock, utimensat, futimens,
  <sys/poll.h> and timespec st_atim/st_mtim/st_ctim.  Enable them and
  correct the comments that described NuttX 7.
- Correct the toolchain file's note on int32_t: NuttX 12 takes it from
  __INT32_TYPE__ ('long int' with arm-none-eabi GCC), so 'int *' and
  'int32_t *' mixes are -Wincompatible-pointer-types warnings (downgraded
  from errors in CMakeLists.txt for HOST_NUTTX).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mono_dl_open (NULL, ...) asks for a handle on the main program, which
reaches dlopen (NULL, flags) through mono_dl_open_file ().  NuttX's
dlopen () does not accept NULL: it duplicates the file name, which faults
on NULL.

On NuttX return a static sentinel for a NULL file name.  Symbol lookups
through it return NULL and closing it does nothing, which matches a
statically linked image with no exported dynamic symbol table; P/Invokes
are resolved by the host's PINVOKE_OVERRIDE callback.  This replaces the
patch to NuttX's lib_dlopen.c that the NuttX 7 firmware carried.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The NuttX 7 firmware only had signals 0-31, so the suspend, restart and
abort signals were fixed at 20, 21 and 22.  NuttX 12 supports signals up
to 63, reserves no real-time signals, and numbers 20-22 as SIGTSTP,
SIGTTIN and SIGTTOU.

Use SIGRTMIN + 1 (suspend), SIGRTMIN + 2 (restart) and SIGRTMIN + 3
(abort).  They stay fixed rather than searched for, so traces compare
between runs.  Suspend remains cooperative on NuttX (CMakeLists.txt).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
build-nuttx.sh: take the build directory from MONO_BUILD_DIR when it is
set, so that several NuttX checkouts can build this runtime without
sharing one build directory inside the runtime tree.  The default is
unchanged (build-nuttx-<type>).

pal_networking.h: declare nxsock_close_notify (), which the Meadow.OS
firmware calls from its close() wrapper.  It had no prototype
(-Wmissing-prototypes).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@NevynUK
NevynUK merged commit c668e4a into MergeManagedCode Oct 14, 2026
NevynUK added a commit to WildernessLabs/Meadow.OS that referenced this pull request Oct 14, 2026
WildernessLabs/runtime#2 merged Phase1 into the runtime's MergeManagedCode
as c668e4a3aea; the tree is unchanged (5cf48371256).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant