最近做的項目使用CLION構建,而這個採用CMakeLists.txt管理,因此為了更好的學習,故找到了一篇大牛級別的入門文章,有文章有代碼,本文是花了一點時間把這篇文章學習後的重要點記錄吧,原作者github地址:https://github.com/wzpan/cmake-demo。
1.單個源文件CMakeLists.txt 的語法比較簡單,由命令、注釋和空格組成,其中命令是不區分大小寫的。符號 # 後面的內容被認為是注釋。命令由命令名稱、小括號和參數組成,參數之間使用空格進行間隔。
首先創建一個main.cpp
#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}編寫第一個CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(cmakeLearn)
add_executable(main main.cpp)cmake_minimum_required:指定運行此配置文件所需的 CMake 的最低版本;
project:參數值是 cmakeLearn,該命令表示項目的名稱是 cmakeLearn 。
add_executable:將名為main.cpp的源文件編譯成一個名稱為 cmakeLearn 的可執行文件。
現在查看一下路徑:
light@city:~/CLionProjects/cmakeLearn$ ls
CMakeLists.txt main.cpp輸入下列命令進行cmake
cmake .cmake過程
light@city:~/CLionProjects/cmakeLearn$ cmake .
-- The C compiler identification is GNU 5.5.0
-- The CXX compiler identification is GNU 5.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: /home/light/CLionProjects/cmakeLearncmake 後 生成了Makefile
light@city:~/CLionProjects/cmakeLearn$ ls
CMakeCache.txt cmake_install.cmake main.cpp
CMakeFiles CMakeLists.txt Makefile然後執行make
light@city:~/CLionProjects/cmakeLearn$ make
Scanning dependencies of target main
[ 50%] Building CXX object CMakeFiles/main.dir/main.cpp.o
[100%] Linking CXX executable main
[100%] Built target main執行
light@city:~/CLionProjects/cmakeLearn$ ./main
Hello, World!2.多個源文件2.1 同一目錄,多個源文件在1中的cmake添加下面這行:
# 查找當前目錄下的所有源文件
# 並將名稱保存到 DIR_SRCS 變量
aux_source_directory(. DIR_SRCS)當本地源文件很多,如果將源文件都加到裡面就很煩,所以這裡採用aux_source_directory。CMake 會將當前目錄所有源文件的文件名賦值給變量 DIR_SRCS ,再指示變量 DIR_SRCS 中的源文件需要編譯成一個名稱為 Demo 的可執行文件。
這樣就避免出現下面這種情況:
# 指定生成目標
add_executable(Demo main.cc MathFunctions.cc xx.cc ....cc)小結:
查找當前目錄下的所有源文件,並將名稱保存到 DIR_SRCS 變量。
2.2 多個目錄,多個源文件此時目錄架構:
./Demo3
|
+--- main.cc
|
+--- math/
|
+--- MathFunctions.cc
|
+--- MathFunctions.h對於這種情況,需要分別在項目根目錄 Demo3 和 math 目錄裡各編寫一個 CMakeLists.txt 文件。
為了方便,我們可以先將 math 目錄裡的文件編譯成靜態庫再由 main 函數調用。
這裡與上述2.1CMakeLists不同之處是在上面基礎上加上了:
# 添加 math 子目錄
add_subdirectory(math)
# 添加連結庫
target_link_libraries(Demo MathFunctions)以此完成:
最後,在子目錄下指定連結庫名字:
子目錄中的 CMakeLists.txt:
# 查找當前目錄下的所有源文件
# 並將名稱保存到 DIR_LIB_SRCS 變量
aux_source_directory(. DIR_LIB_SRCS)
# 生成連結庫
add_library (MathFunctions ${DIR_LIB_SRCS})小結:
將 src 目錄中的源文件編譯為靜態連結庫。
3.自定義編譯選項CMake 允許為項目增加編譯選項,從而可以根據用戶的環境和需求選擇最合適的編譯方案。
例如,可以將 MathFunctions 庫設為一個可選的庫,如果該選項為 ON ,就使用該庫定義的數學函數來進行運算。否則就調用標準庫中的數學函數庫。
本節CMake與2不同如下三塊:
(1)加入一個配置頭文件,用於處理 CMake 對源碼的設置
# 加入一個配置頭文件,用於處理 CMake 對源碼的設置
configure_file (
"${PROJECT_SOURCE_DIR}/config.h.in"
"${PROJECT_BINARY_DIR}/config.h"
)configure_file 命令用於加入一個配置頭文件 config.h ,這個文件由 CMake 從 config.h.in生成,通過這樣的機制,將可以通過預定義一些參數和變量來控制代碼的生成。
例如:修改main.cc:
#include "config.h"
...
...
...
#ifdef USE_MYMATH
#include "math/MathFunctions.h"
#else
#include
#endif根據 USE_MYMATH 的預定義值來決定是否調用標準庫還是 MathFunctions 庫。
上修改main.cc中引用了一個 config.h 文件,這個文件預定義了 USE_MYMATH 的值。但我們並不直接編寫這個文件,為了方便從 CMakeLists.txt 中導入配置,我們編寫一個 config.h.in 文件:
#cmakedefine USE_MYMATH這樣 CMake 會自動根據 CMakeLists 配置文件中的設置自動生成 config.h 文件。
這裡使用了ccmake進行可視化編譯選擇,Ubuntu上安裝:
sudo apt-get install cmake-curses-gui運行ccmake .後:
hjkl控制方向移動,enter 鍵可以修改該選項。修改完成後可以按下 c 選項完成配置,之後再按 g 鍵確認生成 Makefile 。ccmake 的其他操作可以參考窗口下方給出的指令提示。
下面來看一下config.h文件內容:
USE_MYMATH 為 ON#define USE_MYMATHUSE_MYMATH 為 OFF/* #undef USE_MYMATH */(2)是否加入 MathFunctions 庫
# 是否加入 MathFunctions 庫
if (USE_MYMATH)
include_directories ("${PROJECT_SOURCE_DIR}/math")
add_subdirectory (math)
set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif (USE_MYMATH)option 命令添加了一個 USE_MYMATH 選項,並且默認值為 ON 。
(3)是否使用自己的 MathFunctions 庫
# 是否使用自己的 MathFunctions 庫
option (USE_MYMATH
"Use provided math implementation" ON)根據 USE_MYMATH 變量的值來決定是否使用我們自己編寫的 MathFunctions 庫。
4.安裝和測試4.1 安裝之前在編譯一些原始碼程序的時候,先make後make install,這樣會把一些頭文件與靜態/動態庫安裝到指定的目錄下。
那在CMAKE中同樣可以這麼做,如下:
首先先在 math/CMakeLists.txt 文件裡添加下面兩行:
指定 MathFunctions 庫的安裝路徑
install (TARGETS MathFunctions DESTINATION bin)
install (FILES MathFunctions.h DESTINATION include)指明 MathFunctions 庫的安裝路徑。之後同樣修改根目錄的 CMakeLists 文件,在末尾添加下面幾行:
# 指定安裝路徑
install (TARGETS Demo DESTINATION bin)
install (FILES "${PROJECT_BINARY_DIR}/config.h"
DESTINATION include)通過上面定製,後安裝如下:
light@city:~/cmake-demo/Demo5$ sudo make install
[ 50%] Built target MathFunctions
[100%] Built target Demo
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/bin/Demo
-- Installing: /usr/local/include/config.h
-- Installing: /usr/local/lib/libMathFunctions.a
-- Installing: /usr/local/include/MathFunctions.h據此完成了安裝工作。
4.2 測試CMake 提供了一個稱為 CTest 的測試工具。我們要做的只是在項目根目錄的 CMakeLists 文件中調用一系列的 add_test 命令。
啟動測試:
# 啟用測試
enable_testing()(1)無幫助信息測試
# 測試程序是否成功運行
add_test (test_run Demo 5 2)(2)有幫助信息測試
# 測試 2 的 10 次方
add_test (test_2_10 Demo 2 10)
set_tests_properties (test_2_10)
PROPERTIES PASS_REGULAR_EXPRESSION "is 1024")其中 PASS_REGULAR_EXPRESSION 用來測試輸出是否包含後面跟著的字符串。
5.支持gdb讓 CMake 支持 gdb 的設置也很容易,只需要指定 Debug 模式下開啟 -g 選項:
set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")6.添加版本號在編寫項目中給項目添加版本號:
set (Demo_VERSION_MAJOR 1)
set (Demo_VERSION_MINOR 0)分別指定當前的項目的主版本號和副版本號。
如果想在代碼中獲取信息,可以修改config.h.in文件,添加兩個預定義變量:
// the configured options and settings for Tutorial
#define Demo_VERSION_MAJOR @Demo_VERSION_MAJOR@
#define Demo_VERSION_MINOR @Demo_VERSION_MINOR@主程序調用,列印:
printf("%s Version %d.%d\n",
argv[0],
Demo_VERSION_MAJOR,
Demo_VERSION_MINOR);7.生成安裝包如何配置生成各種平臺上的安裝包,包括二進位安裝包和源碼安裝包。為了完成這個任務,我們需要用到 CPack ,它同樣也是由 CMake 提供的一個工具,專門用於打包。
我們做如下三個工作:
導入 InstallRequiredSystemLibraries 模塊,以便之後導入 CPack 模塊;
設置一些 CPack 相關變量,包括版權資訊和版本信息,其中版本信息用了上一節定義的版本號;
導入 CPack 模塊。
對應CMakeLists.txt如下:
# 構建一個 CPack 安裝包
include (InstallRequiredSystemLibraries)
set (CPACK_RESOURCE_FILE_LICENSE
"${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
set (CPACK_PACKAGE_VERSION_MAJOR "${Demo_VERSION_MAJOR}")
set (CPACK_PACKAGE_VERSION_MINOR "${Demo_VERSION_MINOR}")
include (CPack)下面就是如何使用:
輸入cpack .,也可以指定二進位與源碼安裝包:
cpack -C CPackConfig.cmakecpack -C CPackSourceConfig.cmakecpack安裝:
light@city:~/cmake-demo/Demo8$ cpack -CPackConfig.cmake
CPack: Create package using STGZ
CPack: Install projects
CPack: - Run preinstall target for: Demo8
CPack: - Install project: Demo8
CPack: Create package
CPack: - package: /home/light/cmake-demo/Demo8/Demo8-1.0.1-Linux.sh generated.
CPack: Create package using TGZ
CPack: Install projects
CPack: - Run preinstall target for: Demo8
CPack: - Install project: Demo8
CPack: Create package
CPack: - package: /home/light/cmake-demo/Demo8/Demo8-1.0.1-Linux.tar.gz generated.
CPack: Create package using TZ
CPack: Install projects
CPack: - Run preinstall target for: Demo8
CPack: - Install project: Demo8
CPack: Create package
CPack: - package: /home/light/cmake-demo/Demo8/Demo8-1.0.1-Linux.tar.Z generated.此時會在本地目錄下創建3個不同格式的二進位包文件:
light@city:~/cmake-demo/Demo8$ ls Demo8*
Demo8-1.0.1-Linux.sh Demo8-1.0.1-Linux.tar.gz Demo8-1.0.1-Linux.tar.Z隨便選擇一個安裝,例如sh:
sh Demo8-1.0.1-Linux.sh![]()
使用:
light@city:~/cmake-demo/Demo8$ ./Demo8-1.0.1-Linux/bin/Demo 5 2
Now we use our own Math library.
5 ^ 2 is 25