構建 C 語言開發環境

作者 | Martin Lampacher

編譯 | 王瑞平

有些 C/C++ 項目開發週期極長。在處理此類項目過程中,構建開發環境就像施展魔法一樣:測試框架被巧妙集成在一起,CI/CD 流程將開發者從繁瑣重複的工作中解脫出來。

作爲程序員,在開發過程中,我只有一個簡單的願望:在當前的開發環境中將 C 庫簡化爲少數幾個文件。

在本文中,我們將介紹如何爲 C 語言項目構建容器化開發環境,也將介紹如何使用 CMake 設置構建系統、使用 Unity 設置測試環境以及如何在 CI 流水線中構建容器化環境。

01 現代化開發環境

接下來,我們將展示如何爲 C 項目構建完整的、容器化的開發環境:

· 創建 Docker 鏡像作爲 vscode 的開發容器;

· 基於最小化的 Dummy 庫,在容器中設置構建庫的工具;

· 設置靜態代碼分析器 clang-tidy 檢查代碼是否有常見錯誤;

·clang-format 維持代碼庫的格式保持正常和整潔;

· 設置 Unity,通過在主機上執行 Ceedling 測試虛擬函數;

· 最後,我們將設置 GitHub 工作流,使用本地 Docker 鏡像執行、構建測試項目。

在本文中,我將使用 Docker 命令行接口。如果你不明白爲什麼需要某些參數,建議參考在線文檔。你也可以直接打開 GitHub 上的示例項目。

02 在 Docker 中運行程序

有時,使用嵌入式系統C/C++ 需要安裝大量專用工具編譯器。如果你正在同時處理不同的項目,版本之間很容易發生衝突。因此,我更傾向於在 Docker 容器中運行所有程序。

1. 爲什麼是 Docker? 存在哪些陷阱?

如果你是 Docker 新手,需注意以下幾點:

(1)Dockerfiles 不穩定:昨天構建出的 Dockerfile 今天就可能無法使用,存在太多的外部依賴關係;

(2)Docker 不是平臺獨立型的,例如 Apple ARM;

(3)某些 Docker 特性僅在 Linux 或專用 Windows 中獲得了支持;例如,並非所有平臺都支持將 USB 設備安裝到 Docker 容器之中,這是自 2016 年以來的限制;

鑑於此,建議你不要將 “賭注”“押” 在同一項技術上,並且你需要隨時做好切換的準備。

2. 讓我們這樣做

讓我們從零開始,構建空存儲庫

確保安裝 Dockor 並順利運行,在項目的根目錄中創建如下內容:builder.Dockerfile

這個 Dockerifle 指定了基本鏡像並安裝了一些包,便於在後續步驟中使用。我不會詳細介紹每一個軟件包:在創建鏡像時,你很快就能注意到缺少了什麼,可以擴展軟件包列表,重要的是以下幾點:

· 對於基本圖像,我強烈建議使用特定標籤。apt 包在基本鏡像之間變化很大,選擇標記可以爲你節省更多時間;

· 我傾向於在鏡像開發過程中使用特定平臺 ,這一點對後續開發步驟的順利進行很重要。

如果不使用 vscode,也可以指定不同的鏡像。在本文中,我們將使用 vscode,也將堅持使用 Dev 容器所支持的鏡像。

鏡像是用如下的命令構建出來的,執行起來可能需要一點時間:

3. 詳細命令行調用的快捷方式

Docker 命令非常冗長,因此,我通常將常用命令放在 makefile 項目根目錄中。假設安裝 make 後可進行如下操作:

現在,執行如下操作重建鏡像:

讓我們從圖像中旋轉容器並進行測試:

當使用 apt 時,已安裝的工具版本取決於基礎鏡像,也取決於包註冊表。如果需要安裝特定的版本,可以通過執行自定義的 RUN 命令。

03 Visual Studio 代碼開發容器

沒有在本地安裝所有工具的缺點是: 你選擇的 IDE 無法利用這些工具,例如,當使用 vscode 時,如果沒有安裝編譯器,你將無法正確設置 智能提示 或任何其它的 輔助程序

vscode 允許你在開發容器中運行編輯器。這也是我們選擇將 mcr.microsoft.com/vscode/devcontainers/base 當作基礎圖像的原因:我們可以在容器中鏈接到 vscode,因此所有工具都將被安裝在 Docker 鏡像中。

值得注意的是,vscode 實例與本地 vscode 安裝不匹配,與遠程實例非常相似。

通過創建.devcontainer/devcontainer.json 文件,我們可以讓 vscode 使用新構建的圖像作爲開發容器,還可以在 vscode 實例中安裝 3 個擴展,通過使用 customizations.extensions 字段中的 devcontainer.json 配置文件:

如果你從現在開始重新加載窗口或重新打開 vscode,vscode 應該會詢問你是否需要使用檢測到的開發容器。

需要一段時間爲 vscode 設置你的容器安裝擴展,並用 vscode 連接到 Linux 容器

04 系統架構

我們將使用 CMake 構建單獨的.c 和.h 對。

CMakeLists.txt 簡單定義了名爲 “Dummy” 的庫,並將相應的文件添加到庫中。

重要的是:這已在開發容器和 vscode 中被構建出來了! 在你的遠程實例中打開集成終端並執行 CMake,如下所示:

05 安裝 clang 工具:格式化和靜態代碼分析

C 和 C++ 的靈活性也伴隨着大量 “footguns” 的出現;因此,我嘗試在項目中添加至少一個最小的靜態代碼分析任務,這有助於發現最明顯的錯誤。市面上有很多工具,但到目前爲止,我個人更偏愛 clang-tidy。

另外,在代碼庫上進行協作時,格式化器極好;當我們在安裝 clang-tidy 時,不妨繼續安裝 clang-format。

你需要將兩個配置文件 clang-format 和.clang-tidy 放置到項目根目錄中,以便任何 IDE 都能自動拾取它們:

06 添加單元測試框架

我們已經能夠構建並分析庫,還提供了格式化功能。在開發環境中,我們還需要一個單元測試框架

在本文中,我選擇了 Unity 測試框架,通過 Ceedling 在主機上執行。順便說一句,使用這個框架便於嵌入式系統在目標硬件上執行任務。

1. 安裝 Unity 和 Ceedling

在構建者鏡像的第一步中,我們已經安裝了 ruby,所以,安裝單元測試工具變得更加簡單:

重建鏡像後,我們就可以開始了!

2. 配置 Unity 和運行單元測試

簡而言之,你需要在一個專門的 unity_config.h 文件中將配置開關設置爲 Unity 並配置 Ceedling 與 project.yml. Ceedling,爲你生成所有的測試運行程序。

你需要做的就是 添加 你的 測試文件,然後 “告訴” Ceedling 如何檢測它們:

然後,我們可以創建第一個單元測試 tests/unittest/test/test_dummy.c:

07 結論

到這裏,所有的工作就都完成了,包括庫的構建等,報告也可以使用了。神奇的是,所有這些操作都不會使計算機因工具而 “堵塞”

最後,值得一提的是:有了 Docker 桌面,你不僅可以輕鬆檢查圖像漏洞,還能檢查 Dockerfile 中的每一步:

現在,你已具備在 GitHub 上用 CI 設置容器化 C/C++ 項目的所有技能。有了這項技能,你能輕鬆地在文檔中添加特定編譯器清理設置 CI 時出現的所有錯誤

參考資料

1.https://code.visualstudio.com/docs/devcontainers/tutorial

2.https://interrupt.memfault.com/blog/a-modern-c-dev-env

3.https://www.throwtheswitch.org/unity

4.https://embeddedartistry.com/blog/2019/02/25/unit-testing-and-reporting-on-a-build-server-using-ceedling-and-unity/

5.https://github.com/features/actions

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/p_oKh-wsN8pN2H-3YHvXhA