您好,登錄后才能下訂單哦!
本篇內容介紹了“怎么使用Bazel構建Golang程序”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
讓我們從將 Go 與 Bazel 結合使用的基礎知識開始。
為此,我們需要從 github.com/bazelbuild/… 獲取 Go 語言的官方構建規則。
在配置部分,您會發現:我們需要將以下這段 Starlark
語言代碼,放入名為 WORKSPACE
的配置文件里面:
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "io_bazel_rules_go", sha256 = "8e968b5fcea1d2d64071872b12737bbb5514524ee5f0a4f54f5920266c261acb", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.28.0/rules_go-v0.28.0.zip", "https://github.com/bazelbuild/rules_go/releases/download/v0.28.0/rules_go-v0.28.0.zip", ], ) load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") go_rules_dependencies() go_register_toolchains(version = "1.16.5")
讓我們逐步了解這段代碼所做的事情。
首先,我們使用load
指令來加載并提取新功能,以在 Bazel 文件當中能夠使用該功能。我們調用了兩次load
指令,第一次用于導入下載 HTTP 代碼庫的能力,第二次則是從剛下載的代碼庫中加載特定于 Go 的命令。
對于導入本身,我們需要提供一個導入名稱。通常的命名方案是:逆反域名,后面跟命名空間和項目名稱;并需將/
和.
全部都轉換為下劃線_
。例如:github.com/user/project
變成com_github_user_project
。io_bazel_rules_go
這個項目由于是Bazel官方項目中的一部分,所以它使用的是bazel.io
而不是github.com
。
如果您并不熟悉 Bazel,那么,您需要了解到:實際的構建配置是通過BUILD
文件完成的。我們可以將 Go 視為任何其他語言,并使用遵循相同結構的規則:go_binary
、go_library
和go_test
。我在我的 Github 上準備了一個最小化的例子:github.com/HappyCerber…。您會注意到,我們需要從導入的io_bazel_rules_go
代碼庫中加載這些規則,以使其在BUILD
文件中可用。
現在我們知道,從頭全新開始是很容易。但是,如果您已經有一個 Golang 項目,并且需要將其轉換為 使用 Bazel 構建怎么辦?為此,我們需要使用 Bazel 官方項目中提供的另一個工具 Gazelle
。
為了演示,我將使用一個第三方項目,我目前正在為即將到來的系統設計課程修改該項目。
首先,我們需要創建一個WORKSPACE
文件,并從 Gazelle
代碼庫的設置部分復制粘貼代碼。
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "io_bazel_rules_go", sha256 = "8e968b5fcea1d2d64071872b12737bbb5514524ee5f0a4f54f5920266c261acb", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.28.0/rules_go-v0.28.0.zip", "https://github.com/bazelbuild/rules_go/releases/download/v0.28.0/rules_go-v0.28.0.zip", ], ) http_archive( name = "bazel_gazelle", sha256 = "62ca106be173579c0a167deb23358fdfe71ffa1e4cfdddf5582af26520f1c66f", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.23.0/bazel-gazelle-v0.23.0.tar.gz", "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.23.0/bazel-gazelle-v0.23.0.tar.gz", ], ) load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") go_rules_dependencies() go_register_toolchains(version = "1.16.5") gazelle_dependencies()
您會注意到,上述代碼也導入了上一節中所提到的規則。
現在,要真正運行 Gazelle,我們需要將以下代碼添加到我們的主BUILD
文件中:
load("@bazel_gazelle//:def.bzl", "gazelle") # gazelle:prefix github.com/aler9/rtsp-simple-server gazelle(name = "gazelle")
gazelle:prefix
注釋后面的路徑是整個項目所使用的 Go 導入路徑。例如,main.go
中有以下包的導入:
import ( "os" "github.com/aler9/rtsp-simple-server/internal/core" )
至此,我們終于可以真正運行Gazelle,讓它BUILD
為我們的項目生成文件了。
bazel run //:gazelle
之后,我們應該BUILD
自動生成項目的所有文件:
git status On branch main Your branch is up to date with 'origin/main'. Untracked files: (use "git add <file>..." to include in what will be committed) BUILD WORKSPACE bazel-bin bazel-out bazel-test bazel-testlogs internal/aac/BUILD.bazel internal/conf/BUILD.bazel internal/confenv/BUILD.bazel internal/confwatcher/BUILD.bazel internal/core/BUILD.bazel internal/externalcmd/BUILD.bazel internal/h364/BUILD.bazel internal/hls/BUILD.bazel internal/logger/BUILD.bazel internal/rlimit/BUILD.bazel internal/rtcpsenderset/BUILD.bazel internal/rtmp/BUILD.bazel nothing added to commit but untracked files present (use "git add" to track)
但是,如果您嘗試使用bazel build //...
命令構建項目,實際上您會看到許多關于未定義代碼庫的錯誤。這是因為我們仍然缺少項目依賴項的定義。然而,Gazelle 連這件事也可以為我們辦好(to_macro
參數是可選的):
bazel run //:gazelle -- update-repos -from_file=go.mod -to_macro=deps.bzl%go_dependencies
此命令將生成一個文件名為deps.bzl
的新文件(如果我們在WORKSPACE
中有使用repository_macro
指令定義過,那么我們省略該to_macro
指令),加載該文件,以導入構建項目所需的所有代碼庫。
load("@bazel_gazelle//:deps.bzl", "go_repository") def go_dependencies(): go_repository( name = "com_github_alecthomas_template", importpath = "github.com/alecthomas/template", sum = "h2:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=", version = "v0.0.0-20190718012654-fb15b899a751", ) go_repository( name = "com_github_alecthomas_units", importpath = "github.com/alecthomas/units", sum = "h2:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=", version = "v0.0.0-20190924025748-f65c72e2690d", ) go_repository( name = "com_github_aler9_gortsplib", importpath = "github.com/aler9/gortsplib", sum = "h2:Bf0hzdN1jUWsb5Mzezq1pd18EIBeKXxk5clIpHZJ1Lk=", version = "v0.0.0-20210724151831-dae5a1f04033", ) go_repository( ...
在這個代碼庫里,我實際上遇到了一個小問題。構建仍然是失敗的,因為它導入的org_golang_x_tools
被錯誤地推斷為依賴項(通過從deps.bzl
中刪除它來修復這個問題)。您可以在我的項目分支:github.com/HappyCerber…上看到rtsp-simple-server
的最終結果。
您可以在后續繼續使用 Gazelle 來管理依賴項,這也是您可以將代碼庫引入基于 Bazel 的項目而無需實際轉換它的方法:
bazel run //:gazelle -- update-repos github.com/some/repo
您可能會遇到的最后一個問題是密封測試。如果您看到測試因訪問被拒絕、文件未找到或操作不允許失敗而失敗,那是因為 Bazel 強制執行密封測試。這意味著每個測試都必須完全獨立并且獨立于任何其他測試。
對于單元測試,任何文件都需要作為測試的依賴項提供并通過運行文件機制訪問。
環境變量中提供了每個測試的臨時目錄,您將使用TEST_TMPDIR
而不是傳統的os.TempDir()
函數。
密封集成和系統測試需要從一開始就仔細設計,因此轉換現有的此類測試可能很棘手。遺憾的是,我在這里沒有放之四海而皆準的建議。雖然將您的測試轉換為密封測試可能很煩人,但這是一項值得的努力,它將為您帶來更好的測試可重復性和更低的易碎性。
“怎么使用Bazel構建Golang程序”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。