CMake 簡單介紹
CMake特點
- CMake需要用戶用CMake規范的語法編寫CMake腳本,該語法簡單易用,入門極其順手
- 原生支持 C/C++/Fortran/Java 的相依性的自動分析功能,免除了程序員對代碼依賴的調整,對整個開發工作幫助很大
- 支持 SWIG、Qt、FLTK 開發框架
- 支持跨平臺編譯,這是CMake名字的來源
- 能夠轉換特殊平臺的 IDE 項目文檔,如xcode
- 與Dart、CTest 和 CPack 集成,可以組成自動化的構建系統
CMake vs GNU AutoTools
使用CMake,程序員必需編寫好CMake腳本CMAkeLists.txt,對于一些復雜的項目,可能需要編寫CMake模塊,但對于構建過程而言,則是極其簡單的。
相形之下,GNU AutoTools是很復雜的,無論是程序員在撰寫Makefile.am,還是構建時的步驟。致命的是,GNU AutoTools間很難兼容。
GNU AutoTools構建流程
CMake 構建流程
另外,CMake的構建過程會比GNU AutTools在速度上有優勢,在輸出上更是很友好。
下面的是來自Google的趨勢圖,可以看出CMake的應用情況。
簡單的CMake項目
我們先來看個簡單的CMake項目。這里有4個文件:CMakeLists.txt, main.cpp, pr.cpp, pr.h。
CMakeLists.txt的內容如下:
project(MyProject)
cmake_minimum_required(VERSION2.8)
add_library(pr SHARED pr.cpp)
target_link_libraries(pr m)
add_library(prs STATIC pr.cpp)
target_link_libraries(prs m)
set_target_properties(prs PROPERTIES OUTPUT_NAME pr)
add_executable(mypr main.cpp)
target_link_libraries(mypr pr)
set(PR_HEADER pr.h)
install(TARGETS mypr pr prs
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib/static)
install(FILES ${PR_HEADER}
DESTINATION include)
這個CMake腳本聲明了此項目名為MyProject,并要求cmake的最少版本為2.8。
通常情況下2.6以上的特性不會用到,除非在一些復雜的項目中要自己處理一些問題而用到例如function這樣的宏。
- add_executable的作用是指示CMake生成一個可執行文件。
- add_library的作用是指示CMake生成一個庫,根據參數SHARED還是STATIC來決定生成動態庫還是靜態庫。
- target_link_libraries指示傳遞給ld的外部庫,相當于傳給gcc的-lxx。
- set_target_properties則是用于修改構建目標的一些屬性,如上的語句則是讓目標prs的輸出libprs.a改名為libpr.a。
- set是CMake中常用的命令,用于設置變量,也能修改內部變量
- install用于生成make install使用的語句
要構建這個項目,可在所在目錄建立一個目錄,例如名為build,并切換到該目錄,然后執行cmake .. && make
路徑
一般的項目會涉及到多個模塊,文檔以及測試用例等。下圖為一般CMake項目的文件布局。每一層目錄如果包含有構建目標,一般都會有一個CMakeLists.txt。
包含CMakeLists.txt的子目錄通常由上層的CMakeLists.txt用語句add_subdirectory來包含。對于這個項目而言,頂層的CMakeLists.txt包含如下的語句:
add_subdirectory(include)
add_subdirectory(src)
add_subdirectory(tests)
add_subdirectory(docs)
在多個模塊的情況下,可能一個模塊的鏈接依賴於其它模塊,例如一個可執行二進制需要鏈接某些模塊,此時link_directories將有發揮作用。
如在CMakeLists.txt增加:link_directories(${MyProject_BINARY_DIR}/src/libxxx
${MyProject_BINARY_DIR}/src/libyyy)
將指示CMake在LDFLAGS附加-Lsrc/libxxx -Lsrc/libyyy。
放置在src下的代碼要引用include的頭文件,可以使用相對路徑引用,也可以讓include放置在頭文件搜索路徑中,即CPPFLAGS,-Iinclude。如何指示CMake呢?只需要加上include_directories(BEFORE include),或者include_directories(BEFORE ${MyProject_SOURCE_DIR}/include),前者引用CMakeLists.txt的相對路徑,而后者則是依項目的完整路徑。
其它
在上面提及到set可以修改一些內部變量,例如可以修改編譯器的參數,如
set(CMAKE_C_FLAGS ”-std=c99 -O2 -pipe -Wall -Wextra”)
set(CMAKE_C_FLAGS_DEBUG ”${CMAKE_C_FLAGS} -g -ggdb -pg”)
set(CMAKE_C_FLAGS_RELEASE ”${CMAKE_C_FLAGS} -s -DNDEBUG”)
CMake還提供了一些find函數,如find_package、find_library,用于檢查項目構建的依賴或者控制功能的開啟。
這些功能已經超出今天的簡單介紹,有興趣的朋友請參考官方資訊。
參考
http://www.cmake.org/Wiki/CMake:Articles
http://www.cmake.org/Wiki/CMake_FAQ
http://techbase.kde.org/Development/CMake
http://techbase.kde.org/Policies/CMake_Coding_Style