Description
Hi all,
I tried to link against a relocatable shared library on macOS with the following demo project: https://github.com/amyspark/rust-demo-rpath
The library rpath-meson
is built with Ninja:
cd rpath-meson
ninja
The library at this point is relocatable, as described in "Dynamic Library Identification" over at the Apple Developer forums:
otool output
❯ otool -L ./rpath-meson/librpath_meson.dylib
./rpath-meson/librpath_meson.dylib:
@rpath/librpath_meson.dylib (compatibility version 0.0.0, current version 0.0.0)
❯ otool -l ./rpath-meson/librpath_meson.dylib
./rpath-meson/librpath_meson.dylib:
Load command 0
cmd LC_SEGMENT_64
cmdsize 312
segname __TEXT
vmaddr 0x0000000000000000
vmsize 0x0000000000004000
fileoff 0
filesize 16384
maxprot 0x00000005
initprot 0x00000005
nsects 3
flags 0x0
Section
sectname __text
segname __TEXT
addr 0x0000000000003f90
size 0x000000000000000d
offset 16272
align 2^4 (16)
reloff 0
nreloc 0
flags 0x80000400
reserved1 0
reserved2 0
Section
sectname __cstring
segname __TEXT
addr 0x0000000000003f9d
size 0x000000000000000c
offset 16285
align 2^0 (1)
reloff 0
nreloc 0
flags 0x00000002
reserved1 0
reserved2 0
Section
sectname __unwind_info
segname __TEXT
addr 0x0000000000003fac
size 0x0000000000000048
offset 16300
align 2^2 (4)
reloff 0
nreloc 0
flags 0x00000000
reserved1 0
reserved2 0
Load command 1
cmd LC_SEGMENT_64
cmdsize 72
segname __LINKEDIT
vmaddr 0x0000000000004000
vmsize 0x0000000000004000
fileoff 16384
filesize 424
maxprot 0x00000001
initprot 0x00000001
nsects 0
flags 0x0
Load command 2
cmd LC_ID_DYLIB
cmdsize 56
name @rpath/librpath_meson.dylib (offset 24)
time stamp 1 Thu Jan 1 00:00:01 1970
current version 0.0.0
compatibility version 0.0.0
Load command 3
cmd LC_DYLD_CHAINED_FIXUPS
cmdsize 16
dataoff 16384
datasize 48
Load command 4
cmd LC_DYLD_EXPORTS_TRIE
cmdsize 16
dataoff 16432
datasize 16
Load command 5
cmd LC_SYMTAB
cmdsize 24
symoff 16456
nsyms 10
stroff 16616
strsize 192
Load command 6
cmd LC_DYSYMTAB
cmdsize 80
ilocalsym 0
nlocalsym 9
iextdefsym 9
nextdefsym 1
iundefsym 10
nundefsym 0
tocoff 0
ntoc 0
modtaboff 0
nmodtab 0
extrefsymoff 0
nextrefsyms 0
indirectsymoff 0
nindirectsyms 0
extreloff 0
nextrel 0
locreloff 0
nlocrel 0
Load command 7
cmd LC_UUID
cmdsize 24
uuid 42B5791C-F7EB-36DF-9F5B-123FBCC7C095
Load command 8
cmd LC_BUILD_VERSION
cmdsize 32
platform 1
minos 12.0
sdk 13.1
ntools 1
tool 3
version 820.1
Load command 9
cmd LC_SOURCE_VERSION
cmdsize 16
version 0.0
Load command 10
cmd LC_FUNCTION_STARTS
cmdsize 16
dataoff 16448
datasize 8
Load command 11
cmd LC_DATA_IN_CODE
cmdsize 16
dataoff 16456
datasize 0
This library is made available to Cargo through pkg-config
using:
❯ env PKG_CONFIG_PATH=$PWD/rpath-meson RUST_BACKTRACE=1 cargo run
I expected to see this happen:
❯ ./target/debug/rpath-demo
"Hello world"
Instead, this happened:
❯ ./target/debug/rpath-demo
dyld[5172]: Library not loaded: '@rpath/librpath_meson.dylib'
Referenced from: '/Users/amalia/Documents/rust-demo-rpath/target/debug/rpath-demo'
Reason: tried: '/Users/amalia/Documents/rust-demo-rpath/target/debug/deps/librpath_meson.dylib' (no such file), '/Users/amalia/Documents/rust-demo-rpath/target/debug/librpath_meson.dylib' (no such file), '/usr/local/Cellar/rust/1.79.0/lib/rustlib/x86_64-apple-darwin/lib/librpath_meson.dylib' (no such file), '/Users/amalia/lib/librpath_meson.dylib' (no such file), '/usr/local/lib/librpath_meson.dylib' (no such file), '/usr/lib/librpath_meson.dylib' (no such file)
fish: Job 1, 'env PKG_CONFIG_PATH=$PWD/rpath-…' terminated by signal SIGABRT (Abort)
This is because Cargo does not insert RPATH entries on its own. From searching older issues, a list of which is attached below, it seems that Cargo expects the environment to add the requisite flags. I have added such a flag through the pkg-config module; even though it is properly detected by pkg-config
and forwarded as a rustc-link-arg
entry, rustc-link-arg
flags are skipped by Cargo. This seems to be a known issue:
- Cargo can't set rpath into library or binary cargo#9966 (comment) (inability to set RPATH entries within Rust source code)
- Add a way to set arbitrary rpaths. cargo#5077 (setting arbitrary
-rpath
flags is disallowed) - rustc-link-arg does not propagate transitively cargo#9554 (comment) (detecting and using
DEP_*
environment variables for that) - Generate .cargo/config rusterlium/rustler#192 (linker flags inserted externally to fix producing a loadable module on macOS)
Using DEP_*
environment variables is very vaguely documented in rust-lang/cargo#7846 (comment) (there's no mention if cargo:rustc-link-arg
s are exposed like cargo:include
entries). However, it does not scale because it needs the participation of all consumers of the relocatable library.
Using a pkg-config module or other such tool would still need Cargo to support bubbling rustc-link-arg
s up to those crates generating loadable binaries.
Would it be possible for Rust/Cargo to consider bubbling up linker flags from -sys
crates up to the apex consumer (shared library/executable), or insert them on its own?
Meta
rustc --version --verbose
:
rustc 1.79.0 (129f3b996 2024-06-10) (Homebrew)
binary: rustc
commit-hash: 129f3b9964af4d4a709d1383930ade12dfe7c081
commit-date: 2024-06-10
host: x86_64-apple-darwin
release: 1.79.0
LLVM version: 18.1.7
Backtrace
rust-demo-rpath on main [⇡] via 🦀 v1.79.0
❯ env PKG_CONFIG_PATH=$PWD/rpath-meson RUST_BACKTRACE=1 cargo run
Compiling rpath-sys v0.1.0 (/Users/amalia/Documents/rust-demo-rpath/rpath-sys)
Compiling libc v0.2.155
Compiling rpath-demo v0.1.0 (/Users/amalia/Documents/rust-demo-rpath/rpath-demo)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 3.25s
Running `target/debug/rpath-demo`
dyld[5172]: Library not loaded: '@rpath/librpath_meson.dylib'
Referenced from: '/Users/amalia/Documents/rust-demo-rpath/target/debug/rpath-demo'
Reason: tried: '/Users/amalia/Documents/rust-demo-rpath/target/debug/deps/librpath_meson.dylib' (no such file), '/Users/amalia/Documents/rust-demo-rpath/target/debug/librpath_meson.dylib' (no such file), '/usr/local/Cellar/rust/1.79.0/lib/rustlib/x86_64-apple-darwin/lib/librpath_meson.dylib' (no such file), '/Users/amalia/lib/librpath_meson.dylib' (no such file), '/usr/local/lib/librpath_meson.dylib' (no such file), '/usr/lib/librpath_meson.dylib' (no such file)
fish: Job 1, 'env PKG_CONFIG_PATH=$PWD/rpath-…' terminated by signal SIGABRT (Abort)