第一次使用Cmake,搜索了不少使用教程,包括《Cmake實踐》、《Cmake手冊》等,可是在針對最新的C++11條件下編程仍是會存在一點點問題,須要實驗不少次錯誤並搜索大量文章才能解決問題。這裏用新手日記的方式告訴一個Cmake小白如何在C++11下使用Cmake。ios
通常狀況下,直接閱讀文檔會不太適應新手,沒有感官的認識,沒有經驗。這裏將本身的學習過程記錄下來,方便本身查閱,也方便其餘新手學習。c++
首先先聲明一下Cmake腳本,其實就是CMakeLists.txt的基本語法規則:編程
1、單文件編譯ubuntu
(1)操做過程學習
<1>建立一個目錄t1. ui
<2>編寫代碼:spa
main.cppc++11
1 #include <iostream> 2 #include <vector> 3 int main() 4 { 5 6 using namespace std; 7 vector<int> V(5,3); 8 for(auto e:V) 9 cout << e << endl; 10 cout << "OK" << endl; 11 return 0; 12 13 }
<3>編寫CMakeLists.txtcode
【注意】不要忘記「CMakeLists.txt」中「.」前還有一個「s」,若是你很粗心,估計會在這裏抓耳撓腮。blog
PROJECT (HELLO)
SET(CMAKE_C_COMPILER g++) if(CMAKE_COMPILER_IS_GNUCXX) add_compile_options(-std=c++11)
message(STATUS "optional:-std=c++11") endif(CMAKE_COMPILER_IS_GNUCXX)
SET(SRC_LIST main.cpp) ADD_EXECUTABLE(hello ${SRC_LIST})
<4>在t1文件夾下編譯
先運行,注意Cmake後面的小點點「.」表示當前目錄。
Cmake .
再運行
make
<5>運行程序
此時,再t1文件夾下會產生hello文件,運行
./hello
程序就正確運行啦。
輸出
@ubuntu:~/t1$ ./hello 3 3 3 3 3 OK
(2)過程解釋
首先,在CMakeLists.txt中,命令能夠使用大寫、小寫、混寫。
PROJECT (HELLO)是CMakeLists.txt的第一句,告訴編譯器這個工程名叫hello。
SET(CMAKE_C_COMPILER g++)聲明使用g++編譯器,由於若是是.c文件的話一般使用默認的gcc編譯器。
add_compile_options(-std=c++11)告訴編譯器使用的是c++11,可是若是不設置g++編譯器,又不判斷一下編譯器的話會出現下面的運行結果:
@ubuntu:~/t1$ make Scanning dependencies of target hello [ 50%] Building CXX object CMakeFiles/hello.dir/main.o c++: error: unrecognized command line option ‘-std=C++11’ CMakeFiles/hello.dir/build.make:62: recipe for target 'CMakeFiles/hello.dir/main.o' failed make[2]: *** [CMakeFiles/hello.dir/main.o] Error 1 CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/hello.dir/all' failed make[1]: *** [CMakeFiles/hello.dir/all] Error 2 Makefile:83: recipe for target 'all' failed make: *** [all] Error 2
有的博客裏說可以編譯完成,可是在這裏有時候就完不成。固然有時候也能完成,這個可能和具體的系統有關吧。
當出現上述問題時,能夠使用設置編譯器的方式解決,也能夠使用if語句進行判斷,這裏爲了可以將全部狀況都講清楚,就暫時畫蛇添足這個寫了。其中CMAKE_COMPILER_IS_GNUCXX用於判斷編譯器類型。
可是做者也碰到這樣的問題,若是不設置編譯器爲g++,第一次設置編譯器爲std=c++11屬性時報錯,可是一旦設置完成功運行以後,即便吧編譯器設置的語句去掉,把t1下面除了main.cpp和CMakeLists.txt以外的語句去掉,也能正常編譯。真的有些奇怪。
message(STATUS "optional:-std=c++11")能夠用於打印一些提示信息,這裏在運行完CMake .以後,就把「」中的文字打印出來了。實際上, 除了用STATUS打印普通標識,message還有一些其餘的打印功能,如用SEND_ERROR,產生錯誤信息,生成過程被跳過。若是使用 FATAL_ERROR,當即終止全部 cmake 過程。
接着SET(SRC_LIST main.cpp) 和ADD_EXECUTABLE(hello ${SRC_LIST}) 語句。定義了這個工程會生成一個文件名爲 hello 的可執行文件,相關的源文件是 SRC_LIST 中 定義的源文件列表, 本例中也能夠直接寫成 ADD_EXECUTABLE(hello main.c)。
${}來引用變量,這是 cmake 的變量應用方式,可是,有一些例外,比 如在 IF 控制語句,變量是直接使用變量名引用(如這裏的CMAKE_COMPILER_IS_GNUCXX),而不須要${}。若是使用了${}去應用變量,其實 IF 會去判斷名爲${}所表明的值的變量,那固然是不存在的了。
(3)一點注意
在CMakeLists.txt腳本中,設置編譯選項能夠經過add_compile_options
命令,也能夠經過set命令修改CMAKE_CXX_FLAGS
或CMAKE_C_FLAGS
。
使用這兩種方式在有的狀況下效果是同樣的,但請注意它們仍是有區別的: add_compile_options
命令添加的編譯選項是針對全部編譯器的(包括c和c++編譯器),而set命令設置CMAKE_C_FLAGS
或CMAKE_CXX_FLAGS
變量則是分別只針對c和c++編譯器的。所以,下面的代碼也是同樣的效果哦!
PROJECT (HELLO) SET(CMAKE_C_COMPILER g++) if(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") endif(CMAKE_COMPILER_IS_GNUCXX) SET(SRC_LIST main.cpp) ADD_EXECUTABLE(hello ${SRC_LIST})