Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add rlib to rockbox-server crate-type so cdylib can pull it in

dlopen kept failing with "cannot locate symbol start_server" even after
adding extern "C" + #[used] keepalives. Root cause: rockbox-server's
crate-type was ["staticlib"] only — Cargo doesn't include staticlib-only
deps in the rustc rlib link graph for downstream cdylib builds, so
nothing in rockbox-server (start_server, start_servers, start_broker, the
HTTP/gRPC/GraphQL/MPD servers) made it into librockbox_expo.so.

Adding "rlib" to crate-type lets us reference rockbox-server items as
real Rust modules. The keepalive in daemon.rs now does
static _KEEPALIVE_ROCKBOX_SERVER: &[&str] = &rockbox_server::AUDIO_EXTENSIONS;
which forces rustc to compile rockbox-server's rlib into the cdylib,
bringing along start_server / start_servers / start_broker and every
sub-server they spawn.

Result: librockbox_expo.so jumps 14 MB → 44 MB (the full daemon code
is now actually linked, not stripped). All three start_* entry points
plus the netstream rb_net_* shims are now T (defined text), not U.

Desktop builds unaffected — the staticlib output for the Zig linker
is still produced (crate-type is now [staticlib, rlib]).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

+15 -3
+11 -2
crates/expo/src/daemon.rs
··· 44 44 fn start_servers(); 45 45 } 46 46 47 - /// `#[used]` keepalive: takes the address of start_server / start_servers 48 - /// so rustc treats them as live and pulls in their containing rlib. 47 + /// `#[used]` keepalives: take the address of start_server / start_servers 48 + /// so the symbols themselves don't get GC'd at link time. 49 49 #[used] 50 50 static _KEEPALIVE_START_SERVER: unsafe extern "C" fn() = start_server; 51 51 #[used] 52 52 static _KEEPALIVE_START_SERVERS: unsafe extern "C" fn() = start_servers; 53 + 54 + /// Force-pull rockbox-server's rlib into the link. `extern "C"` decls alone 55 + /// don't do this — rustc treats them as external and waits for the linker 56 + /// to satisfy them, which fails because rockbox-server's code was already 57 + /// dead-code-stripped. Referencing any pub Rust item (a const here) makes 58 + /// rustc include rockbox-server's compilation unit, which in turn provides 59 + /// the start_server / start_servers symbols. 60 + #[used] 61 + static _KEEPALIVE_ROCKBOX_SERVER: &[&str] = &rockbox_server::AUDIO_EXTENSIONS; 53 62 54 63 /// Same keepalive trick for the netstream Rust crate's C-ABI exports — 55 64 /// the C firmware's streamfd.c calls rb_net_open / rb_net_read / etc., but
+4 -1
crates/server/Cargo.toml
··· 4 4 version = "0.1.0" 5 5 6 6 [lib] 7 - crate-type = ["staticlib"] 7 + # rlib is needed so other Rust crates (like rockbox-expo's embedded-daemon 8 + # build) can reference rockbox-server items directly. The desktop build 9 + # also produces librockbox_server.a (staticlib) for the Zig linker. 10 + crate-type = ["staticlib", "rlib"] 8 11 9 12 [dependencies] 10 13 anyhow = "1.0.89"