Компиляция завершается неудачно с «перемещением R_X86_64_32 против` .rodata.str1.8 'не может использоваться при создании общего объекта »


85

Я пытаюсь скомпилировать этот исходный код из make-файла на VPS, но он не работает. VPS - это ОС 64 Cent

Вот полная ошибка

# make
gcc -c -O3 -w -DLINUX -I../SDK/amx/ ../SDK/amx/*.c
g++ -c -O3 -w -DLINUX -I../SDK/amx/ ../SDK/*.cpp
g++ -c -O3 -w -DLINUX -I../SDK/amx/ *.cpp
g++ -O2 -fshort-wchar -shared -o "TCP_V1.so" *.o
/usr/bin/ld: TCP-LINUX_V1.o: relocation R_X86_64_32 against `.rodata.str1.8' can not be     used when making a shared object; recompile with -fPIC
TCP-LINUX_V1.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
make: *** [all] Error 1

Вот мой make-файл:

GPP=g++
GCC=gcc
OUTFILE="TCP_V1.so"

COMPILE_FLAGS=-c -O3 -w -DLINUX -I../SDK/amx/

all:
    $(GCC) $(COMPILE_FLAGS) ../SDK/amx/*.c
    $(GPP) $(COMPILE_FLAGS) ../SDK/*.cpp
    $(GPP) $(COMPILE_FLAGS) *.cpp
    $(GPP) -O2 -fshort-wchar -shared -o $(OUTFILE) *.o

Кто-нибудь знает, что случилось?


7
Вы пробовали recompile with -fPIC?
Йоахим Исакссон

Извините, но я не знаю, как это сделать. Не могу найти в Google ничего о "-fPIC".
user1667191

4
Попробуйте что-нибудь вродеCOMPILE_FLAGS=-c -O3 -w -DLINUX -fPIC -I../SDK/amx/
Йоахим Исакссон


11
если вы выполните поиск в Google по запросу -fPIC, вы точно ничего не найдете. Удалите минус или используйте кавычки «-fPIC», иначе вы пропустите все результаты, содержащие fPIC.
d00d 07

Ответы:


119

Делайте то, что вам говорит компилятор, т.е. перекомпилируйте с -fPIC. Чтобы узнать, что делает этот флаг и зачем он вам нужен в этом случае, см. Параметры генерации кода в руководстве GCC.

Вкратце, термин независимый от позиции код (PIC) относится к сгенерированному машинному коду, который не зависит от адреса памяти, т.е. не делает никаких предположений о том, где он был загружен в RAM. В общие объекты (SO) должен быть включен только независимый от позиции код, поскольку они должны иметь возможность динамически изменять свое местоположение в ОЗУ.

Наконец, вы также можете прочитать об этом в Википедии .


3
Не могли бы вы объяснить, как перекомпилировать с -fPIC?
Beni Bogosel

13
@Beni Bogosel: Это очень просто. Вы просто добавляете его -fPICко всем вызовам компилятора для всех исходных файлов (единиц перевода, например, *.cppфайлов) библиотеки. Конкретный способ сделать это зависит от используемой вами системы сборки. Например, в CMake вы можете выпустить set_target_properties(${LIBRARY_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON). В случае с этим парнем (использующим старый добрый Make), ему придется это сделать, COMPILE_FLAGS+=-fPICпоскольку он использует эту переменную для обозначения набора флагов компиляции для всех исходных файлов своей библиотеки.
Александр Шукаев

1
чтобы включить -fPIC с помощью configure: configure --enable-shared, см. stackoverflow.com/a/850464/440403
camino

50

В моем случае эта ошибка возникла из-за того, что makeкоманда ожидала получить разделяемые библиотеки ( *.soфайлы) из удаленного каталога, указанного LDFLAGSпеременной среды. По ошибке там были доступны только статические библиотеки ( *.laили *.aфайлы).

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

По сути, это была замаскированная ошибка «файл не найден».

В моем случае мне пришлось удалить неуместный --disable-sharedпереключатель при configureвызове необходимой программы, поскольку как общие, так и статические библиотеки были созданы по умолчанию.


Я заметил, что большинство программ создают библиотеки обоих типов одновременно, поэтому моя, вероятно, является крайним случаем. В общем, может случиться так, что вам придется включать общие библиотеки, в зависимости от значений по умолчанию.

Чтобы изучить вашу конкретную ситуацию с переключателями компиляции и значениями по умолчанию, я бы зачитал сводку, которая отображается ./configure --help | less, как правило, в разделе Дополнительные функции. Я часто обнаруживал, что это чтение более надежно, чем руководства по установке, которые не обновляются по мере развития программ зависимостей.


1
Отлично, "это была замаскированная ошибка" файл не найден ". В моем случае зависимость еще не была установлена.
Litty

+1 В моем случае более новая копия openssl была собрана вручную и установлена ​​без разделяемых библиотек. Библиотека, которую я пытался собрать, уже была скомпилирована с -fPIC. Может ли компилятор каким-либо образом распознать эту ошибку, чтобы выдать менее непонятное сообщение об ошибке, например: «Ожидается найти общую библиотеку libssl.so, но обнаружена только несовместимая статическая библиотека /usr/local/ssl/lib/libssl.a». ?
Rohan Mahy

1
Благодарю. У меня была команда make -j, и параллельное выполнение этого программного пакета было запрещено.
MikeBergmann

В моем случае у меня есть строка «find_library (NGHTTP2_LIB NAMES libnghttp2.a libnghttp2.so libnghttp2.dylib)». и он собирал только файл .a, позже я изменил его на find_library (NGHTTP2_LIB NAMES libnghttp2.so libnghttp2.a libnghttp2.dylib) ", и он начал работать. Меня беспокоит, что он раньше работал у меня?
Naba Chinde

1
@NabaChinde Боюсь, что у меня нет ответа на ваш вопрос еще и потому, что мне не хватает контекстной информации о ваших результатах. Я бы настоятельно рекомендовал задать отдельный вопрос, в котором вы объясните свою рабочую ситуацию и неожиданное поведение.
XavierStuvw

11

Дело не всегда в флагах компиляции, у меня такая же ошибка на gentoo при использовании distcc.

Причина в том, что на сервере distcc используется не усиленный профиль, а на клиенте профиль усилен. Проверьте это обсуждение: https://forums.gentoo.org/viewtopic-p-7463994.html


10

Исправлено с -no-pieопцией на этапе компоновщика:

g++-8 -L"/home/pedro/workspace/project/lib" -no-pie ...

4

Простая очистка проекта решила эту проблему для меня.

Мой проект - это приложение на C ++ (не разделяемая библиотека). Я случайно получал эту ошибку после множества успешных сборок.



0

Я получаю то же решение, что и комментарий @ camino к ответу https://stackoverflow.com/a/19365454/10593190 и XavierStuvw .

Я заставил его работать (для установки ffmpeg), просто переустановив все с самого начала, $ ./configureзаменив все экземпляры на $ ./configure --enable-shared(сначала обязательно удалите все папки и файлы, включая файлы .so из предыдущей попытки).

По-видимому, это работает, потому что https://stackoverflow.com/a/13812368/10593190 .

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.