Skip to content

[build] E: Build libsqlite3.so alongside libsqlite3.a#268

Open
esaurez wants to merge 1 commit into
nanvix/v3.49.0from
feat/build-shared-library
Open

[build] E: Build libsqlite3.so alongside libsqlite3.a#268
esaurez wants to merge 1 commit into
nanvix/v3.49.0from
feat/build-shared-library

Conversation

@esaurez

@esaurez esaurez commented Jun 17, 2026

Copy link
Copy Markdown

Summary

Builds libsqlite3.so alongside the existing libsqlite3.a so consumers can dlopen sqlite3 at run time instead of statically linking it.

Why

Today the Nanvix sqlite port ships only libsqlite3.a. Anything that wants sqlite3 (e.g., cpython's _sqlite3 extension) has to statically embed it into the consumer binary. That works for cpython's monolithic python.elf but does not allow:

  • Sharing a single libsqlite3 implementation across multiple .so consumers in the same process.
  • Building a cpython _sqlite3.so that resolves sqlite3 via DT_NEEDED libsqlite3.so (the model already used by _ssl.solibssl.so and _ctypes.solibffi.so on Nanvix).

Producing libsqlite3.so here unblocks the cpython migration of _sqlite3 from --whole-archive .a in python.elf to DT_NEEDED .so.

What changed

sqlite uses autotools and the upstream --enable-shared path goes through libtool, which does not know about i686-nanvix. Rather than teaching libtool a new platform target, this PR keeps --disable-shared and links libsqlite3.so manually from the .a inside the build recipe, the same approach already taken by nanvix/libffi#235.

Concretely:

  • Makefile.nanvix:
    • CONFIGURE_ENV CFLAGS gains -fPIC so the same .o files compile into both .a and .so.
    • build recipe extended with a gcc -shared invocation that links libsqlite3.so from libsqlite3.a via -Wl,--whole-archive with DT_SONAME=libsqlite3.so and -nostdlib (libc / libm / libz UND, bind at dlopen).
    • LIB_ARTIFACTS gains libsqlite3.so, so the existing install recipe copies it to LIB_OUT automatically.
  • .nanvix/z.py:
    • _staged_output_files extended with libsqlite3.so so Windows tar-copy mode copies the install-staged .so back to the host workspace after the container exits.

Architecture

libsqlite3.so       (PIC-recompiled from libsqlite3.a)
  └── UND libc / libm / libz symbols (memcpy, malloc, deflate, ...)
      → resolved against the host executable's .dynsym at dlopen time

libsqlite3.a (unchanged shape; same .o files now compiled with -fPIC)

libsqlite3.so has no transitive .so dependencies (sqlite3 is self-contained; libc/libm/libz symbols are UND), so the loader does not need to walk any DT_NEEDED chain to load it.

Dependencies

Runtime dep (already merged upstream):

  • nanvix/nanvix#2473dlfcn init-array + DT_RUNPATH support. Required for any consumer to dlopen("libsqlite3.so") at run time.

Validation

Build runs end-to-end inside the toolchain-gcc Docker image:

$ ./z build
... (compiles sqlite3 sources with -fPIC) ...
i686-nanvix-gcc -shared -fPIC -nostdlib \
    -Wl,-soname,libsqlite3.so -Wl,-z,noexecstack \
    -Wl,--whole-archive libsqlite3.a -Wl,--no-whole-archive \
    -o libsqlite3.so
install -m 644 libsqlite3.a libsqlite3.so     /mnt/workspace/.nanvix/out/release/lib/
success: Build complete

Structural verification of the produced libsqlite3.so (~996 KB):

$ i686-nanvix-readelf -d .nanvix/out/release/lib/libsqlite3.so | grep -E 'SONAME|NEEDED'
 0x0000000e (SONAME)                     Library soname: [libsqlite3.so]

$ i686-nanvix-nm -D .nanvix/out/release/lib/libsqlite3.so | grep ' T sqlite3_' | head -5
0003d2c9 T sqlite3_aggregate_context
0003d46e T sqlite3_aggregate_count
0007b993 T sqlite3_auto_extension
000ba62e T sqlite3_autovacuum_pages
00033058 T sqlite3_backup_finish

SONAME correctly set, no spurious DT_NEEDED, full sqlite3_* public API exported, libc symbols left UND for runtime binding. The existing libsqlite3.a and sqlite3.elf test binary continue to build unchanged.

Adds a libsqlite3.so link step to the `build` recipe that links the
.so from the (now PIC) static archive via -Wl,--whole-archive so every
sqlite3 entry point becomes part of the .so's .dynsym. Sets
DT_SONAME=libsqlite3.so so consumers that link against it emit a
proper DT_NEEDED entry.

libsqlite3 is self-contained -- no transitive .so deps -- so the .so
records no DT_NEEDED of its own. libc / libm / libz symbols are left
UND via -nostdlib and bind at dlopen time against the host
executable's .dynsym, matching the model already used by libffi.so /
libssl.so.

Changes:

- Makefile.nanvix:
  - CONFIGURE_ENV CFLAGS gains -fPIC so the .o files used by
    libsqlite3.a are also usable by the .so link.
  - `build` recipe extended with a gcc -shared invocation that links
    libsqlite3.so from libsqlite3.a after the upstream `make all`
    completes.
  - LIB_ARTIFACTS gains "libsqlite3.so", so the `install` recipe
    copies it to LIB_OUT alongside libsqlite3.a (and `package` /
    `verify-package` pick it up via the same list).

- .nanvix/z.py:
  - _staged_output_files extended with libsqlite3.so so Windows
    tar-copy mode copies the install-staged .so back to the host
    workspace after the container exits.

Runtime dependency: the shared-library build becomes useful once the
loader changes in nanvix/nanvix#2473 ([syscall] E: Run dlopen
ctors/dtors and DT_RUNPATH) ship.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Builds and stages a Nanvix-compatible libsqlite3.so alongside the existing static libsqlite3.a, enabling consumers to dlopen() SQLite at runtime (e.g., CPython _sqlite3.so via DT_NEEDED libsqlite3.so) without going through upstream libtool-based --enable-shared.

Changes:

  • Add libsqlite3.so to the staged/install artifacts and to Windows tar-copy output files.
  • Compile SQLite objects as PIC (-fPIC) and manually link libsqlite3.so from libsqlite3.a via --whole-archive.
  • Clean up the newly produced shared object in make clean.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
Makefile.nanvix Adds PIC compilation and a manual gcc -shared link step to produce/stage libsqlite3.so.
.nanvix/z.py Ensures Windows tar-copy mode also copies the install-staged libsqlite3.so back to the host workspace.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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.

2 participants