"공유 객체를 만들 때`.rodata.str1.8 '에 대한 재배치 R_X86_64_32를 사용할 수 없습니다."로 컴파일 실패


84

VPS의 makefile에서이 소스 코드를 컴파일하려고하는데 작동하지 않습니다. VPS는 64 Cent OS입니다.

다음은 전체 오류입니다.

# 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

내 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

아무도 무엇이 잘못되었는지 알고 있습니까?


6
해봤 어 recompile with -fPIC?
— Joachim Isaksson 2013 년

죄송합니다. 어떻게해야하는지 잘 모르겠습니다. Google에서 "-fPIC"에 대한 정보를 찾을 수 없습니다.
— user1667191

4
같은 것을 시도하십시오COMPILE_FLAGS=-c -O3 -w -DLINUX -fPIC -I../SDK/amx/
— Joachim Isaksson


9
Google에서 -fPIC를 검색하면 확실히 아무것도 찾을 수 없습니다. 마이너스를 제거하거나 따옴표 "-fPIC"를 사용하십시오. 그렇지 않으면 fPIC를 포함하는 모든 결과를 생략합니다.
— d00d

답변:


119

컴파일러가 지시하는대로 수행하십시오. 즉, -fPIC. 이 플래그의 기능과이 경우에 필요한 이유를 알아 보려면 GCC 매뉴얼의 코드 생성 옵션 을 참조하십시오 .

간단히 말해서, 위치 독립적 코드 (PIC)라는 용어는 메모리 주소에 구애받지 않는 생성 된 기계 코드를 의미합니다. 즉, RAM에로드 된 위치에 대해 어떠한 가정도하지 않습니다. 위치 독립적 코드 만 공유 객체 (SO)에 포함되어야합니다. RAM에서 위치를 동적으로 변경할 수있는 기능이 있어야합니다.

마지막으로 Wikipedia 에서도 읽을 수 있습니다.


3
-fPIC로 재 컴파일하는 방법을 설명해 주시겠습니까?
— Beni Bogosel 2014 년

12
@Beni Bogosel : 이것은 매우 간단합니다. 라이브러리의 -fPIC모든 소스 파일 (예 : *.cpp파일)에 대한 모든 컴파일러 호출에을 추가하기 만하면 됩니다. 이를 수행하는 구체적인 방법은 사용하는 빌드 시스템에 따라 다릅니다. 예를 들어 CMake에서 set_target_properties(${LIBRARY_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON). 이 사람의 경우 (평범한 오래된 Make 사용), COMPILE_FLAGS+=-fPIC이 변수를 사용하여 라이브러리의 모든 소스 파일에 대한 컴파일 플래그 집합을 나타 내기 때문에해야합니다.
— Alexander Shukaev 2014 년

1
configure를 사용하여 -fPIC를 활성화하려면 : configure --enable-shared, stackoverflow.com/a/850464/440403
— camino

49

제 경우에는 make명령이 환경 변수로 *.so표시된 원격 디렉토리에서 공유 라이브러리 ( 파일) 를 가져올 것으로 예상 했기 때문에이 오류가 발생했습니다 LDFLAGS. 실수로 정적 라이브러리 ( *.la또는 *.a파일) 만 사용할 수있었습니다 .

따라서 내 문제는 내가 컴파일하는 프로그램이 아니라 가져 오려는 원격 라이브러리에 있습니다. 따라서 -fPIC재배치 오류로 인해 중단 된 컴파일에 플래그 (예 :)를 추가 할 필요가 없습니다 . 오히려 공유 객체를 사용할 수 있도록 원격 라이브러리를 다시 컴파일했습니다.

기본적으로 disguise에서 파일을 찾을 수 없음 오류였습니다.

제 경우에는 공유 라이브러리와 정적 라이브러리가 모두 기본적으로 빌드 되었기 때문에 필수 프로그램 호출 --disable-shared에서 잘못 배치 된 스위치 를 제거해야했습니다 configure.


나는 대부분의 프로그램이 동시에 두 가지 유형의 라이브러리를 빌드한다는 것을 알았습니다. 일반적으로 기본값에 따라 공유 라이브러리를 활성화해야하는 경우가 있습니다.

컴파일 스위치 및 기본값을 사용하여 특정 상황을 검사하기 위해 ./configure --help | less일반적으로 옵션 기능 섹션에서 와 함께 표시되는 요약을 읽습니다 . 나는 종종이 책이 의존성 프로그램이 발전하는 동안 업데이트되지 않는 설치 가이드보다 더 신뢰할 만하다는 것을 발견했습니다.


1
완벽합니다. "변장에서 파일을 찾을 수없는 오류였습니다." 제 경우에는 종속성이 아직 설치되지 않았습니다.
— Litty

+1 제 경우에는 새로운 openssl 사본이 수동으로 빌드되고 공유 라이브러리없이 설치되었습니다. 빌드하려는 라이브러리는 이미 -fPIC로 컴파일되었습니다. 어쨌든 컴파일러가이 오류를 인식하여 덜 모호한 오류 메시지를 제공 할 수 있습니까 (예 : "공유 라이브러리 libssl.so를 찾을 것으로 예상했지만 호환되지 않는 정적 라이브러리 /usr/local/ssl/lib/libssl.a 만 찾았습니다."). ?
— 로한 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

항상 컴파일 플래그에 관한 것은 아닙니다. distcc를 사용할 때 젠투에서 같은 오류가 발생합니다.

그 이유는 distcc 서버에서는 강화되지 않은 프로필을 사용하고 있고 클라이언트에서는 프로필이 강화되기 때문입니다. 이 토론을 확인하십시오 : https://forums.gentoo.org/viewtopic-p-7463994.html


9

-no-pie링커 단계의 옵션으로 수정했습니다 .

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

4

프로젝트를 청소하는 것만으로도 문제가 해결되었습니다.

내 프로젝트는 C ++ 애플리케이션입니다 (공유 라이브러리가 아님). 많은 성공적인 빌드 후에 무작위 로이 오류가 발생했습니다.


2

나는 같은 문제가 있었다. -fPIC플래그를 사용하여 다시 컴파일하십시오 .


0

https://stackoverflow.com/a/19365454/10593190 및 XavierStuvw의 답변에 대한 @camino의 의견과 동일한 솔루션을 얻고 있습니다.

(ffmpeg를 설치하기 위해) 모든 인스턴스를 $ ./configure대체 하여 처음부터 모든 것을 다시 설치하여 작동하도록 했습니다 $ ./configure --enable-shared(먼저 이전 시도에서 .so 파일을 포함하여 모든 폴더와 파일을 삭제하십시오).

https://stackoverflow.com/a/13812368/10593190 때문에 분명히 작동합니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.