Carpe Diem

備忘録

Bazel + CEL でgo_default_libraryが必要になる問題の対処方法

背景

Bazelで依存関係を管理している環境で、celライブラリを導入したところ次のようなエラーが発生しました。

'@com_github_google_cel_go//cel:cel': target 'cel' not declared in package 'cel' defined by /external/com_github_google_cel_go/cel/BUILD.bazel and referenced by '@com_github_bufbuild_protovalidate_go//internal/celext:celext'
'@com_github_google_cel_go//common/overloads:overloads': target 'overloads' not declared in package 'common/overloads' defined by /external/com_github_google_cel_go/common/overloads/BUILD.bazel and referenced by '@com_github_bufbuild_protovalidate_go//internal/celext:celext'
'@com_github_google_cel_go//common/types:types': target 'types' not declared in package 'common/types' defined by /external/com_github_google_cel_go/common/types/BUILD.bazel and referenced by '@com_github_bufbuild_protovalidate_go//internal/celext:celext'
'@com_github_google_cel_go//common/types/ref:ref': target 'ref' not declared in package 'common/types/ref' defined by /external/com_github_google_cel_go/common/types/ref/BUILD.bazel and referenced by '@com_github_bufbuild_protovalidate_go//internal/celext:celext'
'@com_github_google_cel_go//common/types/traits:traits': target 'traits' not declared in package 'common/types/traits' defined by /external/com_github_google_cel_go/common/types/traits/BUILD.bazel and referenced by '@com_github_bufbuild_protovalidate_go//internal/celext:celext'
'@com_github_google_cel_go//ext:ext': target 'ext' not declared in package 'ext' defined by /external/com_github_google_cel_go/ext/BUILD.bazel and referenced by '@com_github_bufbuild_protovalidate_go//internal/celext:celext'
'@com_github_google_cel_go//cel:cel': target 'cel' not declared in package 'cel' defined by /external/com_github_google_cel_go/cel/BUILD.bazel and referenced by '@com_github_bufbuild_protovalidate_go//internal/expression:expression'
'@com_github_google_cel_go//interpreter:interpreter': target 'interpreter' not declared in package 'interpreter' defined by /external/com_github_google_cel_go/interpreter/BUILD.bazel and referenced by '@com_github_bufbuild_protovalidate_go//internal/expression:expression'
'@com_github_google_cel_go//cel:cel': target 'cel' not declared in package 'cel' defined by /external/com_github_google_cel_go/cel/BUILD.bazel and referenced by '@com_github_bufbuild_protovalidate_go//internal/constraints:constraints'
'@com_github_google_cel_go//cel:cel': target 'cel' not declared in package 'cel' defined by /external/com_github_google_cel_go/cel/BUILD.bazel and referenced by '@com_github_bufbuild_protovalidate_go//internal/evaluator:evaluator'

これはcel-goに依存していた場合のBazelのターゲットの記述が本来は

go_library(
    ...
    deps = [
        ...
        "@com_github_google_cel_go//cel:go_default_library",
        ...
    ],
)

であるべきが、gazelleを使ったところ

go_library(
    ...
    deps = [
        ...
        "@com_github_google_cel_go//cel",
        ...
    ],
)

となってターゲットの記述が不適切になってしまったせいです。

今回はこの回避策方法について説明します。

環境

  • Bazel v6.5.0
  • bazel-gazelle v0.35.0

原因詳細

cel-goはBazelを使っており、中でBUILD.bazelを持っています。

go_library(
    name = "go_default_library",
    srcs = [
        "cel.go",
        "decls.go",
        "env.go",
        "folding.go",
        "io.go",
        "inlining.go",
        "library.go",
        "macro.go",
        "optimizer.go",
        "options.go",
        "program.go",
        "validator.go",
    ],
    importpath = "github.com/google/cel-go/cel",
    ...

ref: https://github.com/google/cel-go/blob/6df4157bffbfbf57c28c795c4a2d353ed2313cc7/cel/BUILD.bazel#L7-L23

従ってこれに依存する場合、Bazelのターゲット名はgithub.com/google/cel-go/cel:go_default_libraryとなります。

しかしGoの一般的なライブラリはBazelを使っておらず、gazelleがそれを考慮してくれないため

        "@com_github_google_cel_go//cel",
        "@com_github_google_uuid//:uuid",

のように処理してしまうのが原因です。

対応方法

2つの方法を紹介します。

方法1:手動でターゲット名を設定してkeepを付ける

gazelleは# keepがあればそこを変更しないので、

go_library(
    ....
    deps = [
        ...
        "@com_github_google_cel_go//cel:go_default_library",  # keep
        ...
    ],
)

# keep
go_library(
    ....
    deps = [
        ...
        "@com_github_google_cel_go//cel:go_default_library",
        ...
    ],
)

といった記述にすることでターゲット名であるgo_default_libraryが削られるのを防げます。

しかしこれは

  • 前者であればcel-goの別pkgが必要となったときに都度対応が必要になる
  • 後者であれば他の依存ライブラリがgazelleで更新されなくなる

といった課題がありあまりよくありません。

方法2:deps.bzlを編集する

cel-goのdeps.bzlは次のようになっていますが、

    go_repository(
        name = "com_github_google_cel_go",
        build_file_proto_mode = "disable_global",
        importpath = "github.com/google/cel-go",
        sum = "h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84=",
        version = "v0.20.1",
    )

これにbuild_naming_conventionを付けます。

    go_repository(
        name = "com_github_google_cel_go",
        build_file_proto_mode = "disable_global",
        build_naming_convention = "go_default_library",  # ここ
        importpath = "github.com/google/cel-go",
        sum = "h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84=",
        version = "v0.20.1",
    )

こうするとgazelleが解釈してくれて、BUILD.bazel"@com_github_google_cel_go//cel:go_default_library"となってくれます。

まとめ

Bazelを使っているライブラリに依存していた場合、ターゲット名がうまく解釈されない場合の対応方法を紹介しました。

参考