1, cmake 的介紹,下載,安裝和使用 html
2, cmake 的手冊詳解,我關注了 -C和-G 的使用 linux
3, 在Linux中構建cmake 的工程 ios
第一個問題: cmake 介紹,下載和安裝以及使用:https://fukun.org/archives/0421949.html c++
cmake是kitware公司以及一些開源開發者在開發幾個工具套件(VTK)的過程當中所產生的衍生品。後來通過發展,最終造成體系,在2001年成爲一個獨立的開放源代碼項目。其官方網站是www.cmake.org,能夠經過訪問官方網站來得到更多關於cmake的信息,並且目前官方的英文文檔比之前有了很大的改進,能夠做爲實踐中的參考手冊。 git
cmake的流行離不開KDE4的選擇。KDE開發者在使用autotools近10年以後,終於決定爲KDE4項目選擇一個新的工程構建工具。之因此如此,用KDE開發者們本身話來講,就是:只有少數幾個"編譯專家"可以掌握KDE如今的構建體系。在經歷了unsermake,scons以及cmake的選型和嘗試以後,KDE4最終決定使用cmake做爲本身的構建系統。在遷移過程當中,進展一場的順利,並得到了cmake開發者的支持。因此,目前的KDE4開發版本已經徹底使用cmake來進行構建。 數據庫
隨着cmake 在KDE4項目中的成功,愈來愈多的項目正在使用cmake做爲其構建工具,這也使得cmake正在成爲一個主流的構建體系。 編程
1、爲什麼要使用項目構建工具? bootstrap
爲什麼要使用cmake和autotools之類的項目構建工具? 我想,這恐怕是剛剛接觸軟件項目的人最應該問的問題之一了。 ubuntu
"Hello, world!"這個最經典的程序相信咱們每一個人都寫過。不管在什麼平臺下,編譯和運行這個程序都僅須要很是簡單的操做。但事實上,hello,world最多隻能算是一個實例程序,根本算不上一個真正的軟件項目。 windows
任何一個軟件項目,除了寫代碼以外,還有一個更爲重要的任務,就是如何組織和管理這些代碼,使項目代碼層次結構清晰易讀,這對之後的維護工做大有裨益。使想一下,若是把一個像KDE4那麼大的項目像hello world那樣,把所有代碼都放到一個main.cpp文件中,那將會是多麼恐怖的一件事情。別說KDE4,就是咱們隨便一個幾千行代碼的小項目,也不會有人幹這種蠢事。
決定代碼的組織方式及其編譯方式,也是程序設計的一部分。所以,咱們須要cmake和autotools這樣的工具來幫助咱們構建並維護項目代碼。
看到這裏,也許你會想到makefile,makefile不就是管理代碼自動化編譯的工具嗎?爲何還要用別的構建工具?
其實,cmake和autotools正是makefile的上層工具,它們的目的正是爲了產生可移植的makefile,並簡化本身動手寫makefile時的巨大工做量。若是你本身動手寫過makefile,你會發現,makefile一般依賴於你當前的編譯平臺,並且編寫makefile的工做量比較大,解決依賴關係時也容易出錯。所以,對於大多數項目,應當考慮使用更自動化一些的 cmake或者autotools來生成makefile,而不是上來就動手編寫。
總之,項目構建工具可以幫咱們在不一樣平臺上更好地組織和管理咱們的代碼及其編譯過程,這是咱們使用它的主要緣由。
2、cmake的主要特色:
cmake和autotools是不一樣的項目管理工具,有各自的特色和用戶羣。存在即爲合理,所以咱們不會對二者進行優劣比較,這裏只給出cmake的一些主要特色:
1.開放源代碼,使用類 BSD 許可發佈。
2.跨平臺,並可生成 native 編譯配置文件,在 Linux/Unix 平臺,生成 makefile,在 蘋果平臺,能夠生成 xcode,在 Windows 平臺,能夠生成 MSVC 的工程文件。
3.可以管理大型項目,KDE4 就是最好的證實。
4.簡化編譯構建過程和編譯過程。Cmake 的工具鏈很是簡單:cmake+make。
5.高效率,按照 KDE 官方說法,CMake 構建 KDE4 的 kdelibs 要比使用 autotools 來 構建 KDE3.5.6 的 kdelibs 快 40%,主要是由於 Cmake 在工具鏈中沒有 libtool。
6.可擴展,能夠爲 cmake 編寫特定功能的模塊,擴充 cmake 功能。
3、安裝cmake
安裝cmake 對任何用戶而言都不應再成爲一個問題。幾乎全部主流的Linux發行版的源中都包含有cmake的安裝包,直接從源中添加便可。固然,也能夠在官方網站下載源代碼自行編譯安裝。
對於Windows和Mac用戶,cmake的官方網站上有相應的安裝包,下載安裝便可,無須贅述。
注:爲了可以測試本文中的實例程序,若是讀者的Linux系統中所帶的cmake版本低於2.6,請從官網下載2.6版本或以上的源代碼進行編譯並安裝。
在linux下安裝cmake
首先下載源碼包
http://www.cmake.org/cmake/resources/software.html
這裏下載的是cmake-2.6.4.tar.gz
隨便找個目錄解壓縮
Example |
|
1 2 |
tar -xzvf cmake-2.6.4.tar.gz cd cmake-2.6.4 |
依次執行:
Example |
|
1 2 3 |
./bootstrap make make install |
cmake 會默認安裝在 /usr/local/bin 下面
4、從"Hello, world!"開始
瞭解cmake的基本原理並在系統中安好cmake後,咱們就能夠用cmake來演示那個最經典的"Hello, world!"了。
第一步,咱們給這個項目起個名字——就叫HELLO吧。所以,第一部爲項目代碼創建目錄hello,與此項目有關的全部代碼和文檔都位於此目錄下。
第二步,在hello目錄下創建一個main.c文件,其代碼以下:
Example |
|
1 2 3 4 5 6 |
#include int main(void) { printf("Hello,Worldn"); return 0; } |
第三步,在hello目錄下創建一個新的文件CMakeLists.txt,它就是 cmake所處理的"代碼"。其實,使用cmake管理項目自己也是在編程,因此稱之爲"代碼(或腳本)"並不爲過。在CMakeLists.txt文件中輸入下面的代碼(#後面的內容爲代碼行註釋):
#cmake最低版本需求,不加入此行會受到警告信息
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
PROJECT(HELLO) #項目名稱
#把當前目錄(.)下全部源代碼文件和頭文件加入變量SRC_LIST
AUX_SOURCE_DIRECTORY(. SRC_LIST)
#生成應用程序 hello (在windows下會自動生成hello.exe)
ADD_EXECUTABLE(hello ${SRC_LIST})
至此,整個hello項目就已經構建完畢,能夠進行編譯了。
第四步,編譯項目。
爲了使用外部編譯方式編譯項目,須要先在目錄hello下新建一個目錄build(也能夠是其餘任何目錄名)。如今,項目總體的目錄結構爲:
hello/
|– CMakeLists.txt
|– build /
`– main.c
在windows下,cmake提供了圖形界面,設定hello爲source目錄,build爲二進制目錄,而後點擊configure便可開始構建,以後進入build目錄運行make命令編譯。
在linux命令行下,首先進入目錄build,而後運行命令(注:後面的".."不可缺乏):
該命令使cmake檢測編譯環境,並生成相應的makefile。接着,運行命令make進行編譯。編譯後,生成的全部中間文件和可執行文件會在build目錄下。 下面是我在ubuntu上的運行過程:
$ ls
hello
$ cd hello/build/
$ ls
$ cmake ..
– The C compiler identification is GNU
– The CXX compiler identification is GNU
– Check for working C compiler: /usr/bin/gcc
– Check for working C compiler: /usr/bin/gcc — works
– Detecting C compiler ABI info
– Detecting C compiler ABI info - done
– Check for working CXX compiler: /usr/bin/c++
– Check for working CXX compiler: /usr/bin/c++ — works
– Detecting CXX compiler ABI info
– Detecting CXX compiler ABI info - done
– Configuring done
– Generating done
– Build files have been written to: /home/kermit/Project/cmake/hello/build
$ make
Scanning dependencies of target hello
[100%] Building C object CMakeFiles/hello.dir/main.c.o
Linking C executable hello
[100%] Built target hello
$ ls
CMakeCache.txt CMakeFiles cmake_install.cmake hello Makefile
$ ./hello
Hello,World
上面,咱們提到了一個名詞,叫外部編譯方式。其實,cmake還能夠直接在當前目錄進行編譯,無須創建build目錄。可是,這種作法會將全部生成的中間文件和源代碼混在一塊兒,並且cmake生成的makefile沒法跟蹤全部的中間文件,即沒法使用"make distclean"命令將全部的中間文件刪除。所以,咱們推薦創建build目錄進行編譯,全部的中間文件都會生成在build目錄下,須要刪除時直接清空該目錄便可。這就是所謂的外部編譯方式。
第二個問題:
cmake 的手冊詳解:http://www.cnblogs.com/coderfenghc/archive/2012/06/16/CMake_ch_01.html
第三個問題:在Linux中使用cmake 構建應用程序: http://www.ibm.com/developerworks/cn/linux/l-cn-cmake/
CMake 是一個跨平臺的自動化建構系統,它使用一個名爲 CMakeLists.txt 的文件來描述構建過程,能夠產生標準的構建文件,如 Unix 的 Makefile 或Windows Visual C++ 的 projects/workspaces 。文件 CMakeLists.txt 須要手工編寫,也能夠經過編寫腳本進行半自動的生成。CMake 提供了比 autoconfig 更簡潔的語法。在 linux 平臺下使用 CMake 生成 Makefile 並編譯的流程以下:
現假設咱們的項目中只有一個源文件 main.cpp
清單 1 源文件 main.cpp
1 #include<iostream>
2
3 int main()
4 {
5 std::cout<<"Hello word!"<<std::endl;
6 return 0;
7 }
爲了構建該項目,咱們須要編寫文件 CMakeLists.txt 並將其與 main.cpp 放在 同一個目錄下:
清單 2 CMakeLists.txt
1 PROJECT(main)
2 CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
3 AUX_SOURCE_DIRECTORY(. DIR_SRCS)
4 ADD_EXECUTABLE(main ${DIR_SRCS})
CMakeLists.txt 的語法比較簡單,由命令、註釋和空格組成,其中命令是不區分大小寫的,符號"#"後面的內容被認爲是註釋。命令由命令名稱、小括號和參數組成,參數之間使用空格進行間隔。例如對於清單2的 CMakeLists.txt 文件:第一行是一條命令,名稱是 PROJECT ,參數是 main ,該命令表示項目的名稱是 main 。第二行的命令限定了 CMake 的版本。第三行使用命令 AUX_SOURCE_DIRECTORY 將當前目錄中的源文件名稱賦值給變量 DIR_SRCS 。 CMake 手冊中對命令 AUX_SOURCE_DIRECTORY 的描述以下:
aux_source_directory(<dir> <variable>)
該命令會把參數 <dir> 中全部的源文件名稱賦值給參數 <variable> 。 第四行使用命令 ADD_EXECUTABLE 指示變量 DIR_SRCS 中的源文件須要編譯 成一個名稱爲 main 的可執行文件。
完成了文件 CMakeLists.txt 的編寫後須要使用 cmake 或 ccmake 命令生成Makefile 。 ccmake 與命令 cmake 的不一樣之處在於 ccmake 提供了一個圖形化的操做界面。cmake 命令的執行方式以下:
cmake [options] <path-to-source>
這裏咱們進入了 main.cpp 所在的目錄後執行 "cmake ." 後就能夠獲得 Makefile 並使用 make 進行編譯,以下圖所示。
圖 1. camke 的運行結果
處理多源文件目錄的方法
CMake 處理源代碼分佈在不一樣目錄中的狀況也十分簡單。現假設咱們的源代碼分佈狀況以下:
圖 2. 源代碼分佈狀況
其中 src 目錄下的文件要編譯成一個連接庫。
第一步,項目主目錄中的 CMakeLists.txt
在目錄 step2 中建立文件 CMakeLists.txt 。文件內容以下:
清單 3 目錄 step2 中的 CMakeLists.txt
1 PROJECT(main)
2 CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
3 ADD_SUBDIRECTORY( src )
4 AUX_SOURCE_DIRECTORY(. DIR_SRCS)
5 ADD_EXECUTABLE(main ${DIR_SRCS} )
6 TARGET_LINK_LIBRARIES( main Test )
相對於清單 2,該文件添加了下面的內容: 第三行,使用命令 ADD_SUBDIRECTORY 指明本項目包含一個子目錄 src 。第六行,使用命令 TARGET_LINK_LIBRARIES 指明可執行文件 main 須要鏈接一個名爲Test的連接庫 。
第二步,子目錄中的 CmakeLists.txt
在子目錄 src 中建立 CmakeLists.txt。文件內容以下:
清單 4. 目錄 src 中的 CmakeLists.txt
1 AUX_SOURCE_DIRECTORY(. DIR_TEST1_SRCS)
2 ADD_LIBRARY ( Test ${DIR_TEST1_SRCS})
在該文件中使用命令 ADD_LIBRARY 將 src 目錄中的源文件編譯爲共享庫。
第三步,執行 cmake
至此咱們完成了項目中全部 CMakeLists.txt 文件的編寫,進入目錄 step2 中依次執行命令 "cmake ." 和 "make" 獲得結果以下:
圖3. 處理多源文件目錄時 cmake 的執行結果
在執行 cmake 的過程當中,首先解析目錄 step2 中的 CMakeLists.txt ,當程序執行命令 ADD_SUBDIRECTORY( src ) 時進入目錄 src 對其中的 CMakeLists.txt 進行解析。
在工程中查找並使用其餘程序庫的方法
在開發軟件的時候咱們會用到一些函數庫,這些函數庫在不一樣的系統中安裝的位置可能不一樣,編譯的時候須要首先找到這些軟件包的頭文件以及連接庫所在的目錄以便生成編譯選項。例如一個須要使用博克利數據庫項目,須要頭文件db_cxx.h 和連接庫 libdb_cxx.so ,如今該項目中有一個源代碼文件 main.cpp ,放在項目的根目錄中。
第一步,程序庫說明文件
在項目的根目錄中建立目錄 cmake/modules/ ,在 cmake/modules/ 下建立文件 Findlibdb_cxx.cmake ,內容以下:
清單 5. 文件 Findlibdb_cxx.cmake
01 MESSAGE(STATUS "Using bundled Findlibdb.cmake...")
02
03 FIND_PATH(
04 LIBDB_CXX_INCLUDE_DIR
05 db_cxx.h
06 /usr/include/
07 /usr/local/include/
08 )
09
10 FIND_LIBRARY(
11 LIBDB_CXX_LIBRARIES NAMES db_cxx
12 PATHS /usr/lib/ /usr/local/lib/
13 )
文件 Findlibdb_cxx.cmake 的命名要符合規範: FindlibNAME.cmake ,其中NAME 是函數庫的名稱。Findlibdb_cxx.cmake 的語法與 CMakeLists.txt 相同。這裏使用了三個命令: MESSAGE , FIND_PATH 和 FIND_LIBRARY 。
第二步, 項目的根目錄中的 CmakeList.txt
在項目的根目錄中建立 CmakeList.txt :
清單 6. 能夠查找連接庫的 CMakeList.txt
01 PROJECT(main)
02 CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
03 SET(CMAKE_SOURCE_DIR .)
04 SET(CMAKE_MODULE_PATH ${CMAKE_ROOT}/Modules ${CMAKE_SOURCE_DIR}/cmake/modules)
05 AUX_SOURCE_DIRECTORY(. DIR_SRCS)
06 ADD_EXECUTABLE(main ${DIR_SRCS})
0708 FIND_PACKAGE( libdb_cxx REQUIRED)
09 MARK_AS_ADVANCED(
10 LIBDB_CXX_INCLUDE_DIR
11 LIBDB_CXX_LIBRARIES
12 )
13 IF (LIBDB_CXX_INCLUDE_DIR AND LIBDB_CXX_LIBRARIES)
14 MESSAGE(STATUS "Found libdb libraries")
15 INCLUDE_DIRECTORIES(${LIBDB_CXX_INCLUDE_DIR})
16 MESSAGE( ${LIBDB_CXX_LIBRARIES} )
17 TARGET_LINK_LIBRARIES(main ${LIBDB_CXX_LIBRARIES}18 )
19 ENDIF (LIBDB_CXX_INCLUDE_DIR AND LIBDB_CXX_LIBRARIES)
在該文件中第4行表示到目錄 ./cmake/modules 中查找 Findlibdb_cxx.cmake ,8-19 行表示查找連接庫和頭文件的過程。第8行使用命令 FIND_PACKAGE 進行查找,這條命令執行後 CMake 會到變量 CMAKE_MODULE_PATH 指示的目錄中查找文件 Findlibdb_cxx.cmake 並執行。第13-19行是條件判斷語句,表示若是 LIBDB_CXX_INCLUDE_DIR 和 LIBDB_CXX_LIBRARIES 都已經被賦值,則設置編譯時到 LIBDB_CXX_INCLUDE_DIR 尋找頭文件而且設置可執行文件 main 須要與連接庫 LIBDB_CXX_LIBRARIES 進行鏈接。
第三步,執行 cmake
完成 Findlibdb_cxx.cmake 和 CMakeList.txt 的編寫後在項目的根目錄依次執行 "cmake . " 和 "make " 能夠進行編譯,結果以下圖所示:
圖 4. 使用其餘程序庫時 cmake 的執行結果
使用 cmake 生成 debug 版和 release 版的程序
在 Visual Studio 中咱們能夠生成 debug 版和 release 版的程序,使用 CMake 咱們也能夠達到上述效果。debug 版的項目生成的可執行文件須要有調試信息而且不須要進行優化,而 release 版的不須要調試信息但須要優化。這些特性在 gcc/g++ 中是經過編譯時的參數來決定的,若是將優化程度調到最高須要設置參數-O3,最低是 -O0 即不作優化;添加調試信息的參數是 -g -ggdb ,若是不添加這個參數,調試信息就不會被包含在生成的二進制文件中。
CMake 中有一個變量 CMAKE_BUILD_TYPE ,能夠的取值是 Debug Release RelWithDebInfo 和 MinSizeRel。當這個變量值爲 Debug 的時候,CMake 會使用變量 CMAKE_CXX_FLAGS_DEBUG 和 CMAKE_C_FLAGS_DEBUG 中的字符串做爲編譯選項生成 Makefile ,當這個變量值爲 Release 的時候,工程會使用變量 CMAKE_CXX_FLAGS_RELEASE 和 CMAKE_C_FLAGS_RELEASE 選項生成 Makefile。
現假設項目中只有一個文件 main.cpp ,下面是一個能夠選擇生成 debug 版和 release 版的程序的 CMakeList.txt :
清單 7
第 5 和 6 行設置了兩個變量 CMAKE_CXX_FLAGS_DEBUG 和 CMAKE_CXX_FLAGS_RELEASE, 這兩個變量是分別用於 debug 和 release 的編譯選項。編輯 CMakeList.txt 後須要執行 ccmake 命令生成 Makefile 。在進入項目的根目錄,輸入 "ccmake ." 進入一個圖形化界面,以下圖所示:
圖 5. ccmake 的界面
按照界面中的提示進行操做,按 "c" 進行 configure ,這時界面中顯示出了配置變量 CMAKE_BUILD_TYPE 的條目。以下圖所示:
圖 6. 執行了 configure 之後 ccmake 的界面
下面咱們首先生成 Debug 版的 Makefile :將變量 CMAKE_BUILD_TYPE 設置爲 Debug ,按 "c" 進行 configure ,按 "g" 生成 Makefile 並退出。這時執行命令 find * | xargs grep "O0" 後結果以下:
清單 8 find * | xargs grep "O0"的執行結果
這個結果說明生成的 Makefile 中使用了變量 CMAKE_CXX_FLAGS_DEBUG 做爲編譯時的參數。
下面咱們將生成 Release 版的 Makefile :再次執行命令 "ccmake ." 將變量CMAKE_BUILD_TYPE 設置爲 Release ,生成 Makefile 並退出。執行命令 find * | xargs grep "O0" 後結果以下:
清單 9 find * | xargs grep "O0"的執行結果
CMakeLists.txt:SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
而執行命令 find * | xargs grep "O3" 後結果以下:
清單 10. find * | xargs grep "O3"的執行結果
這兩個結果說明生成的 Makefile 中使用了變量 CMAKE_CXX_FLAGS_RELEASE 做爲編譯時的參數。
轉載於:https://blog.csdn.net/appleml/article/details/52829412
相關文章:https://blog.csdn.net/wzzfeitian/article/details/40963457
https://blog.csdn.net/k346k346/article/details/46898635
語 法:https://www.mawenbao.com/note/cmake.html#fn1
https://www.jianshu.com/p/8909efe13308
https://gearyyoung.gitbooks.io/cmake-api/content/cmake/CMake%E8%AF%AD%E6%B3%95.html