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
好了,簡簡單單介紹到這裡,歡迎留言交流_