gopls and multiple workspaces

227 views
Skip to first unread message

Cristian Donoso

unread,
Jul 25, 2020, 9:31:43 PM7/25/20
to golang-tools
Hi everyone,

I've been using gopls through YouCompleteMe and it works.... fine-ish.
The main problem is that I we have an internal repo where we build everything through bazel and we have vendored in dependencies (so go doesn't downloads anything). GOPATH is not really usable because we use bazel for finding packages.

A common structure would be like this

/root
   /tools
       /pkg_a
             some_file.go
   /build
       /pkg_b
            other_file.go
    /third_party
        /org_golang_google_protobuf/....
        ....

For our code, we follow the import paths from our repo root. So for the packages in the example, the import paths would be:
  • tools/pkg_a
  • build/pkg_b
For third_party stuff, we use bazel local_repositories, so the import path is what you'd obtain from github or other repo. Using the BUILD files we get the go compiler to find stuff.

The problem is that I have not been able to get gopls to recognize this situation and correctly find the packages. I have delved into the gopls source and am starting to get a feel about how package resolution works, albeit is a slow process. I'm willing to make contributions to both gopls and YouCompleteMe, but I could really use some guidance about where to look, as I feel that even my conceptual understanding of the problem might be wrong.

Would someone be willing to point me in the right direction. I'm happy to have a VC to discuss if you feel it might be faster.

Thank you very much for reading.
Best,

Duco van Amstel

unread,
Jul 26, 2020, 5:35:24 AM7/26/20
to Cristian Donoso, golang-tools
Hello Cristian,

If you are using Bazel as your build system then the core issue is not actually in gopls or your IDE. Both gopls and other tooling resolve the location of the source code of packages (for example dependencies) via the golang.org/x/tools/go/packages interface. This package in turn makes use of a loader / resolver binary implementing a well-defined protocol (with the default being logic based on go list). One can configure it to use a custom driver instead via an environment variable.

Because your repo's setup does deliberately not follow Go's default source-code storage layout, etc and instead uses Bazel the default go list driver is not able to resolve your package's dependencies and that's why gopls or any other IDE tooling (using either go list or go/packages) can not resolve the source locations.

The solution is to write a Bazel-aware driver and use that instead of the default one. The key issue for this is the long-running rules_go#512 which has unfortunately not yet been solved. I know someone did some efforts on it in the past but not up to a working version (the maintainer of rules_go and gazelle). The issue in question does actually have a comment calling for people in the community to pick this up.

Duco

NB: I won't be able to respond immediately to any follow-ups as I will be away from my computers for the next week but others on this list can answer as well.

--
You received this message because you are subscribed to the Google Groups "golang-tools" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-tools...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-tools/705baac2-21b4-435d-afa8-eae5a5af5c4fn%40googlegroups.com.

adam...@uber.com

unread,
Jul 26, 2020, 7:46:20 PM7/26/20
to golang-tools
An existing workaround is to modify your Bazel build file(s) to include the go_path rule. This way you can generate the directory structure compatible with the standard go source-code storage layout. It does not always work, but it's the best we have right now I think...

Adam

Reply all
Reply to author
Forward
0 new messages