在學校的程式相關課程中(資料結構、演算法、物件導向、C/C++程式設計 ...),都沒有使用過Github裡面的開源專案來協助開發,直到大三開始製作實務專題時才首次接觸到,接下來去公司實習、進實驗室接計畫,也經常需要使用到開源專案,但是其軟體規模通常都非常大,也依賴了許多其他第三方的程式庫,這時候就需要使用到CMake來幫助我們管理專案。
在學習CMake的過程中,找到了以下比較有架構與體系、參考價值的資源,其他的基本上都太過於零碎而難以了解全貌。
線上資源:
- CMake Tutorial
- CMake 入門 維基教科書
- CMake Reference Documentation 書籍:
- Cmake 實踐
- 程序員的自我修養 鏈接、裝載與庫
- CMake菜譜(CMake Cookbook中文版)
但是在學習過程中,仍然有許多疑問是這些書籍或教程沒辦法解答的,網路上也搜尋不太到相關的範例(可能是我Google能力太爛),例如說動態庫的版本號,沒有一個範例和我說要如何更新才能實現多版本共存或使用指定版本編譯,但這個功能在軟體實作上卻非常重要,因為第三方函式庫會一直更新,很容易陷入相依性地獄中。 而且上述的教學內容雖然完整且詳細,但是大部分都沒有實際案例,有時會不知道它所介紹的CMake語法的應用場景為何,等到需要使用時早已忘光概念。 因此這個旅程將以開發專案與實際應用的視角來學習CMake,但是內容將不僅限於CMake的使用,我也會分享在開發專案過程中所遇到的問題與解決方案,順便還一下以前欠下的知識債(Knowledge Debt)。
接下來是我預計要撰寫的章節介紹
-
第一章 [Day3] 編譯流程 : 簡介預處理 (pre-processing)、編譯 (compilation)、彙編 (assembly) 與鏈接 (linking)的流程。
-
第二章 編譯單一原始碼
- 2.1. [Day4] 工具程式比較 : 使用make編譯單一原始碼後,說明g++、make和CMake 之間的關係。
- 2.2. [Day5] 第一個CMake專案: 在了解過反人類的Makefile語法後,說明CMake的簡單易懂。
-
第三章 編譯多檔案
-
3.1. [Day6] 編譯多檔案與檔案架構:要編譯多檔案就必須要知道鏈接(Linking)的原理,雖然在第一篇中有說明過,但是在這裡要重點強調。
-
3.2. [Day7] 定義與宣告—多檔案共用變數:要在多檔案間共用變數需要關鍵字extern,但是這篇會將重點放在extern的實現原理:定義與宣告的差異。
-
3.3. [Day8] 重複定義問題-Define Guard:在使用多檔案時必須使用Define Guard,否則會遇到重複定義問題,因此這篇會說明原理。
-
3.4. [Day9] 子目錄:專案規模越來越大目錄架構會更加複雜,因此每一層目錄中最好都要有CMakeLists.txt來負責管理,這篇會說明如何在各個目錄中將原始碼編譯成庫,並且在最後鍊結成執行檔。
-
-
第四章 庫
- 4.1. [Day10] 動態與靜態庫:說明彼此的不同,以及為何要使用庫,並強調現代專案為何都使用動態庫的原因。
- 4.2. [Day11] 庫的實際應用經驗--使用別人的庫:會分享實際上要如何在專案中使用別人的庫來建構專案,內容是在公司實習時廠商提供的CAN BUS Driver程式庫的使用經驗。
-
第五章 版本與安裝
-
5.1. [Day12] 動態庫與版本號:以CAN BUS Driver為例,介紹動態庫的版本號是如何實現的原理,怎麼使用軟鍊結管理不同版本,以及各版本之間的兼容性原理-ABI二進制接口。
-
5.2. [Day13] 實際操作動態庫的版本號:為了更熟悉動態庫的特性,會從編譯出帶版本號的動態庫,接下來依序更新補釘版本、次要版本、主要版本。
-
5.3. [Day14] 從原始碼安裝庫:庫有兩種安裝方式,一種是直接安裝在專案內部,另外一種是安裝到系統目錄下。
-
5.4. [Day15] 解除安裝庫:能安裝,當然要能刪除啦!
-
5.5. [Day16] 使用包管理器管理庫:將自己的庫打包成 .deb 安裝檔後使用Linux的包管理器管理安裝的檔案,並比較從 原始碼安裝庫 和 使用包管理器安裝庫 各自的優缺點。
-
5.6. [Day17] 發布軟體流程:ABI Cheacker->Release:發布軟體前,先用debug模式編譯,讓ABI Checker來檢測二進制接口是否損壞,來保證庫的向後兼容性,接下來用release模式編譯後發布。
-
5.7. [Day18] 版本號與宏:如何使用.h.in參數檔讓CMake產生宏(Marco)來當作版本號。
-
-
第六章 製作與使用第三方庫
- 6.1. [Day19] 使用第三方庫:find_package()是如何找到別的第三方庫的原理。
- 6.2. [Day21] 使用第三方庫--以json為例:使用find_package()找到第三方庫的實際範例。
- 6.3. [Day22] 製作第三方庫(一):製作Config.cmake,讓其他專案能透過find_package搜尋到自己的專案。
- 6.3. [Day20] 使用第三方庫--以OpenCV為例:使用find_package()提供的資訊來編譯程式的第三方庫範例。
- 6.4. [Day23] 製作第三方庫(二):如何在自己製作的Config.cmake檔案中包含編譯資訊。
- 6.5. [Day24] 製作第三方庫(三):如何製作ConfigVersion.cmake檔案來說明此庫的版本相容性,讓find_package除了知道此專案要求的第三方庫是什麼版本之外,並在所需版本號不一致時提醒使用者。
- 6.6. [Day25] 使用第三方庫--以Glog為例:使用命名空間鍊結程式庫的範例。
- 6.6. [Day26] 製作第三方庫(四):如何導出庫的命名空間,必免函式庫重名造成錯誤。
- 6.7. [Day27] 自動下載依賴項:當使用的專案依賴了許多第三方函式庫,一個個手動編譯與安裝會太過耗費時間,於是CMake提供了一個能夠自動下載專案所需依賴項的功能模組。
-
第七章 測試與除錯專案
- 7.1. 自動化測試:讓專案在建構完成後,能夠自我測試功能。
- 7.2. GBD介紹:簡單介紹GDB以及其必要性,並且會配合一個不能使用printf解決bug的範例,以及Debug模式編譯選項。
- 7.3. 在專案中使用GBD:如何使用GBD這個Debugger,怎麼產生符號表,以及跨檔案行號的中斷點如何使用。
-
第八章 CMake 常用語法補充
- 8.1. 指定c++標準
- 8.2. if, else流程控制:使用Tutorial的範例讓使用者選擇是否使用自己編寫的函式庫。
- 8.3. if, else跨平台範例
- 8.4. for 迴圈控制:使用編譯一整個資料夾來說明for語法。
- 8.5. target與非target的差別:講解在CMake官方文件中都建議使用者用target令的原因。
- 8.6. 統整CMake產生的預定義變量
-
其他(不確定要不要放)
- cmake build vs make cmake install vs make install
- cmake vs make : [cmake --build, --install, --target package vs make, make install, make package]
- 透過-S分析程式碼
- 構建系統make, nijia etc.
- #define Guard vs #pragma once
- CMake GUI
- #include 與 #include “filename”的差異