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

Testing, cài đặt, và so với Make

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

  • Thêm bài kiểm thử bằng enable_testing và add_test
  • Chạy ctest và đọc kết quả
  • Viết quy tắc install
  • Chọn giữa Make và CMake cho một dự án cụ thể

Bài cuối của Phần 14 lắp phần kiểm thử và cài đặt vào CMake, rồi trả lời câu hỏi thực tế: dự án của bạn nên dùng Make hay CMake. Cả hai đều được chạy thật với CMake 4.4.2 và MinGW.

#CTest

Thêm kiểm thử vào CMakeLists.txt
enable_testing()

add_executable(test_toan tests/test_toan.c)
target_link_libraries(test_toan PRIVATE toan)

add_test(NAME toan COMMAND test_toan)
CTest
Bộ chạy kiểm thử đi kèm CMake. Bạn khai báo một bài kiểm thử là một lệnh; CTest chạy nó và coi mã thoát 0 là đạt, khác 0 là hỏng. Đó chính là quy ước mã thoát của khung kiểm thử tự viết ở Bài 57.1.
tests/test_toan.c
#include "toan.h"
#include <stdio.h>

int main(void) {
    int hong = 0;
    if (cong(2, 3) != 5) { printf("cong SAI\n"); hong = 1; }
    if (nhan(2, 3) != 6) { printf("nhan SAI\n"); hong = 1; }
    if (!hong) printf("moi test dat\n");
    return hong;                 /* 0 dat, khac 0 hong: CTest doc cai nay */
}

#Chạy ctest

terminal
cmake --build build
[ 83%] Building C object CMakeFiles/test_toan.dir/tests/test_toan.c.obj
[100%] Linking C executable test_toan.exe
[100%] Built target test_toan
# Vao thu muc dung roi chay ctest
cd build && ctest --output-on-failure
Test project .../build
    Start 1: toan
1/1 Test #1: toan .............................   Passed    0.04 sec

100% tests passed out of 1

Total Test time (real) =   0.06 sec

#Cài đặt

Quy tắc install
install(TARGETS app DESTINATION bin)
install(DIRECTORY include/ DESTINATION include)
terminal
# --prefix chon thu muc goc de cai vao
cmake --install build --prefix ./staged
-- Install configuration: "Release"
-- Installing: .../staged/bin/app.exe
-- Installing: .../staged/include
-- Installing: .../staged/include/toan.h
find staged -type f
staged/bin/app.exe
staged/include/toan.h

#Make hay CMake

Tình huốngChọnVì sao
Bài tập, chương trình một tệpMakeCMake là thừa cho việc này
Dự án nhỏ, một nền tảngMakeĐủ dùng, đơn giản, hiểu hết
Thư viện cho người khác dùngCMakeXuất được cấu hình để find_package
Phải dựng trên Linux và WindowsCMakeSinh tệp dựng cho từng nền tảng
Dùng IDE (Visual Studio, CLion)CMakeIDE tích hợp CMake sẵn
Có nhiều phụ thuộc bên ngoàiCMakeFetchContent và find_package
Cần compile_commands.json dễCMakeMột cờ là có
Chọn sai công cụ
# Dung CMake cho mot bai tap 50 dong: # CMakeLists.txt, thu muc build/, cmake -S -B, cmake --build... # -> nhieu buoc hon la loi ich, va che mat viec hoc gcc truc tiep. # Dung Make cho mot thu vien da nen tang: # viet tay quy tac cho .so tren Linux VA .dll tren Windows, # xu ly khac biet duong dan, tu quan ly phien ban... # -> tu viet lai cai CMake da lam san.
Chọn đúng
# Bai tap / chuong trinh nho: gcc -std=c17 -Wall -Wextra bai_tap.c -o bai_tap # Hoac mot Makefile 20 dong (Bai 37.4). # Thu vien / du an da nen tang / nhieu phu thuoc: # CMakeLists.txt, va de CMake lo phan da nen tang. # Quy tac: dung cong cu DON GIAN NHAT du cho cong viec. # Make cho den khi ban CAN cai CMake cho, roi chuyen.

#CMakeLists đầy đủ

CMakeLists.txt, gộp cả chương
cmake_minimum_required(VERSION 3.16)
project(MyApp VERSION 1.0.0 LANGUAGES C)

# ===== Chuan ngon ngu =====
set(CMAKE_C_STANDARD 17)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)

# ===== Build type =====
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE Debug)
endif()
set(CMAKE_C_FLAGS_DEBUG   "-g3 -O0 -DDEBUG")
set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG")

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

# ===== Chuong trinh chinh =====
add_executable(app src/main.c)
target_link_libraries(app PRIVATE toan)

# ===== Tuy chon sanitizer =====
option(ENABLE_ASAN "Bat AddressSanitizer" OFF)
if(ENABLE_ASAN)
    target_compile_options(app PRIVATE -fsanitize=address,undefined)
    target_link_options(app    PRIVATE -fsanitize=address,undefined)
endif()

# ===== Kiem thu =====
enable_testing()
add_executable(test_toan tests/test_toan.c)
target_link_libraries(test_toan PRIVATE toan)
add_test(NAME toan COMMAND test_toan)

# ===== Cai dat =====
install(TARGETS app DESTINATION bin)
install(DIRECTORY include/ DESTINATION include)

Tự làm thử

  1. Thêm enable_testing và một add_test vào dự án của bạn, rồi chạy ctest.
  2. Làm một bài kiểm thử hỏng và xác nhận ctest báo FAIL.
  3. Viết một bài kiểm thử trả về 0 dù có khẳng định hỏng, và thấy CTest vẫn báo PASS.
  4. Thêm quy tắc install và cài vào một thư mục cục bộ bằng --prefix.
  5. Với ba dự án bạn từng viết, quyết định mỗi cái nên Make hay CMake.
  6. Đổi bộ sinh sang Ninja và đo chênh lệch thời gian dựng.

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

  • enable_testing và add_test khai báo bài kiểm thử; CTest chạy và đọc mã thoát.
  • CTest là lớp điều phối; bạn vẫn cần khung kiểm thử bên trong mỗi chương trình để biết cái gì hỏng.
  • install sắp sản phẩm theo cây thư mục chuẩn; --prefix chọn thư mục gốc.
  • Dùng Make cho dự án nhỏ một nền tảng, CMake cho thư viện, đa nền tảng, và nhiều phụ thuộc.
  • Bốn lệnh cấu hình, dựng, kiểm thử, cài đặt giống nhau trên mọi nền tảng: đó là lợi ích cốt lõi của CMake.