CMake教學系列三建立CMake專案
下載範例
下面指令將會下載本文所需的範例
1 | git clone https://gitlab.com/CLIUtils/modern-cmake.git |
CMakeLists.txt解說
- 在第29行
add_library(MyLibExample simple_lib.cpp simple_lib.hpp)
增加了一個名為MyLibExample
的target
並且將會編譯一個MyLibExample
library - 第34行增加了一個
add_executable(MyExample simple_example.cpp)
增加了一個名為MyExample
的target
並且將會編譯一個MyExample
的執行檔 - 第38行
target_link_libraries(MyExample PRIVATE MyLibExample)
連接了MyLibExample
和MyExample
這兩個target
,注意你必須先製作target
才能夠連接他們
建置專案、編譯
接下來你可以用以下指令建置專案並且編譯。CMake會產生一個build
資料夾,在裡面你應該會看到libMyLibExample.a
library和MyExample
執行檔。你可以查看CMakeCache.txt
看有哪些cache variable
,接下來用./build/MyExample
執行MyExample
執行檔
1 | cmake -S . -B build |
常見錯誤
路徑中有空白
1 | set(VAR a b v) |
這個寫法會讓VAR變成一個list,並且擁有a b c三個元素,因此如果你的路徑像這樣,你的路徑就會被拆成兩段。
1 | set(MY_DIR "/path/with spaces/") |
解決方法就是在${MY_DIR}
外面再包一個引號
1 | set(MY_DIR "/path/with spaces/") |
除錯
印出變數
雖然message
指令也可以印出變數,不過你有更好的選擇,cmake_print_properties
、cmake_print_variables
,記得要先include(CMakePrintHelpers)
。如此一來你可以更加容易的印出target
的屬性
1 | include(CMakePrintHelpers) |
–trace-source 和 –trace-expand
--trace-source
讓你可以指定只要看你想看的CMakeLists.txt
,--trace-expand
變數全部展開,例如原本是
1 | add_library(simple_lib ${SOURCES} ${HEADERS} ) |
加了--trace-expand
變成
1 | add_library(simple_lib simple_lib.c simple_lib.h ) |
下載這個範例,並且試看看cmake -S . -B build --trace-source=CMakeLists.txt
、 cmake -S . -B build --trace-source=CMakeLists.txt --trace-expand
有什麼不一樣
1 | git clone git@github.com:hsf-training/hsf-training-cmake-webpage.git |
除錯CMake的find_…模組
沿用上面的範例,在這個範例你可以看到第16行有一個find_library(MATH_LIBRARY m)
1 | git clone git@github.com:hsf-training/hsf-training-cmake-webpage.git |
試看看cmake -S . -B build --debug-find
。記得要先清除build
資料夾否會出現debug訊息。你也可以用CMAKE_FIND_DEBUG_MODE來針對你想要debug的find_…模組來除錯
1 | set(CMAKE_FIND_DEBUG_MODE TRUE) |
設定build types
如果你想要執行C++ debugger,你會需要設定很多flag,CMake提供四種build types來幫你設定這些flag。
- CMAKE_BUILD_TYPE=Debug : 輸出所有除錯訊息
- CMAKE_BUILD_TYPE=RelWithDebInfo : release build 不過有一些額外的除錯訊息
- CMAKE_BUILD_TYPE=Release : 最佳化release build
- CMAKE_BUILD_TYPE=MinSizeRel : minimum size release
下面範例示範如何用CMake的Debug模式編譯,並且用GDB除錯GDB指令1
2
3
4cd hsf-training-cmake-webpage/code/04-debug
cmake -S . -B build-debug -DCMAKE_BUILD_TYPE=Debug
cmake --build build-debug
gdb build-debug/simple_example1
2
3
4
5# GDB
break my_sin
r
watch sign
c
尋找套件
1 | find_package(MyPackage 1.2) |
這個命令會首先尋找CMAKE_MODULE_PATH這份路徑清單,在這些路徑底下尋找FindMyPackage.cmake
這個檔案,注意他是直接把find_package
第一個參數MyPackage
產生出FindMyPackage.cmake
這個搜尋目標,所以如果我們寫成find_package(OpenCV 3)
,那搜尋目標就是FindOpenCV.cmake
。
如果找不到FindMyPackage.cmake
他就會接著尋找MyPackageConfig.cmake
,如果MyPackage_DIR
存在的話也會搜尋這個路徑。
在CMake3.12+之後,如果你的套件不是安裝在系統預設路徑,你可以設定環境變數<PackageName>_ROOT
讓CMake搜尋。以下以Bash命令設定環境變數為例
1 | export HDF5_ROOT=$HOME/software/hdf5-1.12.0 |
或者是設定CMAKE環境變數,以下以Bash命令設定環境變數為例
1 | export CMAKE_PREFIX_PATH=$HOME/software/hdf5-1.12.0:$HOME/software/boost-1.74.0:$CMAKE_PREFIX_PATH |
FindPackage.cmake
這是舊方法(MODULE
方法),這裡有CMake提供的FindPackage清單
PackageConfig
這是由package開發者所提供,簡而言之如果你是package開發者,你應該提供<package>Config.cmake
並且自行維護。
CMake結合PkgConfig
參考:
https://hsf-training.github.io/hsf-training-cmake-webpage/08-debugging/index.html
https://hsf-training.github.io/hsf-training-cmake-webpage/09-findingpackages/index.html
現代CMake觀念
https://pabloariasal.github.io/2018/02/19/its-time-to-do-cmake-right/
CMake結合PkgConfig
https://stackoverflow.com/a/74038236
CMake教學系列三建立CMake專案