1. Static Library (정적 라이브러리)
이 글은 C++ 라이브러리의 종류와 정적 라이브러리(Static Library)의 생성 및 사용 방법을 설명합니다.
1.1 라이브러리란?
라이브러리는 이미 작성된 코드나 바이너리를 재사용할 수 있도록 모아 놓은 것이다.
대표적인 예로 C++ 표준 라이브러리(STL)가 있으며, vector, string, iostream, memory, array 등의 헤더를 통해 사용한다.
1.2 C++ 라이브러리의 종류
① 헤더 전용(Header-only) 라이브러리
- 모든 구현이 헤더 파일에 포함되어 있다.
- 별도의 링크 과정 없이 #include만 하면 사용할 수 있다.
② 정적 라이브러리(Static Library)
- 컴파일된 오브젝트 파일들을 하나로 묶은 라이브러리이다.
- 운영체제별 확장자
- Windows: .lib
- Linux: .a
- 링크 시 실행 파일에 필요한 코드가 포함된다.
③ 동적 라이브러리(Dynamic/Shared Library)
- 실행 파일과 분리되어 존재한다.
- 운영체제별 확장자
- Windows: .dll
- Linux: .so
- 프로그램 실행 시(Load Time) 또는 실행 중(Runtime)에 로드되어 연결된다.
1.3 정적 라이브러리의 동작 원리
빌드 과정은 다음과 같다.
CPP 파일
↓
오브젝트 파일(.o)
↓
여러 오브젝트 파일을 묶음
↓
정적 라이브러리(.a)
↓
링커가 필요한 코드만 선택
↓
실행 파일 생성
정적 라이브러리는 단순히 오브젝트 파일들의 묶음(Archive) 이며, 링커는 그 안에서 실제로 필요한 코드와 데이터만 골라 실행 파일에 포함한다.
1.4 정적 라이브러리 만들기
예를 들어 Cat.cpp를 컴파일하여 오브젝트 파일을 만든 후,
g++ -c Cat.cpp
ar 명령으로 라이브러리를 생성한다.
ar rs libcat.a cat.o
- ar: 아카이브 생성 도구
- r: 파일 추가
- s: 인덱스 생성
1.5 정적 라이브러리 사용하기
링크할 때
g++ main.cpp -L. -lcat
를 사용한다.
옵션 의미는 다음과 같다.
- -lcat
- libcat.a 라이브러리를 링크
- -L.
- 현재 디렉터리에서 라이브러리를 검색
기본적으로 컴파일러는 시스템 라이브러리 경로에서만 라이브러리를 찾기 때문에, 현재 디렉터리를 검색하도록 -L.을 추가해야 한다.
※ 핵심 정리
- 라이브러리는 재사용 가능한 코드 모음이다.
- C++ 라이브러리는 헤더 전용(Header-only), 정적(Static), 동적(Dynamic) 라이브러리로 나뉜다.
- 정적 라이브러리는 여러 오브젝트 파일을 묶은 아카이브 파일이며, 링크 시 필요한 코드만 실행 파일에 포함된다.
- Linux에서는 ar 명령으로 .a 파일을 만들고, -l과 -L 옵션을 사용해 링크한다.
- 다음 단계에서는 동적(Shared) 라이브러리의 생성과 사용 방법을 다룬다.
2. Dynamic Library (동적 라이브러리)
이번 내용은 다이나믹 라이브러리(Shared Library) 의 개념과 생성 및 사용 방법, 그리고 로드 타임 바인딩과 런타임 바인딩의 차이를 설명합니다.
2.1 스태틱 라이브러리와 다이나믹 라이브러리의 차이
- 스태틱 라이브러리(.a): 링크 시점(Link Time)에 실행 파일에 포함된다.
- 다이나믹 라이브러리(.so): 실행 파일에는 라이브러리 정보만 포함되고, 실제 라이브러리는 프로그램 실행 시(Load Time) 또는 실행 중(Runtime) 에 로드된다.
2.2 로드 타임 바인딩
- 공유 라이브러리를 만들기 위해서는 먼저 -fPIC(Position Independent Code) 옵션으로 오브젝트 파일을 생성해야 한다.
- -shared 옵션을 이용해 .so(Shared Object) 파일을 생성한다.
- 실행 파일은 라이브러리의 심볼 정보만 가지고 있으며, 실행 시 로더가 .so 파일을 찾아 연결한다.
- 라이브러리를 찾지 못하면:
- LD_LIBRARY_PATH 환경 변수를 설정하거나
- rpath(-Wl,-rpath) 옵션으로 라이브러리 위치를 실행 파일에 포함시킨다.
2.3 왜 -fPIC가 필요한가?
- 하나의 공유 라이브러리는 여러 프로세스에서 동시에 사용할 수 있다.
- 따라서 절대 주소가 아닌 상대 주소(Position Independent Code) 를 사용해야 어느 프로세스에 로드되더라도 정상 동작한다.
2.4 런타임 바인딩
프로그램 실행 중에 필요한 라이브러리를 직접 불러오는 방식이다.
주요 함수:
- dlopen() : 라이브러리 열기
- dlsym() : 함수(심볼) 찾기
- dlclose() : 라이브러리 닫기
특징
- 실행 중 원하는 라이브러리를 동적으로 로드 가능
- 함수 포인터를 이용해 함수를 호출
- C++ 함수는 네임 맹글링(Name Mangling) 때문에 심볼 이름을 정확히 알아야 한다.
- 컴파일 시 -ldl 옵션으로 libdl 라이브러리를 링크해야 한다.
2.5 로드 타임 vs 런타임 바인딩
| 로드 타임 | 런타임 |
| 프로그램 시작 시 자동 로드 | 실행 중 필요할 때 직접 로드 |
| 사용이 간단 | 구현이 더 복잡 |
| 컴파일·링크 과정에서 오류 발견 가능 | 실행 중 오류 처리 필요 |
| 일반적으로 더 많이 사용 | 플러그인 등 특수한 경우에 사용 |
2.6 스태틱 라이브러리와 다이나믹 라이브러리 선택
- 스태틱 라이브러리 사용을 기본적으로 추천한다.
- 저장 공간이 충분한 현대 환경에서는 용량 문제가 크지 않다.
- 배포와 관리가 단순하다.
- 하지만 다음과 같은 경우에는 다이나믹 라이브러리가 적합하다.
- 실행 파일은 그대로 두고 라이브러리만 교체하여 기능을 업데이트해야 하는 경우
- 플러그인 시스템처럼 실행 중 모듈을 추가하거나 교체해야 하는 경우
7. 핵심 정리
- 스태틱 라이브러리: 링크 시 실행 파일에 포함된다.
- 다이나믹 라이브러리: 실행 시 또는 실행 중 로드된다.
- 공유 라이브러리는 -fPIC 으로 생성해야 한다.
- 로드 타임 바인딩은 일반적인 방식이며, 런타임 바인딩은 dlopen, dlsym, dlclose를 이용해 구현한다.
- 대부분의 경우 스태틱 라이브러리가 단순하고 관리하기 쉽지만, 업데이트나 플러그인 구조에서는 다이나믹 라이브러리가 유용하다.
'Fundamental of CS > : : C++' 카테고리의 다른 글
| [Compile Process] Attributes 속성 (0) | 2024.07.16 |
|---|---|
| [Compile Process] 컴파일 상수 constexpr (0) | 2024.07.16 |
| [Compile Process] Assembly, Debug (0) | 2024.07.16 |
| [Compile Process] 전처리기(PreProcess), 그리고 링커(Linker)의 Static & Extern (0) | 2024.07.16 |
| [Compile Process] Compile Process, Header File (0) | 2024.07.16 |