Fundamental of CS/: : C++

[Compile Process] Static & Dynamic Library (정적, 동적 라이브러리)

Jay.P Morgan 2024. 7. 16. 10:53

 

 

  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를 이용해 구현한다.
  • 대부분의 경우 스태틱 라이브러리가 단순하고 관리하기 쉽지만, 업데이트나 플러그인 구조에서는 다이나믹 라이브러리가 유용하다.