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
- src/
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 打包即可。