Hi Tianon, On Fri, Sep 12, 2025 at 04:21:58PM -0700, Tianon Gravi wrote: > Looking at this again, and I'm kind of concerned by how similar this > new script is to > https://salsa.debian.org/go-team/compiler/golang/-/blob/0b1574525525719281c84cfa55ec7ca7719be8d9/debian/helpers/goenv.sh > which we already maintain in the compiler packages -- I bet there's > some way we could make either the new script work for the > bootstrapping use case or better would be the other way around? That > raises the question of which source package the script should live in.
There is another angle here. The proposed wrappers need to work without using DEB_HOST_* environment variables as those are Debian-isms, but the wrappers are supposed to be outside package building. Effectively, we may avoid a dependency on dpkg-architecture at runtime by calling it at build time and recording the output. So instead of having one goenv.sh for all architectures, the script could be interpolated per architecture and included in an Arch:any package. The existing goenv.sh entry point may be kept for compatibility and may then forward to the appropriately interpolated script selecting it via its DEB_HOST_GNU_TYPE. So it's shuffling things around rather than increasing maintenance cost. But then when I talked to Mathias Gibbens in Brest, we basically agreed that compatibility with gccgo was a minor concern given that it is horribly outdated and that we might forget about those wrappers and have dh-golang handle the environment setup. Then turn things upside down and turn gccgo into a wrapper that reverses the process and turns GOARCH/GOOS/GO386/GOARM back into a GNU triplet to call the right gccgo executable when such a need arises (if ever). > I think it would be pretty reasonable/easy to split that script into > "things we need to set for bootstrapping" and "things we need to set > for cross-building with Go", especially given I just removed a bunch > of bootstrap-specific logic from it in my latest touching of it (while > making src:golang-X.Y itself cross-buildable). That gets us back to the question of where that script should live. Basically any go package (including the compiler itself), would have to transitively build-depend on this, so building this script should not require a go compiler (to avoid a cycle). golang-defaults might be a good fit here even though adding a binary package just for shipping a script may feel odd. > Maybe it does make sense to have a variant of that script that lives > in every src:golang-X.Y? I don't know, because there's very little in > it right now that's specific to a particular version of Go (although > it *has* had to have complicated logic that in the past, like when the > value for GO386 had to change, and getting it right across the > bootstrapping boundary was extra complicated). That is a good alternative to golang-defaults, because it avoids the aforementioned cycle and the duplication is limited to a few versions all maintained by the same people (making it feasible to keep the copies in sync). > Personally, I'm not very convinced by any gccgo compatibility, > especially since I don't think gccgo has kept/reasonably can keep up > with modern Go versions very well (and in the meantime, Go has gotten Seems like that's a consensus item then. > I also need to admit that I don't actually understand the need for so > many explicit package names -- is there some existing convention that > will automatically install the correct package based on existing > Build-Depends or something that warrants all this extra complexity? Over the years, we have introduced a convention to handle "cross toolchain dependency translation". Given a compiler supporting the convention (e.g. gcc or gfortran), you may annotate your Build-Depends as either COMPILER-for-build or COMPILER-for-host (both lacking :native and :any). In the latter case, you are expected to prefix all compiler invocations (even when building natively) with the GNU triplet (e.g. x86_64-linux-gnu-gcc) and then you get object files for the explicitly selected architecture. In the former case, you are expected to call the compiler without a prefix and then you get object files for some architecture that your CPU can actually execute without emulation. This typically is the architecture of the dpkg package, but it may change e.g. when cross grading. The big question now becomes what the Multi-Arch field of golang-VER-go should be. It presently is implicitly "no", but that means that you cannot depend on a runnable go compiler. Keep in mind that :native is not applicable to Depends. We may argue that it should be Multi-Arch: foreign. Doing is a quite lax interpretation of the proposed policy text, because it effectively means that invoking the go compiler without exporting GOARCH/GOOS and so on would not be a supported interface, but that's what is happening a lot presently. On the flip side, I see little use cases for actually requiring the Go compiler executable to have a particular architecture. Possibly, some packages cannot work with CGO, which is practically required for any kind of cross compilation and there we would want to force the Go compiler executable to be a host architecture one (thus requiring CPU emulation to run it). If that is a sensible use case, it should likely be Multi-Arch: allowed, but then we got to update every single source package changing golang-go to golang-go:native or golang-go:any (their effect is the same, but the former is more explicit in Build-Depends). Do you have an opinion here? I think the main two questions are: * Do we want to support selecting a Go compiler executable of a particular architecture? + If yes, it cannot be M-A:foreign. * Do we want to update the Build-Depends of every Go thing to enable cross compilation? + If no, it must be M-A:foreign. There is a slightly more complex scheme that may be easier on the consumer side: * Rename golang-VER-go to golang-VER-go-compiler (name TBD). * Mark the renamed golang-VER-go-compiler M-A:allowed. * Introduce a new, empyt Arch:any M-A:same package using the freed name golang-VER-go. It depends on golang-VER-go-compiler:any. * Move the golang-1.24-src dependency from golang-VER-go-compiler to golang-VER-go. * Do a similar thing in golang-defaults for golang-go. Then the many packages that presently depend on golang-go would get the native Go compiler. Many of them would cross build, because dh-golang already exports the right environment variables. Those that really do need a Go compiler executable for the host architecture (expected to be rare and incompatible with cross compilation) could additionally depend on golang-go-compiler (without :any or :native) to express this. This scheme would thus allow answering the two questions above as yes and no respectively. If going that more complex route, we may add the interpolated goenv.sh to the golang-VER-go package in an architecture-dependent path. Whether to incur this additional complexity depends on whether we anticipate any dependencies on a Go compiler executable of a particular architecture. We may also go for M-A:foreign without the shuffling now and do the shuffling later if such a need arises practically. Helmut

