bazelbuild/rules_go

Per-arch_target linker flags

motiejus opened this issue · 3 comments

Background

I am writing a zig-bazed C++ toolchain for rules_go to (cross-)compile cgo (background here and here). Primary reason: the full toolchain is <40MB and supports many target OSes and architectures, and foregoes the requirement of a host C compiler.

A prototype works well for Linux targets, but requires additional flags for Darwin:

go_binary(
    name = "gognu",
    embed = [":go_lib"],
    gc_linkopts = select({
        "@platforms//os:macos": ["-s", "-w", "-buildmode=pie"],
        "//conditions:default": [],
    }),
    visibility = ["//visibility:public"],
)

Problem: these flags are required for every go_binary that may compile to macos. There are thousands of go_binary targets in our go repository. Since this is intended to be used company-wide, these extra flags should be instantiated in a single place, ideally, when instantiating rules_go repository.

What did you expect to see?

I would like to specify default gc_linkopts for all go_binary targets that target @platforms//os:macos somewhere when instantiating the toolchain.

  1. Can this be done? I am still quite new to rules_go, so I may have missed a knob.
  2. If it can't be done now, would you accept a patch that enables this? If yes, I would appreciate a pointer on the "best place" where/how this should be configured.

Some links

Full target here. For more background about the flags for Darwin see here: ziglang/zig#9050 (comment)

What version of rules_go are you using?

0.26

What version of gazelle are you using?

0.23

What version of Bazel are you using?

4.1.0

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

Yes

What operating system and processor architecture are you using?

x86_64-linux

I think it's easier to do in Gazelle than in rules_go. You can write a macro called go_binary that wraps the original go_binary and add gc_linkopts, then patch Gazelle to generate the load statement to load the macro instead.

Maybe we can add a Gazelle directive that can customize the load statement for go_binary?

I think it's easier to do in Gazelle than in rules_go. You can write a macro called go_binary that wraps the original go_binary and add gc_linkopts, then patch Gazelle to generate the load statement to load the macro instead.

I like your idea, as long as we don't have to carry a patch in gazelle. Given that ...

Maybe we can add a Gazelle directive that can customize the load statement for go_binary?

go_toolchain has link_flags and cgo_link_flags, which are a step towards the right direction, though unreachable when registering a toolchain for a specific arch.

Can these (and gc_linkopts) be exposed to the macros that register the toolchains?

Gazelle is definitely the easiest way, and there are other benefits by using a macro instead of go_binary directly. We also have a sizable Go codebase and use this Gazelle directive at the root:

  # gazelle:map_kind go_binary go_deployable //tools/go:def.bzl

Then Gazelle creates go_deployable rules instead, which for us also defines a container image. No fork is necessary. You are welcome to use a macro named go_binary too, of course.

I think that should work well for you, but please feel free to reopen if not. I'm also happy to review a PR adding those knobs to go_toolchain.. that does not seem too objectionable. Thanks