GIỚI THIỆU VỀ MAKE VÀ CMAKE

make là một công cụ giúp tự động hóa quá trình biên dịch mã nguồn, nhờ đó mà chúng ta có thể biên dịch các project phức tạp một cách dễ dàng và nhanh chóng hơn. Các cài đặt cho quá trình biên dịch một project được lưu trong file Makefile để make có thể sử dụng. Tuy nhiên, độ phức tạp của Makefile cũng tỉ lệ thuận với độ phức tạp của project, do đó CMake đã ra đời để giải quyết vấn đề này.

Bạn đang xem: Cmake là gì

CMake giúp tự động sinh ra Makefile make có thể sử dụng để biên dịch project của bạn. Đối với từng project, các cài đặt cho CMake được lưu trong file CMakeLists.txt.

MỘT SỐ CMAKE COMMAND QUAN TRỌNG

+ cmake_minimum_required() – quy định phiên bản CMake tối thiểu cần cho project.Ví dụ: cmake_minimum_required(VERSION 2.8)

+ project() – đặt tên cho project hiện tại.Ví dụ: project(Demo)

+ find_package()Ví dụ: find_package(OpenCV REQUIRED)

+ set() – tạo hoặc thay đổi giá trị của một biến.Ví dụ: set(INCLUDE_PATH ../library_1 ../library_2)

+ file() – tạo một danh sách các file thỏa mãn pattern cho trước, thường được sử dụng thay cho set() trong một số trường hợp.Ví dụ: file(GLOB SOURCE “*.cpp”)

+ add_subdirectory() – thêm một sub-directory vào project, sub-directory này chứa một file CMakeLists.txt riêng. Được dùng để chia project thành nhiều phần nhỏ hơn hoặc khi cần thêm Unit Testing.

+ target_include_directories() – chỉ ra các thư mực chứa các file header dành cho một đối tượng cụ thể. Đối tượng này phải được tạo ra bởi lệnh add_library() hoặc add_executable().

+ target_link_libraries() – thêm libraries vào target file.Ví dụ: target_link_libraries(targetFile lib_1 lib_2)

+ include_directories() – chỉ ra các thư mục chứa các file header.Ví dụ: include_directories(../include_1 ../include_2)

+ link_directories() – chỉ ra các thư mục chứa static và shared libraries. Ví dụ: link_directories(../library_1 ../library_2)

+ add_library() – tạo static và shared library từ các source files.Ví dụ: add_library(staticLib STATIC sourcefile_1 sourcefile_2)add_library(sharedLib SHARED sourcefile_1 sourcefile_2)

+ target_compile_definitions() – thêm các macro cho quá trình biên dịch, được dùng cho CMake >= 3.12Ví dụ: add_compile_definitions(VERSION=1.2 DEBUG)

+ target_compile_options() – thêm các options cho compiler trong quá trình biên dịch.Ví dụ: add_compile_options(-std=c99 -Os -Wall)

+ add_executable() – tạo executable file từ các source files.Ví dụ: add_executable(targetFile sourcefile_A sourcefile_B sourcefile_C)

+ set_target_properties() – thay đổi thuộc tính của một hoặc nhiều target.Ví dụ: set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME ${TARGET}.axf)

+ add_custom_target() –

+ add_custom_command() –

+ install() -cài đặt file runtime/library vào directory được chỉ định khi lệnh “make install” được thực thi.Ví dụ: install(TARGETS staticLib sharedLib DESTINATION /usr/local/lib)

MỘT SỐ CMAKE VARIABLES THƯỜNG DÙNG

+ CMAKE_BUILD_TYPE – chọn kiểu build cho source code, gồm: DEBUG, RELEASE, RelWithDebInfo và MinSizeRel.

+ CMAKE_INSTALL_PREFIX – chọn directory để install thư viện, executable khi gọi lệnh “make install”;

+ CMAKE_SOURCE_DIR – directory chứa file CMakeLists.txt đầu tiên được xử lý. Đây chính là directory mà chúng ta sẽ sử dụng cùng với lệnh cmake;

+ CMAKE_BINARY_DIR – directory của folder build, nơi mà chúng ta sẽ gọi lệnh “cmake ..”;

+ CMAKE_CURRENT_SOURCE_DIR – directory chứa file CMakeLists.txt đang được xử lý;

+ CMAKE_CURRENT_BINARY_DIR – directory của folder build, nơi mà file CMakeLists.txt đang được xử lý sẽ được sử dụng bởi cmake;

+ PROJECT_SOURCE_DIR – directory (full path) chứa file CMakeLists.txt có chứa command PROJECT();

+ PROJECT_BINARY_DIR – directory (full path) của folder build, nơi mà file CMakeLists.txt có chứa command PROJECT() sẽ được sử dụng bởi cmake;

+ CMAKE__COMPILER – chọn compiler cho từng ngôn ngữ, ví dụ: CMAKE_C_COMPILER=avr-gcc;

+ CMAKE_SYSTEM_NAME – được sử dụng để chỉ ra tên của “target system” khi cross-compiling (tức là hệ thống mà tại đó code được thực thi). Target system có thể là Linux, Windows hoặc Generic (nếu target system không có hệ điều hành, chẳng hạn như các dòng vi điều khiển 8-bit).

VÍ DỤ 1 – build source code

Biên dịch một project có sử dụng thư viện OpenCV với CMake và make.

Cấu trúc project:DemoProject|—- build|—- libraries|—-|—- argparse.h|—-|—- argparse.cpp|—- displayImage.cpp|—- CMakeLists.txtTrong đó, thư mục build được dùng để chứa các build files và binary file.

File: CMakeLists.txt


cmake_minimum_required(VERSION 2.8)project(Demo)find_package(OpenCV REQUIRED)# Target filenameset(TARGET_FILE displayImage)# Path to libraries set(INCLUDE_PATH ./libraries)# Load required source files in librariesset(LIB_SOURCES ${INCLUDE_PATH}/argparse.cpp)# Load all source files in project folderset(SOURCES displayImage.cpp)message(STATUS "OpenCV_INCLUDE_DIRS = ${OpenCV_INCLUDE_DIRS}")message(STATUS "OpenCV_LIBS = ${OpenCV_LIBS}")include_directories(${OpenCV_INCLUDE_DIRS} ${INCLUDE_PATH})add_compile_options(-std=c++11 -g -O3 -Wall -Werror)add_executable(${TARGET_FILE} ${SOURCES} ${LIB_SOURCES})target_link_libraries(${TARGET_FILE} ${OpenCV_LIBS})

#include "iostream"#include "opencv2/highgui/highgui.hpp"#include "opencv2/imgproc/imgproc.hpp"#include "argparse.h"using namespace std;int main(int argc, char** argv){ArgumentParser ap(argc, argv);ap.add_argument("-f", "--file", "None", "Path to input file");ap.parse_args(); cv::Mat image = cv::imread(ap.get("file")); cv::imshow("Image", image); cv::waitKey(0); return 0;}
Tạo build files với CMake:$ cd build$ cmake ..

Nếu mọi thứ OK, chúng ta sẽ có được kết quả như hình 1 và 2:


*
Hình 1 – CMake result message
*
Hình 2 – các build files đã được tạo
*
Hình 3 – file binary displayImage đã được build thành công
VÍ DỤ 2 – tạo thư viện tĩnh và thư viện động

Cũng với project ở ví dụ 1, lần này chúng ta sẽ tạo thư viện tĩnh (static library) từ các file trong thư mục libraries, sau đó sử dụng thư viện vừa tạo ở chương trình chính.

Xem thêm: Màn Hình Amoled Là Gì ? Chất Lượng Và Cơ Chế Hoạt Động Ra Sao

Cấu trúc project:DemoProject|—- build|—- libraries|—-|—- argparse.h|—-|—- argparse.cpp|—-|—- CMakeLists.txt|—- displayImage.cpp|—- CMakeLists.txtTrong đó, thư mục build được dùng để chứa các build files và binary file.

File: libraries/CMakeLists.txt


cmake_minimum_required(VERSION 3.4)add_compile_options(-std=c++11-Wall-Werror-O2)set(LIB_NAME argparse)add_library(${LIB_NAME} STATIC argparse.cpp)target_include_directories(${LIB_NAME} PUBLIC .)
Giải thích:Dòng 12: tạo thư viện tĩnh có tên argparse từ file argparse.cpp; để tạo thư viện động, chỉ cần thay STATIC bởi SHARED;– Dòng 13: chỉ ra thư mục chứa các file header được dùng cho thư viện argparse; keyword PUBLIC được sử dụng để cho phép chương trình chính có thể tìm thấy các file header cần thiết tại thư mục này, ngược lại, hãy sử dụng PRIVATE.

File: CMakeLists.txt


cmake_minimum_required(VERSION 3.4)project(Demo)find_package(OpenCV REQUIRED)add_subdirectory(libraries)# Target filenameset(TARGET_FILE displayImage)# Load all source files in project folderset(SOURCES displayImage.cpp)message(STATUS "OpenCV_INCLUDE_DIRS = ${OpenCV_INCLUDE_DIRS}")message(STATUS "OpenCV_LIBS = ${OpenCV_LIBS}")include_directories(${OpenCV_INCLUDE_DIRS})add_compile_options(-std=c++11-Wall-Werror-O2)add_executable(${TARGET_FILE} ${SOURCES})target_link_libraries(${TARGET_FILE} ${OpenCV_LIBS} argparse)
Giải thích:Dòng 6: thêm thư mục libraries chứa thư viện argparse vào project; với add_subdirectory(), chúng ta có thể tạo và liên kết thư viện vào chương trình chính chỉ với 01 lần build;– Dòng 17: vì khi tạo thư viện argparse, chúng ta đã khai báo thư mục chứa các file header của thư viện này với keywork PUBLIC nên bây giờ không cần phải khai báo lại các file header này nữa. – Dòng 27: liên kết thư viện argparse đã được tạo vào chương trình chính.

Tạo build files với CMake:$ cd build$ cmake ..

Build project với Make:$ make

Sau khi build xong, bên trong thư mục build sẽ như sau:


*
Hình 4 – bên trong thư mục build có chứa thư mục libraries
*
Hình 5 – bên trong thư mục libraries có chứa thư viện libargparse.a

Reference:<1> CMake – Công cụ sinh Makefile, Project file cho source code C/C++.<2> CMake – useful variables.<3> Debug vs Release in CMake.<4> What is the difference between include_directories and target_include_directories in CMake?<5> CMake cross-compiling.<6> CMake Directory Varialbles.

Bài viết liên quan

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *