TLDR: Is there a way I can include all symbols from a static library in a Rust executable? Maybe a linker arg?
I'm trying to build an executable which contains a statically-linked python interpreter. Symbols appear to be missing from the final executable, which is problematic because then other Python extensions can't find the symbols they need.
MacOS 10.15.4, if relevant.
I'm using the pyo3
crate, running its test suite as an example (cargo test --lib
). Let's take for example the symbol _PyTime_AsMilliseconds
.
First off, I can see in in libpython3.8.a
:
$ nm /Users/davidhewitt/.pyenv/versions/3.8.2/lib/libpython3.8.a | grep _PyTime_AsMilliseconds
0000000000000a40 T __PyTime_AsMilliseconds
Now, if I look in the pyo3
rlib, I can see the symbol was pulled into the rlib fine:
$ nm target/debug/deps/libpyo3-e43c0718695f9b17.rlib | grep _PyTime_AsMilliseconds
0000000000000a40 T __PyTime_AsMilliseconds
However, the pyo3
test suite has an error. The root cause is that the Python instruction import socket
fails, claiming the symbol __PyTime_AsMilliseconds
is missing. If I inspect the test executable, target/debug/deps/pyo3-274d132b5da7df6c
, this is indeed true. That symbol isn't there.
I guess that the linker has determined that that symbol wasn't used in the final executable, so stripped it out. That's technically not wrong, but unfortunately Python's socket module is implemented as a .so
dynamic library which expects all the Python interpreter's symbols it needs to be available at runtime.
Is there something I can do to work around this behaviour? I guess I want to force all symbols from the rlib to be present in the final executable. Possibly something like the link arg -Wl,-force_load
, but I can't figure out the right invocation.
Thanks in advance!