CMake使用總結(jié)

1.安裝

?$sudo apt-get install cmake


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

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

? ? ? ? ? ? ? ? ? ? ? ? ? ? |——CMakeLists.txt (內(nèi)容為: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) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#可執(zhí)行文件叫做helloDemo,它的源碼文件是"demo.cxx" ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#和"demo_b.cxx"

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

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

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

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

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

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


3.CMake 執(zhí)行過程

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

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

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

$cmake .

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


4.項目文件組織

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

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

CMakeSample

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

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

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

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

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

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

|--- Hello

|--- Demo

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

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


5.CMake的內(nèi)置變量

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

CMAKE_C_COMPILER

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

CMAKE_CXX_COMPILER

指定C++編譯器

CMAKE_C_FLAGS

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

EXECUTABLE_OUTPUT_PATH

指定可執(zhí)行文件存放的路徑。

LIBRARY_OUTPUT_PATH

指定庫文件放置的路徑

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

BUILD_SHARED_LIBS ? ??Switch between shared and static libraries

內(nèi)置變量的使用:

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

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


6.CMake的常用命令

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

include_directories

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

link_directories

動態(tài)鏈接庫或靜態(tài)鏈接庫的搜索路徑,相當于指定gcc的-L參數(shù)

add_subdirectory

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

add_definitions

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

add_executable

編譯可執(zhí)行程序

target_link_libraries

指定鏈接庫,相同于指定-l參數(shù)

7.CMake語法介紹

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

命令的形式如下:

command (args ...)

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

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

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

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

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

set(Foo a b c)

command(${Foo})

等價于

command(a b c)

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

流程控制

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

條件語句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)

循環(huán)結(jié)構(gòu)

set(VAR a b c)

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

foreach(f ${VAR})

some_command(${f})

endforeach(f)

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

# 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參數(shù)

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

link_directories:動態(tài)鏈接庫或靜態(tài)鏈接庫的搜索路徑,相當于gcc的-L參數(shù)

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

add_subdirectory:包含子目錄

>> add_subdirectory (Hello)

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

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

add_definitions:添加編譯參數(shù)

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

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

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

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

add_library:

>> add_library(Hello hello.cxx)??#將hello.cxx編譯成靜態(tài)庫如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)??怎樣添加動態(tài)庫和靜態(tài)庫

>> target_link_libraries命令添加即可

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

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

>>?注意大小寫

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

>> include_directories與link_directories

>>可以多次調(diào)用以設(shè)置多個路徑

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

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

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

Debug版會使用參數(shù)-g;Release版使用-O3 –DNDEBUG

>>?另一種設(shè)置方法——例如DEBUG版設(shè)置編譯參數(shù)DDEBUG

IF(DEBUG_mode)

add_definitions(-DDEBUG)

ENDIF()

在執(zhí)行cmake時增加參數(shù)即可,例如cmake -D DEBUG_mode=ON

7)??怎樣設(shè)置條件編譯

例如debug版設(shè)置編譯選項DEBUG,并且更改不應(yīng)改變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;

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

>>?期望的效果:在執(zhí)行cmake時直接通過參數(shù)指定一個開關(guān)項,生成相應(yīng)的makefile——可以這樣做,例如cmake –DDEBUGVERSION=ON

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

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

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

用于確保編譯目標項目前依賴項必須先構(gòu)建好

>>add_dependencies

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

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

>> SET_TARGET_PROPERTIES(ss7gw PROPERTIES

RUNTIME_OUTPUT_DIRECTORY "${BIN_DIR}")

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

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

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

>>cmake_minimum_required(VERSION 2.6)

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

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

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

>> TBD

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

>>數(shù)字比較LESS、GREATER、EQUAL,字串比STRLESS、STRGREATER、STREQUAL,

>> Eg:

set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)

set(AAA abc)

IF(AAA STREQUAL abc)

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

ENDIF()

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

>>?是

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

>> TBD

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

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

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

>> 可以,TBD

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

make VERBOSE=1

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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

友情鏈接更多精彩內(nèi)容