Я разрабатываю библиотеку Rust, которая имеет Python привязок с использованием PyO3, которые построены с использованием maturin.
Проблема
Если я создаю привязки в своей ОС (Arch, с Glib c 2.31), то сгенерированный .whl не работает в старых системах, потому что Glib c несовместим и вызывает ошибку, например:
ImportError: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found
(required by /home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/my_package.cpython-37m-x86_64-linux-gnu.so)
Текущее решение
Чтобы решить эту проблему, мы строим наши привязки на centos 6.9 , который имеет Glib c 2.12, поэтому «должен быть совместим» почти со всеми Linux дистрибутивами.
Фактический вопрос
Это явно обходной путь, и должно быть лучшее решение.
Как правильно скомпилировать библиотеки maturin таким образом, чтобы они работали на большинстве из Linux дистрибутивов?
Насколько я понимаю, это то, для чего предназначен many linux standard , тогда почему он не работает? Что мне не хватает?
Моя гипотеза и тесты
Я предполагаю, что возможным решением было бы статически связать Glib c с библиотекой и, следовательно, настроить таргетинг на musl который предназначен для компиляции stati c.
Можно ли это сделать? Я нашел этот блог , в котором говорится, что это можно сделать, но я вижу, что внутри файлов .whl (которые представляют собой просто python устанавливаемые архивы) есть .so
, поэтому общая библиотека .
Можно ли было бы создать общую библиотеку, которая статически связала библиотеку c с помощью musl?
Я нашел возможный рабочий пример этого: Внутри тензорного потока, который tf_nightly-2.4.0.dev20200710-cp36-cp36m-manylinux2010_x86_64
, есть файл /tensorflow/python/_pywrap_utils.so
, который:
file _pywrap_utils.so [2]
_pywrap_utils.so: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), statically linked, BuildID[md5/uuid]=aee3c5fa4ae1243775857b2643b80ea0, not stripped
Но, похоже, он все равно динамически связывается:
ldd _pywrap_utils.so
linux-vdso.so.1 (0x00007fffb3782000)
libtensorflow_framework.so.2 => not found
_pywrap_tensorflow_internal.so => not found
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f5c95672000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f5c95658000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f5c95491000)
libm.so.6 => /usr/lib/libm.so.6 (0x00007f5c9534a000)
/usr/lib64/ld-linux-x86-64.so.2 (0x00007f5c95a9f000)```
Так возможно ли это на самом деле?
Некоторые люди , категорически не советуют делать это, почему? Я понимаю, что разные реализации потоков и распределителей в одном и том же исполняемом файле могут привести к проблемам совместимости.
Я пытался изменить Cargo.toml
с
[lib]
crate-type = ["cdylib"]
на это ( как показано здесь )
[lib]
crate-type = ["staticlib"]
, но Maturin, похоже, не доволен этим.
? maturin failed
Caused by: Cargo didn't build a cdylib. Did you miss crate-type = ["cdylib"] in the lib section of your Cargo.toml?
Возможно, это можно сделать с помощью флага компиляции crt-static
?