Ошибка компоновщика: «перемещение R_X86_64_PC32 против символа` xmlFree '... перекомпилировать с -fPI C », но некорректная библиотека уже была скомпилирована с -fPIC - PullRequest
1 голос
/ 07 мая 2020

Я пытаюсь создать общую библиотеку. Моя цель - собрать все зависимости в виде библиотек stati c в единую общую библиотеку. Насколько я понимаю, это можно сделать с помощью флага -Wl,--whole-archive. Вот фрагмент моего сценария CMake, отвечающего за настройку общей библиотеки.

    # shared library
    add_library(semsim SHARED "${SEMSIM_HEADERS}" "${SEMSIM_SOURCES}") # created the shared library
    #fPIC for linux shared library strs
    set_property(TARGET semsim PROPERTY POSITION_INDEPENDENT_CODE ON) #turn fPIC on 
    target_compile_options(semsim PRIVATE -Wl,--whole-archive) # enable pulling static libraries into shared library

Ошибка, которую я получаю при попытке компиляции (включен подробный режим):

/usr/bin/c++ -fPIC -std=c++14 -g  -shared -Wl,-soname,libsemsim.so -o libsemsim.so CMakeFiles/semsim.dir/CurlGet.cpp.o CMakeFiles/semsim.dir/RDFNode.cpp.o CMakeFiles/semsim.dir/Subject.cpp.o CMakeFiles/semsim.dir/Predicate.cpp.o CMakeFiles/semsim.dir/Resource.cpp.o CMakeFiles/semsim.dir/Triple.cpp.o CMakeFiles/semsim.dir/SemsimUtils.cpp.o CMakeFiles/semsim.dir/MetaID.cpp.o CMakeFiles/semsim.dir/XmlAssistant.cpp.o CMakeFiles/semsim.dir/Reader.cpp.o CMakeFiles/semsim.dir/Editor.cpp.o CMakeFiles/semsim.dir/Writer.cpp.o CMakeFiles/semsim.dir/RDF.cpp.o CMakeFiles/semsim.dir/Participant.cpp.o CMakeFiles/semsim.dir/PhysicalEntity.cpp.o CMakeFiles/semsim.dir/PhysicalPhenomenon.cpp.o CMakeFiles/semsim.dir/PhysicalProcess.cpp.o CMakeFiles/semsim.dir/PhysicalPropertyResource.cpp.o CMakeFiles/semsim.dir/PhysicalForce.cpp.o CMakeFiles/semsim.dir/Query.cpp.o CMakeFiles/semsim.dir/SemsimCombineArchive.cpp.o CMakeFiles/semsim.dir/Triples.cpp.o ../../third_party/libCombine-0.2.3/INSTALL/lib/libcombine-static.a ../../third_party/zipper/INSTALL/lib/libZipper-static.a ../../third_party/zlib-1.2.11/INSTALL/lib/libz.a /usr/local/lib/libbz2.a /usr/local/lib/libxml2.a -ldl -lbz2 -lz -lcurl -lxslt 
/usr/bin/ld: /usr/local/lib/libxml2.a(uri.o): relocation R_X86_64_PC32 against symbol `xmlFree' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status

Однако, согласно этому вопросу, /usr/local/lib/lxml2.a уже скомпилирован fPIC:

(base) ciaran@DESKTOP:/usr/local/lib$ ls
cmake            libcharset.so.1.0.0  libraptor2.a         librasqal.la        librdf.so        libxml2.so.2
libbz2.a         libcurlcpp.a         libraptor2.la        librasqal.so        librdf.so.0      libxml2.so.2.9.10
libcharset.a     libiconv.la          libraptor2.so        librasqal.so.3      librdf.so.0.0.0  pkgconfig
libcharset.la    libiconv.so          libraptor2.so.0      librasqal.so.3.0.0  libxml2.a        python2.7
libcharset.so    libiconv.so.2        libraptor2.so.0.0.0  librdf.a            libxml2.la       python3.6
libcharset.so.1  libiconv.so.2.6.1    librasqal.a          librdf.la           libxml2.so       xml2Conf.sh
(base) ciaran@DESKTOP:/usr/local/lib$ readelf -d libxml2.a | grep TEXT
(base) ciaran@DESKTOP:/usr/local/lib$

Это наводит меня на мысль, что, возможно, я неправильно понял сообщение об ошибке - может ли кто-нибудь пролить свет на то, что здесь происходит?

1 Ответ

1 голос
/ 09 мая 2020

Вы правильно поняли сообщение об ошибке или, по крайней мере, не поняли существенно.

Однако, согласно этому вопросу, /usr/local/lib/lxml2.a был уже скомпилирован fPI C

Вы делаете вывод, потому что команда:

/usr/local/lib$ readelf -d libxml2.a | grep TEXT

ничего не выводит, что показывает, что вы выбрали второй по популярности ответ на этот вопрос, хотя на момент написания этой статьи он не получил столько голосов, сколько самый популярный ответ

Думаю, вы сделали это, потому что самый популярный ответ говорит вам, как проверить объектный файл для PI C -ness, и вы хотите протестировать библиотеку, как это делает второй по популярности ответ. Или, возможно, потому, что вы сначала попробовали самый популярный ответ, и он показал, что ваш libxml2.a был PI C.

Но второй по популярности ответ проверяет общий , и вы используете ее для тестирования объектных файлов в библиотеке stati c. Общая библиотека сильно отличается от объектного файла или его библиотеки stati c, и вопрос, на который был дан этот ответ, спрашивает, как проверить PI C -носпособность объектного файла . Таким образом, этот ответ не отвечает на вопрос: на самом деле он предлагает, как проверить, действительно ли файл с именем, подобным общей библиотеке, является общей библиотекой.

Самый популярный ответ действительно отвечает на вопрос, и был ли правильный ответ, тогда он будет правильным и для вас, потому что компоновщик диагностировал:

/usr/local/lib/libxml2.a(uri.o): relocation R_X86_64_PC32 against symbol `xmlFree' \
can not be used when making a shared object; recompile with -fPIC

- это то, что объектный файл uri.o, заархивированный в libxml2.a, не является PI C.

Но самый популярный ответ, несмотря на его популярность, неверен. Тест на PI C, который он предлагает - без дополнительных аргументов - может ошибочно идентифицировать объектные файлы, не относящиеся к PI C, как PI C (как вы, возможно, заметили).

Ни один из ответов на этот вопрос - правильный ответ для вас, и неважно почему. Сам системный компоновщик является высшим авторитетом в отношении того, является ли объектный файл независимым от позиции. Любой однострочный тест, кроме попытки связать объектный файл с DSO, - это просто попытка переосмыслить компоновщик: если его вердикт отличается от компоновщика, это означает, что тест не работает, а не компоновщик.

И вы уже знаете вердикт линкера. Он попытался связать libxml2.a(uri.o) с DSO и обнаружил, что не может, потому что он содержит запись о перемещении, не зависящую от позиции.

/usr/local/lib/libxml2.a, который у вас есть, был построен на традиционное предположение по умолчанию, что объектные файлы, заархивированные в нем, не нужно компилировать в позиционно-независимый код (с -fPIC), потому что библиотека stati c будет вводиться только для связывания не-позиционно-независимых исполняемых файлов. Если вы хотите связать какой-либо двоичный файл PI, вы свяжете его с общей библиотекой libxml2.so, которая по определению является PI. Кроме того, ваш libxml2.a был построен с помощью компилятора, который по умолчанию не генерирует объектный код PI. Возможно, ваш текущий компилятор все еще имеет эту все более устаревшую черту, но вам не нужно выяснять.

Вам необходимо заменить локальную libxml2 инсталляцию той, в которой объектные файлы находятся в libxml2 были скомпилированы с помощью fPIC. Если вы уже знаете, как это сделать, можете пропустить остальную часть этого и продолжить.

Если у вас есть где-то исходный пакет libxml2, который был собран и установлен, и вы хотите придерживаться эту ревизию, затем cd в свой каталог root и запустите:

make uninstall

В противном случае удалите установку, удалив, как root, все файлы и символические ссылки, соответствующие /usr/local/lib/libxml2 и каталогу /usr/local/include/libxml2

Если вы хотите использовать уже имеющийся у вас пакет с исходным кодом (где вы запустили make uninstall), то в его каталоге root запустите:

make distclean

для восстановления первоначального состояния.

Если у вас нет пакета с исходным кодом, который вы хотите использовать, клонируйте или загрузите и извлеките последнюю версию из https://gitlab.gnome.org/GNOME/libxml2/, затем cd в каталог root и запустите:

./autogen.sh

для создания системы сборки.

Все, что вы сделали до сих пор, в каталоге root пакета затем запустите:

./configure CFLAGS=-fPIC [any other non-default configuration options]

Если это завершится успешно, запустите:

make

Если это завершится успешно, то как root запустите:

make install

Если это завершится успешно, то /usr/local/lib/libxml2.a будет воссоздан, содержащий файлы объектов PI, и вы сможете связать свою общую библиотеку с ним.

Если вы не уверены насчет [any other non-default configuration options] для команду ./configure, затем запустите:

./configure -h

, чтобы получить помощь и / или получить совет.

...