Live data from Hacker News

Go is portable, until it isn't

simpleobservability.com

21–30 of 138 posts

Re: Go is portable, until it isn't

#21
post #2

This seems to imply that Go's binaries are otherwise compatible with multiple platforms like amd64 and arm64, other than the issue with linking dynamic libraries. I suspect that's not true either even if it might be technically possible to achieve it through some trickery (and why not risc-v, and other architectures too?).

[deleted]

Re: Go is portable, until it isn't

#22
post #3

Earlier quoted context omitted.

Of course you still need one binary per CPU architecture. But when you rely on a dynamic link, you need to build from the same architecture as the target system. At that point cross-compiling stops being reliable.

Is it some tooling issue? Why is is an issue to cross-compile programs with dynamic linking?

In general, cross compilers can do dynamic linking.

Re: Go is portable, until it isn't

#23
post #9

I ran into this issue when porting term.everything[0] from typescript to go. I had some c library dependencies that I did need to link, so I had to use cgo. My solution was to do the build process on alpine linux[1] and use static linking[2]. This way it statically links musl libc, which is much friendlier with static linking than glibc. Now, I have a static binary that runs in alpine, Debian, and even bare container…

I didn't see an explanation in the README that part of what the first GIF[1] shows is an effect created by video editing software (and not a screencapture that's just demonstrating the program actually running). "Screen images simulated" are the words usually chosen to start off the disclaimers in fine print shown at the bottom of the screen when similar effects appear in commercials. I think that it would make sense to adopt a similar explanation wrt the effect used for the GIF.

1. https://github.com/mmulet/term.everything/blob/main/resource...>

Re: Go is portable, until it isn't

#24
post #22

Earlier quoted context omitted.

Is it some tooling issue? Why is is an issue to cross-compile programs with dynamic linking?

In general, cross compilers can do dynamic linking.

In my experience, the cross-compiler will refuse to link against shared libraries that "don't exist", which they usually don't in a cross compiler setup (e.g. cross compiling an aarch64 application that uses SDL on a ppc64le host with ppc64le SDL libraries)

The usual workaround, I think, is to use dlopen/dlsym from within the program. This is how the Nim language handles libraries in the general case: at compile time, C imports are converted into a block of dlopen/dl* calls, with compiler options for indicating some (or all) libraries should be passed to the linker instead, either for static or dynamic linking.

Alternatively I think you could "trick" the linker with a stub library just containing the symbol names it wants, but never tried that.

Re: Go is portable, until it isn't

#25
post #3

Earlier quoted context omitted.

Of course you still need one binary per CPU architecture. But when you rely on a dynamic link, you need to build from the same architecture as the target system. At that point cross-compiling stops being reliable.

Is it some tooling issue? Why is is an issue to cross-compile programs with dynamic linking?

It's a tooling issue. No one has done the work to make things work as smoothly as they could.

Traditionally, cross-compilers generally didn't even work the way that the Zig and Go toolchains approach it—achieving cross-compilation could be expected to be a much more trying process. The Zig folks and the Go folks broke with tradition by choosing to architect their compilers more sensibly for the 21st century, but the effects of the older convention remains.

Re: Go is portable, until it isn't

#26

Once you use CGO, portability is gone. Your binary is no longer staticly compiled. This can happen subtley without you knowing it. If you use a function in the standard library that happens to call into a CGO function, you are no longer static. This happens with things like os.UserHomeDir or some networking things like DNS lookups. You can "force" go to do static compiling by disabling CGO, but that means you can't u…

> This happens with things like os.UserHomeDir or some networking things like DNS lookups. The docs do not mention this CGO dependency, are you sure? https://pkg.go.dev/os#UserHomeDir

I was surprised too, that I had to check the docs, so I assume the user was misinformed.

Re: Go is portable, until it isn't

#27
post #19

You hit this real quick when trying to build container images from the scratch. Theoretically you can drop a Go binary into a blank rootfs and it will run. This works most of the time, but anything that depends on Go's Postgres client requires libpq which requires libc. Queue EFILE runtime errors after running the container.

> anything that depends on Go's Postgres client requires libpq which requires libc

Try https://github.com/lib/pq

Re: Go is portable, until it isn't

#28
post #15

Interesting that it uses the C API to collect journals. I would’ve thought to just invoke journalctl CLI. On platforms like macOS where the CLI doesn’t exist it’s an error when you exec, not a build time error.

That's really not such a weird choice. The systemd library is pervasive and compatible.

The weird bit is the analysis[1], which complains that a Go binary doesn't run on Alpine Linux, a system which is explicitly and intentionally (also IMHO ridiculously, but that's editorializing) binary-incompatible with the stable Linux C ABI as it's existed for almost three decades now. It's really no more "Linux" than is Android, for the same reason, and you don't complain that your Go binaries don't run there.

[1] I'll just skip without explaination how weird it was to see the author complain that the build breaks because they can't get systemd log output on... a mac.

Re: Go is portable, until it isn't

#30

Earlier quoted context omitted.

> This happens with things like os.UserHomeDir or some networking things like DNS lookups. The docs do not mention this CGO dependency, are you sure? https://pkg.go.dev/os#UserHomeDir

I was surprised too, that I had to check the docs, so I assume the user was misinformed.

Perhaps I misremembered or things changed? For instance, the os/user results in a dynamicly linked executable: https://play.golang.com/p/7QsmcjJI4H5

There are multiple standard library functions that do it.. I recall some in "net" and some in "os".

Post reply on HN