如何通过 Bazel go_binary 访问 Go 应用程序 运行 中的数据文件
How to access data files inside Go application running through Bazel go_binary
我有一个包含 go_binary 目标的 BUILD.bazel 文件。在这个应用程序中,我需要访问位于同一目录中的 YAML 文件(例如 config.yml)。
go_binary 看起来像这样:
go_binary(
name = "app1",
data = ["config.yml"],
embed = [":app1_lib"],
visibility = ["//visibility:public"],
)
我可以看到文件已添加到 /private/var/tmp/_bazel/52b44015c7f2ec78df04b9a822df93c1/execroot/__main__/bazel-out/darwin-fastbuild/bin/services/app1/app1_/app1.runfiles/__main__/services/app1
文件夹中。
在我的 Go 应用程序中访问此文件的最佳方式是什么?
到目前为止我发现我可以做到
url := fmt.Sprintf("%s/services/app1/config.yml", os.Getenv("PWD"))
...但我想避免必须明确指定文件夹结构。
这就是您在 Bazel 中访问数据文件的简单方式...您指定文件的完整路径,从 WORKSPACE 根目录开始。如果您的文件有目标 //services/app1:config.yml
,那么路径就是 serivces/app1/config.yml
.
不需要前缀$PWD
除非你出于某种原因需要一个绝对路径。这样做的首选方法是:
const config = "services/app1/config.yml"
abs, err := filepath.Abs(config)
if err != nil {
return err
}
假设您没有调用 chdir...我避免在我的程序中调用 chdir,主要是出于这个原因。
请注意,这不是 URL,如果您需要 URL,您可以:
u := url.URL{Scheme: "file", Path: filepath.ToSlash(abs)}
另请注意,如果您使用多个存储库中的文件,则必须包括存储库,并以 "external"
为前缀。例如,@some-repo//dir/pkg:target
是 external/some-repo-dir/pkg/target
... 即使它在您的 BUILD 文件中只是 ":target"
。呃,对吧?
为什么 Bazel 这样做?
您的代码可能 link 将来自整个工作区的包打包在一起。看起来很明显,在您的情况下,您只希望能够从与包相同的目录中读取 config.yml
,但您同样可以将 data = ["config.yml"]
传递给某些 go_library()
你的 deps
.
为了让它在任何地方都一样工作,每个人都需要使用数据文件的完整路径。有点冗长,但是哦。
如果您只是从 genrule
或构建规则而不是 bazel run
调用 go_binary
,您可以将配置文件的路径作为命令行参数传递,如果你比较喜欢。这会让您在没有完整路径的情况下指定它。
我有一个包含 go_binary 目标的 BUILD.bazel 文件。在这个应用程序中,我需要访问位于同一目录中的 YAML 文件(例如 config.yml)。
go_binary 看起来像这样:
go_binary(
name = "app1",
data = ["config.yml"],
embed = [":app1_lib"],
visibility = ["//visibility:public"],
)
我可以看到文件已添加到 /private/var/tmp/_bazel/52b44015c7f2ec78df04b9a822df93c1/execroot/__main__/bazel-out/darwin-fastbuild/bin/services/app1/app1_/app1.runfiles/__main__/services/app1
文件夹中。
在我的 Go 应用程序中访问此文件的最佳方式是什么?
到目前为止我发现我可以做到
url := fmt.Sprintf("%s/services/app1/config.yml", os.Getenv("PWD"))
...但我想避免必须明确指定文件夹结构。
这就是您在 Bazel 中访问数据文件的简单方式...您指定文件的完整路径,从 WORKSPACE 根目录开始。如果您的文件有目标 //services/app1:config.yml
,那么路径就是 serivces/app1/config.yml
.
不需要前缀$PWD
除非你出于某种原因需要一个绝对路径。这样做的首选方法是:
const config = "services/app1/config.yml"
abs, err := filepath.Abs(config)
if err != nil {
return err
}
假设您没有调用 chdir...我避免在我的程序中调用 chdir,主要是出于这个原因。
请注意,这不是 URL,如果您需要 URL,您可以:
u := url.URL{Scheme: "file", Path: filepath.ToSlash(abs)}
另请注意,如果您使用多个存储库中的文件,则必须包括存储库,并以 "external"
为前缀。例如,@some-repo//dir/pkg:target
是 external/some-repo-dir/pkg/target
... 即使它在您的 BUILD 文件中只是 ":target"
。呃,对吧?
为什么 Bazel 这样做?
您的代码可能 link 将来自整个工作区的包打包在一起。看起来很明显,在您的情况下,您只希望能够从与包相同的目录中读取 config.yml
,但您同样可以将 data = ["config.yml"]
传递给某些 go_library()
你的 deps
.
为了让它在任何地方都一样工作,每个人都需要使用数据文件的完整路径。有点冗长,但是哦。
如果您只是从 genrule
或构建规则而不是 bazel run
调用 go_binary
,您可以将配置文件的路径作为命令行参数传递,如果你比较喜欢。这会让您在没有完整路径的情况下指定它。