從零學(xué)習(xí)cmake構(gòu)建系統(tǒng)
什么是cmake
根據(jù)其官網(wǎng)的定義,cmake是一個(gè)開源跨平臺(tái)的,用于構(gòu)建、測(cè)試和打包軟件的一個(gè)套件工具。與cmake相關(guān)的幾個(gè)概念需要明晰,如GCC,make和makefile。
- GCC:GCC是GNU Compiler Collection(就是GNU編譯器套件),也可以簡(jiǎn)單認(rèn)為是編譯器,它可以編譯很多種編程語言(括C、C++、Objective-C、Fortran、Java等等)
- make:make工具可以看成是一個(gè)智能的批處理工具,它本身并沒有編譯和鏈接的功能,而是用類似于批處理的方式通過調(diào)用makefile文件中用戶指定的命令來進(jìn)行編譯和鏈接的。
- makefile,makefile就是GCC命令的集合,make工具就根據(jù)makefile中的命令進(jìn)行編譯和鏈接的
- cmake,當(dāng)項(xiàng)目非常大時(shí),手寫makefile會(huì)非常煩碎,而且不同平臺(tái)makefile也會(huì)不同,所以cmake就是可以根據(jù)CMakeLists.txt自動(dòng)生成makefile。
入門實(shí)踐
我們已經(jīng)對(duì)于cmake有了一個(gè)總體上的認(rèn)識(shí),接下來就通過官方提供的幾個(gè)例子介紹下如何使用cmake。
構(gòu)建單個(gè)源文件
項(xiàng)目只有一個(gè)源文件,結(jié)構(gòu)如下,我們一般會(huì)新建一個(gè)目錄存儲(chǔ)cmake運(yùn)行的產(chǎn)物,這里我新建了一個(gè)build目錄。
├── CMakeLists.txt ├── build └── main.cc
main.cc的內(nèi)容如下
#include <stdio.h> #include <stdlib.h> /** * power - Calculate the power of number. * @param base: Base value. * @param exponent: Exponent value. * * @return base raised to the power exponent. */ double power(double base, int exponent) { int result = base; int i; if (exponent == 0) { return 1; } for(i = 1; i < exponent; ++i){ result = result * base; } return result; } int main(int argc, char *argv[]) { if (argc < 3){ printf("Usage: %s base exponent \n", argv[0]); return 1; } double base = atof(argv[1]); int exponent = atoi(argv[2]); double result = power(base, exponent); printf("%g ^ %d is %g\n", base, exponent, result); return 0; }
CMakeLists.txt的內(nèi)容如下:
# Cmake的最低版本號(hào)的要求 cmake_minimum_required (VERSION 2.8) # 項(xiàng)目信息 project (Demo1) # 指定生成目標(biāo) add_executable(Demo main.cc)
在build目錄下執(zhí)行cmake .. 然后執(zhí)行make命令就可以得到Demo1的可執(zhí)行文件。
同一個(gè)目錄,多個(gè)源文件
如果我們將Demo1中main.cc的power函數(shù)抽取出來放到MathFunctions.cc中,項(xiàng)目結(jié)構(gòu)如下:
├── CMakeLists.txt ├── MathFunctions.cc ├── MathFunctions.h ├── build └── main.cc
那么該如何編譯呢,我們可以通過在add_executable命令中增加將MathFunctions.cc,效果如下add_executable(Demo main.cc MathFunctions.cc),但是如果有很多文件的情況下,一個(gè)文件一個(gè)文件的添加很麻煩,cmake提供了aux_source_directory命令,該命令會(huì)查找指定目錄下所有的源文件,然后將結(jié)果存到指定的變量名。CMakeLists.txt文件內(nèi)容如下
# CMake 最低版本號(hào)要求 cmake_minimum_required (VERSION 2.8) # 項(xiàng)目信息 project (Demo2) # 查找目錄下的所有源文件 # 并將名稱保存到 DIR_SRCS 變量 aux_source_directory(. DIR_SRCS) # 指定生成目標(biāo) add_executable(Demo ${DIR_SRCS})
多個(gè)目錄多個(gè)源文件
現(xiàn)在我們將MathFounction.h和MathFounction.cpp移動(dòng)到math目錄下,項(xiàng)目結(jié)構(gòu)如下:
├── CMakeLists.txt ├── build ├── main.cc └── math ├── CMakeLists.txt ├── MathFunctions.cc └── MathFunctions.h
面對(duì)這種情況我們需要在Demo3目錄下和math目錄下各自編寫一個(gè)CmakeLists.txt文件,我們可以將math目錄里面的文件編譯成靜態(tài)庫再由main函數(shù)調(diào)用。 Demo3目錄下的CMakeLists.txt內(nèi)容如下
# CMake 最低版本號(hào)要求 cmake_minimum_required (VERSION 2.8) # 項(xiàng)目信息 project (Demo3) # 查找目錄下的所有源文件 # 并將名稱保存到 DIR_SRCS 變量 aux_source_directory(. DIR_SRCS) # 添加 math 子目錄 add_subdirectory(math) # 指定生成目標(biāo) add_executable(Demo ${DIR_SRCS}) # 添加鏈接庫 target_link_libraries(Demo MathFunctions)
add_subdictory(math)指明本項(xiàng)目包含一個(gè)子目錄math,這樣,math目錄下的CMakeLists.txt文件和源代碼也會(huì)被使用,最后一行target_link_libraries指明可執(zhí)行文件需要鏈接一個(gè)名為MathFunctions的鏈接庫。math目錄下CMakeLists.txt內(nèi)容如下
# 查找當(dāng)前目錄下的所有源文件 # 并將名稱保存到 DIR_LIB_SRCS 變量 aux_source_directory(. DIR_LIB_SRCS) # 指定生成 MathFunctions 鏈接庫 add_library (MathFunctions ${DIR_LIB_SRCS})
該文件中使用命令add_library將src目錄中源文件編譯為靜態(tài)鏈接庫
自定義編譯選項(xiàng)
CMake允許為項(xiàng)目增加編譯選項(xiàng),從而可以根據(jù)用戶的環(huán)境和要求選擇最合適的編譯方案,例如可以將MathFunctions庫設(shè)置為一個(gè)可選的庫,如果該選項(xiàng)為ON,則使用該庫定義的函數(shù)來進(jìn)行運(yùn)算,否則就調(diào)用標(biāo)準(zhǔn)庫的數(shù)學(xué)函數(shù)庫。 為了實(shí)現(xiàn)這樣的目的我們需要在頂層的CMakeLists.txt中添加該選項(xiàng),其內(nèi)容如下
cmake_minimum_required (VERSION 2.8) # 項(xiàng)目信息 project (Demo4) set(CMAKE_INCLUDE_CURRENT_DIR ON) # 是否使用自己的 MathFunctions 庫 option (USE_MYMATH "Use provided math implementation" ON) # 加入一個(gè)配置頭文件,用于處理 CMake 對(duì)源碼的設(shè)置 configure_file ( "${PROJECT_SOURCE_DIR}/config.h.in" "${PROJECT_BINARY_DIR}/config.h" ) # 是否加入 MathFunctions 庫 if (USE_MYMATH) include_directories ("${PROJECT_SOURCE_DIR}/math") add_subdirectory (math) set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions) endif (USE_MYMATH) # 查找當(dāng)前目錄下的所有源文件 # 并將名稱保存到 DIR_SRCS 變量 aux_source_directory(. DIR_SRCS) # 指定生成目標(biāo) add_executable (Demo ${DIR_SRCS}) target_link_libraries (Demo ${EXTRA_LIBS})
其中configure_file命令用于加入一個(gè)配置文件config.h,這個(gè)文件由CMake從config.h.in生成,通過這樣的機(jī)制可以通過預(yù)定義一些參數(shù)和變量來控制代碼的生成,config.h.in內(nèi)容如下:
#cmakedefine USE_MYMATH
其中的option命令添加了一個(gè)USE_MYMATH選項(xiàng),并且默認(rèn)值為ON。之后根據(jù)USE_MYMATH變量的值決定是否使用我門自己編寫的MathFounctions庫
然后需要更改main.cc文件讓其根據(jù)USE_MYMATH的值確定是否調(diào)用標(biāo)準(zhǔn)庫,內(nèi)容如下:
#include <stdio.h> #include <stdlib.h> #include <config.h> #ifdef USE_MYMATH #include <MathFunctions.h> #else #include <math.h> #endif int main(int argc, char *argv[]) { if (argc < 3){ printf("Usage: %s base exponent \n", argv[0]); return 1; } double base = atof(argv[1]); int exponent = atoi(argv[2]); #ifdef USE_MYMATH printf("Now we use our own Math library. \n"); double result = power(base, exponent); #else printf("Now we use the standard library. \n"); double result = pow(base, exponent); #endif printf("%g ^ %d is %g\n", base, exponent, result); return 0; }
值得注意的是這里引入了一個(gè)config.h,這個(gè)文件預(yù)定義了 USE_MYMATH 的值。但我們并不直接編寫這個(gè)文件,而是由CMake根據(jù)config.h.in自動(dòng)生成。
最后
這篇文章主要介紹了cmake的簡(jiǎn)單使用,更多關(guān)于cmake構(gòu)建系統(tǒng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語言編程時(shí)常犯十八個(gè)錯(cuò)誤小結(jié)
C語言的最大特點(diǎn)是:功能強(qiáng)、使用方便靈活。C編譯的程序?qū)φZ法檢查并不象其它高級(jí)語言那么嚴(yán)格,這就給編程人員留下“靈活的余地”,但還是由于這個(gè)靈活給程序的調(diào)試帶來了許多不便,尤其對(duì)初學(xué)C語言的人來說,經(jīng)常會(huì)出一些連自己都不知道錯(cuò)在哪里的錯(cuò)誤2013-07-07C++ STL標(biāo)準(zhǔn)庫std::vector的使用詳解
vector 是表示可以改變大小的數(shù)組的序列容器,本文主要介紹了C++ STL標(biāo)準(zhǔn)庫std::vector的使用詳解,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03c++實(shí)現(xiàn)一個(gè)簡(jiǎn)易的網(wǎng)絡(luò)緩沖區(qū)的實(shí)踐
這篇文章主要介紹了c++實(shí)現(xiàn)一個(gè)簡(jiǎn)易的網(wǎng)絡(luò)緩沖區(qū)的實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12C語言數(shù)據(jù)的存儲(chǔ)和取出詳細(xì)講解
這篇文章主要介紹了C語言數(shù)據(jù)的存儲(chǔ)和取出詳細(xì)講解,作者使用圖文代碼實(shí)例講解,有感興趣的同學(xué)可以學(xué)習(xí)研究下2021-02-02C++ boost 時(shí)間與日期處理詳細(xì)介紹
這篇文章主要介紹了C++ boost 時(shí)間與日期處理詳細(xì)介紹的相關(guān)資料,這里提供實(shí)例代碼,及實(shí)現(xiàn)效果,需要的朋友可以參考下2016-11-11