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ống | Chọn | Vì sao |
|---|---|---|
| Bài tập, chương trình một tệp | Make | CMake là thừa cho việc này |
| Dự án nhỏ, một nền tảng | Make | Đủ dùng, đơn giản, hiểu hết |
| Thư viện cho người khác dùng | CMake | Xuất được cấu hình để find_package |
| Phải dựng trên Linux và Windows | CMake | Sinh tệp dựng cho từng nền tảng |
| Dùng IDE (Visual Studio, CLion) | CMake | IDE tích hợp CMake sẵn |
| Có nhiều phụ thuộc bên ngoài | CMake | FetchContent và find_package |
| Cần compile_commands.json dễ | CMake | Mộ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ử
- Thêm
enable_testingvà mộtadd_testvào dự án của bạn, rồi chạyctest. - Làm một bài kiểm thử hỏng và xác nhận
ctestbáo FAIL. - 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.
- Thêm quy tắc
installvà cài vào một thư mục cục bộ bằng--prefix. - Với ba dự án bạn từng viết, quyết định mỗi cái nên Make hay CMake.
- Đổi bộ sinh sang
Ninjavà đ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_testingvàadd_testkhai 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.
installsắp sản phẩm theo cây thư mục chuẩn;--prefixchọ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.