본문 바로가기
Bioinformatics/Technology

libstdc++.a를 fPIC 옵션으로 다시 컴파일하는 경우 문제 해결(linux)

by 임은천 2013. 1. 31.

이 문제는 동적 라이브러리를 생성할 때 발생한다. 다른 정적 라이브러리들을 링킹하는 과정에서 fPIC 옵션을 지정한 경우, 모든 정적 라이브러리가 fPIC 옵션을 가지고 컴파일 되어야 한다. 하지만, 그 중에 fPIC으로 컴파일 되지 않은 라이브러리가 있는 경우에는 이를 다시 컴파일 해주어야 한다. 이 중 libstdc++는 조금 머리 아픈 경우로써, 재컴파일 하려면 몇 가지 단계를 거쳐야 하므로 이를 정리한다. 사실 이 문제는 GCC 4.7 버전에서 해결되었다.(http://gcc.gnu.org/bugzilla/show_bug.cgi?id=28811)


실제 에러 메시지는 다음과 같이 보인다.


/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/4.6/libstdc++.a(ctype.o): relocation R_X86_64_32S against `vtable for std::ctype<wchar_t>' can not be used when making a shared object; recompile with -fPIC


먼저 다음 명령으로 gcc의 최신 버전을 받는다. 이 글은 GCC 4.7.2 버전을 기준으로 설명한다.


sudo apt-get install gcc-4.7

sudo apt-get install g++4.7

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.7 20

sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.7 20

sudo update-alternatives --config gcc

sudo update-alternatives --config g++


그리고 혹시 경로 문제가 발생할 수 있으므로 다음을 ~/.bashrc에 추가한다.


export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH


export LIBRARY_PATH=/usr/lib/i386-linux-gnu


export C_INCLUDE_PATH=/usr/include/x86_64-linux-gnu


export CPLUS_INCLUDE_PATH=/usr/include/x86_64-linux-gnu


다음으로 해야 하는 일은 이제 단순하다. 여러분이 작성한 소스 코드는 반드시 -fPIC 옵션을 이용해서 컴파일 한다. 또한, 링크를 할 때 반드시 다음 옵션을 추가한다.


-fPIC -static-libgcc -static-libstdc++


이제 libstdc++ 관련 빌드 문제는 해결되었을 것이다. 이클립스에서는 다음과 같이 해야 한다. 프로젝트 탐색깅에서 프로젝트 이름에서 마우스 오른쪽 버튼 -> Properties -> C/C++ Build -> Generate Makefiles automatically를 해제한다. 이제 수동으로 Make File들을 수정할 수 있다. 단 수정 전에 최소한 한 번은 빌드를 해서 전체 Makefile을 처음부터 다시 작성하는 수고를 하지는 말자.

makefile에서는 라이브러리 연결에 관련된 내용을 수정할 수 있다. 내용을 보면 다음과 같은 내용이 있을 것이다.


# Tool invocations

libbustard_importer.so: $(OBJS) $(USER_OBJS)

@echo 'Building target: $@'

@echo 'Invoking: GCC C++ Linker'

g++ -L/usr/local/lib -shared -o "libbustard_importer.so" $(OBJS) $(USER_OBJS) $(LIBS)

@echo 'Finished building target: $@'

@echo ' '


이것을 아래와 같이 추가해 준다. 바꾸고 저장하는 과정에서 경고가 나오더라도 무시하고 수정한다.


# Tool invocations

libbustard_importer.so: $(OBJS) $(USER_OBJS)

@echo 'Building target: $@'

@echo 'Invoking: GCC C++ Linker'

g++ -fPIC -static-libgcc -static-libstdc++ -L/usr/local/lib -shared -o "libbustard_importer.so" $(OBJS) $(USER_OBJS) $(LIBS)

@echo 'Finished building target: $@'

@echo ' '


다음으로 objects.mk도 수정해야 한다.


LIBS := -lboost_filesystem -lboost_iostreams -lboost_system


이것을 아래와 같이 추가해 준다.


LIBS := -Wl,-Bstatic -lboost_filesystem -Wl,-Bstatic -lboost_iostreams -Wl,-Bstatic -Wl,-Bstatic -lboost_system


아마 이제 정상적으로 so 파일을 생성할 수 있을 것이다. 만약 boost 라이브러리에서 fPIC 문제가 발생한다면 다음과 같이 한다.


sudo ./b2 cxxflags="-fPIC -m64" -j8 -a --prefix=/usr/local

sudo ./b2 install cxxflags="-fPIC -m64" -j8 --prefix=/usr/local


64 비트 컴퓨터일 경우 위와 같이 한다. 만약 LZMA(liblzma.a) 같은 압축 라이브러리에서 fPIC 문제가 발생하면 다음과 같이 한다. XZ Utils(http://tukaani.org/xz/)를 다운로드 받는다.


sudo ./configure --prefix=/usr/local --with-pic

sudo make

sudo make install


중요한 것은 모든 컴파일에서 옵션이 같은 것이 fPIC 관련 에러를 줄이는 방법이다.


댓글