rules_go icon indicating copy to clipboard operation
rules_go copied to clipboard

How to cross compile to a different libc implementation?

Open popovicu opened this issue 1 year ago • 4 comments

What version of rules_go are you using?

0.46.0

What version of gazelle are you using?

0.35.0

What version of Bazel are you using?

Bazelisk version: v1.19.0

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

Yes

What operating system and processor architecture are you using?

Linux x86_64

Any other potentially useful information about your toolchain?

No

What did you do?

go_binary(
    name = "myprogram",
    srcs = [
        "myprogram.go",
    ],
    deps = [
       ...
    ],
    static = "on",
    cgo=False,
)

go_cross_binary(
    name = "myprogram_rpi0",
    platform = "//platforms:rpi0_linux",
    target = ":myprogram",
)

I want to deploy my binary on a Raspberry Pi Zero and when I just build the myprogram target, I se these warnings:

/tmp/go-link-2058405138/000004.o:cgo_unix_cgo.cgo2.c:function _cgo_97ab22c4dc7b_C2func_getaddrinfo: warning: Using 'getaddrin
fo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking       
/tmp/go-link-2058405138/000004.o:cgo_unix_cgo.cgo2.c:function _cgo_97ab22c4dc7b_Cfunc_getaddrinfo: warning: Using 'getaddrinf
o' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

My Raspberry Pi Zero platform is defined like this:

platform(
    name = "rpi0_linux",
    constraint_values = [
        "@platforms//os:linux",
        "@platforms//cpu:armv7",
        "@rules_go//go/toolchain:cgo_off",
        "@rules_go//go/constraints/arm:5",
    ],
)

Ultimately, I will want to have musl libc implementation on my Raspberry Pi Zero. How can I avoid the assumption that the libc implementation is GNU on my target platform when cross compiling?

What did you expect to see?

I don't want to see glibc warnings in my build.

What did you see instead?

glibc-related warnings. I understand that static compilation still has some dynamic linking involved in the final product, but this build assumes glibc on the target, I wouldn't want it to do that.

popovicu avatar Aug 05 '24 05:08 popovicu

Are you also seeing these warnings with a non-Bazel Go build? It would be very helpful to see and compare the exact command lines the Bazel build and the Go build run.

fmeum avatar Aug 05 '24 07:08 fmeum

Hm, this project has grown quite a bit in size and it's very Bazel-centric. Is there any set of CLI flags I can pass to get some debug info? It would be hard to simply rebuild using plain Go.

That said, is it possible for Go to cross compile to another libc at all? What I find in other forums is that it's very centered towards the host's libc implementation.

LLVM/clang on the other hand can cross compile between libcs.

popovicu avatar Aug 05 '24 17:08 popovicu

You could override Go rules with local_repository or local_path_override and flip this flag in code: https://github.com/bazelbuild/rules_go/blob/6f206adcc9c2527a411a002669db1b7efafbeae8/go/tools/builders/env.go#L76

Together with --subcommands, this should allow you to see all compilation commands, including compiler and linker invocations.

fmeum avatar Aug 09 '24 10:08 fmeum

Thanks for sharing this tip, @fmeum! It's really helpful. Just wondering, do you know if this is documented somewhere? I think it would be useful to add to the docs, if not. I was considering raising a PR for this.

Wanted to add, to test locally I thought a patch would be simpler, so in case it helps, here's an example:

├── patches
│   ├── BUILD.bazel (empty)
│   └── verbose.patch
├── BUILD.bazel
├── MODULE.bazel

MODULE.bazel

bazel_dep(name = "rules_go", version = "0.49.0")
single_version_override(
    module_name = "rules_go",
    patch_strip = 1,
    patches = ["//patches:verbose.patch"],
    version = "0.49.0",
)

verbose.patch

diff --git a/go/tools/builders/env.go b/go/tools/builders/env.go
index bb01ac20..8f70fff5 100644
--- a/go/tools/builders/env.go
+++ b/go/tools/builders/env.go
@@ -75,7 +75,7 @@ func envFlags(flags *flag.FlagSet) *env {
 	flags.StringVar(&env.goroot, "goroot", "", "The value to set for GOROOT.")
 	flags.Var(&tagFlag{}, "tags", "List of build tags considered true.")
 	flags.StringVar(&env.installSuffix, "installsuffix", "", "Standard library under GOROOT/pkg")
-	flags.BoolVar(&env.verbose, "v", false, "Whether subprocess command lines should be printed")
+	flags.BoolVar(&env.verbose, "v", true, "Whether subprocess command lines should be printed")
 	flags.BoolVar(&env.shouldPreserveWorkDir, "work", false, "if true, the temporary work directory will be preserved")
 	return env
 }

For reference: https://sourcegraph.com/github.com/bazelbuild/examples/-/blob/bzlmod/02-override_bazel_module/MODULE.bazel?L26 // https://github.com/bazelbuild/examples/blob/main/bzlmod/02-override_bazel_module/MODULE.bazel#L26

albertocavalcante avatar Aug 14 '24 08:08 albertocavalcante