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並且將會編譯一個MyLibExamplelibrary - 第34行增加了一個
add_executable(MyExample simple_example.cpp)增加了一個名為MyExample的target並且將會編譯一個MyExample的執行檔 - 第38行
target_link_libraries(MyExample PRIVATE MyLibExample)連接了MyLibExample和MyExample這兩個target,注意你必須先製作target才能夠連接他們
建置專案、編譯
接下來你可以用以下指令建置專案並且編譯。CMake會產生一個build資料夾,在裡面你應該會看到libMyLibExample.alibrary和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專案