cmake 学习笔记(一)
- 最大的Qt4程序群(KDE4)采用cmake作為構建系統
- Qt4的python綁定(pyside)采用了cmake作為構建系統
- 開源的圖像處理庫 opencv 采用cmake 作為構建系統
- ...
看來不學習一下cmake是不行了,一點一點來吧,找個最簡單的C程序,慢慢復雜化,試試看:
| 例子一 | 單個源文件 main.c |
| 例子二 | ==>分解成多個 main.c hello.h hello.c |
| 例子三 | ==>先生成一個靜態庫,鏈接該庫 |
| 例子四 | ==>將源文件放置到不同的目錄 |
| 例子五 | ==>控制生成的程序和庫所在的目錄 |
| 例子六 | ==>使用動態庫而不是靜態庫 |
例子一
一個經典的C程序,如何用cmake來進行構建程序呢?
//main.c #include <stdio.h> int main() {printf("Hello World!/n");return 0; }編寫一個 CMakeList.txt 文件(可看做cmake的工程文件):
project(HELLO) set(SRC_LIST main.c) add_executable(hello ${SRC_LIST})然后,建立一個任意目錄(比如本目錄下創建一個build子目錄),在該build目錄下調用cmake
- 注意:為了簡單起見,我們從一開始就采用cmake的 out-of-source 方式來構建(即生成中間產物與源代碼分離),并始終堅持這種方法,這也就是此處為什么單獨創建一個目錄,然后在該目錄下執行 cmake 的原因
或者
cmake .. -G"MinGW Makefiles" make即可生成可執行程序 hello(.exe)
目錄結構
+ | +--- main.c +--- CMakeList.txt | /--+ build/|+--- hello.execmake 真的不太好用哈,使用cmake的過程,本身也就是一個編程的過程,只有多練才行。
我們先看看:前面提到的這些都是什么呢?
CMakeList.txt
第一行?project?不是強制性的,但最好始終都加上。這一行會引入兩個變量
- HELLO_BINARY_DIR 和 HELLO_SOURCE_DIR
同時,cmake自動定義了兩個等價的變量
-
PROJECT_BINARY_DIR?和?PROJECT_SOURCE_DIR
因為是out-of-source方式構建,所以我們要時刻區分這兩個變量對應的目錄
可以通過message來輸出變量的值
message(${PROJECT_SOURCE_DIR})set?命令用來設置變量
add_exectuable?告訴工程生成一個可執行文件。
add_library?則告訴生成一個庫文件。
- 注意:CMakeList.txt 文件中,命令名字是不區分大小寫的,而參數和變量是大小寫相關的。
cmake命令
cmake 命令后跟一個路徑(..),用來指出 CMakeList.txt 所在的位置。
由于系統中可能有多套構建環境,我們可以通過-G來制定生成哪種工程文件,通過?cmake?-h?可得到詳細信息。
要顯示執行構建過程中詳細的信息(比如為了得到更詳細的出錯信息),可以在CMakeList.txt內加入:
- SET( CMAKE_VERBOSE_MAKEFILE on )
或者執行make時
- $ make VERBOSE=1
或者
- $ export VERBOSE=1
- $ make
例子二
一個源文件的例子一似乎沒什么意思,拆成3個文件再試試看:
- hello.h 頭文件
- hello.c
- main.c
- 然后準備好CMakeList.txt 文件
?
project(HELLO) set(SRC_LIST main.c hello.c) add_executable(hello ${SRC_LIST})執行cmake的過程同上,目錄結構
?
+ | +--- main.c +--- hello.h +--- hello.c +--- CMakeList.txt | /--+ build/|+--- hello.exe例子很簡單,沒什么可說的。
例子三
接前面的例子,我們將 hello.c 生成一個庫,然后再使用會怎么樣?
改寫一下前面的CMakeList.txt文件試試:
project(HELLO) set(LIB_SRC hello.c) set(APP_SRC main.c) add_library(libhello ${LIB_SRC}) add_executable(hello ${APP_SRC}) target_link_libraries(hello libhello)和前面相比,我們添加了一個新的目標 libhello,并將其鏈接進hello程序
然后想前面一樣,運行cmake,得到
+ | +--- main.c +--- hello.h +--- hello.c +--- CMakeList.txt | /--+ build/|+--- hello.exe+--- libhello.lib里面有一點不爽,對不?
- 因為我的可執行程序(add_executable)占據了 hello 這個名字,所以 add_library 就不能使用這個名字了
- 然后,我們去了個libhello 的名字,這將導致生成的庫為 libhello.lib(或 liblibhello.a),很不爽
- 想生成 hello.lib(或libhello.a) 怎么辦?
添加一行
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")就可以了
例子四
在前面,我們成功地使用了庫,可是源代碼放在同一個路徑下,還是不太正規,怎么辦呢?分開放唄
我們期待是這樣一種結構
+ | +--- CMakeList.txt +--+ src/ | | | +--- main.c | /--- CMakeList.txt | +--+ libhello/ | | | +--- hello.h | +--- hello.c | /--- CMakeList.txt | /--+ build/哇,現在需要3個CMakeList.txt 文件了,每個源文件目錄都需要一個,還好,每一個都不是太復雜
- 頂層的CMakeList.txt 文件
- src 中的 CMakeList.txt 文件
- libhello 中的 CMakeList.txt 文件
恩,和前面一樣,建立一個build目錄,在其內運行cmake,然后可以得到
- build/src/hello.exe
- build/libhello/hello.lib
回頭看看,這次多了點什么,頂層的 CMakeList.txt 文件中使用 add_subdirectory 告訴cmake去子目錄尋找新的CMakeList.txt 子文件
在 src 的 CMakeList.txt 文件中,新增加了include_directories,用來指明頭文件所在的路徑。
例子五
前面還是有一點不爽:如果想讓可執行文件在 bin 目錄,庫文件在 lib 目錄怎么辦?
就像下面顯示的一樣:
+ build/|+--+ bin/| || /--- hello.exe|/--+ lib/|/--- hello.lib- 一種辦法:修改頂級的 CMakeList.txt 文件
不是build中的目錄默認和源代碼中結構一樣么,我們可以指定其對應的目錄在build中的名字。
這樣一來:build/src 就成了 build/bin 了,可是除了 hello.exe,中間產物也進來了。還不是我們最想要的。
- 另一種方法:不修改頂級的文件,修改其他兩個文件
src/CMakeList.txt 文件
include_directories(${PROJECT_SOURCE_DIR}/libhello) #link_directories(${PROJECT_BINARY_DIR}/lib) set(APP_SRC main.c) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) add_executable(hello ${APP_SRC}) target_link_libraries(hello libhello)libhello/CMakeList.txt 文件
set(LIB_SRC hello.c) add_library(libhello ${LIB_SRC}) set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")例子六
在例子三至五中,我們始終用的靜態庫,那么用動態庫應該更酷一點吧。 試著寫一下
如果不考慮windows下,這個例子應該是很簡單的,只需要在上個例子的 libhello/CMakeList.txt 文件中的add_library命令中加入一個SHARED參數:
add_library(libhello SHARED ${LIB_SRC})可是,我們既然用cmake了,還是兼顧不同的平臺吧,于是,事情有點復雜:
- 修改 hello.h 文件
- 修改 libhello/CMakeList.txt 文件
恩,剩下來的工作就和原來一樣了。
總結
以上是生活随笔為你收集整理的cmake 学习笔记(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 银行主动提高信用卡临时额度条件
- 下一篇: 招行附属卡年费多少?怎么减免年费?