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
First off, I can see in in
$ 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
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!