CMake 入門/Out-of-source Build

維基教科書,自由的教學讀本
跳至導覽 跳至搜尋

CMake 如何決定目錄[編輯]

CMake 的參數格式如下

cmake [選項] <source tree 根目錄>
cmake [選項] <binary tree 根目錄>

在 CMake 命令列最後一項所指定的路徑將被視為 source tree 根目錄,當其他選項預設時此目錄為必要參數。若命令列沒有給定路徑 CMake 才會將目前工作資料夾當成 source tree 根目錄。 source tree 根目錄必須含有 CMakeLists.txt ,否則會發生錯誤。

另外,當命令列指定的路徑下含有 CMakeCache.txt 時(通常是前次建置時遺留下的),該路徑也會被當成 binary tree 根目錄,否則 CMake 一律會把目前工作資料夾當成 binary tree 根目錄。

取得路徑資訊[編輯]

CMake 提供了幾個變數讓使用者在撰寫 CMakeLists 時取得路徑資訊,這裡先介紹其中幾個:

CMAKE_SOURCE_DIR
內容為 source tree 根目錄的完整路徑,也就是 CMake 開始建置過程的進入點。
CMAKE_BINARY_DIR
內容為 binary tree 根目錄的完整路徑,在 in-source build 的時候值與 CMAKE_SOURCE_DIR 相同。
PROJECT_SOURCE_DIR
目前所屬專案的原始碼根目錄,即內含 project() 指令的 CMakeLists 所在資料夾。前面的例子沒有階層之分,所以 PROJECT_SOURCE_DIR 和 CMAKE_SOURCE_DIR 相同;更複雜的專案會包含數個子專案,子專案下面還可能會有多個資料夾,PROJECT_SOURCE_DIR 內容為目前正在處理中的專案最上層目錄。
PROJECT_BINARY_DIR
目前所屬專案的建置根目錄,專案意義同上。在 in-source build 時和 PROJECT_SOURCE_DIR 相同。
CMAKE_CURRENT_SOURCE_DIR
目前正在處理的 CMakeLists.txt 所在位置。
CMAKE_CURRENT_BINARY_DIR
目前正在處理的 CMakeLists.txt 對應的建置資料夾位置。當然,在 in-source build 時和 CMAKE_CURRENT_SOURCE_DIR 相同。

這裡要注意的是,CMake 中都使用絕對路徑來表示檔案位置。

為了瞭解 CMake 目前的 source tree 和 binary tree 為何,我們可以在 CMakeLists 當中加上:

message("CMAKE_SOURCE_DIR= ${CMAKE_SOURCE_DIR}")
message("CMAKE_BINARY_DIR= ${CMAKE_BINARY_DIR}")

在源碼之外建置[編輯]

本章採用和之前相同的範例,目錄樹的架構如下,各原始碼的內容請參考前一節--建置基本的執行檔

  • ex2/
    • src/
      • CMakeLists.txt
      • calc.c
      • calc.h
      • main.c


Note
若是沿用前一個例子的檔案,請先清除源碼根目錄所有CMake 中間檔,否則源碼根目錄含有前次留下的 CMakeCache.txt,仍會被 CMake 優先視為建置根目錄,於是執行 In-source build


設目前工作目錄為 ex2/,執行下列指令:

$ mkdir -p build
$ cd build
$ cmake ../src
$ make

如果你的編譯器並非系統預設,別忘了依照需求指定 Generator:

$ cmake -G "Unix Makefiles" ../src
$ cmake -G "MSYS Makefiles" ../src
> cmake -G "Visual Studio 9 2008" ../src


執行結束後,ex2/build 下會出現各項中間檔、makefile 以及最終的 ex2 執行檔,但 ex2/src 原封不動,只有三個 C 源碼和一個 CMakeLists.txt。之後若出現什麼疑難雜症,可以輕鬆將 ex2/build 砍掉重練。

注意事項[編輯]

在執行 Out-of-source build 之前必須先確定所指定的源碼根目錄是否乾淨,若是該目錄下含有前次留下的 CMakeCache.txt 仍會執行 In-source build。

由於 CMake 生成的 makefile 當中並不會包含 make distclean 的 rule,因此強烈建議採用 out-of-source build,發布的時候只需將乾淨的 source tree 打包即可。