🥬

Gazelle/Bazel でビルドできなくなった go-git v5.5 をビルドする

2023/01/31に公開

go-git は Go だけで実装された .git を操作するためのパッケージです。

https://github.com/go-git/go-git

git に依存せずに .git をいじりたい場合に重宝します。

v5.5 で依存パッケージに https://github.com/cloudflare/circl が含まれるようになりました:

https://github.com/go-git/go-git/pull/620

https://github.com/ProtonMail/go-crypto/pull/104

その結果、Gazelle によって生成された BUILD ファイルでは Bazel によるビルドができなくなってしまいました:

ERROR: /path/to/project/vendor/github.com/cloudflare/circl/dh/x25519/BUILD.bazel:3:11: GoCompilePkg project/vendor/github.com/cloudflare/circl/dh/x25519/go_default_library.a failed: (Exit 1): builder failed: error executing command sandbox/bin/external/go_sdk/builder compilepkg -sdk external/go_sdk -installsuffix darwin_amd64 -src project/vendor/github.com/cloudflare/circl/dh/x25519/curve.go ... (remaining 40 arguments skipped)

Use --sandbox_debug to see verbose messages from the sandbox
project/vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.s:7: #include: open project/vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.h: no such file or directory
compilepkg: error running subcommand external/go_sdk/pkg/tool/darwin_amd64/asm: exit status 1

cloudflare/circl パッケージに含まれる Go Assembler#include で別ディレクトリのヘッダーファイルを指定してるのを、Gazelle でうまく解決できないのが問題のようです:

https://github.com/cloudflare/circl/blob/7cdab52ea2fddc9d9a1a44d6f8936dfd297f17f4/dh/x25519/curve_amd64.s#L1-L7

Gazelle 側に Issue がありました:

https://github.com/bazelbuild/bazel-gazelle/issues/1393

解決策

Issue にある通りに BUILD ファイルを上書きします。まず、math/fp25519/BUILD.bazel の方には、ヘッダーファイルを参照できるようにしておく必要があります:

load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_source")

# この部分
go_source(
    name = "headers",
    srcs = ["fp_amd64.h"],
    visibility = ["//visibility:public"],
)

go_library(
    name = "go_default_library",
    ... # こっちは生成されるやつ
)

include している dh/x25519/BUILD.bazel 側は、これを embed します:

load("@io_bazel_rules_go//go:def.bzl", "go_library")

go_library(
    name = "go_default_library",
    srcs = [
        ...
    ],
    embed = [
        "//project/vendor/github.com/cloudflare/circl/math/fp25519:headers", # keep
    ],
    ...
)

include してるファイルは deps ではなく embed で指定しなければいけません。embedgo_librarygo_source しか指定できませんが、ファイルを個別に埋め込みたい場合は、exports_files で参照できるようにして、embedsrcs で埋め込むとかも可能です:

go_library(
    name = "go_default_library",
    srcs = [
        ...
    ],
    embedsrcs = [
        "//project/vendor/github.com/cloudflare/circl/math/fp25519:fp_amd64.h", # keep
    ],
    ...
)

これを math/fp25519dh/x25519 の組み合わせと、math/fp448dh/x448 の組み合わせで書き換えます。

問題は、Gazelle で自動生成したファイルに対してどうやって上書きするかですね。わたしは go mod vendor したものに Gazelle を適用して BUILD ファイルを生成するような自作ルールを利用してたので、その間に BUILD ファイルを上書きするような機能を追加して解決しました:

go_project( # 自作ルール
    build_files = {
        ":build/cloudflare_circl_dh_x448.bazel": "github.com/cloudflare/circl/dh/x448",
        ":build/cloudflare_circl_math_fp448.bazel": "github.com/cloudflare/circl/math/fp448",
        ":build/cloudflare_circl_dh_x25519.bazel": "github.com/cloudflare/circl/dh/x25519",
        ":build/cloudflare_circl_math_fp25519.bazel": "github.com/cloudflare/circl/math/fp25519",
    },
)

BUILD ファイルへの patch で管理してもいいかと思いましたが、どうせ生成内容が変わったら patch が適用できなくなるかもなので、上書きする BUILD ファイルを丸ごと管理することにしました。

go_repository を使ってる場合の方法は試してないのでわからないです)

おしまい

Gazelle 側を治す方法も試しましたが、Go Assembler のデファクトスタンダートな方法がわからない(雑に #include "../path/to/header" の部分を集めるだけでいいの?そもそも ../ なファイルを参照していいのだろうか)ので途中まで作って諦めちゃいました。

MIXI DEVELOPERS NOTE

Discussion