Я пытаюсь понять, почему компоновщику не хватает некоторых статических библиотек при компиляции общего объекта.У меня проблемы с компиляцией с Makefile с использованием gcc 8.3.1 на CentOS 6 (установлен с помощью devtoolset-8).Этот make-файл отлично работает с gcc 9.1.0, установленным с Homebrew на OSX.
Шаг 1: Создание libcpysim.a
У меня есть набор файлов C ++, которые скомпилированы со следующими параметрами:
g++ -Wall -Wno-unused-result -Wsign-compare -Wunreachable-code -fwrapv -std=c++14 -libstdc++ -fPIC -c -g -O0 -I ./cpysim -o sim_core.o sim_core.cpp
Все эти файлы затем архивируются в статическую библиотеку:
ar rcs libcpysim.a sim_core.o foo.o bar.o ...
Шаг 2: Cythonizing код C ++ для создания общей библиотеки
Этап Cythonizing по сути3 части:
- Преобразование Cython в C ++
- Компиляция C ++ для объекта
- Связывание этого объекта с общей библиотекой
IЯ использую distutils, поэтому шаги 2 и 3 являются просто сгенерированными командами, которые я могу запустить из командной строки.Чтобы привести пример, сгенерированный Cython C ++ компилируется с
gcc -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -DNPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION -I. -I../build -I../dSFMT-src-2.2.3 -I../build/include -I../cpysim -I/tools/conda/anaconda3/2019.03/lib/python3.7/site-packages/numpy/core/include -I/tools/conda/anaconda3/2019.03/include/python3.7m -c afepma.cpp -o build/temp.linux-x86_64-3.7/afepma.o -libstdc++ -std=c++14 -g -O0
, и это затем связывается с
g++ -pthread -shared -B /tools/conda/anaconda3/2019.03/compiler_compat -L/tools/conda/anaconda3/2019.03/lib -Wl,-rpath=/tools/conda/anaconda3/2019.03/lib -Wl,--no-as-needed -Wl,--sysroot=/ build/temp.linux-x86_64-3.7/afepma.o -L../build -L../build/lib -lcpysim -o ../build/afepma.cpython-37m-x86_64-linux-gnu.so -g
Важно отметить, что статическая библиотека передаетсяс -lcpysim
.Если я запускаю это в подробном режиме с -Wl,-verbose
, я вижу в журнале, что эта библиотека была найдена:
attempt to open /tools/conda/anaconda3/2019.03/lib/libcpysim.so failed
attempt to open /tools/conda/anaconda3/2019.03/lib/libcpysim.a failed
attempt to open ../build/libcpysim.so failed
attempt to open ../build/libcpysim.a succeeded
Проблема
Когда я импортирую это и запускаю в python(опять же, это нормально работает с OSX, то же самое, что и Anaconda), я получаю неопределенный символ:
File "/project/sei/colin/system-model/sim/cpysim.py", line 39, in <module>
import build.afepma as afepma
ImportError: /project/sei/colin/system-model/build/afepma.cpython-37m-x86_64-linux-gnu.so: undefined symbol: _ZN6cpysim3Rng5RandnEv
Проверка объекта, на самом деле он отсутствует:
[colin:system-model]$ nm -pa build/afepma.cpython-37m-x86_64-linux-gnu.so | grep Randn
U _ZN6cpysim3Rng5RandnEv
и, очевидно, он присутствуетв версии для OSX.
Я прочитал одно предложение поместить библиотеки ПОСЛЕ основного объекта в команду компоновщика: Скомпилировать код Python в статически связанный исполняемый файл с помощью Cython
Другой предлагает включить весь архив: Связывание архивов (.a) в общий объект (.so)
Наконец, я обнаружил, что это конкретно относится к Cython: Какстатически связывать библиотеку при компиляции расширения модуля Python
Что касается первого предложения, я уже делаю это, библиотеки идут после основного объекта.Что касается второго предложения, то было бы неразумно включать весь архив в каждый общий объект.
Третье предложение работает, команда создания ссылок distutils выглядит следующим образом:
g++ -pthread -shared -B /tools/conda/anaconda3/2019.03/compiler_compat -L/tools/conda/anaconda3/2019.03/lib -Wl,-rpath=/tools/conda/anaconda3/2019.03/lib -Wl,--no-as-needed -Wl,--sysroot=/ build/temp.linux-x86_64-3.7/afepma.o ../build/libcpysim.a -L../build -L../build/lib -lcpysim -o ../build/afepma.cpython-37m-x86_64-linux-gnu.so -g
НО ПОЧЕМУ
В частности, почему поведение отличается между моими двумя платформами (я понимаю, конечно, это разумно, но я хочу точно знать, почему).
Кроме того, почему первое связываниекоманда, когда libcpysim.a
фактически была передана как библиотека, компоновщик не поднял _ZN6cpysim3Rng5RandnEv
, как мне кажется, должен?