Embed whole python interpreter using static linking

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!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.