CMake入門以及學習筆記

使用cef3替代chromium內核開發產品過程中,第一次接觸到系統構建,使用了最常見的CMake。CMake雖然在構建系統中用的比較多,但是使用到的程序員還是很少的。現在在國內能找到的相關資料和博客比較多,本人在學習中也看了很多人的博客,比如 CMake學習(一)  , CMake語法之流程控制 等。再次感謝這些作者的分享。下邊提供一些系統學習的資料。

CMake的官網地址:http://www.cmake.org/

CMake主要的文檔《learning_cmake》 《CMake Practice》,這個百度上搜索一下,很容易下載到。

學習CMake之前,借用下 《CMake Practice》中的一段話,如果你的情況符合以下幾條就不要浪費時間在CMake上。

1,如果你沒有實際的項目需求,那麼看到這裏就可以停下來了,因爲cmake的學習過程就是實踐過程,沒有實踐,讀的再多幾天後也會忘記。
2,如果你的工程只有幾個文件,直接編寫Makefile是最好的選擇。
3,如果使用的是C/C++/Java之外的語言,請不要使用cmake(至少目前是這樣)。
4,如果你使用的語言有非常完備的構建體系,比如java的ant,也不需要學習cmake,雖然有成功的例子,比如QT4.3的csharp綁定qyoto。
5,如果項目已經採用了非常完備的工程管理工具,並且不存在維護問題,沒有必要遷移到cmake。
6,如果僅僅使用qt編程,沒有必要使用cmake,因爲qmake管理Qt工程的專業性和自動化程度比cmake要高很多。

 

學習CMake之前,最好能找到一個比較簡單地例子對照教程看,並且一開始編寫一些簡單地例子。這樣不僅能學得快,也容易建立學習的自信。

下邊主要講三點,也是最常用到的三點。

一、CMake常用命令:

CMakelist中,命令名字是不區分大小寫的,而參數和變量是大小寫相關的。

CMake中使用"#"表示註釋該行代碼。

命令:

與其他語言編程語言不同的是,CMake腳本的語法中沒有賦值操作,無論是賦值,還是比較、判斷操作,都是通過內置命令來完成的,例如"set(),math()等"。所有的內置命令調用形式爲:

command(arg1 arg2 arg3 ... argn)

每個參數均以空格,或者分號分割。注:不建議使用分號分割參數.

message():顯示一個消息。如message("Hello world");

cmake_minimum_required():需要的最低版本; cmake_minimum_required(version 2.6)  

project():項目的名稱 如project(hello)

set():Cmake中的賦值操作都是通過這個來做的。如 SET(HELLO_SRCS  Hello.c Hello.cpp  world.c   world.cpp)

add_definitions():設置編譯選項;

subdirs:CMake 是以遞歸的方式工作;處理完當前目錄,再去 SUBDIRS 中的目錄

add_library :生成一個鏈接庫;

add_executable:添加生成文件;如:ADD_EXECUTABLE (Hello ${HELLO_SRCS})

add_dependencies:包含一個依賴庫文件夾;

add_subdirectory:向當前工程添加存放源文件的子目錄;

aux_source_directory :不在當前目錄下的其他地方的源文件;

include_directories:  指明文件所在路徑;

set_target_properties:設置文件爲另外一個名字。set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

source_group:當文件都在同一個路徑下面使用

 

二、CMake變量以及變量的引用

    CMake中的變量無需聲明,並且沒有類型概念,這一點類似於python;變量可以認爲都是全局的,哪怕在一個宏中定義的變量,也可以在宏的外面被訪問到;所有的變量都是一個列表變量,下文在舉例時會詳細說明這一點;CMake對於變量是大小寫敏感的。

    在CMake中,有兩種引用方式:對於變量值的引用,和直接引用這個變量本身,使用方式分別是:${varName} 和 varName。

 

三、CMake的宏與函數

    同大多數腳本語言一樣,CMake中也有宏和函數的概念,關鍵字分別爲"macro"和"function",具體用法如下:

# 宏

macro( [arg1 [arg2 [arg3 ...]]])

     COMMAND1(ARGS ...)

     COMMAND2(ARGS ...)

     ...

endmacro()
 

# 函數

function( [arg1 [arg2 [arg3 ...]]])

     COMMAND1(ARGS ...)

     COMMAND2(ARGS ...)

     ...

endfunction()

以簡單的求和函數爲例,我們來看宏的一個示例:

macro(sum outvar)

     set(_args ${ARGN})

     set(result 0)

     foreach(_var ${_args})

         math(EXPR result "result+result+{_var}")

     endforeach()

     set(outvaroutvar{result})

endmacro()

sum(addResult 1 2 3 4 5)

message("Result is :${addResult}")

    上面是一段求和宏定義,我們來解讀一下代碼:"${ARGN}"是CMake中的一個變量,指代宏中傳入的多餘參數。因爲我們這個宏sum中只定義了一個 參數"outvar",其餘需要求和的數字都是不定形式傳入的,所以需要先將多餘的參數傳入一個單獨的變量中。當然,在這個示例中,第一行代碼顯得多餘, 因爲似乎沒必要將額外參數單獨放在一個變量中,但是建議這麼做。對上面這個宏再進一步加強:如果我們想限制這個宏中傳入的參數數目(儘管在這個宏中實際上 是不必要的),那麼可以將宏改寫一下:

macro(sum outvar)

     set(_args ${ARGN})

     list(LENGTH _args argLength)

     if(NOT argLength LESS 4) # 限制不能超過4個數字

         message(FATAL_ERROR "to much args!")

     endif()

     set(result 0)

     foreach(_var ${ARGN})

         math(EXPR result "result+result+{_var}")

     endforeach()

     set(outvaroutvar{result})

endmacro()

sum(addResult 1 2 3 4 5)

message("Result is :${addResult}")

    而CMake中的函數("function")與宏唯一的區別就在於,函數不能像宏那樣將計算結果傳出來(也不是完全不能,只是複雜一些),並且函數中的變量是局部的,而宏中的變量在外面也可以被訪問到,請看下例:

macro(macroTest)

     set(test1 "aaa")

endmacro()

function(funTest)

     set(test2 "bbb")

endfunction()

macroTest()

message("${test1}")

funTest()

message("${test2}")

運行這段代碼後,只會打印出一條信息"aaa",由此可以看到宏與函數的區別

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章