cmake 入門筆記

以下內容為本人的著作,如需要轉載,請聲明原文鏈接 微信公眾號「englyf」//www.cnblogs.com/englyf/p/16667896.html


1. cmake 是什麼?

這些年大型 C/C++ 工程都紛紛轉到了 cmake 環境下,那麼這個工具到底有什麼魅力吸引著大家呢?無它,軟體工程崇尚實用主義,而 cmake 的功能強悍而靈活,趁手的工具用起來!為了從 makefile 下解放大夥的雙手,cmake 在設計之初的目標就是奔著用於對程式構建過程進行管理,它會自動對工程生成相應的 makefile 和其它輔助構建資訊。

注意:cmake 不是編譯器,僅是構建管理工具,比如調度編譯器/鏈接器等等

2. cmake 的配置文件 CMakeLists.txt

使用 cmake 來構建工程成功輸出目標文件,這個過程需要依賴於配置的設定。而這個設定存放在文件 CMakeLists.txt 中,每個構建工程都至少有一個這樣的文件(如果工程有子工程,那麼每個子工程又會有對應的配置文件),該文件可按需訂製。一般會在工程的根目錄下創建這個文件 CMakeLists.txt。舉個栗子,這裡有個最簡單的配置示例(假設本工程不包含子工程,只有一個源文件 main.cpp 而且存放於工程根目錄下):

# 指定最低要求的 cmake 版本 3.10
cmake_minimum_required(VERSION 3.10)

# 設置工程名 test
project(test)

# 指定編譯輸出可執行結果文件 test, 指定編譯源文件 main.cpp
add_executable(test main.cpp)

當然,除了把配置內容寫在配置文件 CMakeLists.txt 中,還可以在執行 cmake 指令時傳入多樣化的參數,不過通過傳參的方式用起來不靈活而且不利於持續輸出的開發理念。同一套產品輸出給不同的客戶時,可以將不同客戶的需求轉化為不同的配置文件,分別調用於構建目標結果文件。

3. CMakeLists.txt 變數

CMakeLists.txt 文件內部同樣支援變數,包括變數定義和引用等。

eg. 定義變數 USE_CUSTOM_SRC,並設置默認值 OFF (如果引用該變數前,沒有賦值,那麼當前值為默認值):

option (USE_CUSTOM_SRC "something you want to mark" OFF)

或者只是定義變數 USE_CUSTOM_SRC,並賦值 true

SET(USE_CUSTOM_SRC true)

或者通過調用其它程式並接收輸出值,跳過定義,如在調用變數 CMAKE_CURRENT_SOURCE_DIR 代表的目錄下執行程式 git 帶上參數 "log --format='%h' -1" 以獲取 SHA1 值並且保存到變數 GIT_SHA1 中。

exec_program(
        "git"
        ${CMAKE_CURRENT_SOURCE_DIR}
        ARGS "log --format='%h' -1"
        OUTPUT_VARIABLE GIT_SHA1
    )

在調用 cmake 時同樣可以在傳入的參數中指定變數 USE_CUSTOM_SRC 並賦值,變數前加 -D,如:

cmake -DUSE_CUSTOM_SRC=ON

CMakeLists.txt 中,已定義的變數可直接引用:

if(USE_CUSTOM_SRC)
    xxx
else()
    xxx
endif()

4. CMakeLists.txt 定義源碼相關的宏定義

如果需要為源碼編譯器添加宏定義呢?
如下:

add_definitions(-DUSE_CUSTOM_SRC)

這段語句定義了適用於源程式碼中的預編譯宏 USE_CUSTOM_SRC, 以 -D 為前綴。
注意:這裡的 USE_CUSTOM_SRC (適用範圍是被 cmake 管理的工程源程式碼) 與上面的 CMakeLists.txt 變數 USE_CUSTOM_SRC (適用範圍是 cmake 讀取的 CMakeLists.txt 文件內容內) 不一樣

5. 執行方法

先說一下我的環境:

WIN10 + WSL Ubuntu 18.4

wsl 環境下要求安裝有cmake、gcc、g++ 等基本工具。

首先進入 wsl 環境,看一下當前的工作目錄內容:

admin@DESKTOP:/mnt/g/test$ ls -l
total 0
-rwxrwxrwx 1 root root  89 Jun 26 16:12 CMakeLists.txt
-rwxrwxrwx 1 root root 354 Jun 26 17:13 main.cpp

源文件 main.cpp 實現了執行指令 ls -l . 的功能,下面是文件內容

#include <unistd.h>
#include <stdio.h>

int main()
{
    pid_t pid = fork();
    if (pid == -1) {
        perror("fork error");
    }

    if (pid == 0) {
        execl("/bin/ls", "ls", "-l", ".", (char *)NULL);
    }

    return 0;
}

創建構建輸出目錄 build,然後導航到輸出目錄

mkdir build
cd build

執行 cmake,輸入參數是存放 CMakeLists.txt 文件的相對目錄,目的是配置構建工程和生成用於原生構建的必需資訊並保存到當前目錄文件中,也就是所謂的配置構建系統

admin@DESKTOP:/mnt/g/test/build$ cmake ../
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/g/test/build

再次執行 cmake,調用當前目錄的構建系統實現項目構建,包括編譯/鏈接和輸出二進位目標文件。

admin@DESKTOP:/mnt/g/test/build$ cmake --build .
Scanning dependencies of target test
[ 50%] Building CXX object CMakeFiles/test.dir/main.cpp.o
[100%] Linking CXX executable test
[100%] Built target test

這一步的操作其實也可以直接調用make實現,比如需要用到加速的選項-j等就比較推薦這樣子調用

make -jn

看一下輸出的二進位目標文件是否存在

admin@DESKTOP:/mnt/g/test/build$ ls -l
total 40
-rwxrwxrwx 1 root root 12704 Jul 12 21:34 CMakeCache.txt
drwxrwxrwx 1 root root   512 Jul 12 21:39 CMakeFiles
-rwxrwxrwx 1 root root  4847 Jul 12 21:34 Makefile
-rwxrwxrwx 1 root root  1552 Jul 12 21:34 cmake_install.cmake
-rwxrwxrwx 1 root root  8392 Jul 12 21:39 test

最後執行一下目標文件,看看實際執行結果和程式碼的意圖是否一致

admin@DESKTOP:/mnt/g/test/build$ ./test
total 40
-rwxrwxrwx 1 root root 12704 Jul 12 21:34 CMakeCache.txt
drwxrwxrwx 1 root root   512 Jul 12 21:39 CMakeFiles
-rwxrwxrwx 1 root root  4847 Jul 12 21:34 Makefile
-rwxrwxrwx 1 root root  1552 Jul 12 21:34 cmake_install.cmake
-rwxrwxrwx 1 root root  8392 Jul 12 21:39 test

好了,簡簡單單介紹到這裡,歡迎留言交流_

Tags: