[리눅스] 정적라이브러리 작성, 공유 라이브러리 작성, 차이점 보기
아래와 같이 caculator라는 프로그램이 같은 디렉토리에 있는 lib내의 libcalcops라는 라이브러리를 사용할 수 있도록 만들어보도록 하겠습니다.
아주 간략하게 무슨 프로그램이냐를 설명해드리면, calculator라는 이 프로그램은 사용자로부터 두 수를 입력받아 덧셈, 뺄셈, 나눗셈의 결과를 출력해주는 프로그램입니다.
우리는 더 쉽게 calculator라는 프로그램을 구현하기 위해서(사실은 그냥 짜는게 더 쉽지만 라이브러리를 연동하는 방법을 알기 위해서) lib/libcalcops의 라이브러리를 가져다가 쓸겁니다. 물론 우리가 만들어 쓸거에요.
이 라이브러리에는 실제 연산 동작(calc operation)이 구현되어있습니다.

우선 현재 디렉토리에 mkdir lib를 이용해서 lib를 저장할 수 있는 디렉토리를 만들어줍시다.
# mkdir lib # cd lib |
라이브러리 소스코드 작성
너무나 간단한 연산 동작을 하는 함수를 정의한 헤더파일과 구현한 c파일을 작성하고 컴파일 해줍니다.
calc_operations.h
#ifndef __CALC_OPERATION_H_
#define __CALC_OPERATION_H_
int add(int a,int b);
int sub(int a,int b);
int mult(int a,int b);
double div(int a,int b);
#endif
calc_operations.c
#include "calc_operations.h"
int add(int a,int b){
return a+b;
}
int sub(int a,int b){
return a-b;
}
int mult(int a,int b){
return a*b;
}
double div(int a,int b){
return (double)a/(double)b;
}
여기까지는 뭐 누구나 아는 프로그램이지요. 아래와 같이 컴파일하게 되면 object파일이 하나 생성되겠죠.
# gcc -c calc_operations.c # ls calc_operations.c calc_operations.h calc_operations.o |
이제 이것을 ar로 rc옵션을 주어 정적라이브러리 아카이브를 만듭니다.
# ar rc libcalcops.a calc_operations.o # ls calc_operations.c calc_operations.h calc_operations.o libcalcops.a |
프로그램 구현
이제 lib밖으로(cd ..) 이동해주세요. 여기서 소스 코드를 구현하도록 하겠습니다.
calculator.c
#include <stdio.h>
#include "lib/calc_operations.h"
int main(){
int a,b;
scanf("%d %d",&a,&b);
printf("%d + %d = %d\n", a,b,add(a,b));
printf("%d - %d = %d\n", a,b,sub(a,b));
printf("%d * %d = %d\n", a,b,mult(a,b));
printf("%d / %d = %f\n", a,b,div(a,b));
}
이제 아래와 같이 컴파일하도록 해봅시다. 아래 옵션 중에서 -L은 라이브러리가 위치한 디렉토리를 명시해주고 -lcalcops는 우리가 작성한 lib파일 이름입니다. 우리가 lib파일 이름을 libcalcops.a라고 정의하였을때 옵션은 -lcalcops라고 명시해주면 됩니다. lib가 -l로 바뀌고 확장자 .a를 빼주는 식이죠.
# gcc calculator.c -L ./lib -lcalcops # ./a.out 7 3 7 + 3 = 10 7 - 3 = 4 7 * 3 = 21 7 / 3 = 2.333333 |
기존의 .o파일과 .a를 지우고 나서도 calculator 프로그램이 동작할까요? 지우고 실행을 다시 해보도록 합시다.
# rm -rf *.a *.o # ls calc_operations.c calc_operations.h # cd .. # # ./calculator 10 3 10 + 3 = 13 10 - 3 = 7 10 * 3 = 30 10 / 3 = 3.333333 |
보시다시피 잘 동작하는 것을 알 수 있습니다. 추측해볼 수 있는 것은 런타임과는 관계가 없고 컴파일시(calculator)에 프로그램에 적재되는 것을 알 수 있고 실제로도 그렇습니다.
공유라이브러리
공유라이브러리는 컴파일 방식만 변경하면 됩니다. lib 디렉토리로 이동해주세요.
아래의 명령으로 라이브러리를 컴파일해줍니다. 그런후에 /usr/lib 디렉토리에 복사해줍니다.
# gcc -shared -o libcalcops.so calc_operations.c # cp libcalcops.so /usr/lib |
이제 calculator 프로그램을 컴파일 할것인데, 위의 컴파일 옵션보다 더 간단합니다.
# gcc calculator.c -lcalcops # ./a.out 8 3 8 + 3 = 11 8 - 3 = 5 8 * 3 = 24 8 / 3 = 2.666667 |
그렇다면 아까와 같이 /usr/lib/libcalcops.so파일을 삭제하고 위 프로그램을 다시 실행해보도록 해봅시다.
# ./a.out ./a.out: error while loading shared libraries: libcalcops.so: cannot open shared object file: No such file or directory |
정적라이브러리와는 다르게 라이브러리 파일이 삭제되면 실행 프로그램도 실행되지 않네요. 우리가 추측해볼 수 있는것은 프로그램이 시작시에 적재되는 것을 의심해볼 수 있고 실제로도 그렇습니다.
왜 하필 /usr/lib에 파일을 복사했을까요? 공유라이브러리할때 /etc/ld.so.conf 설정파일로부터 라이브러리 파일이 있는 지 봅니다.
제 시스템을 기준으로 설명드리면 아래와 같이 /etc/ld.so.conf 파일이 작성되어 있습니다.
include /etc/ld.so.conf.d/*.conf |
다시 /etc/ld.so.conf.d/ 디렉토리를 보면 libc.conf와 x86_64-linux-gnu.conf 파일 두개가 존재합니다. 하기의 경로에 lib파일이 있으면 실행되며 추가적으로 경로를 추가 후 저장하고 나와서 ldconfig 명령을 주어 반영하면 됩니다.
| libc.conf | x86_64-linux-gnu.conf |
| # libc default configuration /usr/local/lib /usr/lib |
# Multiarch support /usr/local/lib/x86_64-linux-gnu /lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu |