C / C ++ 項目中的 DevOps 挑戰
- JFrog 軟件工程師兼 Conan.io 的創建者叠戈·羅德裏格斯 - 洛薩達( Diego Rodriguez-Losada )
這種表現強大的語言在所有行業中持續得到使用和青睞。然而,盡管 DevOps 在 Java 等軟件開發的其他主要領域已經普遍存在,但實施現代 C 和 C ++項目的 DevOps 並不容易,盡管實際上解決方案可以提供幫助。
我們來看看 C / C ++ 開發人員面臨的挑戰,然後看看如何解決這些挑戰。
概覽
C 和 C ++ 語言由於許多重要原因而受到許多開發人員的青睞。但是,實施現代 DevOps 和持續集成 C 和 C ++ 項目並不容易。由於 C / C ++ 編程語言和生態系統的性質,它仍然具有挑戰性。今天,我們有知識和經驗來確定我們需要滿足當今 DevOps 對 C 和 C ++ 的需求。我將用下面的案例來證明這是可能的。 開發 C 和 C ++ 項目 理想情況下,我們希望從開發人員變更到生產的 CI / CD 流程盡可能平穩和快速。但是,與其他開發語言相比,C / C ++ 開發人員面臨著更大的挑戰: 編譯時間長:這不是因為 C 和 C ++ 編譯器很慢。事實上,他們正在快速發展,在整個 IT 世界中擁有一些最先進最精彩的技術。但是,C / C ++ 有頭文件的問題,預處理程序基本上在每個編譯單元中一遍又一遍地復制每個包含的文件,使得編譯的代碼行膨脹起來。有一些機制作為預編譯頭文件,可以部分緩解第二次和後續重建的問題。另外,與其他語言相比,C / C ++ 語言被廣泛用於大型項目,擁有數百萬行代碼( MLoc ) - 一個典型的 AAA 遊戲有20個 MLoc 。 不同的平臺和生態系統,不同的構建系統: C 和 C ++ 無處不在。它們被用於計算機,嵌入式設備,移動設備等等。但是在每個平臺上,他們將使用不同的編譯器(例如 Windows 中的 MSVC cl.exe ,Linux 中的 GCC,OSX 上的 apple-clang )以及許多不同的編譯系統。CMake,MSBuild 和 Makefiles 或 autotools 被廣泛使用,但公司也在使用其他許多構建系統,甚至開發自己的定制解決方案。 二進制兼容性: C 和 C ++ 是為本機/二進制代碼構建的,但是使用某個編譯器版本編譯的二進制文件與其他編譯器不兼容,甚至不能與不同版本的相同編譯器兼容。這個問題被稱為 ABI (應用程序二進制接口)不兼容性,其他語言不需要處理。ABI 不兼容可能會導致鏈接錯誤,這些鏈接錯誤在構建時很容易被捕獲,但通常會產生運行時錯誤。 代碼內嵌和嵌入:共享庫直接嵌入它們鏈接的靜態庫的本地代碼。但是不僅如此,即使靜態庫也可能嵌入從另一個庫的頭文件中聲明的代碼。這意味著可能有必要從源代碼庫重建二進制文件,這些文件根本就沒有被修改,只是因為它的一些依賴關系已經改變了。 缺乏 OSS 的標準: OSS 庫可以在 GitHub,GitLab 或者 Bitbucket 中托管他們的源代碼,但是這並不能使它們準備好使用。用戶需要從源代碼構建二進制代碼(這可能很痛苦),從系統包管理器(可能已經過時,每個平臺都不相同)或者使用其他安裝程序或預編譯的模塊(必須從一個網站)。之後,他們通常還需要對消費者構建系統進行不同的調整,這對每個平臺也是不同的。 現代 DevOps 對 C 和 C ++ 的要求 鑒於以上列出的挑戰,C 和C ++ 項目的現代 DevOps 實踐和工具要求是什麽? 管理和重用二進制文件:每次構建源代碼都非常昂貴,容易出錯並且不適合大型項目。重復使用二進制文件應該對不同的平臺保持一致,並處理 ABI 兼容性問題。 管理單個存儲庫或服務器中的所有二進制文件:在開發人員或 DevOps 工程師中,在多個系統(例如 Debian 中的 apt,RH 中的 rpm,Windows 中的 nuget / choco 和 OSX 中的 pkg )中創建和維護軟件包非常昂貴。能夠從同一地點存儲,管理和檢索二進制文件是一個非常簡單的基礎設施和流程,因此節省了大量的時間。 適應從傳統到最新的任何構建系統,平臺和工具:如果每個人都使用單一構建系統,創建良好的 CI 和包管理將會簡單得多。但是思考項目可以遷移到構建系統顯然是天真的。將一些圖書館或項目遷移到新的構建系統的成本是巨大的投資,可能需要幾個月的時間。流程和工具必須能夠適應處理任何構建系統和現有的遺留工具。 與其他工具有良好的集成:不僅要構建系統,而且工具必須盡可能簡單地與其他工具集成。例如,為 Linux / OSX 和 Windows 提供的 Travis 和 Appveyor 雲服務等持續集成平臺,非常受歡迎,可用於開放源碼軟件項目,以及 Jenkins,這是業界專有代碼的實際標準。此外,工具必須與流行的 IDE (例如 Visual Studio 或 XCode )以及測試,覆蓋,靜態分析,多控制版本系統等完美集成。 Conan C / C ++ 包管理案例研究 Conan 是一個免費的 OSS C / C ++ 包管理器。它是分布式的,可移植的和多平臺的,運行在許多操作系統上,比如 Windows,Linux,Mac,BSD 和 Solaris ,而且針對任何可能的 C / C ++ 應用程序。 Conan 如何滿足上述要求: Conan 能夠為任何數量的不同配置構建,上傳和共享二進制文件。它管理二進制文件,根據需要為每個相應的平臺檢索正確的文件,並且還可以根據需要從源代碼構建,最大限度地減少 ABI 不兼容問題。 Conan軟件包和預先構建的二進制文件可以上傳到服務器並在其中共享。可以使用JFrog Artifactory Pro 在團隊內或公司範圍內私下共享。如果需要,可以使用 JFrog Bintray 在全球範圍內分發Conan軟件包,包括私有或公共存儲庫,完全免費用於 OSS 項目。所有支持平臺的所有不同二進制文件都可以在同一臺服務器上進行上傳和管理,界面完全相同。 Conan 與任何構建系統一起工作。它包括與 CMake,Visual Studio,Makefiles,SCons,QMake 等等的內置集成。它還具有良好的用戶端可擴展性,可以使用“ 生成器 ” 來支持任何其他構建系統。這意味著可以開發擴展以將柯南依賴關系模型轉換為任何構建系統格式,並生成可由這些構建系統讀取的文件。 Conan 可以很好地與不同的 CI 系統集成,包括 Travis,Appveyor 和 GitLab 的特定工具和幫助程序,還可以在 Jenkins Artifactory 插件中使用自定義的 DSL 。 Conan 軟件包的配置是用 Python 編寫的,所以它們可以用標準的 Python 語法很容易地自定義行為,使用戶可以輕松地插入本文前面提到的許多不同的工具:靜態分析,測試,代碼覆蓋面,等等。 讓我們來看看從 DevOps 的角度來看一個典型的流程,來說明 Conan 如何工作。首先,開發人員將某些源代碼更改為特定的庫( LibB ),並將這些更改提交給共享版本控制系統服務器( Git Repo )。 圖表:C / C ++與 Conan,Artifactory 和 Jenkins(構建系統:CMake,VS,MakeFile)的 CI 循環示例。 然後,CI 系統監控 Git 存儲庫,理想情況下使用 Git hooks ,因為不建議進行輪詢,並為其啟動一個工作(Jenkins)。下面是一個如何用 Jenkins pipeline 定義的例子: 上例中的第一個階段很簡單。第二個階段調用內部分割成兩個子任務的包創建: LibB 依賴關系以二進制形式被檢索,以避免從源重建並浪費時間。 所有傳遞依賴關系的依賴關系圖被構建,並且一個或多個文件被寫入。在這個例子中,LibB 使用 CMake 作為構建系統,Conan 生成一個 “conanbuildinfo.cmake” 文件,其中包含所有的依賴關系信息,以便 LibB 查找並正確鏈接到它們。然後 Conan 將調用 LibB 生成系統為它生成一個二進制包。最後,在上一個 Jenkinsfile 階段 “Upload packages” 中,生成的二進制文件被上傳到 Conan 包服務器(JFrog Artifactory)。LibB 二進制包可立即供開發人員或其他 CI 作業使用。 此示例說明了 “conan create” 命令中使用 “-s arch = x86” 參數指定的 32 位系統結構的構建配置。請註意,可以使用針對不同編譯器,操作系統,體系結構等的並行任務和作業並行構建許多其他配置。 結論 與其他正在開發的編程語言相比,C 和 C ++ 有更多的挑戰。這也使得嘗試實施現代 DevOps 時更具挑戰性,但並非不可能。C / C ++ 已經被忽略了,現在是時候更新工具來滿足開發人員的需求了。您在 C / C ++ 項目中實施了哪些 DevOps 原則和實踐呢? 作者:靳日陽
C / C ++ 項目中的 DevOps 挑戰