Thư viện trong C/C++ được chia làm 2 loại là Static LibrariesShared Libraries (hay Dynamic Libraries).

Static Libraries

Thư viện tĩnh (Static Libraries) là các thư viện được liên kết tĩnh. Mỗi thư viện tĩnh là một file chứa các object được biên dịch từ source code, trong đó các object này lưu trữ định nghĩa của các hàm (functions) và biến (variables). Các file của thư viện tĩnh có thể được liên kết với các object khác để tạo ra một thư viện mới hoặc một file thực thi (executable).




  • Với GCC (trình biên dịch trên Linux) hoặc MinGW (GCC trên Windows), các thư viện tĩnh có dạng lib*.a.
  • Với MSVC (trình biên dịch của Visual Studio trên Windows), các thư viện tĩnh có dạng ***.lib.


Thư viện tĩnh thường được cung cấp dưới dạng các file đã biên dịch sẵn (.a, .lib) kèm theo các file header tương ứng. Khi sử dụng, ứng dụng cần include header files và link tới các file thư viện.

Trong trường hợp open source, người dùng thường có thêm lựa chọn là tải source code về, tự build thành thư viện tĩnh và sử dụng.

Lưu ý: Khi sử dụng thư viện tĩnh, nếu thư viện có thay đổi, để ứng dụng hoặc thư viện đang sử dụng cập nhật các thay đổi này, bắt buộc phải build lại ứng dụng hoặc thư viện đó.

Shared Libraries (hay Dynamic Libraries)

Shared Libraries còn gọi là thư viện liên kết động. Nó là file chứa các objects được build từ source code, các file objects này chứa các define của functions, variables. Những file Shared Libraries được load vào file executable của application lúc runtime. Vì nhiều chương trình có thể sử dụng chung các thư viện này nên nó được gọi là Shared Libraries.




  • Shared Libraries có thể được load ngay lúc bắt đầu chạy chương trình (gọi là implicit linking) hoặc load/unload khi cần thiết (gọi là explicit linking). 
  • Với GCC (compiler cho Linux), MinGW (GCC cho môi trường Windows) thì shared lib sẽ có tên dạng lib***.so và đi kèm là file lib***.dll.a (file này chứa thông tin về file lib***.so, khi build thì application phải link với file này thì khi chạy application mới biết cần load file lib***.so nào vào)
  • Với MSVC (compiler của Visual Studio cho Windows) thì shared lib sẽ có name ***.dll và đi kèm là file ***.lib (tác dụng của file này tương tự file lib***.dll.a đã nói ở trên)
  • Shared lib thường được cung cấp dưới dạng các file thư viện đã được build sẵn (.dll.a đi kèm .so, hoặc .lib đi kèm .dll) + các file headers tương ứng. Các application sử dụng thư viện phải include header files và khi build thì phải link tới các file .dll.a hoặc .lib. Khi chạy thì file executable (application) phải load các file .so hoặc .dll tương ứng vào. File executable (application) sẽ search các file shared lib trong chính folder chứa nó và 1 số folder mặc định khác (Trên windows là C:\Windows\System32 còn trên Linux là folder được chỉ định thông qua LD_LIBRARY_PATH). Với open source thì thường có thêm option là download source về tự build thành shared lib và sử dụng



So sánh giữa shared library và static library: 




  • Shared Library được lưu trong bộ nhớ và sẽ được các process ánh xạ đến khi cần. Trong khi mỗi process dùng thư viện static cần có 1 bản copy của nó.
  • Static library có ưu điểm hơn về mặt tốc độ thực thi nhưng shared library lại biên dịch nhanh hơn.
  • Shared library có kích thước chương trình thực thi nhỏ hơn (vì chỉ cần copy 1 lần)
  • Mỗi lần muốn update ứng dụng thì ứng dụng dùng static lib cần build lại cả chương trình, trong khi dùng shared lib chỉ cần nhớ build lại lib đó.


Cách tạo static library và dynamic lybrary.


1. Library code. (sử dụng chung để compile 2 loại thư viện).


my_math.c

#ifndef MY_MATH_H
#define MY_MATH_H

int add(int a, int b);
int subtract(int a, int b);

#endif // MY_MATH_H


my_math.h

#include "my_math.h"

int add(int a, int b) {
    return a + b;
}

int subtract(int a, int b) {
    return a - b;


main.c (chương trình sử dụng thư viện trên).

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

int main() {
    printf("10 + 5 = %d\n", add(10, 5));
    printf("10 - 5 = %d\n", subtract(10, 5));
    return 0;
}


Tạo thêm 2 thư viện static và dynamic để lưu 2 thư viện được tạo ra. Cây thư mục sẽ có dạng như sau:

├── dynamic

├── main.c

├── my_math.c

├── my_math.h

└── static


2. Compile Static Library.


- Biên dịch mã nguồn thư viện thành file đối tượng bằng cờ -c để dừng lại trước bước liên kết. Lệnh này sẽ tạo ra file my_math.o.

gcc -c my_math.c -o static/my_math.o


- Tạo thư viện tĩnh bằng lệnh ar (archiver). Tên thư viện phải bắt đầu bằng lib và kết thúc bằng .a. Lệnh này sẽ tạo ra file libmymath.a.

ar rcs static/libmymath.a static/my_math.o


- Biên dịch và liên kết chương trình chính với thư viện tĩnh:

  • -I static: thêm đường dẫn tìm header
  • -L static: thêm đường dẫn tìm library
  • -lmymath: chỉ định tên thư viện là mylibrary; compiler sẽ tự động thêm tiền tố lib và hậu tố .a (tức là tìm libmylibrary.a)
  • -o static_app: đặt tên file thực thi đầu ra là static_app
gcc main.c -Istatic -Lstatic -lmymath -o app_static

-> app_static là chương trình main.c sử dụng static library.


3. Compile Dynamic Library.


- Biên dịch mã nguồn thư viện thành mã độc lập vị trí (PIC) bằng các cờ -fPIC-c. Lệnh này tạo ra file my_math.o.

gcc -c -fPIC my_library.c


- Tạo thư viện động bằng cờ -shared. Tên thư viện phải bắt đầu bằng lib và kết thúc bằng .so. Lệnh này tạo ra file libmylibrary.so.

gcc -shared -o libmylibrary.so my_library.o


Biên dịch và liên kết chương trình chính với thư viện động (lệnh biên dịch giống hệt như khi dùng thư viện tĩnh):

gcc main.c -Idynamic -Ldynamic -lmymath -o app_dynamic

-> app_dynamic là chương trình main sử dụng dynamic library.


Kết quả: cả 2 cách đều compile thành công nhưng để chạy được app_dynamic. Bạn cần thêm thư viện .so vừa build vào path của hệ thống để hẹ thống có thể thấy được:

export LD_LIBRARY_PATH=.

Ta có thể thấy chương trình sử dụng dynamic library sẽ nhẹ hơn so với static.