Encryption

[GCC] Static/Shared Library 생성 및 사용

yeonx 2023. 10. 6. 10:49
728x90

라이브러리를 생성하기 위한 큰 그림

예시)

모듈 별로 작성하지 않고 하나의 파일로 이루어진 프로그램은 다음과 같다.
#include <stdio.h>
int sum(int a, int b);
int main(int argc, char **argv)
{
    int value;
    value = sum(120, 199);
    printf("%d\n", value);
}
int sum(int a, int b)
{
    return a+b;
}​


sum함수를 모듈 형식으로 완전히 분리시켜 보기 위해서 3개의 파일이 만들어져야 한다.

1. sum함수의 선언이 들어 있는 include 파일
2. sum함수를 사용할 main 함수가 있는 C파일
3. sum함수가 정의되어 있는 C파일


include 파일은 아주 간단하게 만들 수 있다. include 파일의 이름은 sum.h로 정의한다.
int sum(int a, int b);​


이제 sum 함수가 정의되어 있는 C코드를 만들어보자. 파일 이름은 sum.c로 정의한다.

int sum(int a, int b){
	return a+b;
}​


마지막으로 main 함수를 만들어 보자. 파일의 이름은 calc.c로 정의한다.

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

int main()
{
    int value;
    value = sum(130, 199);
    printf("%d\n", value);
}


헤더 파일의 경로

우리는 #include 키워드를 이용해서, 포함시킬 헤더파일을 지정할 수 있다. 이때 헤더 파일의 완전한 경로를 포함시켜줘야 한다. 만약 따옴표""를 사용했다면, 이는 현재 디렉토리에서 헤더파일을 찾겠다는 것을 의미한다. 그렇지 않고 <>를 사용했다면, 표준 include 디렉토리와 컴파일러 옵션을 통해서 지정된 디렉토리에서 찾게된다.

헤더파일을 찾을 경로의 지정은 -l옵션을 이용하면 된다. 예를 들어 /home/yundream/include에서 찾도록 하길 원한다면 다음과 같이 하면 된다.
# gcc -I/home/yundream/include -o sum sum.c​


만약 /home/yundream/include를 헤더파일 찾기 경로로 지정하고 싶다면, 다음과 같이 하면 된다.

#include "/home/yundream/include"


모듈별 분할 컴파일

이 3개의 파일(sum.h sum.c calc.c)을 컴파일해서 실행가능한 프로그램을 만들어보자.

1. 가장 먼저 해야할 일은 sum.c와 calc.c를 기계어가 해석가능한 object코드로 만드는 일이다. 오브젝트 코드는 gcc에 -c옵션을 이용해서 만들어 낼 수 있다.

# gcc -c sum.c calc.c

그 후 sum.o와 calc.o라는 파일이 생성된다. 확장자 .o는 이 파일이 오브젝트 파일이라는 것을 알려준다.

2. 이제 두 개의 object파일을 링크시켜서 실행파일을 만들면 된다. -o옵션을 이용하면, 만들어진 오브젝트 파일들을 합쳐줄 수 있다.

# gcc -o calc sum.o calc.o

이제 실행파일인 calc가 만들어진다.

 

정적 라이브러리 생성

  • 오브젝트 파일 생성
gcc -c sum.c sub.c mul.c div.c
-c 옵션은 링크를 안하고 컴파일만 하는 옵션

 

  • .a파일 생성
ar rc libmycalc.a sum.o sub.o mul.o div.o
오브젝트 파일들을 하나로 모아서 라이브러리 생성
rc : 이 옵션으로 정적라이브러리를 만들 수 있다.
r : 정적라이브러리를 만들겠다는 옵션
c : 새로 생성하겠다는 옵션

실행 결과 libmycalc.a라는 파일이 생성됨.
t옵션을 이용하면, 해당 라이브러리가 어떤 오브젝트를 포함하고 있는지도 확인할 수 있다.
ar t libmycalc.a​

 

이제 정적라이브러리를 이용하여 실행파일을 만든다. 이전에는 4개의 오브젝트 파일을 모두 링크시켜줘야 했지만, 이제는 libmycalc.a만 링크시켜주면된다.

 

라이브러리의 링크 방식은 오브젝트를 링크하는 것과는 약간의 차이가 있다. library의 위치를 명확히 명시해 주어야 한다. -L 옵션을 이용해서 라이브러리가 있는 디렉토리의 위치를 명시해주고, -l옵션을 이용하여 라이브러리 파일의 이름을 정해줘야함. 

 

  • 라이브러리를 링크
gcc -o testStaticCalc main.c -L./ -lmycalc
main.c를 정적라이브러리를 이용해서 컴파일하는 방법

-L./ : 현재 디렉토리를 라이브러리 찾기 디렉토리로 하겠다는 의미
-l : 이 옵션 뒤에 붙이는 라이브러리 파일의 이름을 주목해야 한다. *라이브러리 이름은 lib와 .a를 제외한 이름을 사용한다.

 

공유 라이브러리 생성

 

특징 : 공유 라이브러리를 사용하도록 제작된 프로그램은 실행 시에 사용할 라이브러리를 호출하는 과정을 거치게 된다.

 

오브젝트를 이용해서 만든다는 점에서 정적라이브러리와 비슷하지만, 호출시에 링크하기 위한 부가적인 정보를 필요로 하므로, 정적라이브러리와는 전혀 다른 형태로 만들어진다.

 

  • 오브젝트 파일 생성
gcc -fPIC -c sum.c sub.c mul.c div.c
PIC(position independent code) 동적 라이브러리로 사용하도록 하는 옵션

-fPIC :이를 통해 컴파일

 

  • .so파일 생성
gcc -shared -o libmysharedcalc.so sum.o sub.o mul.o div.o
오브젝트 파일들을 하나로 모아서 라이브러리 생성

-shared : 공유라이브러리 파일을 생성

 

  • 라이브러리를 링크
gcc -o testSharedCalc main.c -L./ -lmysharedcalc
링크과정은 정적 라이브러리와 동일

 

  • 사용

정적 라이브러리 처럼 바로 실행하게 되면 에러가 발생하게 된다.

 

원인은 파일을 찾는 디렉토리에 실행파일이 없기 때문이다.

 

정적 라이브러라는 실행파일에 라이브러리가 붙여지므로 일단 실행파일이 만들어지면, 독자적으로 실행이 가능하다. 그러나 공유라이브러리는 라이브러리가 붙여지는 방식이 아니고, 라이브러리를 호출해서 해당 함수코드를 실행하는 방식이다. 그러므로, 호출할 라이브러리의 위치를 알고 있어야 한다.

 

환경 변수 LD_LIBRARY_PATH를 사용한다.

export LD_LIBRARY_PATH=./:/home/myhome/lib

이제 프로그램을 실행시키면 LD_LIBRARY_PATH에 등록된 디렉토리에서 먼저 검색하게 되고, 프로그램은 무사히 실행될 것이다.

 

 

참고 : https://d-yong.tistory.com/5

'Encryption' 카테고리의 다른 글

[Linux] LD_LIBRARY_PATH  (1) 2023.10.06
Static Library와 Dynamic Library  (1) 2023.10.06
[OpenSSL] File 암호화 및 복호화 (대칭키/encryption password)  (0) 2023.10.05
Hash와 Salt  (1) 2023.10.05
해쉬 알고리즘(Hash Algorithm)  (1) 2023.10.05