`go_binary` should create a binary with `name` by default
This is the behavior which one expects as this is basically what every other rule does, including the other language specific _binary ones.
Because of the edge case described in #2463, the default behavior was changed to output binaries at NAME_/NAME instead of just NAME.
go_binary already offers attributes basename and out to control the output but the default is unexpected and tailored towards an edge case. It would be better if one would only have to set those attributes in the edge case when using a sane default.
@fmeum @linzhp What do you think of this suggestion? This introduces a minor incompatibility, but the new behavior would be simpler, in line with what most users would expect and what other rulesets like rules_cc do.
There's a fairly simple workaround (set out or basename) for anyone affected. We could implement that in gazelle fix automatically.
I'm trying to remember the history of why it was this way without looking at the code. I think at some point in the distant past, Bazel discouraged setting the output executable name to be the same as the target name. I might be thinking of attr.output though.
Aesthetically, NAME_/NAME looks bad. Practically, it avoids the confusing errors that users (Go developers who knows nothing about Bazel) would see in #2463. Scripts that need the binary path should not guess Bazel's output path (which is considered implementation details) and instead rely on bazel cquery --output files (or bazel run --run_under echo for old bazel versions). However, I am pretty sure there are many scripts out there hard-coding the output path, which requires migrations.
gazelle fix for the edge cases would help, but I wonder if the development and migration effort has any benefit other than aesthetics. @mering ?
I'm torn. rules_go is definitely the odd one among the rulesets with its naming scheme, but given the subtle issues and the best practices that @linzhp mentioned, I don't know whether a breaking change would be warranted (even with Gazelle support).
It's also about the runfiles path to put into the runfiles libraries. They also need to use NAME_/NAME. Of course one can wrap every file using runfiles path in a custom rule to use to_rlocation_path(ctx, file) or pass them all as cmd parameter but this is often just very impractical. We are also migrating an huge existing code base, so it is a big amount of useless work, not even considering the effort to explain to colleagues why this works differently for go than for basically every other rule. This is one of the examples why people find Bazel difficult to use.
This feels like go_default_library to me: so named because //foo/bar:bar was expected to have the import path example.com/foo/bar/bar, but everyone actually expected example.com/foo/bar. Fixing that was worth it, though it did cause some small breaks.
I'm less confident about this. Changing the output file name would let people guess Bazel's output path: even though it's probably not a good idea for compatibility, running bazel query is hard for new users, and many people don't do it. The runfiles reason @mering mentioned is good to.
On the other hand, anyone who has hard-coded or guessed the path will be broken. It's harder to mitigate this with gazelle fix, since people might not upgrade at the same time. Maybe we should implement the gazelle fix half first, wait six months, then implement this?
It's harder to mitigate this with
gazelle fix, since people might not upgrade at the same time. Maybe we should implement thegazelle fixhalf first, wait six months, then implement this?
I agree with gazelle fix first but suggest to add a transition/flag to actively opt into the new behavior of rules_go for testing at the same time. After 3 months, one could flip the default of the transition leaving broken people the flag as immediate mitigation while they work towards the real fix. After another 3 months, one should remove the transition together with the old behavior.