Cmake的介紹和使用 Cmake實踐
Cmake優點:
1.開發原始碼,實用類BSD許可釋出。
2.跨平臺,並可以生成native編譯配置檔案,在linux/unix平臺,生成makefile,在mac平臺可以生成xcode,在windows平臺可以生成msvc工程的配置檔案。
3.能夠管理大型專案
4.簡化編譯構建過程和編譯過程,只需要cmake+make就可以
5.高效率
6.可擴充套件,可以為cmake編寫特定功能的模組,擴充cmake功能
如何安裝cmake
1.Cmake的安裝可以使用autotools進行安裝,點選連結,可以對軟體進行下載。
2../configure
3.make
4.sudo make install
Cmake的原理
Helloworld cmake
//main.cpp
#include<cstdio>
int main()
{
printf("hello world from main\n");
return 0;
}
建立CMakeLists.txt(注意大小寫一個字母都不能錯)
向該檔案中加入以下幾行(稍後會做解釋)
PROJECT (HELLO)
SET(SRC_LIST main.cpp)
MESSAGE(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir "${HELLO_SOURCE_DIR})
ADD_EXECUTABLE(hello ${SRC_LIST})
執行以下命令:
cmake . (別忘記加上這個點,表示當前目錄)
注意執行完這句話之後會生成幾個檔案如下:
CMakeFiles, CMakeCache.txt, cmake_install.cmake等檔案,並且生成了Makefile
然後執行make 就可以生成可執行檔案hello
這是當前目錄下就會生成可執行檔案如下圖:
對例子的解釋:
CMakeLists.txt的內容如下:
PROJECT (HELLO)
SET(SRC_LIST main.cpp)
MESSAGE(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir "${HELLO_SOURCE_DIR})
ADD_EXECUTABLE(hello ${SRC_LIST})
Project的指令的語法是:
PROJECT(projectname [CXX] [C] [JAVA])
這個執行是用來定義工程的名稱的和定義工程支援的語言。這個指令也隱式的定義了兩個cmake變數:<projectname>_BINARY_DIR以及<projectname>_BINARY_DIR,這裡就是HELLO_BINARY_DIR和HELLO_SOURCE_DIR,兩個變數指的都是當前工程的路徑。
SET指令的語法:
SET(VAR[VALUE] [CACHE TYPE DOCSTRING [FORCE]])
Set指令是用來顯式的定義變數的,我們之前用到的是SET(SRC_LIST main.cpp)如果有多個原始檔,也可以定義成SET(SRC_LIST main.cpp t1.cpp t2.cpp)。
MESSAGE指令的語法是:
MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display" ...)
這個指令用於向終端輸出使用者資訊,包含三種類型:
SEND_ERROR,產生錯誤,生成過程被跳過。
SATUS,輸出字首為-的資訊。
FATAL_ERROR,立即終止所有cmake過程。
我們在這裡使用的是STATUS資訊輸出,顯示了由PROJECT指令頂一頂兩個飲食變數HELLO_BINARY_DIR和HELLO_SOURCE_DIR。
ADD_EXECUTABLE(hello ${SRC_LIST})
定義了這個工程會生成一個檔名為hello的可執行檔案,相關的原始檔是SRC_LIST中定義的原始檔列表,本例中你可以直接寫成ADD_EXECUTABLE(hello main.c)。
將本例改寫成一個最簡化的CMakeLists.txt:
PROJECT(HELLO)
ADD_EXECUTABLE(hello main.c)
下面我們介紹一個比較實用的例子,即包含生成靜態庫又包含引入外部標頭檔案和連結庫的cmake demo。
先按照工程規範建立工程目錄,並編寫程式碼,以下面的工程目錄為例進行解釋這個例子,工程的目錄結構為:
編譯工程要實現的目標:
1. 新增子目錄doc,用以放置這個工程的文件hello.txt
2. 生成hello的靜態庫,並在main可執行程式連結hello靜態庫
3. 在這個工程中新增COPYRIGHT,README
4. 在工程目錄中新增一個run.sh的指令碼,用以呼叫生成的二進位制可執行檔案
5. 將生成的二進位制檔案生成到bin子目錄中
6. 編寫安裝程式
1. 編寫CMakeLists.txt
由於一個工程目錄中包含多個專案,其中在此專案中包含util專案和main專案,其中util專案是用以生成main程式需要的靜態庫,main是用以生成可執行檔案。
在工程專案中的父目錄向有一個CMakeLists.txt是用以宣告定義工程需要的Cmake設定還定義了子目錄src,用以遞迴的呼叫src中的MakeLists.txt。其中工程目錄的CMakeLists.txt內容定義如下:
PROJECT(HELLO)
ADD_SUBDIRECTORY(src)
在src裡面的CMakeLists.txt是用以定義src目錄包含的兩個工程的依賴關係分別進行編譯。
util目錄裡面的CMakeLists.txt是用以定義生成util靜態庫的規則,其中內容如下:
SET(LIBRARY_OUTPUT_PATH ${HELLO_SOURCE_DIR}/lib)
SET(CMAKE_C_COMPILER g++)
SET(SRC_LIST hello.c)
INCLUDE_DIRECTORIES(${HELLO_SOURCE_DIR}/include)
ADD_LIBRARY(util STATIC ${SRC_LIST})
其中SET(LIBRARY_OUTPUT_PATH ${HELLO_SOURCE_DIR}/lib)定義了庫生成的路徑,LIBRARY_OUTPUT_PATH是一個內部變數,存放庫生成路徑。
SET(SRC_LIST hello.c)是用來定義庫檔案需要的原始檔。
INCLUDE_DIRECTORIES(${HELLO_SOURCE_DIR}/include)是用來定義非標準庫標頭檔案要搜尋的路徑。其中INCLUDE_DIRECTORIES命令的格式為:
INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)
ADD_LIBRARY(util STATIC ${SRC_LIST})是用來定義生成的庫的名字,以及生成庫的型別和生成庫需要的原始檔,其中ADD_LIBRARY命令格式為:
ADD_LIBRARY(libname [SHARED|STATIC|MODULE]
[EXCLUDE_FROM_ALL]
source1 source2 ... sourceN)
SET(CMAKE_C_COMPILER g++)是用來定義c的編譯器為g++,防止出現C和C++程式碼在不指定C編譯器的情況下預設使用gcc,導致系統編譯混亂。
在main目錄中的CMakeLists.txt是用來定義可執行程式編譯和連結時所需要的一些命令或環境。內容如下:
SET(EXECUTABLE_OUTPUT_PATH ${HELLO_SOURCE_DIR}/bin)
SET(SRC_LIST main.cpp)
INCLUDE_DIRECTORIES(${HELLO_SOURCE_DIR}/include)
LINK_DIRECTORIES(${HELLO_SOURCE_DIR}/lib)
ADD_EXECUTABLE(hello ${SRC_LIST})
TARGET_LINK_LIBRARIES(hello util)
INCLUDE_DIRECTORIES命令是定義工程的include資料夾,其中存放使用到的庫的標頭檔案,LINK_DIRECTORIES是定義工程的庫檔案,其中存放著庫檔案,ADD_EXECUTABLE是定義生成的可執行檔案,TARGET_LINK_LIBRARIES用以定義連結時需要的庫檔案。
2.在工程目錄下建立build目錄,並採用out-of-source方式編譯專案。執行命令make ..,執行結果如下:
執行make,這時在build目錄下生成了中間編譯檔案:
執行make命令,結果如下:
可以看到工程建立和編譯成功了。
2. 安裝
在工程目錄下新增COPYRIGHT、README、和run.sh,重新編輯工程目錄下的CMakeLists.txt。在CMakeLists.txt中新增如下命令:
INSTALL(FILES COPYRIGHT README DESTINATION share/doc/cmake_demo)
INSTALL(PROGRAMS run.sh DESTINATION bin)
INSTALL(PROGRAMS bin/hello DESTINATION bin)
INSTALL(DIRECTORY doc/ DESTINATION share/doc/cmake_demo)
這些命令表示在執行make install命令時,安裝程式會拷貝相應的檔案、目錄或程式到指定的字首開始的目錄中,cmake執行命令如下:
cmake -DCMAKE_INSTALL_PREFIX=~/data/cmake_demo ..這時將工程目錄安裝到~/data/cmake_demo目錄下。執行結果如下:
其中cmake編譯c、c++工程完畢。