bazelbuild / bazel-gazelle

Gazelle is a Bazel build file generator for Bazel projects. It natively supports Go and protobuf, and it may be extended to support new languages and custom rule sets.
Apache License 2.0
1.19k stars 378 forks source link

Error about GOCACHE is not defined and $HOME is not defined when using go binary in a genrule #931

Closed ob closed 3 years ago

ob commented 4 years ago

What version of gazelle are you using?

0.22.1

What version of rules_go are you using?

0.24.3

What version of Bazel are you using?

3.5.0

Does this issue reproduce with the latest releases of all the above?

Yes.

What operating system and processor architecture are you using?

Mac OS X 10.15.7 (19H2)

What did you do?

I'm trying to run controller-gen from Kubernetes controller-tools in a genrule according to the default Makefile generated by kubebuilder.

The Makefile has:

# Generate code
generate: controller-gen
    $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."

Where $(CONTROLLER_GEN) is the binary produced by compiling the Go code from controller-tools.

I added controller-tools as a go_repository in my WORKSPACE file:

    go_repository(
        name = "io_k8s_sigs_controller_tools",
        importpath = "sigs.k8s.io/controller-tools",
        version = "0.3.0",
    }

and modified the BUILD.bazel file generated by Gazelle in my api/v1alpha1 directory like so:

filegroup(
    name = "sources",
    srcs = glob(["*.go"],
)

go_library(
    name = "go_default_library",
    srcs = [
        ":generated_deepcopy",
        ":sources",
    ],
   # more fields elided
)

genrule(
    name = "generated_deepcopy",
    srcs = [":sources"],
    outs = ["zz_generated.deepcopy.go"],
    cmd = "$(location @io_k8s_sigs_controller_tools//cmd/controller-gen:controller-gen) object:headerFile=/dev/null paths=./...",
    message = "ControllerGen",
    tools = [
        "sources",
        "@go_sdk//:files",
        "@io_k8s_sigs_controller_tools//cmd/controller-gen",
    ],
)

What did you expect to see?

A successful build.

What did you see instead?

$ bazel build //operator
INFO: Using Bazel Remote listening on 127.0.0.1:55619
INFO: Running Bazel version 3.5.0
INFO: Invocation ID: d17f454e-4ef9-43e6-876c-889266ec3708
INFO: Analyzed target //operator:release (1 packages loaded, 11 targets configured).
INFO: Found 1 target...
ERROR: .../api/v1alpha1/BUILD.bazel:29:8: ControllerGen //../api/v1alpha1:generated_deepcopy failed (Exit 1) bash failed: error executing command /bin/bash -c ... (remaining 1 argument(s) skipped)

Use --sandbox_debug to see verbose messages from the sandbox
Error: go [-e -json -compiled=true -test=false -export=false -deps=true -find=false -tags ignore_autogenerated -- ./...]: exit status 1: build cache is required, but could not be located: GOCACHE is not defined and $HOME is not defined

Usage:
  controller-gen [flags]

  ** USAGE INFO ELIDED **

run `controller-gen object:headerFile=/dev/null paths=./... -w` to see all available markers, or `controller-gen object:headerFile=/dev/null paths=./... -h` for usage
Target //operator failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 2.132s, Critical Path: 1.91s
INFO: 0 processes.
INFO: Build Event Protocol files produced successfully.
FAILED: Build did NOT complete successfully

I have also tried adding some environment variables to the genrule's cmd attribute, for instance:

cmd = "GOCACHE=$(rootpath @go_sdk//:bin/go) $(location ... which gives the error:

   Error: go [-e -json -compiled=true -test=false -export=false -deps=true -find=false -tags ignore_autogenerated -- ./...]: exit status 1: build cache is required, but could not be located: GOCACHE is not an absolute path

and cmd = "GOCACHE=/tmp/gocache $(location ... which gives a lot of compilation errors like:

external/go_sdk/src/cmd/go/internal/modcmd/edit.go:23:2: cannot find package "golang.org/x/mod/modfile" in any of:
        /usr/local/Cellar/go/1.15/libexec/src/golang.org/x/mod/modfile (from $GOROOT)
        ($GOPATH not set. For more details see: 'go help gopath')
ob commented 3 years ago

Looking around I found this go_genrule() in the kubernetes repository that is supposed to set up the Go toolchains so you can run them... Unfortunately it doesn't work either, I get:

ERROR: .../operator/api/v1alpha1/BUILD.bazel:31:11: error executing shell command: '/bin/bash -c bazel-out/host/bin/external/io_k8s_sigs_controller_tools/cmd/controller-gen/controller-gen_/controller-gen object paths=./...' failed (Exit 1) bash failed: error executing command /bin/bash -c 'bazel-out/host/bin/external/io_k8s_sigs_controller_tools/cmd/controller-gen/controller-gen_/controller-gen object paths=./...'

Use --sandbox_debug to see verbose messages from the sandbox
Error: go [-e -json -compiled=true -test=false -export=false -deps=true -find=false -tags ignore_autogenerated -- ./...]: exit status 2: go: GOPATH entry is relative; must be absolute path: "bazel-out/darwin-fastbuild/bin/operator/api/v1alpha1/gopath".
For more details see: 'go help gopath'
jayconrod commented 3 years ago

Sorry, this doesn't really seem like an issue with Gazelle or rules_go. The folks maintaining go_genrule may be able to help more.

Every go build command requires a build cache. The location of the cache is set with GOCACHE, though it can be derived from HOME if that's set. Neither is set by default for Bazel actions. In module mode, commands also require GOMODCACHE, to be set; that can be derived from GOPATH or HOME.

If you can avoid invoking the go command in a Bazel action that would be ideal. Having one build system shell out to another is always going to be a bit messy.

Also, consider writing a new Bazel rule instead. That will give you more control over the environment Feel free to open an issue in rules_go if you run into problems with that.