Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Archives
Today
Total
관리 메뉴

nomad-programmer

[Programming/C] 정적 라이브러리 (Static Library) 본문

Programming/C

[Programming/C] 정적 라이브러리 (Static Library)

scii 2020. 6. 18. 20:10
오브젝트 파일(*.o)들을 정적 라이브러리 파일(*.a, *.lib)로 만들어서 사용하면 좋은 점

오브젝트 파일에 존재하는 함수를 하나라도 사용한다면, 빌드할 때 오브젝트 파일의 모든 코드를 가져와 하나의 파일로 빌드된다.
하지만 오브젝트 파일들을 정적 라이브러리로 만들게되면, 사용하고 있는 오브젝트 코드만 가져와 하나의 파일로 빌드된다.

즉, 정적 라이브러리가 아닌 오브젝트 파일을 쓰게 된다면 사용하지도 않는 오브젝트 코드들도 모두 함께 빌드되어버린다.
때문에 파일의 크기가 커지고 느려진다.
오브젝트 파일이 아닌 정적 라이브러리 파일을 쓰도록 하자.

 

먼저 오브젝트 파일을 생성한다.

오브젝트 파일 생성

gcc -I<헤더파일 디렉토리 경로> test_code.c encrypt.o checksum.o -o test_code

이런식으로 프로그램을 컴파일할 때 오브젝트 파일의 전체 경로명을 추가하여 컴파일해도 된다.

하지만 공유할 오브젝트 파일이 많아지면 복잡하고 귀찮아진다.

이럴때, 오브젝트 파일의 아카이브를 만들면 수 많은 오브젝트 파일에 대해 한꺼번에 컴파일러에 알려줄 수 있다.

 

Archive

아카이브(Archive)는 그저 수 많은 오브젝트 파일을 하나의 파일로 묶어 놓은 것이다. 단 하나의 아카이브 파일을 만들면 다른 프로젝트에 훨씬 더 쉽게 코드를 공유할 수 있다.

*.zip이나 *.tar 파일과 같은 *.a 아카이브 파일도 바로 그런 파일이다.

"nm libmyfunc.a" 이런식으로 nm 명령을 사용하면 아카이브 파일 안을 들여다 볼 수 있다.

 

ar명령으로 아카이브 생성하는 방법

아카이브 명령(ar)은 여러 오브젝트 파일을 하나의 아카이브 파일에 저장한다.

ar -rcs libsecurity.a encrypt.o checksum.o

/*

r 옵션은 이미 *.a파일이 존재하면 갱신하라는 옵션이다.
c 옵션은 아카이브를 만들 때 화면에 아무런 설명도 출력하지 말라는 옵션이다.
s 옵션은 *.a파일의 앞에 색인을 생성하라고 ar명령에 지시하는 옵션이다.

*/
아카이브의 이름은 반드시 lib<이름>.a 로 해야 한다. 이런 형태로 이름을 붙이지 않으면 컴파일러가 아카이브 파일을 찾을 때 문제가 발생한다.
정적 라이브러리는 lib로 이름이 시작된다. 이것이 아카이브 이름을 짓는 표준이다.

ar명령으로 생성된 아카이브 파일

라이브러리 아카이브를 만드는 궁극적인 이유는 다른 프로그램에서 사용하기 위한 것이다. 만든 아카이브를 표준 디렉토리에 설치했다면 -l 옵션을 사용해 컴파일할 수 있다.

gcc test_code.c -lsecurity -o test_code

/*

-l 라이브러리 앞에 소스 파일들을 나열해야 한다.
security로 지정하면 libsecurity.a 라는 파일을 찾으라고 컴파일러에 알려준다.

*/

아카이브 이름을 lib<이름>.a 로 붙이는 것이 왜 중요한지 알것이라 생각한다. -l 옵션 다음에 나오는 이름이 아카이브 이름의 일부에 정확히 대응되어야 한다.

따라서 아카이브 이름이 libtest.a 라면 -ltest 옵션으로 프로그램을 컴파일할 수 있다.

그런데 아카이브를 표준 디렉토리가 아닌 외부에 두었다면, 어느 디렉토리를 검색할 지 알려주기 위해 -L 옵션을 사용해야 한다.

gcc test_code.c -L/my_lib -lsecurity -o test

/* 

-L 옵션으로 어느 디렉토리에 라이브러리가 있는지 알려준다.

*/

 

cmake를 이용하여 정적 라이브러리 컴파일

정적 라이브러리의 헤더파일 디렉토리와 정적 라이브러리 libsecurity.a
cmake에 헤더파일 디렉토리, 라이브러리 파일 지정

#include <stdio.h>

#include "encrypt.h"
#include "checksum.h"

int main(void) {
    char s[] = "Hello, World!!";
    encrypt(s);
    printf("암호 문장: %s\n", s);
    printf("체크섬: %d\n", checksum(s));
    encrypt(s);
    printf("복호화 문장: %s\n", s);
    printf("체크섬: %d\n", checksum(s));

    return 0;
}

// 결과
/*

암호 문장: Wzssp3?Hpms{>>
체크섬: 699838
복호화 문장: Hello, World!!
체크섬: 334257

*/

만약 gcc로 정적 라이브러리와 함께 컴파일하려면 아래와 같이 하면되겠다.

gcc -I<헤더파일 디렉토리> -L<라이브러리 디렉토리> -lsecurity -o test_code

/*

-L<경로명> 옵션은 표준 라이브러리 디렉토리 목록에 경로명을 추가한다.
-l<라이브러리명> 옵션은 파일을 /usr/lib와 같은 표준 디렉토리에서 찾아 링크한다.
-I<경로명> 옵션은 표준 헤더 파일 디렉토리 목록에 경로명을 추가한다.

*/

* 라이브러리 아카이브는 정적으로 링크된다.

 

아카이브에서 오브젝트 파일 꺼내기

ar -x libsecurity.a encrypt.o

/* 

-x 명령으로 아카이브 안에 존재하는 오브젝트 파일을 꺼낼 수 있다.

*/
Comments