CMake使用總結

1.安裝

?$sudo apt-get install cmake


2.示例:簡單的文件目錄

? ? sample |——Demo? (盛放可執行程序binary directory)

? ? ? ? ? ? ? ? ? ? ? ? ? ? |——CMakeLists.txt (內容為:include_directories? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (${HELLO_SOURCE_DIR}/Hello? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #確認compiler能在Hello 庫中找到它include的庫

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?link_directories (${HELLO_BINARY_DIR}/Hello) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#確認一旦built時,linker能找到Hello庫

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? add_executable (helloDemo demo.cxx demo_b.cxx) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#可執行文件叫做helloDemo,它的源碼文件是"demo.cxx" ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#和"demo_b.cxx"

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?target_link_libraries (helloDemo Hello) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#link可執行文件helloDemo 到Hello lib ? ? ? )

? ? ? ? ? ? ? ? | ——Hello? (盛放源代碼source directory)

? ? ? ? ? ? ? ? ? ? ? ? ? ? |——CMakeLists.txt (內容為:add_library (Hello hello.cxx) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#創建Hello 庫,源文件為hello.cxx) ? ? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? |——CMakeLists.txt? (內容為:project (HELLO) #工程名

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? add_subdirectory (Hello) # 子目錄,路徑為 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ${HELLO_SOURCE_DIR})

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? add_subdirectory (Demo) #子目錄 ,路徑為 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ${HELLO_BINARY_DIR} ? )


3.CMake 執行過程

? ? ? CMake在主目錄執行時,會處理該目錄下CMakeLists.txt文件,然后進入到子目錄,處理子目錄下的CMakeLists.txt.

? ? ? 從字面上看,我們差不多可以理解這三個文件的涵義。第一個CMakeLists.txt文件指定包含Hello和Demo兩個子目錄。第二個Hello中的CMakeLists.txt文件則指定生成Hello庫文件,第三個Demo中的CMakeLists.txt文件則是生成一個可執行文件helloDemo,另外兩個附加語句則用來指明頭文件路徑以及所要鏈接的庫。雖然要寫三個CMakeLists文件,但每個文件都非常簡單,總共算起來,并不比一個Makefile文件多多少。更重要的是,這其中隱含著linux哲學:分而治之。每個模塊自行編寫配置文件,只負責自己份內的事務,所以可擴展性好。在進行大型項目開發,就可以體現出優勢了。

? ? ? CMakeLists.txt相當于定義了一套生成Makefile文件的規則,下面就可以生成Makefile文件了,命令如下:

$cmake .

.?表示當前目錄,如果CMakeLists.txt不在當前目錄,請在cmake后面指定。命令執行后,在主目錄下和Demo、Hello子目錄下均會生成一個Makefile文件,有了這個文件,我們就可以敲入make編譯目標程序了。


4.項目文件組織

? ? ? 我們從一個sample入手,了解了CMake的基本用法和語法。但這個例子與實際開發還有一段距離,主要存在以下幾點問題: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?1.生成的二進制程序和源程序混在一起 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2.使用gcc進程程序編譯,而不是使用交叉編譯工具 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 3.為指定編譯選項,通常會生成debug版本供調試用,release版本用于發布

? ? ? 一個項目,通常包含若干子模塊。比如上一篇的sample,我們可以認為它包含兩個子模塊,Hello為程序庫,Demo為主程序。很少有項目會把目標二進制文件和源程序放在一起的,通常會建立一個bin目錄,存放生成的二進制文件,發布程序則放在release。根據我在項目開發中的習慣,將目錄結構修改如下:

CMakeSample

|--- release? (存放程序發布相關文件,包括程序文件、腳本、參數等。)

|--- doc(項目開發中的相關文檔,如設計說明以及通過doxgen等工具從代碼中生成的文檔。)

|--- lib(存放項目中使用的第三方庫)

|--- source(自己編寫的庫不放在lib,應該作為項目的一個模塊放在source目錄下。)

|--- include (包含整個項目中使用的公共頭文件,若子模塊中的頭文件僅被它使用,不放)

|--- bin (bin目錄存放編譯后的調試版本代碼。)

|--- Hello

|--- Demo

其它的子目錄則為各模塊的代碼及頭文件。

按照以上目錄結構,將Hello下的hello.h移到include目錄,因為這個頭文件被Demo模塊包含。這個sample中未使用第三方庫,所以暫時為空。


5.CMake的內置變量

從上文中我們知道,通過set語句可以自定義變量,然而,CMake還包含大量的內置變量,這些變量和自定義變量的用法沒有區別,下面就列出一些常用的變量:

CMAKE_C_COMPILER

指定C編譯器,通常,CMake運行時能夠自動檢測C語言編譯器。進行嵌入式系統開發時,通常需要設置此變量,指定交叉編譯器。

CMAKE_CXX_COMPILER

指定C++編譯器

CMAKE_C_FLAGS

指定編譯C文件時編譯選項,比如-g指定產生調試信息。也可以通過add_definitions命令添加編譯選項。

EXECUTABLE_OUTPUT_PATH

指定可執行文件存放的路徑

LIBRARY_OUTPUT_PATH

指定庫文件放置的路徑

CMAKE_BUILD_TYPE ? ??build 類型(Debug, Release),-DCMAKE_BUILD_TYPE=Debug

BUILD_SHARED_LIBS ? ??Switch between shared and static libraries

內置變量的使用:

>>?在CMakeLists.txt中指定,使用set

>> cmake命令中使用,如cmake -DBUILD_SHARED_LIBS=OFF


6.CMake的常用命令

除了內置變量,我們還可以通過命令來修改編譯選項,現將一些常用的命令列出來:

include_directories

指定頭文件的搜索路徑,相當于指定gcc編譯器的-I參數

link_directories

動態鏈接庫或靜態鏈接庫的搜索路徑,相當于指定gcc的-L參數

add_subdirectory

包含子目錄,當工程包含多個子目錄時,此命令有用

add_definitions

添加編譯參數,比如add_definitions(-DDEBUG)將在gcc命令行添加DEBUG宏定義

add_executable

編譯可執行程序

target_link_libraries

指定鏈接庫,相同于指定-l參數

7.CMake語法介紹

CMake語法非常簡單,包含注釋、命令和空格。以#開頭的行為注釋行,命令則由命令名、括號及以空格進行分隔的參數組成。命令可以是諸如add_library這樣的內置命令,也可以是子定義的宏或者函數。CMake的輸入是主目錄下的CMakeLists.txt文件,該文件可以使用include或者add_directory命令添加其它的輸入文件。

命令的形式如下:

command (args ...)

其中command為命令名,args為空格分隔的參數列表,如果參數中包含空格,使用雙引號引起來。命令不區分大小寫。

lists and strings. CMake的基本數據類型為字符串,字符串又可以組成list類型,有兩種方式:一種通過分號分隔,一種通過空格分隔。比如以下例子給VAR賦了同樣的值:

set(VAR a;b;c)? ? set(VAR a b c)

字符串列表主要用于foreach進行迭代,有些命令也用于對list進行處理。

CMake支持字符串和list類型的簡單變量,變量以${VAR}形式引用。多個參數可以用set命令組成一個list,命令將展開list,例如:

set(Foo a b c)

command(${Foo})

等價于

command(a b c)

如果你希望將list當作一個參數傳遞給命令,就應該用雙引號把list引起來,如command("${Foo}")等價于command("a b c")

流程控制

寫CMakeLists.txt文件就象寫一個簡單的程序,CMake提供了三種流程控制結構:

條件語句if

# some_command will be called if the variable's value is not:

# empty, 0, N, NO, OFF, FALSE, NOTFOUND, or -NOTFOUND.

if(var)

some_command(...)

endif(var)

循環結構

set(VAR a b c)

# loop over a, b,c with the variable f

foreach(f ${VAR})

some_command(${f})

endforeach(f)

宏和函數,函數在2.6及以上版本才支持,函數和宏的區別在于函數中可定義局部變量,而宏定義的變量都是全局變量。

# define a macro hello

macro(hello MESSAGE)

message(${MESSAGE})

endmacro(hello)

# call the macro with the string "hello world"

hello("hello world")

# define a function hello

function(hello MESSAGE)

message(${MESSAGE})

endfunction(hello)

project(HELLO)? #指定項目名稱,生成的VC項目的名稱;

>>使用${HELLO_SOURCE_DIR}表示項目根目錄

include_directories:指定頭文件的搜索路徑,相當于指定gcc的-I參數

>> include_directories (${HELLO_SOURCE_DIR}/Hello)??#增加Hello為include目錄

link_directories:動態鏈接庫或靜態鏈接庫的搜索路徑,相當于gcc的-L參數

>> link_directories (${HELLO_BINARY_DIR}/Hello)?????#增加Hello為link目錄

add_subdirectory:包含子目錄

>> add_subdirectory (Hello)

add_executable:編譯可執行程序,指定編譯,好像也可以添加.o文件

>> add_executable (helloDemo demo.cxx demo_b.cxx)???#將cxx編譯成可執行文件——

add_definitions:添加編譯參數

>> add_definitions(-DDEBUG)將在gcc命令行添加DEBUG宏定義;

>> add_definitions( “-Wall -ansi –pedantic –g”)

target_link_libraries:添加鏈接庫,相同于指定-l參數

>> target_link_libraries(demo Hello) #將可執行文件與Hello連接成最終文件demo

add_library:

>> add_library(Hello hello.cxx)??#將hello.cxx編譯成靜態庫如libHello.a

add_custom_target:

message( status|fatal_error, “message”):

set_target_properties( ... ): lots of properties... OUTPUT_NAME, VERSION, ....

link_libraries( lib1 lib2 ...): All targets link with the same set of libs

8. FAQ

1)??怎樣獲得一個目錄下的所有源文件

>> aux_source_directory( )

>>?將dir中所有源文件(不包括頭文件)保存到變量variable中,然后可以add_executable (ss7gw ${variable})這樣使用。

2)??怎樣指定項目編譯目標

>>??project命令指定

3)??怎樣添加動態庫和靜態庫

>> target_link_libraries命令添加即可

4)??怎樣在執行CMAKE時打印消息

>> message([SEND_ERROR | STATUS | FATAL_ERROR] "message to display" ...)

>>?注意大小寫

5)??怎樣指定頭文件與庫文件路徑

>> include_directories與link_directories

>>可以多次調用以設置多個路徑

>> link_directories僅對其后面的targets起作用

6)??怎樣區分debug、release版本

>>建立debug/release兩目錄,分別在其中執行cmake -DCMAKE_BUILD_TYPE=Debug(或Release),需要編譯不同版本時進入不同目錄執行make即可;

Debug版會使用參數-g;Release版使用-O3 –DNDEBUG

>>?另一種設置方法——例如DEBUG版設置編譯參數DDEBUG

IF(DEBUG_mode)

add_definitions(-DDEBUG)

ENDIF()

在執行cmake時增加參數即可,例如cmake -D DEBUG_mode=ON

7)??怎樣設置條件編譯

例如debug版設置編譯選項DEBUG,并且更改不應改變CMakelist.txt

>>?使用option command,eg:

option(DEBUG_mode "ON for debug or OFF for release" ON)

IF(DEBUG_mode)

add_definitions(-DDEBUG)

ENDIF()

>>?使其生效的方法:首先cmake生成makefile,然后make edit_cache編輯編譯選項;Linux下會打開一個文本框,可以更改,該完后再make生成目標文件——emacs不支持make edit_cache;

>>?局限:這種方法不能直接設置生成的makefile,而是必須使用命令在make前設置參數;對于debug、release版本,相當于需要兩個目錄,分別先cmake一次,然后分別make edit_cache一次;

>>?期望的效果:在執行cmake時直接通過參數指定一個開關項,生成相應的makefile——可以這樣做,例如cmake –DDEBUGVERSION=ON

8)??怎樣添加編譯宏定義

>>?使用add_definitions命令,見命令部分說明

9)??怎樣添加編譯依賴項

用于確保編譯目標項目前依賴項必須先構建好

>>add_dependencies

10)????????怎樣指定目標文件目錄

>>?建立一個新的目錄,在該目錄中執行cmake生成Makefile文件,這樣編譯結果會保存在該目錄——類似

>> SET_TARGET_PROPERTIES(ss7gw PROPERTIES

RUNTIME_OUTPUT_DIRECTORY "${BIN_DIR}")

11)????????很多文件夾,難道需要把每個文件夾編譯成一個庫文件?

>>?可以不在子目錄中使用CMakeList.txt,直接在上層目錄中指定子目錄

12)????????怎樣設定依賴的cmake版本

>>cmake_minimum_required(VERSION 2.6)

13)????????相對路徑怎么指定

>> ${projectname_SOURCE_DIR}表示根源文件目錄,${ projectname _BINARY_DIR}表示根二進制文件目錄?

14)????????怎樣設置編譯中間文件的目錄

>> TBD

15)????????怎樣在IF語句中使用字串或數字比較

>>數字比較LESS、GREATER、EQUAL,字串比STRLESS、STRGREATER、STREQUAL,

>> Eg:

set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)

set(AAA abc)

IF(AAA STREQUAL abc)

message(STATUS "true")???#應該打印true

ENDIF()

16)????????更改h文件時是否只編譯必須的cpp文件

>>?是

17)????????機器上安裝了VC7和VC8,CMAKE會自動搜索編譯器,但是怎樣指定某個版本?

>> TBD

18)????????怎樣根據OS指定編譯選項

>> IF( APPLE ); IF( UNIX ); IF( WIN32 )

19)????????能否自動執行某些編譯前、后命令?

>> 可以,TBD

20)????????怎樣打印make的輸出

make VERBOSE=1

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,497評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,305評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,727評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,193評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,411評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,945評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,777評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,978評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,216評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,657評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,960評論 2 373

推薦閱讀更多精彩內容

  • CMake學習 本篇分享一下有關CMake的一些學習心得以及相關使用。 本文目錄如下: [1、CMake介紹] [...
    AlphaGL閱讀 12,274評論 11 79
  • 注:首發地址 1. 前言 當在做 Android NDK 開發時,如果不熟悉用 CMake 來構建,讀不懂 CMa...
    cfanr閱讀 24,477評論 1 53
  • Cmake 入門 前言 CMake是一個比make更高級的編譯配置工具,它可以根據不同平臺、不同的編譯器,生成相應...
    渝潼不肖生閱讀 2,113評論 1 5
  • 果真是大師級的電影人,吳天明導演的《百鳥朝鳳》整部我是含著眼淚看完的。影片中焦三爺有句話“嗩吶匠人就是要把嗩吶吹到...
    川外晴天閱讀 220評論 0 0
  • 來深的第三個月,誤打誤撞的進入了互聯網行業,從事著自己喜歡的工作。第一次有勇氣將自己打翻重塑,挑戰自己并不擅長的東...
    小小惞閱讀 275評論 0 0