Kompilacja kończy się niepowodzeniem i komunikat „relocation R_X86_64_32 do„ .rodata.str1.8 ”nie może być użyty podczas tworzenia obiektu udostępnionego”


85

Próbuję skompilować ten kod źródłowy z pliku makefile w VPS, ale nie działa. VPS to 64-centowy system operacyjny

Oto pełny błąd

# 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

Oto mój plik makefile:

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

Czy ktoś wie, co się stało?


7
Próbowałeś recompile with -fPIC?
Joachim Isaksson

Przepraszam, ale nie wiem, jak to zrobić. W Google nie można znaleźć nic o „-fPIC”.
user1667191

4
Spróbuj czegoś takiego jakCOMPILE_FLAGS=-c -O3 -w -DLINUX -fPIC -I../SDK/amx/
Joachim Isaksson,


11
jeśli wyszukasz w google -fPIC, na pewno nic nie znajdziesz. Usuń minus lub użyj cudzysłowu „-fPIC”, w przeciwnym razie pominiesz wszystkie wyniki zawierające fPIC.
d00d

Odpowiedzi:


119

Rób to, co każe Ci kompilator, czyli przekompiluj z -fPIC. Aby dowiedzieć się, do czego służy ta flaga i dlaczego jest ona potrzebna w tym przypadku, zobacz Opcje generowania kodu w podręczniku GCC.

W skrócie, termin kod niezależny od pozycji (PIC) odnosi się do wygenerowanego kodu maszynowego, który jest niezależny od adresu pamięci, tj. Nie przyjmuje żadnych założeń co do miejsca załadowania go do pamięci RAM. Jedynie kod niezależny od pozycji powinien być zawarty w obiektach współdzielonych (SO), ponieważ powinny one mieć możliwość dynamicznej zmiany położenia w pamięci RAM.

Wreszcie możesz o tym poczytać również na Wikipedii .


3
Czy mógłbyś wyjaśnić, jak skompilować ponownie z -fPIC?
Beni Bogosel,

13
@Beni Bogosel: To bardzo proste. Po prostu dodajesz -fPICdo wszystkich wywołań kompilatora dla wszystkich plików źródłowych (jednostek tłumaczeniowych, np. *.cppPlików) biblioteki. Konkretny sposób wykonania tego zależy od używanego systemu kompilacji. Na przykład w CMake możesz wydać set_target_properties(${LIBRARY_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON). W przypadku tego gościa (używającego zwykłego starego Make) musiałby to zrobić, COMPILE_FLAGS+=-fPICponieważ używa tej zmiennej do oznaczenia zestawu flag kompilacji dla wszystkich plików źródłowych swojej biblioteki.
Alexander Shukaev,

1
aby włączyć -fPIC używając configure: configure --enable-shared, patrz stackoverflow.com/a/850464/440403
camino

50

W moim przypadku ten błąd wystąpił, ponieważ makepolecenie oczekiwało pobrania udostępnionych bibliotek ( *.soplików) ze zdalnego katalogu wskazanego przez LDFLAGSzmienną środowiskową. Przez pomyłkę były tam dostępne tylko biblioteki statyczne ( *.lalub *.apliki).

Dlatego mój problem nie dotyczył programu, który kompilowałem, ale zdalnych bibliotek, które próbowałem pobrać. Nie musiałem więc dodawać żadnej flagi (powiedzmy -fPIC) do kompilacji przerwanej przez błąd relokacji. Zamiast tego ponownie skompilowałem zdalną bibliotekę, aby udostępnione obiekty były dostępne.

Zasadniczo był to błąd polegający na nie znalezieniu pliku w przebraniu.

W moim przypadku musiałem usunąć niewłaściwie umieszczony --disable-sharedprzełącznik w configurewywołaniu wymaganego programu, ponieważ domyślnie zostały zbudowane biblioteki współdzielone i statyczne.


Zauważyłem, że większość programów buduje oba typy bibliotek w tym samym czasie, więc mój jest prawdopodobnie przypadkiem narożnym. Ogólnie rzecz biorąc, może się zdarzyć, że wolisz włączyć biblioteki współdzielone, w zależności od ustawień domyślnych.

Aby sprawdzić konkretną sytuację z przełącznikami kompilacji i ustawieniami domyślnymi, przeczytałbym podsumowanie, które pojawia się ./configure --help | less, zwykle w sekcji Funkcje opcjonalne. Często stwierdzałem, że ten odczyt jest bardziej wiarygodny niż instrukcje instalacji, które nie są aktualizowane w miarę rozwoju programów zależności.


1
Doskonale, „to był ukryty błąd polegający na nieodnalezieniu pliku”. W moim przypadku zależność nie została jeszcze zainstalowana.
Litty

+1 W moim przypadku nowsza kopia openssl została zbudowana ręcznie i zainstalowana bez współdzielonych bibliotek. Biblioteka, którą próbowałem zbudować, została już skompilowana z opcją -fPIC. Czy mimo to kompilator mógł rozpoznać ten błąd i podać mniej niejasny komunikat o błędzie, na przykład „Oczekiwano znalezienia biblioteki współdzielonej libssl.so, ale znalazł tylko niezgodną bibliotekę statyczną /usr/local/ssl/lib/libssl.a”. ?
Rohan Mahy,

1
Dzięki. Miałem make -j i równoległe wykonywanie nie było dozwolone dla tego pakietu oprogramowania.
MikeBergmann

W moim przypadku mam tę linię "find_library (NGHTTP2_LIB NAMES libnghttp2.a libnghttp2.so libnghttp2.dylib)". i tylko pobierał .a, później zmieniłem go na find_library (NGHTTP2_LIB NAMES libnghttp2.so libnghttp2.a libnghttp2.dylib) ”i zaczęło działać. Martwię się, czego używano wcześniej do pracy?
Naba Chinde

1
@NabaChinde Obawiam się, że nie mam odpowiedzi na Twoje pytanie również dlatego, że brakuje mi informacji kontekstowych na temat Twoich wyników. Z pewnością zachęciłbym do zadania osobnego pytania, w którym wyjaśnisz swoją sytuację w pracy i nieoczekiwane zachowanie.
XavierStuvw


10

Naprawiono to z -no-pieopcją na etapie linkera:

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

4

Po prostu wyczyszczenie projektu rozwiązało to dla mnie.

Mój projekt jest aplikacją C ++ (nie udostępnianą biblioteką). Przypadkowo otrzymałem ten błąd po wielu udanych kompilacjach.



0

Otrzymuję to samo rozwiązanie, co komentarz @ camino na https://stackoverflow.com/a/19365454/10593190 i odpowiedź XavierStuvw .

Mam go do pracy (do instalacji ffmpeg), po prostu przeinstalowując całość od początku, a wszystkie wystąpienia $ ./configurezastąpione przez $ ./configure --enable-shared(najpierw upewnij się, że usunąłeś wszystkie foldery i pliki, w tym pliki .so z poprzedniej próby).

Najwyraźniej to działa, ponieważ https://stackoverflow.com/a/13812368/10593190 .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.