自從上次在為何 C++ 靜態(tài)鏈接庫順序很重要撿回了 C++,自此開始了不歸路。
今天我們來說說,CMake 這個現(xiàn)代 C++ 項目的利器。
前言
為什么我們需要 CMake ? 對于 C++ 開發(fā)者來說,他們會習慣于使用 GNU Make 來編譯 C++ 項目,對于簡單項目來說,這無可厚非,再加上有那么多的開源工具可用,尤其是 autotools 系列,用起來還是挺方便的。目前仍有非常多的 C++ 項目,需要你先使用 ./configure 來預處理,然后再進行編譯,這比只用 Make 來說,方便很多倍,也就是對初學者非常友好 (高階用戶在此就不說了,畢竟如能把 Vim 用到飛起的高手并不多)。
在我個人看來,autotools 系列不那么簡潔(當我看見當前目錄生成一堆臨時文件的時候,會非常討厭,相對的,CMake 可以有專門的編譯目錄真是拯救了我的強迫癥),由于沒有怎么使用過,不便于說出更多其它意見,也無法細致對比。有興趣的也可以看看 What are the differences between Autotools, Cmake and Scons? 上的討論。
從入手難度來說,CMake 是初學者的福音,不過有點麻煩的是,你需要學習一門新的語言,只是相對于編程語言來說,它還是非常簡單的。
準備
大多數(shù)情況下,你只需要直接安裝即可,比如下面三個命令你可以按照自己的機器選擇:
brew install cmake
sudo apt install cmake
pip install cmake
其它的方式就可以直接在官網去下載后安裝。
一個簡單例子
讓我們從一個最簡單的項目開始。
// main.cpp
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("Hello world");
return 0;
}
我們就可以在當前目錄下創(chuàng)建一個 CMakeLists.txt:
# CMake 最低版本號要求,你也可以設置版本范圍,比如 3.1...3.15
cmake_minimum_required (VERSION 3.0)
# 項目信息,可設置版本號以及描述
project (demo VERSION 0.1.0 DESCRIPTION "Demo project")
# 生成一個 demo 的可執(zhí)行文件
add_executable(demo main.cpp)
然后,執(zhí)行經典的四條命令,就可以編譯出可執(zhí)行文件了:
mkdir build
cd build
cmake ..
make
不同于 Make,CMake 可以將配置的過程大大簡化,三行語句,你就可以寫出強大的跨平臺編譯腳本了,你可以從輸出看到,一系列的步驟,都自動化完成了:
-- The C compiler identification is GNU 7.4.0
-- The CXX compiler identification is GNU 7.4.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: /home/xizhibei/demo/build
是不很簡單?再來個復雜點的例子。
一個稍復雜的例子
現(xiàn)在,隨著你加入了更多的功能,你會需要改下你的 CMakeLists.txt。
比如你現(xiàn)在的項目結構是這樣的:
--- root
|-- CMakeLists.txt
|-- main.cpp
|-- include/
|------ a.h
|------ b.h
|-- lib/
|------ a.cpp
|------ b.cpp
那么,對應著的修改如下:
cmake_minimum_required (VERSION 3.0)
project (demo VERSION 0.1.0 DESCRIPTION "Demo project")
# 添加 demo_lib 靜態(tài)庫
add_libary(demo_lib STATIC lib/a.cpp lib/b.cpp)
# 指定頭文件所在位置
target_include_directories(demo_lib PUBLIC ${CMAKE_SOURCE_DIR}/include}
# 同上
add_executable(demo main.cpp)
# 這里不需要再次 target_include_directories 了,因為我們在設置了 include 是 demo_lib 需要的,CMake 會自動添加
# 將 demo_lib 庫鏈接至 demo 執(zhí)行文件
target_link_libraries(demo demo_lib)
其實按照標準一些的方式,我們應該在 lib 下創(chuàng)建一個新的 CMakeLists.txt,然后通過 add_subdirectory(lib) 來做,這里這樣做是為了節(jié)約篇幅。
于是,一個簡單的 C++ 項目就完成了。
其它
一個簡單的例子完成了,但是該如何添加第三方依賴?怎么添加編譯選項?怎么測試?怎么添加文檔?
不急,之后我會慢慢道來,爭取寫一個比較長的系列。
Ref
感謝閱讀,本文首發(fā)于 Github issues: https://github.com/xizhibei/blog/issues/133 (Star 以及 Watch 強烈暗示 :P);另外這篇文章也能在本人博客內閱讀:https://blog.xizhibei.me/2020/03/09/cmake-1-introduction/ 。
本文采用 署名-非商業(yè)性使用-相同方式共享(BY-NC-SA)進行許可。