"공유 객체를 만들 때`.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/10593190XavierStuvw의 답변에 대한 @camino의 의견과 동일한 솔루션을 얻고 있습니다.

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

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

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