본문 바로가기

Linux

정적, 공유 라이브러리

정적 라이브러리(.a)를 만들어 사용하는 방법

  1. 오브젝트를 만들기
    # gcc -c file1.c file2.c
  2. 라이브러리 만들기
    # ar rcv libmystuff.a file1.o file2.o
  3. 라이브러리에 인덱스 만들기
    # ranlib libmystuff.a
  4. "라이브러리 만들기 + 인덱스 만들기" 통합 명령
    # ar rcvs libmystuff.a file1.o file2.o
  5. 라이브러리 파일 내의 함수를 extern 형태로 선언한 헤더 파일 mystuff.h 만들기
  6. 만든 라이브러리 사용하기 (라이브러리 파일은 오브젝트 파일과 동일하게 취급)
    # gcc -o test -L./ test.o -lmystuff

 

공유 라이브러리(.so)를 만들어 사용하는 방법

  1. 오브젝트 만들기
    # gcc -fPIC -c file1.c file2.c
  2. 라이브러리 만들기 (인덱스 과정 불필요)
    # gcc -shared -Wl,-soname,libmystuff.so.1 -o libmystuff.so.1.0.0 file1.o file2.o
  3. 생성된 libmystuff.so.1.0.0 라이브러리 파일을 ldd 명령으로 목록 확인하기
    # ldd mystuff.so.1.0.1
  4. 라이브러리를 만든 후 libmystuff.so.1.0.0의 심볼릭 링크를 만들기
    # ln -s libmystuff.so.1.0.0 libmystuff.so.1    --> 동적 링크를 위한 파일
    # ln -s libmystuff.so.1.0.0 libmystuff.so       --> gcc 링크를 위한 파일
  5. 동적 링커(/lib/ld-linux.so.2)가 찾을 수 있도록 디렉토리 설정하기
    /etc/ld.so.conf 파일을 열어 libmystuff.so.1.0.0 파일이 있는 디렉토리를 추가한다.
  6. /etc/ld.so.conf에 지정된 디렉토리를 찾아다니면서 새로운 심볼릭 링크를 만들고 동적 로더가 읽어 들이는 /etc/ld.so.cache 파일을 새로 갱신한다.
    # ldconfig --> 만든 라이브러리를 /usr/lib 디렉토리에 복사하면 5, 6 절차는 필요없다.
  7. 라이브러리 파일 내의 함수를 extern 형태로 선언한 헤더 파일 mystuff.h 만든다.
  8. 만든 라이브러리 사용하기 (.a와 .so가 둘 다 있으면 .so를 선택)
    # gcc -o test -L./ test.o -lmystuff
  • -fPIC, -fpic 옵션(Position Independent Code)은 공유를 위한 위치 독립적 코드를 생성한다. 이 옵션을 붙이지 않고 컴파일하게 되면 실행은 되지만 실제로 공유가 되지 않는다.
  • -WI 옵션은 뒤에 오는 옵션들이 gcc를 거치지 않고 바로 링커(collect2)에게 전달되도록 해준다.
  • -soname 옵션은 만들어질 공유 라이브러리의 soname을 정하는 것이다. 이것은 파일 명과는 틀린 개념으로 지금과 같이 soname을 libmystuff.so.1이라고 이름을 지어주면 나중에 동적 링커가 공유 라이브러리를 찾을 때 libmystuff.so.1.0.0을 찾는게 아니라 soname인 libmystuff.so.1(libmystuff.so.1.0.0의 심볼릭 링크) 파일을 찾아서 링크하게 된다. 이런 식으로 사용하는 이유는 파일 명과는 상관없이 서로 다른 버전의 공유 라이브러리를 융통성 있게 사용하기 위해서이다. 1.0.0의 맨 앞 1은 메이저 버전이라하여 라이브러리에 중대한 변화가 발생했을 때 바뀌는 번호이다. 메이저 번호가 바뀌었다면 호환이 안된다는 의미와 같다. 그래서 메이저 버전이 틀린 라이브러리로 컴파일된 실행 파일은 같은 이름(mystuff)의 라이브러리가 있다고 하더라도 실행될 수 없다. 두 번째 0은 마이너 버전이며 약간의 변화에 의해 변화되는 번호이다. 마이너 버전이 바뀜으로해서 미치는 영향은 크지 않다. 마지막 0은 패치 버전이며 아주 사소한 변화가 생겼을 때 변하는 버전이다.

 

공유 라이브러리 사용을 권장하는 이유
사용한 라이브러리에 보안 결함이 있을 경우 공유 라이브러리를 사용했다면 공유 라이브러리만 바꾸면 된다. 실행시에 실행 파일과 연결되므로 라이브러리 변경시에 애플리케이션 재컴파일이 불필요하다.

 

헤더, 라이브러리의 위치 지정

C 컴파일러에게 사용자 라이브러리와 헤더 파일의 위치를 알려 주어야 한다.

사용자 헤더 파일의 옵션은 대문자 i를 사용한다.
# gcc -o x11fred -I/usr/openwin/include -L/usr/openwin/lib -lx11 fred.o

 

라이브러리 이름은 항상 lib~로 시작하며 .뒤에 라이브러리 형태를 지정한다.

.a   전통적인 정적 라이브러리
.so 공유 라이브러리

 

표준 라이브러리가 위치하는 디렉토리이다.

/lib

/usr/lib

 

-l 옵션 (소문자 L)

기능 : 사용자 라이브러리를 지정한다.

사용법 : gcc 소스파일이름 -l라이브러리이름

 

-L 옵션

라이브러리 파일 libmy.a의 라이브러리를 쓰고 싶을 때는 lib와 .a를 제외한 my만 쓴다. 그런데 링커가 라이브러리를 찾을 때 표준 라이브러리 파일의 디렉토리로 찾기 떄문에 자기가 만든 라이브러리 디렉토리는 찾지 못한다. 이것은 -L 옵션을 사용해서 해결할 수 있다.

기능 : 사용자 라이브러리의 위치를 지정한다.

사용법 : gcc 소스파일이름 -L라이브러리위치

예 ) gcc ex.c -lmy -Lmylib

 

-lsocket -lnsl : 소켓을 사용하기 위해 libsocket.so와 libnsl.so를 링크한다.

-lpthread : pthread를 사용하기 위해 libpthread.so를 링크한다.

-lrt : 세마포어를 사용하기 위해 librt.so를 링크한다.

 

헤더 파일에는 프로토타입이 선언되어 있지만 링크시에 에러가 발생하면...

clock_gettime 함수는 리눅스 기본 C 라이브러리에 포함되어 있지 않다.

그러므로 컴파일러에서 링크할 때 따로 옵션을 입력해서 해당 라이브러리를 링크시켜야 한다.
이렇게 헤더 파일에는 프로토타입이 선언되어 있지만 링크시에 에러가 발생하면 쉘에서 다음과 같이 실행한다.

# nm -A /usr/lib/*.a 2>/dev/null | grep clock_gettime

 

그럼 원하는 함수가 포함되어 있는 라이브러리 파일 이름을 발견할 수 있다.

이렇게 알아 보면 clock_gettime 함수의 경우에는 librt.a 라이브러리에 포함되어 있는 것을 확인할 수 있다.

그럼 이제 컴파일러 옵션에 다음과 같이 추가한다.
-l[라이브러리 이름에서 앞의 lib를 떼고 뒤의 확장자를 제거한 이름]

즉, librt.a의 경우에는 -lrt라고 추가하면 된다.

'Linux' 카테고리의 다른 글

chmod 권한 설정하기  (0) 2008.12.23
동적 적재(DL) 라이브러리  (0) 2008.12.02
공유라이브러리-2  (0) 2008.09.05
공유 라이브러리-1  (0) 2008.09.05
library 만들기  (0) 2008.09.05