'GCC'에 해당되는 글 2건

  1. [Error] /usr/bin/ld: skipping incompatible ...
  2. -Wl,--no-as-needed 옵션

[Error] /usr/bin/ld: skipping incompatible ...


컴파일시 아래와 같은 오류가 발생하는 경우가 있다.


/usr/bin/ld: skipping incompatible (...) when searching for -l(...)

/usr/bin/ld: cannot find -(...)

collect2: ld returned 1 exit status


(...) 은 임의의 라이브러리 명이다.

해당 오류가 발생하는 원인은 크게 두가지가 있다.


첫번째로 해당 라이브러리가 존재하지 않거나 잘못된 위치를 참조하고 있을 수 있다.

-l 이 아니라 -L 인 경우를 포함해서 사소하고 다양한 이유로 ld 가 터지는 경우이다.

이 경우 locate 명령어 등을 통해 정확한 확인하고 없을 경우 설치한 후 다시 빌드한다.


두번째 경우는 조금 아차 싶은 문제이다.

Cross Compile 작업[각주:1] 시 해당 오류가 발생할 수 있다.

라이브러리 자체가 .so 또는 .o 같은 binary file 이기 때문에 ld 가 호환성 문제를 일으키는 것이다.

간단한 해결 방법은 gcc 실행시 -m32 옵션을 추가해주는 것이다. 

만약 Makefile 을 이용하고 있다면 CFLAGS[각주:2][각주:3](C++ 는 CXXFLAGS) 옵션에 -m32 를 추가하면 된다.

또는 ./configure CFLAGS="-m32" 등을 이용해서 Makefile 을 생성하면 될 것이다.


아키텍쳐 관련 옵션에 대해서는 최신 GCC 문서를 참고하는 것을 추천한다.

https://gcc.gnu.org/onlinedocs/gcc-4.9.1/gcc/i386-and-x86-64-Options.html#i386-and-x86-64-Options





  1. 필자는 x86_64 환경에서 32bit 라이브러리를 참조할 때 해당 문제가 생겼다. [본문으로]
  2. 굳이 LDFLAGS 까지 사용할 필요는 없다. [본문으로]
  3. 예시: CFLAGS="-m32" [본문으로]

-Wl,--no-as-needed 옵션

ELF 파일 포맷에는 동적 라이브러리에 대한 의존성 태그가 포함되어 있으며, 다음과 같은 명령어들로 확인할 수 있다.


maeryo@aftermath.kr:~$ readelf -a "파일명" | grep NEED

maeryo@aftermath.kr:~$ ldd "파일명"


컴파일 시 -l 옵션을 이용하여 동적 라이브러리들을 링크할 때 실제로 참조하지 않는 라이브러리들은 ELF Dynamic Section에 기록되지 않는다.

최신 GCC 기준으로 기본값은 --as-needed 이며 실제 참조한 라이브러리만 기록하게 되는데, 경우에 따라서 반대의 경우가 필요한 상황이 있다.


다음은 간단한 예시이다.


/* test.c */

#include <stdio.h>

 int main() {

    printf("Hello World!\n");

    return 0;

 }


위와 같은 내용이 담긴 test.c 라는 소스 파일이 있다고 가정하겠다.


1. 일반


maeryo@aftermath.kr:~$ gcc -Wall test.c -o test

maeryo@aftermath.kr:~$ readelf -a test | grep NEED
  [ 8] .gnu.version_r VERNEED 0000000000400360 00000360 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x000000006ffffffe (VERNEED) 0x400360 0x000000006fffffff (VERNEEDNUM) 1
maeryo@aftermath.kr:~$ ldd test
linux-vdso.so.1 => (0x00007fff94520000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc7c2841000) /lib64/ld-linux-x86-64.so.2 (0x00007fc7c2c15000)


2. -lz 추가


maeryo@aftermath.kr:~$ gcc -Wall test.c -o test -lpthread -lz

maeryo@aftermath.kr:~$ readelf -a test | grep NEED
  [ 8] .gnu.version_r VERNEED 0000000000400360 00000360 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x000000006ffffffe (VERNEED) 0x400360 0x000000006fffffff (VERNEEDNUM) 1
maeryo@aftermath.kr:~$ ldd test
linux-vdso.so.1 => (0x00007fff94520000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc7c2841000) /lib64/ld-linux-x86-64.so.2 (0x00007fc7c2c15000)

3. -Wl,--no-as-needed 명령어와 -lz 사용시

maeryo@aftermath.kr:~$ gcc -Wall test.c -o test -Wl,--no-as-needed -lz

maeryo@aftermath.kr:~$ readelf -a test | grep NEED
  [ 8] .gnu.version_r VERNEED 0000000000400398 00000398 0x0000000000000001 (NEEDED) Shared library: [libz.so.1] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x000000006ffffffe (VERNEED) 0x400398 0x000000006fffffff (VERNEEDNUM) 1
maeryo@aftermath.kr:~$ ldd test
        linux-vdso.so.1 => (0x00007fffc703e000) libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fb753bfc000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb75383c000) /lib64/ld-linux-x86-64.so.2 (0x00007fb753e27000)