跳到主要內容

[C++] CMake 建置 C/C++ 程式

在編譯程式的時候,會設定一些組態(configuration,簡稱 config)。
這些組態包含我們的編譯過程需要用哪一種編譯器,哪一些函式庫,要編譯哪些檔案和編譯的指令等等。
以 Linux 環境而言(Windows 系統的操作也大同小異,原理都是一樣的),在編譯 C++ 專案時,上述這些組態可以寫在一個叫做 Makefile 的檔案裡。在 Makefile 檔案所在資料夾執行 make 指令,make 這隻程式,就會吃進 Makefile 並根據 Makefile 內的組態設定做出對應編譯的動作。
通常這個 Makefile 寫起來很繁瑣,因此才會有 cmake 這個工具的誕生。

CMake 是一個能自動幫我們產生 Makefile 的程式。
CMake 基本的觀念就是,我們只要指定好編譯器種類,以及我們要編譯的目錄、執行檔名稱等等設定,CMake 就會產生 Makefile。

CMake 基本使用方式,假如我們有個資料夾結構如下:
.
├── build
├── CMakeLists.txt
├── lib
├── reference
│   └── matrix_effect.cpp
└── src
    └── meffect.cpp
這種資料夾結構是我習慣的 hierarchy。用這樣的資料夾做管理,專案比較不會凌亂。
src 資料夾裡面放 .cpp 程式碼。
lib 資料夾放程式碼用到的外部函式庫,即 include 的 header file。
而程式碼編譯成執行檔的動作,則在 build 資料夾內操作。
reference 資料夾內則放一些參考資料跟文件。

build 資料夾內有個 CMakeLists.txt,這個檔案就是 cmake 指令需要的檔案,以這個專案資料夾結構為例,CMakeLists.txt 內容可以這樣寫:


cmake_minimum_required(VERSION 2.8.9)
project(meffect)

include_directories(lib)


file(GLOB SOURCES "src/*.cpp")

add_executable(meffect ${SOURCES})

然後在 build 資料夾內執行:
cmake ..
如果順利的話,會出現 Configuring done 和 Generating done 訊息。
接著執行:
make
這個指令會開始編譯程式碼,編譯成功會顯示:

[ 50%] Building CXX object CMakeFiles/meffect.dir/src/meffect.cpp.o
[100%] Linking CXX executable meffect
[100%] Built target meffect

然後就可以在 build 資料夾內找到程式的執行檔了。

注意:
cmake 會產生一些中間檔案,在 build 資料夾內執行 cmake 後,這些中間檔就會產生在 build 資料夾內。cmake 沒有 clean 指令,因此若 cmake 指令有些錯誤或問題的話,要刪除 cmake 產生的這些殘留檔案,必須將整個 build 資料夾砍掉再新增一個新的 build 資料夾。修好 CMakeLists.txt 後,再重新執行 cmake 一次。
為了避免 CMakeLists.txt 不小心被砍掉,我會將 CMakeLists.txt 放在專案第一層的資料夾內,如上述 hierarchy 所示。

Reference: 這個討論串

留言

這個網誌中的熱門文章

[開箱] Filco Majestouch 2 忍者鍵盤第二代

最近買了一個新款的 Filco 忍者鍵盤第二代,NINJA Majestouch 2: 鍵盤對我來說蠻重要的,以前就很喜歡 Filco 品牌的鍵盤,我大學使用的第一支茶軸鍵盤就是 Filco 的牌子,現在已經充滿了灰塵,使用了至少已有 8 年了吧: 畢業後有買另一個 irock 鍵盤: 這禮拜拆開新鍵盤來看看: 內部包裝 內部包裝 採用按鍵的文字採用側印 鍵帽與拔鍵器 整體外觀 整體而言,美感簡約低調,按鍵的反饋力也很好,是一個適合寫程式的鍵盤。 相較於我的另一個也是德國櫻桃茶軸鍵盤 irock 品牌,我覺得 Filco 的按鍵回饋比較綿密,有漸層的回饋感,且按鍵聲音比較安靜。irock 則比較像機械打字的回饋感,敲字時也都蠻舒壓。

[程式競賽] UVa 572, Oil Deposits,Flood Fill 演算法

原題目簡述如下: 以 m x n 大小的 grid 代表一張地圖,現今要在此地圖內探勘,找出油田。某一區塊如果標示 "@" 代表有油,"*" 代表沒有油。 "@" 相鄰的區域的聯集,可視為一個油田。(所謂相鄰,除了上下左右,斜向的相鄰也算進去) 求任意地圖中,油田的個數。 例如輸入的測資為: *    *   *    *  @ *   @  @  *  @ *   @   *   *  @ @ @  @   * @ @ @   *   *  @ 則油田個數為 2。 想法 採用典型的倒水演算法(Flood Fill),走訪 "@" 出現的區域,從此往下倒水,倒過水的區域標上 id,因此透過 id 的編號,可以得知油田的個數。 實作 先實作倒水演算法的子函式: void floodfill(vector<vector<char> >& map,                vector<vector<int>  >& id_table,                int row, int col, int id) {    if(row < 0 || (row >= map.size()) )   return;    if(col < 0 || (col >= map[0].size())) return;    if(map[row][col] != '@' || id_table[row][col] > 0) return;    id_table[row][col] = id;   ...

[心得] 復古、老派的程式設計之路

最近看到 John Carmack 2018 年的貼文中的幾段話: I’m not a Unix geek.  I get around ok, but I am most comfortable developing in Visual Studio on Windows.  I thought a week of full immersion work in the old school Unix style would be interesting, even if it meant working at a slower pace.  It was sort of an adventure in retro computing — this was fvwm and vi.  Not vim, actual BSD vi. In the end, I didn’t really explore the system all that much, with 95% of my time in just the basic vi / make / gdb operations.  I appreciated the good man pages, as I tried to do everything within the self contained system, without resorting to internet searches.  Seeing references to 30+ year old things like Tektronix terminals was amusing. In the spirit of my retro theme, I had printed out several of Yann LeCun’s old papers and was considering doing everything completely off line, as if I was actually in a mountain cabin somewhere, but I wound up watching a lot of the Stanford CS231N lectur...