Поведение компоновщика со статическими библиотеками - PullRequest
0 голосов
/ 10 июля 2019

Я пытаюсь понять, почему компоновщику не хватает некоторых статических библиотек при компиляции общего объекта.У меня проблемы с компиляцией с 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 части:

  1. Преобразование Cython в C ++
  2. Компиляция C ++ для объекта
  3. Связывание этого объекта с общей библиотекой

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, как мне кажется, должен?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...