Bỏ qua điều hướng, tới nội dung chính
Học C
Bài 38.126 phút đọc

CMakeLists cơ bản và target

Sau bài này bạn sẽ làm được

  • Viết CMakeLists tối thiểu build được
  • Phân biệt add_executable và add_library
  • Dùng target_link_libraries và target_include_directories
  • Giải thích PUBLIC, PRIVATE, INTERFACE

Make là công cụ Unix. CMake không dựng gì cả: nó sinh ra tệp dựng cho nền tảng của bạn, Makefile trên Linux, project Visual Studio trên Windows, Xcode trên macOS. Bài này viết một CMakeLists.txt chạy được và giải thích tư duy target đằng sau nó.

#Vì sao CMake

MakeCMake
HọcDễ hơnKhó hơn
Đa nền tảngKhông, chủ yếu UnixCó
Quản lý phụ thuộcThủ côngTốt hơn
Tích hợp IDEKémTốt: VS, CLion, Xcode
Dự án nhỏĐủ dùngHơi thừa
Dự án lớn, thư việnKhóTốt
Bộ sinh (generator)
Chương trình dựng thật mà CMake tạo tệp cho: Unix Makefiles, MinGW Makefiles, Ninja, Visual Studio, hoặc Xcode. Chọn bằng cờ -G. Cùng một CMakeLists.txt dựng được ở mọi nền tảng vì CMake sinh tệp phù hợp cho từng bộ.

#CMakeLists tối thiểu

CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(MyApp VERSION 1.0.0 LANGUAGES C)

set(CMAKE_C_STANDARD 17)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)          # dung -std=c17, khong phai -std=gnu17

add_executable(app src/main.c)
target_include_directories(app PRIVATE include)

#Cấu hình rồi dựng

terminal
# Buoc 1: cau hinh. -S nguon, -B thu muc dung (out-of-source)
cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release
-- The C compiler identification is GNU 8.1.0
-- Detecting C compiler ABI info - done
-- Check for working C compiler: .../gcc.exe - skipped
-- Detecting C compile features - done
-- Configuring done (4.4s)
-- Generating done (0.1s)
-- Build files have been written to: .../build
# Buoc 2: dung. Goi bo sinh (o day la make) ho ban
cmake --build build
[ 50%] Building C object CMakeFiles/app.dir/src/main.c.obj
[100%] Linking C executable app.exe
[100%] Built target app
./build/app.exe
2+3=5 2*3=6

#Thư viện và liên kết

Thêm một thư viện tĩnh
cmake_minimum_required(VERSION 3.16)
project(MyApp VERSION 1.0.0 LANGUAGES C)

set(CMAKE_C_STANDARD 17)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)

# ===== Thu vien =====
add_library(toan STATIC src/toan.c)
target_include_directories(toan PUBLIC include)
target_compile_options(toan PRIVATE -Wall -Wextra)

# ===== Chuong trinh chinh =====
add_executable(app src/main.c)
target_link_libraries(app PRIVATE toan)
terminal
cmake --build build
[ 33%] Building C object CMakeFiles/toan.dir/src/toan.c.obj
[ 33%] Linking C static library libtoan.a
[ 33%] Built target toan
[ 66%] Building C object CMakeFiles/app.dir/src/main.c.obj
[ 66%] Linking C executable app.exe
[100%] Built target app

#PUBLIC, PRIVATE, INTERFACE

Phạm vi lan truyền
Ba từ khoá quyết định một thuộc tính của thư viện có lan sang thứ liên kết với nó không. PRIVATE: chỉ thư viện dùng. INTERFACE: chỉ người dùng thư viện dùng. PUBLIC: cả hai.
Ba phạm vi, ba nghĩa
add_library(toan STATIC src/toan.c)

target_include_directories(toan
    PUBLIC  include        # header CONG KHAI: toan dung, VA app dung
    PRIVATE src            # header RIENG: chi toan dung, app khong thay
)

target_compile_options(toan
    PRIVATE -Wall -Wextra  # canh bao khi dich toan, KHONG lan sang app
)

target_link_libraries(toan
    PUBLIC  m              # neu toan.h dung <math.h>, app cung can -lm
    PRIVATE pthread        # neu chi toan.c dung pthread, app khong can
)

Tự làm thử

  1. Viết một CMakeLists.txt tối thiểu và dựng một chương trình một tệp.
  2. Cấu hình với -B build và chứng minh không có tệp CMake nào rơi vào thư mục nguồn.
  3. Tách mã thành một thư viện và liên kết chương trình với nó.
  4. Bỏ CMAKE_C_EXTENSIONS OFF và tìm cờ -std mà CMake dùng trong tệp dựng.
  5. Đặt một đường dẫn include là PRIVATE mà lẽ ra PUBLIC, và đọc lỗi liên kết.
  6. Thêm target_compile_options với PRIVATE -Wall và xác nhận cảnh báo không lan sang chương trình.

Trình chấm điểm tự động sẽ được bổ sung ở giai đoạn sau. Hiện tại bạn tự chạy thử trên máy.

Tóm tắt

  • CMake không dựng mà sinh tệp dựng cho nền tảng của bạn qua một bộ sinh; cùng CMakeLists.txt chạy mọi nơi.
  • Khuôn mẫu bốn dòng đầu, và CMAKE_C_EXTENSIONS OFF để dùng chuẩn thuần.
  • Luôn dựng ngoài nguồn với -B build, và dùng cmake --build thay vì gọi bộ sinh trực tiếp.
  • add_library, add_executable, target_link_libraries tạo và nối các target; target mang theo cách dùng nó.
  • PUBLIC lan cả hai chiều, PRIVATE chỉ thư viện, INTERFACE chỉ người dùng; khi phân vân chọn PRIVATE.