CMake---基礎練習1

 

由於卡在一個問題上,幾經排除應該多是CMakeLists.txt寫的不正確,可是又生成了可執行文件,運行可執行文件報錯。多方排除,應該是CMakeLists.txt加載動態庫的時候,函數加載的不全。

猜想多是CMakeLists.txt寫的不正確,由於在CSDN上都是照貓畫虎,知其然不知其因此然,幾經折騰耗費了時間也沒解決問題。索性,系統的學學「Cmake的語法和規則」。

爲何學習「Cmake的語法和規則」?
工程中,只有簡單的幾個文件(如.cpp),那麼首選編寫一個Makefile,固然編寫一個CMakeLists.txt也很簡單。可是,當工程中有不少.cpp .h  .c  .hpp等文件而且還嵌套使用,還有靜態庫/動態庫的時候,這時候選擇編寫一個CMakeLists.txt就很方便了。實際項目中,不能單是幾個簡單的.cpp .h,因此學習「Cmake的語法和規則」對我我的來講是必要的。

基礎第一個例子:
函數

//main.c

#include <stdio.h>
int main()
{
    printf("Hello World from t1 Main!\n ");
    
    return 0;
}
#CMakeLists.txt

PROJECT (HELLO)
SET(SRC_LIST main.c)
MESSAGE(STATUS "This is BINARY dir" ${HELLO_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir" ${HELLO_SOURCE_DIR})
ADD_EXECUTABLE(hello ${SRC_LIST})

看完後面的說明,會發現本例子也能夠改寫成一個最簡化的 CMakeLists.txt:學習

PROJECT(HELLO)
ADD_EXECUTABLE(hello main.c)

 

方式1,新建一個build文件夾ui

方式二,直接在源文件夾下spa

 

 

 

說明:
(0)CMakeLists.txt的使用命令:cmake + make 。
(1)CMakeLists.txt:注意文件名大小寫、文件名正確性。cmakeLists.txt/CmakeLists.txt/CMakeList.txt
(2)cmake .       :注意命令後面的點號,表明本目錄。
(3)cmake ..      :注意命令後面的點號,表明本目錄的上一級目錄。
(4)執行【cmake .】以後,系統自動生成了:CMakeFiles, CMakeCache.txt, cmake_install.cmake 等文件,而且生成了Makefile。不用太關注這些文件的意義,重點是它自動生成了Makefile。
(5)執行【make】以後,系統自動生成了:一個可執行文件。 這個可執行文件名字在ADD_EXECUTABLE(可執行文件名字 ${SRC_LIST})中體現。
(6)CMakeLists.txt:這個文件是 cmake 的構建定義文件。若是工程存在多個目錄,須要確保每一個要管理的目錄都存在一個CMakeLists.txt。【多目錄構建,後面在學】
(7)PROJECT 指令的語法是:
    PROJECT(projectname [CXX] [C] [Java])
    你能夠用這個指令定義工程名稱,並可指定工程支持的語言,支持的語言列表是能夠忽略的,默認狀況表示支持全部語言。
    這個指令隱式的定義了兩個 cmake 變量:<projectname>_BINARY_DIR 以及<projectname>_SOURCE_DIR,這裏就是HELLO_BINARY_DIR 和 HELLO_SOURCE_DIR
(因此CMakeLists.txt 中兩個 MESSAGE指令能夠直接使用了這兩個變量),由於採用的是內部編譯,兩個變量目前指的都是工程所在路徑/../cmake/t1,後面咱們會講到外部編譯,二者所指代的內容會有所不一樣。
同時 cmake 系統也幫助咱們預約義了 PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR變量,他們的值分別跟 HELLO_BINARY_DIR 與 HELLO_SOURCE_DIR 一致。
爲了統一塊兒見,建議之後直接使用 PROJECT_BINARY_DIR,PROJECT_SOURCE_DIR,即便修改了工程名稱,也不會影響這兩個變量。若是使用了<projectname>_SOURCE_DIR ,修改工程名稱後,須要同時修改這些變量。 (8)SET 指令的語法是: SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]]) 現階段,你只須要了解 SET 指令能夠用來顯式的定義變量便可。好比咱們用到的是 SET(SRC_LIST main.c),若是有多個源文件,也能夠定義成:SET(SRC_LIST main.c t1.c t2.c)。 (9)MESSAGE 指令的語法是:MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display" ...) 這個指令用於向終端輸出用戶定義的信息,包含了三種類型:SEND_ERROR,產生錯誤,生成過程被跳過。SATUS ,輸出前綴爲 — 的信息。FATAL_ERROR,當即終止全部 cmake 過程. 咱們在這裏使用的是 STATUS 信息輸出,演示了由 PROJECT 指令定義的兩個隱式變量HELLO_BINARY_DIR 和 HELLO_SOURCE_DIR。 (10)ADD_EXECUTABLE(hello ${SRC_LIST})定義了這個工程會生成一個文件名爲 hello 的可執行文件,相關的源文件是 SRC_LIST 中定義的源文件列表, 本例中你也能夠直接寫成 ADD_EXECUTABLE(hello main.c)。 (111,變量使用${}方式取值,可是在 IF 控制語句中是直接使用變量名 2,指令(參數 1 參數 2...) 參數使用括弧括起,參數之間使用空格或分號分開。 以上面的 ADD_EXECUTABLE 指令爲例,若是存在另一個 func.c 源文件,就要寫成:     ADD_EXECUTABLE(hello main.c func.c)或者     ADD_EXECUTABLE(hello main.c;func.c) 3,指令是大小寫無關的,參數和變量是大小寫相關的。但,推薦你所有使用大寫指令。 上面的 MESSAGE 指令咱們已經用到了這條規則: MESSAGE(STATUS 「This is BINARY dir」 ${HELLO_BINARY_DIR}) 也能夠寫成: MESSAGE(STATUS 「This is BINARY dir ${HELLO_BINARY_DIR}」) 這裏須要特別解釋的是做爲工程名的 HELLO 和生成的可執行文件 hello 是沒有任何關係的。 hello 定義了可執行文件的文件名,你徹底能夠寫成:ADD_EXECUTABLE(t1 main.c) 編譯後會生成一個 t1 可執行文件。 cmake 的語法仍是比較靈活並且考慮到各類狀況,好比SET(SRC_LIST main.c)也能夠寫成 SET(SRC_LIST 「main.c」) 是沒有區別的,可是假設一個源文件的文件名是 fu nc.c(文件名中間包含了空格)。 這時候就必須使用雙引號,若是寫成了 SET(SRC_LIST fu nc.c),就會出現錯誤,提示找不到 fu 文件和 nc.c 文件。這種狀況,就必須寫成:SET(SRC_LIST 「fu nc.c」) 此外,你能夠能夠忽略掉 source 列表中的源文件後綴,好比能夠寫成 ADD_EXECUTABLE(t1 main),cmake 會自動的在本目錄查找 main.c 或者 main.cpp等,固然,最好不要偷這個懶,以避免這個目錄確實存在一個 main.c 一個 main. 同時參數也可使用分號來進行分割。 下面的例子也是合法的: ADD_EXECUTABLE(t1 main.c t1.c)能夠寫成 ADD_EXECUTABLE(t1 main.c;t1.c). 咱們只須要在編寫 CMakeLists.txt 時注意造成統一的風格便可。 (12)清理工程: 運行:make clean 便可對構建結果進行清理。 還有另一個很是重要的提示,就是:剛纔例子中進行的是內部構建(in-source build),而 cmake 強烈推薦的是外部構建(out-of-source build)。 (13)內部構建與外部構建: 上面的例子展現的是 「 內部構建 」 ,相信看到生成的臨時文件比您的代碼文件還要多的時候,估計這輩子你都不但願再使用內部構建:-D 舉個簡單的例子來講明外部構建,以編譯 wxGTK 動態庫和靜態庫爲例,在 Everest 中打包方式是這樣的:解開 wxGTK 後。 在其中創建 static 和 shared 目錄。 進入 static 目錄,運行../configure –enable-static;make 會在 static 目錄生成 wxGTK 的靜態庫。 進入 shared 目錄,運行../configure –enable-shared;make 就會在 shared 目錄生成動態庫。 這就是外部編譯的一個簡單例子。 對於 cmake,內部編譯上面已經演示過了,它生成了一些沒法自動刪除的中間文件,因此,引出了咱們對外部編譯的探討,外部編譯的過程以下: 1,首先,請清除 t1 目錄中除 main.c CmakeLists.txt 以外的全部中間文件,最關鍵的是 CMakeCache.txt。
2,在 t1 目錄中創建 build 目錄,固然你也能夠在任何地方創建 build 目錄,不必定必須在工程目錄中。 3,進入 build 目錄,運行 cmake ..(注意,..表明父目錄,由於父目錄存在咱們須要的CMakeLists.txt,若是你在其餘地方創建了 build 目錄,須要運行 cmake <工程的全路徑>),查看一下 build 目錄,就會發現了生成了編譯須要的 Makefile 以及其餘的中間文件。 4,運行 make 構建工程,就會在當前目錄(build 目錄)中得到目標文件 hello。 上述過程就是所謂的 out-of-source 外部編譯,一個最大的好處是,對於原有的工程沒有任何影響,全部動做所有發生在編譯目錄。經過這一點,也足以說服咱們所有采用外部編譯方式構建工程。這裏須要特別注意的是:經過外部編譯進行工程構建,HELLO_SOURCE_DIR 仍然指代工程路徑,即/learn_Cmake/cmake/t1 而 HELLO_BINARY_DIR 則指代編譯路徑,即/../cmake/t1/build
相關文章
相關標籤/搜索