CMake快速入门教程
前言
Make工具因遵循不同的規(guī)范和標(biāo)準(zhǔn),執(zhí)行的Makefile的格式也是不同。主流的Make工具包括:
GNU Make
QT的qmake
微軟的 MS nmake
BSD的 pmake
每個(gè)平臺(tái)都有自己的工具,則帶來了很大的平臺(tái)兼容性問題。CMake是一種跨平臺(tái)的編譯工具。
準(zhǔn)備階段:
安裝cmake
編寫CMake配置文件CMakeLists.txt
基本流程:
執(zhí)行cmake PATH或者ccmake PATH命令,將CMakeLists.tx文件轉(zhuǎn)化為所需要的Makefile文件。其中PATH為CMAKLISTs.txt所在的目錄
執(zhí)行make命令,編譯原碼生成可執(zhí)行程序,或者庫(kù)文件
單目錄,單文件
一個(gè)簡(jiǎn)單的樣例:
# CMake的最低版本要求
cmake_minimum_required (VERIONS 2.8)
# 項(xiàng)目信息
project(Demo)
# 指定生成目標(biāo)
add_executable(Demo demo.cc)
語法規(guī)則:
命令、空格、注釋組成
命令是不區(qū)分大小寫的
符號(hào)#后面內(nèi)容為注釋
參數(shù)之間使用空格分隔
單目錄,多文件
在實(shí)際項(xiàng)目中,一般不會(huì)只有一個(gè)demo.cc源碼文件,常為一個(gè)目錄下多個(gè)源文件。假設(shè)目錄結(jié)構(gòu)如下:
./Demo
|-- main.cc
|-- foo.cc
|-- foo.h
此時(shí)的CMakeLists.txt內(nèi)容可以更新為如下:
# CMake的最低版本要求
cmake_minimum_required (VERIONS 2.8)
# 項(xiàng)目信息
project(Demo)
# 指定生成目標(biāo)
add_executable(Demo demo.cc foo.cc)
即只需要在add_executable里把依賴的foo.cc源文件添加進(jìn)來即可。
但引入另一個(gè)問題:新增的源文件越來越多,總不能一個(gè)個(gè)手動(dòng)加進(jìn)來吧?
cmake中有 aux_source_directory命令,會(huì)查找指定目錄下所有源文件,并存放到指定的變量名中:
# CMake的最低版本要求
cmake_minimum_required (VERIONS 2.8)
# 項(xiàng)目信息
project(Demo)
# 查找當(dāng)前目錄下所有源文件
aux_source_directory(. DIR_SRCS)
# 指定生成目標(biāo)
add_executable(Demo ${DIR_SRCS})
多目錄,多文件
針對(duì)一個(gè)項(xiàng)目中包含了多了層級(jí)目錄,且每個(gè)目錄下都包含一些源文件。若目錄結(jié)構(gòu)如下:
./Demo
|-- main.cc
|-- utils
|-- foo.cc
|-- foo.h
我們需要分別在Demo和utils目錄下各自編寫一個(gè)CMakeLists.txt文件。
為了方便,可以先將utils目錄里的文件編譯成靜態(tài)庫(kù),再由main函數(shù)調(diào)用。
根目錄中的CMakeLists.txt
# CMake的最低版本要求,如果不滿足則報(bào)錯(cuò)
cmake_minimum_required (VERIONS 2.8 FATAL_ERROR)
# 項(xiàng)目信息
project(Demo)
# 添加 math 子目錄
add_subdirectory(utils)
# 指定生成目標(biāo)
add_executable(Demo main.cc)
# 添加鏈接庫(kù)
target_link_libraries(Demo utils)
add_subdirectory表示會(huì)處理子目錄下的CMakeLists.txt和源代碼
target_link_libraries表示main執(zhí)行文件需要鏈接一個(gè)名為utils的鏈接庫(kù)
utils目錄中的CMakeLists.txt
# 查找當(dāng)前目錄下的所有源文件、并保存到 DIR_LIB_SRCS 變量中
aux_source_directory(. DIR_LIB_SRCS)
# 生成鏈接庫(kù)
add_library(utils ${DIR_LIB_SRCS})
add_library會(huì)將所有源文件編譯為靜態(tài)鏈接庫(kù)
其他編譯選項(xiàng)
如下是一個(gè)項(xiàng)目的CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
project(Demo)
# 定一個(gè)開關(guān)選項(xiàng),支持cmake時(shí)通過 -DUSE_MYUTILS=OFF 指定
option(USE_MYUITLS "whether use customized math" ON)
# 自定義分支邏輯
if(USE_MYUITLS)
include_directories("{PROJECT_SOURCE_DIR}/utils")
add_subdirectory(utils)
set(EXTRA_LIBS ${EXTRA_LIBS} utils)
endif(USE_MYUITLS)
# 查找目錄下所有源文件
aux_source_directory(. DIR_SRCS)
# 添加執(zhí)行文件
add_executable(Demo ${DIR_SRCS})
# 鏈接靜態(tài)庫(kù)
target_link_libraries(Demo ${EXTRA_LIBS})
關(guān)于option的生效機(jī)制,這里詳細(xì)解釋下。如main.cc中的代碼:
#include <stdio.h>
#include <stdlib.h>
#include "config.h" // 此頭文件是cmake自動(dòng)生成的
#ifdef USE_PYUTILS
#include "utils/foo.h"
#else
#include <foo.h> // 假設(shè)標(biāo)準(zhǔn)庫(kù)有foo.h頭文件
#endif
為了打通CMakeLists.txt一鍵便攜式配置,我們需要編寫一個(gè)config.h.in文件:
#cmakedefine USE_MYUTILS
這樣,在執(zhí)行cmake命令時(shí),就可以根據(jù)配置的參數(shù),自動(dòng)生成option相關(guān)的頭文件。若指定-DUSE_MYUTILS=ON時(shí),config.h中的內(nèi)容為:
#define USE_MYUTILS
若為OFF時(shí),則config.h的內(nèi)容為:
/* #undef USE_MYUTILS */
安裝和測(cè)試
camke支持安裝和測(cè)試,通過在生成Makefile后,使用make install和make test來執(zhí)行。
接上述樣例,首先在utils/CMakeLists.txt中加上如下內(nèi)容:
# 指定utils庫(kù)的安裝路徑
install(TARGETS utils DESTINATION bin)
install(FILES utils.h DESTINATION include)
在Demo/CMakeLists.txt添加如下內(nèi)容:
# 指定安裝路徑
install(TARGETS Demo DESTINATION bin)
install(FILES "${PROJECT_BINARY}/config.h" DESTINATION include)
原理 & 流程:
cmake編譯產(chǎn)出的Demo文件和庫(kù)libUtils.o文件將會(huì)被復(fù)制到/usr/local/bin中
頭文件utils.h和config.h則會(huì)被賦值到/use/local/include中
可以通過CMKAE_INSTALL_PREFIX修改默認(rèn)安裝的根目錄/usr/local
關(guān)于測(cè)試,CMake提供一個(gè)稱為CTest的測(cè)試工具,通過add_test命令添加:
# 啟用測(cè)試
enable_testing()
# 測(cè)試程序是否成功運(yùn)行, arg*為函數(shù)接收的參數(shù)
add_test(test_run Demo arg1 arg2)
add_test(test_usage Demo)
set_tests_properties(test_usage PROPERTIES PASS_REGULAR_EXPRESSION "Usage: .....")
add_test(test_result Demo 10 2)
# 測(cè)試輸出的結(jié)果是否包含字符串 "is 100"
set_tests_properties(test_result PROPERTIES PASS_REGULAR_EXPRESSION "is 100")
支持gdb
CMake支持gdb的方式很簡(jiǎn)單,只需指定Debug模式下開啟-g,一個(gè)簡(jiǎn)單的樣例如下:
set(CMAKE_BUILD_TYPE "Debug")
# debug模式下編譯選項(xiàng)
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
# release模式下編譯選項(xiàng)
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
小結(jié)
CMake的語法主要以命令、空格、參數(shù)來組成
可以通過 set(<variable> <value>)設(shè)置變量的值
if語法
if(<condition>)
<commands>
elseif(<condition>) # optional block, can be repeated
<commands>
else() # optional block
<commands>
endif()
for語法
# usage 1:
foreach(<loop_var> <items>)
<commands>
endforeach()
# usage 2:
foreach(<loop_var> RANGE <stop>)
while語法
while(<condition>)
<commands>
endwhile()
附錄:
CMake官方教程文檔
CMake入門實(shí)戰(zhàn)博客
總結(jié)
以上是生活随笔為你收集整理的CMake快速入门教程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 参福来海参是大连的吗?
- 下一篇: 「学习笔记」欧拉数