cmake使用

1. cmake介紹

CMake主要是解決跨平臺編譯的問題。
CMake的用途是能通過一系列的源碼和相關(guān)的配置來生成需要的編譯器平臺上的項目文件叁温。
譬如,如果一個項目需要在Windows上用VS編譯,在Linux上用make編譯,在OS X上用XCODE寒亥,
那么按以前的做法是在整個項目文件里看三個目錄,分別放置VS的sln文件荧关,Linux的makefile溉奕,OS X的XCODE,
然后讓不同需求的人到相應(yīng)的目錄用自己需要的工程文件(這看起來沒有什么不好似乎)忍啤。
有了CMake以后加勤,就不需要這三個目錄了,只要有一個給CMake讀的文件同波,然后CMake的UI上會需要用戶選擇目標平臺鳄梅,
這樣CMake就會生成目標平臺上的工程文件。舉例未檩,如果用戶選的是VS2005平臺卫枝,那么CMake就會在源代碼目錄下生成供VS2005使用的sln文件;
如果是make讹挎,就會生成makefile等等校赤。

2. cmake安裝

2.1 linux環(huán)境

vim ~/.bashrc
alias cmake=/usr/local/xxxxx/cmake/bin/cmake
source ~/.bashrc
cmake -version

3. cmake簡單示例

3.1 簡單示例1

同一級目錄下的兩個文件test.cpp,CMakeLists.txt
src文件test.cpp:

#include <iostream>

int main()
{
    std::cout << "hello." << std::endl;
    return 0;
}

CMakeLists.txt 文件:

cmake_minimum_required(VERSION 3.5)

# set the project name
project (hello_cmake)

message("this is a test msg, project name is : ${PROJECT_NAME}")

# add the executable
add_executable(hello_cmake test.cpp)

執(zhí)行編譯命令:

mkdir build
cd build
cmake ..
make

3.2 簡單示例2(不同目錄)

目錄結(jié)構(gòu):

.
├── CMakeLists.txt
├── include
│   └── hello.h
└── src
    ├── hello.cpp
    └── main.cpp

hello.h文件內(nèi)容:

#ifndef HELLO_H__
#define HELLO_H__
#include <iostream>
void print();
#endif

hello.cpp文件內(nèi)容:

#include "hello.h"

void print()
{
    std::cout << "hello." << std::endl;
}

main.cpp文件內(nèi)容:

#include "hello.h"

int main()
{
    print();
    return 0;
}

CMakeLists.txt文件內(nèi)容:

cmake_minimum_required(VERSION 3.5)
project (hello_headers)
 
# 設(shè)置源文件變量
set(SOURCES
    src/hello.cpp
    src/main.cpp
)
 
# 根據(jù)源文件目錄構(gòu)建可執(zhí)行程序
add_executable(hello_headers ${SOURCES})
 
# 設(shè)置包含目錄
target_include_directories(hello_headers   #目標
    PRIVATE 
        ${PROJECT_SOURCE_DIR}/include      #包含目錄
)

3.3 static link 靜態(tài)庫

目錄結(jié)構(gòu)及內(nèi)容同上,除CMakeLists.txt不同:

cmake_minimum_required(VERSION 3.5)
project(hello_library)
 
#將hello.cpp打包成靜態(tài)庫
add_library(hello_library STATIC 
    src/hello.cpp
)
 
#設(shè)置包含目錄
target_include_directories(hello_library   #目標
    PUBLIC 
        ${PROJECT_SOURCE_DIR}/include      #包含
)
 
 
#—————創(chuàng)建可執(zhí)行程序—————
add_executable(hello_binary 
    src/main.cpp
)
 
# 設(shè)置鏈接期間的鏈接庫
target_link_libraries( hello_binary
    PRIVATE 
        hello_library
)

3.4 dynamic link動態(tài)庫

目錄結(jié)構(gòu)及內(nèi)容同上筒溃,除CMakeLists.txt不同:

cmake_minimum_required(VERSION 3.5)
project(hello_library)
 
#將hello.cpp打包成動態(tài)庫
#Generate the shared library from the library sources
add_library(hello_library SHARED 
    src/hello.cpp
)

#給動態(tài)庫hello_library起一個別名hello::library
add_library(hello::library ALIAS hello_library)
#設(shè)置包含目錄
message(" PROJECT_SOURCE_DIR is : ${PROJECT_SOURCE_DIR}")
target_include_directories(hello_library
    PUBLIC 
        ${PROJECT_SOURCE_DIR}/include
)
 
# 構(gòu)建可執(zhí)行程序
add_executable(hello_binary
    src/main.cpp
)

#添加動態(tài)鏈接庫
target_link_libraries( hello_binary
    PRIVATE 
        hello::library
)

4. cmake語法

4.1 變量

4.1.1 普通變量

基本的變量操作指令是set() unset()
變量名區(qū)分大小寫

set(MyString1 "Text1")
set("My String 2" "Text2")
message(${MyString1})
message(${My\ String\ 3})
unset(MyString1)

4.1.2 環(huán)境變量

set(ENV{<variable>} <value>) unset(ENV{<variable>})

#讀取cmake腳本中定義的環(huán)境變量:
set(ENV{CMAKE_PATH} "myown/path/example")
# 判斷CMAKE_PATH環(huán)境變量是否定義
if(DEFINED ENV{CMAKE_PATH}) //注意此處ENV前沒有$符號
  message("CMAKE_PATH_1: $ENV{CMAKE_PATH}") //注意此處ENV前有$符號
else()
  message("NOT DEFINED CMAKE_PATH VARIABLES")
endif()
# 讀取系統(tǒng)中的環(huán)境變量:
cmake_minimum_required(VERSION 3.20.0)
project(Environment)
#在配置期間打印myenv環(huán)境變量
message("generated with " $ENV{myenv})
# 在構(gòu)建階段過程中打印相同的變量
add_custom_target(EchoEnv ALL COMMAND echo "myenv in build is" $ENV{myenv})

測試命令:
創(chuàng)建build構(gòu)建系統(tǒng):cmake -B build ./
執(zhí)行構(gòu)建: cd build; cmake --build ./

4.1.3 變量作用域

目錄作用域的啟用一般是在父目錄下的CmakeList.txt中有add_subdirectory(“子目錄路徑”)指令马篮,而在子目錄的CMakeLists.txt會將父目錄的所有變量拷貝到當前CMakeLists.txt中,當前CMakeLists.txt中的變量的作用域僅在當前子目錄有效怜奖。
特點:向下有效和數(shù)值拷貝生成副本浑测,在不使用特殊關(guān)鍵字的情況下,嵌套(子)作用域針對普通變量的修改不會影響到父作用域歪玲。
針對變量迁央,普通變量僅僅有效于當前作用域,而緩存變量和環(huán)境變量可以在全局作用域中使用滥崩。

4.2 控制結(jié)構(gòu)

三類控制結(jié)構(gòu):條件塊岖圈、循環(huán)、定義指令
條件塊:

if(<condition>)
  <commands>
elseif(<condition>) # optional block, can be repeated
  <commands>
else() # optional block
  <commands>
endif()

循環(huán):

while(<condition>)
  <commands>
endwhile()

foreach(<loop_variable> IN [LISTS <lists>] [ITEMS <items>])

4.3 指令

4.3.1 自定義指令

CMake中的定義指令通過兩種方法實現(xiàn):macro()和function()

#CMake中的宏
macro(<name> [<argument> ])
  <commands>
endmacro()

函數(shù):

//CMake中的函數(shù)聲明
function(<name> [<argument> ])
  <commands>
endfunction()

4.3.2 實用指令

include指令:
如引用官方和CMake社區(qū)中已經(jīng)配置好了的CMake模板钙皮,所謂的CMake模板就是將CMake代碼劃分到單獨的.cmake文件中蜂科,以保持內(nèi)容的有序和獨立性

include(<file|module> [OPTIONAL] [RESULT_VARIABLE <var>])
include("${CMAKE_CURRENT_LIST_DIR}/<filename>.cmake")

file指令:
file() 指令會以一種與系統(tǒng)無關(guān)的方式讀取、寫入和傳輸文件短条,并使用文件系統(tǒng)导匣、文件鎖、路徑和存檔

file(READ <filename> <out-var> [...])
file({WRITE | APPEND} <filename> <content>...)
 file(DOWNLOAD <url> [<file>] [...])

execute_process指令:

execute_process(COMMAND <cmd1> [<arguments>]  [OPTIONS])

cmake最小版本號設(shè)置:
cmake_minimum_required(VERSION 3.10)

set the project name:
project(Tutorial)

add the executable 生成可執(zhí)行文件:
add_executable(Tutorial tutorial.cpp)

set the project name and version:
project(Tutorial VERSION 1.0)

specify the C++ standard 設(shè)置使用的c++版本:
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

添加靜態(tài)庫:

add_library(message
 STATIC
    Message.hpp
    Message.cpp
  )
add_executable(hello-world hello-world.cpp)
target_link_libraries(hello-world message)

指定編譯器:

# set minimum cmake version & project name and language
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(recipe-06 LANGUAGES C CXX)
 
# CMake將語言的編譯器存儲在CMAKE_<LANG>_COMPILER變量中茸时,其中<LANG>是受支持的任何一種語言贡定,對于我們的目的是CXX、C或Fortran
# 建議使用-D CMAKE_<LANG>_COMPILER CLI選項設(shè)置編譯器可都,而不是導(dǎo)出CXX缓待、CC和FC。
# CLI選項:-D CMAKE_<LANG>_COMPILER 是確毙谠粒跨平臺并與非POSIX兼容的唯一方法命斧,避免變量污染與項目一起構(gòu)建的外部庫環(huán)境,使用CLI中的-D選項嘱兼,例如:
    # $ cmake -D CMAKE_CXX_COMPILER=clang++ ..
message(STATUS "Is the C++ compiler loaded? ${CMAKE_CXX_COMPILER_LOADED}")
if(CMAKE_CXX_COMPILER_LOADED)
 message(STATUS "The C++ compiler ID is: ${CMAKE_CXX_COMPILER_ID}")
 message(STATUS "Is the C++ from GNU? ${CMAKE_COMPILER_IS_GNUCXX}")
 message(STATUS "The C++ compiler version is: ${CMAKE_CXX_COMPILER_VERSION}")
endif()
 
message(STATUS "Is the C compiler loaded? ${CMAKE_C_COMPILER_LOADED}")
if(CMAKE_C_COMPILER_LOADED)
 message(STATUS "The C compiler ID is: ${CMAKE_C_COMPILER_ID}")
 message(STATUS "Is the C from GNU? ${CMAKE_COMPILER_IS_GNUCC}")
 message(STATUS "The C compiler version is: ${CMAKE_C_COMPILER_VERSION}")
endif()
 
 
# CMake提供了額外的變量來與編譯器交互:
 # CMAKE_<LANG>_COMPILER_LOADED:如果為項目啟用了語言<LANG>国葬,則將設(shè)置為TRUE。
 # CMAKE_<LANG>_COMPILER_ID:編譯器標識字符串芹壕,編譯器供應(yīng)商所特有汇四。
 # 例如,GCC用于GNU編譯器集合踢涌,AppleClang用于macOS上的Clang, MSVC用于Microsoft Visual Studio編譯器通孽。
 # 注意,不能保證為所有編譯器或語言定義此變量睁壁。
 # CMAKE_COMPILER_IS_GNU<LANG>:如果語言<LANG>是GNU編譯器集合的一部分背苦,則將此邏輯變量設(shè)置為TRUE互捌。
 # 注意變量名的<LANG>部分遵循GNU約定:C語言為CC, C++語言為CXX, Fortran語言為G77。
 # CMAKE_<LANG>_COMPILER_VERSION:此變量包含一個字符串行剂,該字符串給定語言的編譯器版本

編譯選項指定:

# set minimum cmake version & project name and language
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(recipe-07 LANGUAGES C CXX)
 
# we default to Release build type
if(NOT CMAKE_BUILD_TYPE)
 set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
endif()
 
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
 
message(STATUS "C flags, Debug configuration: ${CMAKE_C_FLAGS_DEBUG}")
message(STATUS "C flags, Release configuration: ${CMAKE_C_FLAGS_RELEASE}")
message(STATUS "C flags, Release configuration with Debug info: ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
message(STATUS "C flags, minimal Release configuration: ${CMAKE_C_FLAGS_MINSIZEREL}")
 
message(STATUS "C++ flags, Debug configuration: ${CMAKE_CXX_FLAGS_DEBUG}")
message(STATUS "C++ flags, Release configuration: ${CMAKE_CXX_FLAGS_RELEASE}")
message(STATUS "C++ flags, Release configuration with Debug info: ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
message(STATUS "C++ flags, minimal Release configuration: ${CMAKE_CXX_FLAGS_MINSIZEREL}")

5. cmake添加打印信息

message([<mode>] "message to display" ...)
mode選項:
(none) = Important information
STATUS = Incidental information
WARNING = CMake Warning, continue processing
AUTHOR_WARNING = CMake Warning (dev), continue processing
SEND_ERROR = CMake Error, continue processing, but skip generation
FATAL_ERROR = CMake Error, stop processing and generation
DEPRECATION = CMake Deprecation Error or Warning if variable
CMAKE_ERROR_DEPRECATED or CMAKE_WARN_DEPRECATED
is enabled, respectively, else no message.

message(STATUS "hello world.")

參考:
cmake語法
cmake菜譜
cmake官方文檔
cmake常用指令

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末秕噪,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子厚宰,更是在濱河造成了極大的恐慌腌巾,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件铲觉,死亡現(xiàn)場離奇詭異澈蝙,居然都是意外死亡,警方通過查閱死者的電腦和手機撵幽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進店門灯荧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人并齐,你說我怎么就攤上這事漏麦。” “怎么了况褪?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵撕贞,是天一觀的道長。 經(jīng)常有香客問我测垛,道長捏膨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任食侮,我火速辦了婚禮号涯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘锯七。我一直安慰自己链快,他們只是感情好,可當我...
    茶點故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布眉尸。 她就那樣靜靜地躺著域蜗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪噪猾。 梳的紋絲不亂的頭發(fā)上霉祸,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天,我揣著相機與錄音袱蜡,去河邊找鬼丝蹭。 笑死,一個胖子當著我的面吹牛坪蚁,可吹牛的內(nèi)容都是我干的奔穿。 我是一名探鬼主播镜沽,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼巫橄!你這毒婦竟也來了淘邻?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤湘换,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后统阿,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體彩倚,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年扶平,在試婚紗的時候發(fā)現(xiàn)自己被綠了帆离。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡结澄,死狀恐怖哥谷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情麻献,我是刑警寧澤们妥,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站勉吻,受9級特大地震影響监婶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜齿桃,卻給世界環(huán)境...
    茶點故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一惑惶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧短纵,春花似錦带污、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至养渴,卻和暖如春雷绢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背理卑。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工翘紊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人藐唠。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓帆疟,卻偏偏與公主長得像鹉究,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子踪宠,可洞房花燭夜當晚...
    茶點故事閱讀 43,728評論 2 351

推薦閱讀更多精彩內(nèi)容