General Knowledge
Chuyên mục này tôi sẽ viết lại những thứ mà tôi đã học được về Linux Programming.
- Makefile là gì?
- Trình biên dịch của 1 chương trình C
- Shared Lib và Static Lib
I. MAKEFILE LÀ GÌ?
Makefile là một tệp tin cấu hình dùng để tự động hóa quá trình biên dịch và xây dựng phần mềm trong môi trường UNIX/Linux. Nó thường được sử dụng với công cụ make để quản lý và thực thi các lệnh biên dịch, liên kết hoặc thực hiện các tác vụ khác như kiểm thử, triển khai, dọn dẹp mã nguồn.
Make file là một script bên trong có chứa các thông tin:
- Cấu trúc của một project(file, dependency).
- Các command line dùng để tạo-hủy file.
Chương trình make sẽ đọc nội dung trong Makefile và thực thi nó.
1. Tại sao cần Makefile?
Khi làm việc với các dự án lớn có nhiều tệp nguồn (.c, .cpp, .h), biên dịch từng tệp riêng lẻ bằng tay có thể trở nên phức tạp. Makefile giúp:
- Tự động hóa quá trình biên dịch thay vì gõ nhiều lệnh thủ công.
- Quản lý phụ thuộc giữa các tệp nguồn, chỉ biên dịch lại các phần cần thiết.
- Tiết kiệm thời gian khi lập trình và xây dựng phần mềm.
- Dễ dàng mở rộng cho các tác vụ khác như kiểm thử, cài đặt, dọn dẹp.
2. Cấu trúc của Makefile
Một Makefile cơ bản có dạng:

- Target: Mục tiêu cần tạo (ví dụ: file nhị phân, thư viện).
- Dependencies: Các tệp phụ thuộc để tạo target.
- Action: Lệnh thực thi (phải có dấu tab ở đầu dòng).
VÍ DỤ:
Giả sử ta có 2 file main.c và hoag.c
// main.c
#include
#include "hoag.h"
int main() {
printf("Hello, Makefile!\n");
hoag_function();
return 0;
}
// hoag.c
#include <stdio.h>
void hoag_function() {
printf("This is a hoag function!\n");
}
// hoag.h
void hoag_function();
Thay vì gõ lệnh thủ công:
gcc -c main.c
gcc -c hoag.c
gcc -o program main.o hoag.o
Ta dùng Makefile
# Compiler settings
CC = gcc
CFLAGS = -Wall -g
# Output target file
program: main.o hoag.o
$(CC) -o program main.o hoag.o
# Compilation rules for .c files to .o
main.o: main.c hoag.h
$(CC) $(CFLAGS) -c main.c
hoag.o: hoag.c hoag.h
$(CC) $(CFLAGS) -c hoag.c
# Cleanup rule
clean:
rm -f *.o program
Chạy make để biên dịch:
make
Sẽ tạo ra file binary program
Chạy chương trình
./program
Dọn dẹp file object và file biên dịch:
make clean
II. Trình biên dịch của 1 chương trình C
Một trình biên dịch của 1 chương trình C trải qua 4 - stage
- Stage 1: Pre - Compling
•Loại bỏ comments
•Mở rộng các macros
•Mở rộng các include file
•Biên dịch các câu lệnh điều kiện
•Kết quả thu được sau bước này là một file “.i”
- Stage 2: Complication
•Ở giai đoạn này, mã nguồn sẽ tiếp tục thực hiện biên dịch từ file “.i” thu được ở bước trước thành một file “.s” (assembly).
- Stage 3: Assembly
•File “.s” ở giai đoạn trước tiếp tục được sử dụng cho giai đoạn này.
•Thông qua assembler, output mà chúng ta thu được là một file “.o”. Đây là file chứa các chỉ lệnh cấp độ ngôn ngữ máy (machine language).
- Stage 4: Linking
•Mỗi một file “.o” thu được ở gian đoạn Assembly là một phần của chương trình.
•Ở giai đoạn linking sẽ liên kết chúng để thu được một file thực thi hoàn chỉnh.
Makefile với 1 file hello.c
.PHONY: stage1 stage2 stage3 stage4 all clean
stage1:
gcc -E hello.c -o hello.i
stage2:
gcc -S hello.i -o hello.S
stage3:
gcc -c hello.S -o hello.o
stage4:
gcc -o hello hello.o
all:
gcc -o hello hello.c
clean
rm -rf hello hello.i hello.S hello.o
III. Shared Lib và Static Lib
- Thư viện là một tập hợp các đoạn mã được biên dịch sẵn để có thể được sử dụng lại trong một chương trình.
- Có 2 loại thư viện:
Static Library (Thư viện tĩnh) - .a
hoặc .lib
Shared Library (Thư viện động) - .so
hoặc .dll
Cả hai đều giúp tái sử dụng mã nguồn và chia sẻ chức năng giữa nhiều chương trình mà không cần viết lại. Tuy nhiên, chúng có sự khác biệt lớn về cách hoạt động, hiệu suất, và quản lý bộ nhớ.
Static Lib
Static Library là một tập hợp các mã biên dịch sẵn được gộp trực tiếp vào file thực thi tại thời điểm biên dịch.

- Mỗi chương trình (A, B, C) có kích thước 2MB.
- Static Library (
.a
) có kích thước 2MB. - Vì thư viện tĩnh được nhúng trực tiếp vào mỗi chương trình, nên mỗi chương trình sẽ chứa một bản sao của thư viện.
- A = 2MB + 2MB = 4MB
- B = 2MB + 2MB = 4MB
- C = 2MB + 2MB = 4MB
- Tổng RAM bị chiếm = 4MB + 4MB + 4MB = 12MB
Shared Lib

- Ba chương trình A, B, C (mỗi cái 2MB) đều sử dụng chung thư viện động (
.so
). - Thư viện
.so
chỉ được tải vào RAM một lần và được chia sẻ giữa các tiến trình. - Các tiến trình A, B, C có thể truy cập thư viện
.so
mà không cần nạp lại nhiều lần, giúp tiết kiệm bộ nhớ RAM.
Tổng kích thước file sau khi biên dịch sẽ là thành 8MB ( Vì thư viện động .so
có kích thước 2MB, nhưng chỉ cần load một lần vào RAM và các chương trình cùng dùng chung.)
Properties |
Static Library |
Shared Library |
Linking time |
Tất cả các thành phần trong thư viện được sao chép vào tệp thực thi tại thời điểm biên dịch (Static Linking). Khi chương trình chạy, hệ điều hành chỉ tải một tệp thực thi duy nhất chứa cả mã nguồn và thư viện. |
Thư viện động được tải vào bộ nhớ khi chương trình chạy (Dynamic Linking). Một thư viện có thể được nhiều chương trình sử dụng cùng lúc. |
Size |
Sử dụng static lib tốn nhiều bộ nhớ hơn shared lib. |
Sử dụng shared lib tốn ít bộ nhớ hơn vì chỉ có duy nhất một bản sao trong bộ nhớ. |
External File changes |
Nếu thư viện thay đổi, cần biên dịch lại toàn bộ chương trình. |
Không cần biên dịch lại chương trình khi thư viện thay đổi. |
Performance |
Chương trình có thể mất nhiều thời gian tải do tệp thực thi lớn. |
Chạy nhanh hơn nếu thư viện đã có sẵn trong bộ nhớ. |
Khi nào nên sử dụng Static Library hoặc Shared Library?
Sử dụng Static Library khi:
- Chương trình cần tự chứa, không phụ thuộc vào thư viện bên ngoài.
- Thư viện ít thay đổi và không cần cập nhật thường xuyên.
- Yêu cầu hiệu suất cao, tránh chi phí load thư viện trong runtime.
- Phần mềm cần dễ dàng triển khai mà không lo thiếu thư viện trên hệ thống.
Sử dụng Shared Library khi:
- Cần chia sẻ thư viện giữa nhiều chương trình, giảm tiêu tốn bộ nhớ RAM.
- Muốn cập nhật thư viện mà không cần biên dịch lại toàn bộ chương trình.
- Muốn giảm kích thước file thực thi, giúp tối ưu bộ nhớ lưu trữ.
- Cần tận dụng khả năng quản lý thư viện của hệ điều hành, như trong Linux với
glibc
,OpenSSL
, v.v.