/bazelpackagesdriver

gopackagesdriver for bazel

Primary LanguageGoApache License 2.0Apache-2.0

bazelpackagesdriver

gopackagesdriver for bazel

Getting started

go install github.com/derivita/bazelpackagesdriver/cmd/bazelpackagesdriver

Set the GOPACKAGESDRIVER env var to the path to bazelpackagesdriver, or rename bazelpackagesdriver to gopackagesdriver and put it somewhere in your path.

You also need a gopls version that is earlier than commit 092357f697aefc45480a378b64b698e063e63da9, or else you need to revert that commit.

Implementation

bazelpackagesdriver is based off of bazel query. It uses bazel query to find the go rules in your workspace and external dependencies. This returns all the attributes passed to those rules, which it uses to generate the information needed by gopls. Unfortunately bazel query doesn't know which files are generated by the go rules. So the driver has special logic to determine where in bazel-bin the files for go_embed_data, go_proto_library, and go_test are generated.

There is also some information that gopls requires which isn't available from the build files. Namely the package name (as it appears in the source code), and which packages from the standard library are imported. So the driver parses each source file to get this information. If generated files are not yet present in bazel-bin, the driver will call bazel build to generate them.

Known issues

  • cgo is not tested.
  • depends on internal implementation details of the go rules, so it won't work if you're doing strange things.
  • Doesn't support NeedSyntax, NeedTypes, NeedExportsFile, or NeedTypesInfo

Ideas for improvement

  • Use bazel aquery to find the generated filenames instead of guessing them.
  • Use an aspect or update the go builder to output the package name and stdlib imports instead of parsing the source with each query. Potenially this could even output all the packages.Package data needed. However that needs to be done carefully: the aspect from https://github.com/jmhodges/rules_go/commits/feature/gopackagesdriver gets unusably slow as the workspace starts getting bigger.

History

This is the third incarnation of this.

First I attempted to update and finish the implementation from https://github.com/jmhodges/rules_go/commits/feature/gopackagesdriver.

I was able to get it working, but the performance was terrible. It's been a long time so I don't remember the details, but it was completely unusable on my project. Additionally the code was complicated, so fixing the performance issues seemed like a big project.

Next I implemented a fuse filesystem that generated a gopath style directory by overlaying the bazel workspace with the generated files from bazel-bin, and external workspaces from the bazel execroot. This worked well enough, but had several issues. For example, git would get very confused if you ran it inside they fuse filsystem. Also fuse on macos is not nearly as well supported as on Linux, and its future is uncertain as Apple is deprecating kernel extensions.

This version re-uses the logic from the filesystem to implement the GOPACKAGESDRIVER protocol.