과거에는 개발자가 shared libraries를 사용하기 위해서는자신이 개발하는 package가 지원해야 하는 모든 플랫폼에 대해서 각 플랫폼에만 국한되는 일은 모두따로따로 작업을 해야만 했다고 한다. , configurationinterface를 따로 설계하여 package installer가 어떤 library들을 설치해야 하는지 선택할 수 있도록 해야만 했다고 한다.GNU Libtool platform-specific dependencies user interface에 대한 정보를 하나의 스크립트에 설정할 수 있게 함에 따라 개발자가 예전에 짊어져야했던 많은 짐을 덜어준다. (GNU Libtool manual 서문의 첫 세 문장을 번역한 것이다. 원문을 보는 것이 아마 더 이해가 빠를 것이다. - click "more" to read it)


 

하지만, 아직 잘모르겠다어쨌든. Linux에서 개발 환경을 구축하는데있어서 GNU Build System을 이해해야 할 필요성을 느끼게 되어 가장먼저 Libtool을 공부하게 되었고, 지금까지 공부한 내용을 예를 들어 정리하고자한다.

* 본문의 내용에 대해서 잘 아시는 분은 틀린부분에 대해서 바로잡아주시고, 명확하지 않은 부분에 대해서는 어떤 보충설명을 하면 좋을지 의견을 남겨주시기 바랍니다.

* 해보시면서 의문이 드는 점도 물어봐주시면 아는대로 성심성의껏 답변해 보도록 하겠습니다.

* 빨간 글씨로 된 부분은 잘 모르겠거나 이해가 안 가는 부분이므로, 이 부분에 대해서 설명해 주실분은 댓글로 친절하게 설명해 주시면 정말 쌩큐베리 감솨 드리겠습니다...


학습목표
- /home/dansoonie/Work/fyi에 libfyi라는 간단한 library를 만들어 build한다.
- /home/dansoonie/
Work/fyitest에서 위에서 build libfyi를 가져다 쓴다
- libfyi를 /usr/lib에 설치한다.
- /home/dansoonie/Work/fyitest에서
/usr/lib에 설치된 libfyi를 가져다 쓴다.

작업 환경:
VMware Player, Ubuntu 8.04 - the Hardy Heron - release in April 2008
libtool version: 1.5.26-lubuntul (1.1220.2.493 2008/02/01 16:58:18)

참고 문헌:
GNU Libtool Manual(첨부파일 참고)


1. Shared Object Library로 만들간단한 소스 작성하기


간단하게 함수 두 개를 가지고 있는 라이브러리를 작성해보자.


/home/dansoonie/Work/fyi/fyi.h listing

#ifndef FYI_H
#define FYI_H

void name();
void birthday();

#endif

/home/dansoonie/Work/fyi/fyi.c listing

#include <stdio.h>
#include "fyi.h"

void name()
{
     printf("Yoon-Soo Lee\");
}

void birthday()
{
     printf("Januaary 18th\n");
}





2. Object File 생성하기


 쉘에서 다음 명령어를 수행한다.($PWD = /home/dansoonie/Work/fyi/)

libtool --mode=compile gcc -g -O -c fyi.c


설명:

     libtool :
libtool 실행 커맨드

     --mode=compile :
mode는 컴파일하기

     gcc -g -O -c fyi.c :
 gcc 실행문
. gcc 옵션은 -c(링크하지 않기)만 꼭 있어야 하고 나머지는 없어도 되는것 같다.

output은

 gcc -g -O -c fyi.c -fPIC -DPIC -o .libs/fyi.o

 gcc -g -O -c fyi.c -o fyi.o >/dev/null 2>&1


생성물은

/home/dansoonie/Work/fyi/fyi.o 

/home/dansoonie/Work/fyi/fyi.lo

/home/dansoonie/Work/fyi/.libs/fyi.o

이다...


shared object library가 지원되는 플랫폼이면 Libtool이 gcc를 실행할때 -fPIC -DPIC 와 같은 옵션을 달아서 실행한다고 한다. PIC가 들어가는 옵션들은 Position-Indipendent code를 의미하므로 shared object library를 만드는데 있어서 매우 중요한 옵션이므로, output에서 그 옵션들이 나오는지 꼭 확인하자 !!!

output의 두번째 줄의 ">/dev/null 2>&1" 은 뭔지 잘 모르겠다... 그냥 gcc의 outputd르 redirect하고 있는것 같은데 정확히 무슨 짓을 하는지는 잘 모르겠다.



3. Library들 link하여 생성하기


 쉘에서 다음 명령어를 수행한다. ($PWD = /home/dansoonie/Work/fyi/)

libtool --mode=link gcc -g -O -o libfyi.la fyi.lo -rpath /usr/lib


설명:

     libtool :
libtool 실행 커맨드

     --mode=link :
mode는 링크하기

    - gcc -g -O -o libfyi.la fyi.lo -rpath /usr/lib :
gcc 실행문. libfyi.la는 libtool control file name으로 확장자가 .a인 standard library name과는 다르다. 어쨌든, 출력을 왜 확장자가 .la인 파일로 정해야 하는지는 잘 모르겠다. fyi.lo는 fyi.la를 출력하기 위해 필요한 파일이고, -rpath 옵션을 통해서 library가 최종적으로 설치(복사)될 경로를 지정해 준다.
질문... /usr/lib, 즉 궁극적으로 설치될 경로를 지정해 주는 이유는 무엇인가? 나중에 libtool을 사용해서 library를 install할때 또 libtool에 argument로 그 경로를 넘겨주는것 같은데 말이다...

output은

 gcc -shared .libs/fyi.o -Wl,-soname -W;, libfyi.so.0 -o .libs/libfyi.so.0.0.0

 (cd .libs && rm -f libfyi.so.0 && ln -s libfyi.so.0.0.0 libfyi.so.0)

 (cd .libs && rm -f libfyi.so && ln -s libfyi.so.0.0.0 libfyi.so)

 ar cru .libs.libfyi.a fyi.o

 ranlib .libs/libfyi.la

 creating libfyi.la

 (cd .libs && rm -f libfyi.la && ln -s ../libfyi.la libfyi.la)


생성물은

/home/dansoonie/Work/fyi/libfyi.la

/home/dansoonie/Work/fyi/.libs/libfyi.a

/home/dansoonie/Work/fyi/.libs/libfyi.la -> ../libfyi.la

/home/dansoonie/Work/fyi/.libs/libfyi.lai

/home/dansoonie/Work/fyi/.libs/libfyi.so -> libfyi.so.0.0.0

/home/dansoonie/Work/fyi/.libs/libfyi.so.0 -> libfyi.so.0.0.0

/home/dansoonie/Work/fyi/.libs/libfyi.so.0.0.0

이다...



4. Library를  executable에 link해서 사용하기


일단 libfyi를 가져다쓸 executable을 테스트로 만들어보자. ($PWD = /home/dansoonie/Work/fyitest/)

/home/dansoonie/Work/fyitest/fyitest.c listing

#include <stdio.h>
#include "fyi.h"

int main()
{
name();
birthday();
return0;
}

 쉘에서 다음 명령어를 수행하여 위의 코드를 컴파일 한다. ($PWD = /home/dansoonie/Work/fyitest/)

gcc -I ../fyi -g -O -c fyitest.c


설명:

    
- -I../fyi :
/home/dansoonie/Work/fyi 디렉터리를 include path에 추가하여 fyi.h가 include될 수 있도록 한다.

     - -g :
debug 정보 포함되도록 컴파일하는 옵션

     - -O :
optimization 하는 옵션

     - -c :
링크는 하지 않는 옵션

생성물은

/home/dansoonie/Work/fyitest/fyitest.o

이다...


fyitest를 libfyi와 링크하여 executable을 만들기 위해서는 쉘에서 다음 명령어를 수행한다.

libtool --mode=link gcc -g -O -o fyitest fyitest.o ../fyi/libfyi.la
* library를 install하기 전에 link를 해서 사용하게 되면 꼭 libtool을 사용해서 link를 해야 한다. Section 3.3 참고


output

gcc -g -O -o .libs/fyitest fyitest.o ../fyi/.libs/libfyiso

creating fyitest


생성물

/home/dansoonie/Work/fyitest/fyitest

/home/dansoonie/Work/fyitest/.lib/fyitest  <- 이 파일 생성의 정체 불명 (실행 안됨)

/home/dansoonie/Work/fyitest/.lib/lt-fyitest  <- 이 파일 생성의 정체 불명 (실행됨)


생성물 실행시 output 결과

Yoon-Soo Lee

January 18th




5. Library를 Install하기


 쉘에서 다음 명령어를 수행한다. ($PWD = /home/dansoonie/Work/fyi/)

libtool --mode=install install -c libfyi.la /usr/lib/libfyi.la

설명
     su 권한 상태에서 명령어를 실행하던지, 저 명령어 앞에 sudo를 사용하여 그 명령어만 su권한으로 실행하도록 한다. 당연히 su 비밀번호는 알아야 한다.

질문... library의 install경로는 libfyi.la에 저장되어있는데 왜 또 따로 /usr/lib이라고 명시해 주었는가? install 명령어 사용 방법이 install [option] SOURCE DEST 라서 그런가? 그리고 중요한 사실은 library를 build할때 -rpath 옵션으로 준 경로랑 위에서 명시해주는 DEST의 경로가 같아야 한다는데, 이렇게 실수를 다분히 유발할 수 있는 여지를 남겨놓은 이유는?

output은

install -c .libs/libfyi.so.0.0.0 /usr/lib/libfyi.so.0.0.0
(cd /usr/lib && { ln -s -f libfyi.so.0.0.0 libfyi.so.0 || { rm -f libfyi.so.0 && ln -s libfyi.so.0.0.0 libfyi.so.0; }; })
(cd /usr/lib && { ln -s -f libfyi.so.0.0.0 libfyi.so || { rm -f libfyi.so && ln -s libfyi.so.0.0.0 libfyi.so; }; })
install -c .libs/libfyi.lai /usr/lib/libfyi.la
install -c .libs/libfyi.a /usr/lib/libfyi.a
chmod 644 /usr/lib/libfyi.a
ranlib /usr/lib/libfyi.a
PATH="$PATH:/sbin" ldconfig -n /usr/lib
-----------------------------------------------------------------------
Libraries have been installed in:
   /usr/lib

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the `LD_LIBRARY_PATH' environment variable
     during execution
   - add LIBDIR to the `LD_RUN_PATH' environment variable
     during linking
   - use the `-Wl,--rpath -Wl,LIBDIR' linker flag
   - have your system administrator add LIBDIR to `/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------

library를 가져다 사용할때 header파일으로의 접근을 쉽게 하기 위해 library의 header 파일을 /usr/include로 복사하는 작업을 다음 명령어를 통해 수행한다. ($PWD = /home/dansoonie/Work/fyi/)
cp fyi.h /usr/include 

설명
     su 권한 상태에서 명령어를 실행하던지, 저 명령어 앞에 sudo를 사용하여 그 명령어만 su권한으로 실행하도록 한다. 당연히 su 비밀번호는 알아야 한다.



6. Install된 Library를  executable에 link해서 사용하기


이전에 만들었던 /home/dansoonie/Work/fyitest/fyitest.c 을 사용하자


 쉘에서 다음 명령어를 수행하여 fyitest.c를 컴파일 한다. ($PWD = /home/dansoonie/Work/fyitest/)

gcc -g -O -c fyitest.c


설명:

 
   - -g :
debug 정보 포함되도록 컴파일하는 옵션

     - -O :
optimization 하는 옵션

     - -c :
링크는 하지 않는 옵션

생성물은

/home/dansoonie/Work/fyitest/fyitest.o

이다...


fyitest를 /usr/lib에 install된 libfyi와 링크하여 executable을 만들기 위해서는 쉘에서 다음 명령어를 수행한다.

gcc -L/usr/lib -lfyi -o fyitest fyitest.o


생성물

/home/dansoonie/Work/fyitest/fyitest


최종 생성물 실행시 output 결과

Yoon-Soo Lee

January 18th



질문... -rpath를 /usr/local/lib으로 하면 6번과정을 마치고 ldd fyitest를 하여 fyitest가 어떤 library를 link했는지 살펴보면 libfyi.so.0 => not found 라고 나온다.


Posted by Dansoonie