使用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",由此可以看到宏與函數的區別