使用cef3替代chromium內核開發產品過程當中,第一次接觸到系統構建,使用了最多見的CMake。CMake雖然在構建系統中用的比較多,可是使用到的程序員仍是不多的。如今在國內能找到的相關資料和博客比較多,本人在學習中也看了不少人的博客,好比 CMake學習(一) , CMake語法之流程控制 等。再次感謝這些做者的分享。下邊提供一些系統學習的資料。html
CMake的官網地址:http://www.cmake.org/java
CMake主要的文檔《learning_cmake》 《CMake Practice》,這個百度上搜索一下,很容易下載到。python
學習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以前,最好能找到一個比較簡單地例子對照教程看,而且一開始編寫一些簡單地例子。這樣不只能學得快,也容易創建學習的自信。編程語言
下邊主要講三點,也是最經常使用到的三點。函數
1、CMake經常使用命令:工具
CMakelist中,命令名字是不區分大小寫的,而參數和變量是大小寫相關的。學習
CMake中使用"#"表示註釋該行代碼。ui
命令:
與其餘語言編程語言不一樣的是,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:當文件都在同一個路徑下面使用
2、CMake變量以及變量的引用
CMake中的變量無需聲明,而且沒有類型概念,這一點相似於python;變量能夠認爲都是全局的,哪怕在一個宏中定義的變量,也能夠在宏的外面被訪問到;全部的變量都是一個列表變量,下文在舉例時會詳細說明這一點;CMake對於變量是大小寫敏感的。
在CMake中,有兩種引用方式:對於變量值的引用,和直接引用這個變量自己,使用方式分別是:${varName} 和 varName。
3、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}+${_var}")
endforeach()
set(${outvar} ${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}+${_var}")
endforeach()
set(${outvar} ${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",由此能夠看到宏與函數的區別