[HN Gopher] Building Statically Linked Go Executables with CGO a...
       ___________________________________________________________________
        
       Building Statically Linked Go Executables with CGO and Zig
        
       Author : todsacerdoti
       Score  : 91 points
       Date   : 2025-03-28 14:11 UTC (8 hours ago)
        
 (HTM) web link (calabro.io)
 (TXT) w3m dump (calabro.io)
        
       | HenriTEL wrote:
       | All the magic seems to happen in                   const lib =
       | b.addLibrary(.{             .linkage = .static,             .name
       | = "cgo_static_linking",             .root_module = lib_mod,
       | });
       | 
       | and
       | 
       | /* #cgo LDFLAGS: -L./zig-out/lib -lcgo_static_linking -static
       | #include "zig_lib.h" */
       | 
       | Now I can only guess why it works. A bit of an explanation
       | wouldn't hurt. Good post btw
        
         | nasretdinov wrote:
         | Most of the magic is due to two things: 1. Zig comes with clang
         | and musl (C library) for lots of architectures, so can be used
         | for cross-compiling, even for non-Zig projects since clang can
         | build C/C++ no problem 2. Musl is designed to be compatible
         | with static linking (glibc is not), so it's the natural choice
         | here too
        
         | MawKKe wrote:
         | Zig builds a statically linked library called
         | "cgo_static_linking" from Zig sources. Zig places the artifact
         | into "./zig-out/lib/cgo_static_linking.a" (or maybe some other
         | extension). The library is exported with C ABI, which Go (cgo)
         | compiler supports.
         | 
         | The #cgo line tells the Go compiler to add custom compilation
         | flags: -l flag tells the compiler that you wish to link to a
         | library called "cgo_static_linking" in to the binary. However,
         | the cgo compiler can't find it since it is not in the default
         | search paths for libraries. The -L option extends the library
         | search path to "./zig-out/lib/", allowing "cgo_static_linking"
         | to be found.
         | 
         | The "#include" line inserts the header file contents as-is into
         | the source file (main.go), bringing the definition of the
         | function available to the compiler. The compiler is then able
         | to compile the Go source, and later link it with the other
         | build artifacts to produce the final executable.
         | 
         | The key here is the "C ABI" which acts as common ground for
         | both languages. The rest is just scaffolding to let the
         | compilers find and connect appropriate files together.
        
       | bat_sy wrote:
       | Hi HN, I tried doing this 2 days ago for AWS lambda arm64
       | runners. And it did not work. Has anyone successfully built a
       | statically linked golang binary arm64 runners in Lambda?
       | 
       | Thanks in advance.
        
       | Laremere wrote:
       | This post seems to be missing an additional opportunity: Zig's
       | build can involve go build! Use Build.addSystemCommand, have it
       | depend on library step, and have the install step depend on that
       | step. This reduces the steps to build to just 'zig build'
        
         | jcalabro wrote:
         | zigception!
        
         | silisili wrote:
         | Do you by chance have a link to a working example of this?
         | Sounds interesting...
        
       | karel-3d wrote:
       | what is the upside for this rather than just building cgo with
       | musl? what does zig add?
        
         | nasretdinov wrote:
         | Zig allows you to cross-compile as easily as Go does. Setting
         | up cross-compilation toolchain otherwise is quite painful
        
           | karel-3d wrote:
           | ah okay.
           | 
           | I was building with cgo+musl before and it was not complex at
           | all, but yeah I didn't think about cross-compiling.
        
       | bradfitz wrote:
       | We tried this a few years back with a very loaded Go server using
       | SQLite (actual C SQLite, not modernc.org/sqlite) and something
       | made performance tank... likely some difference between glibc and
       | musl. We never had time to hunt it down. We talked to Zig folk
       | about sponsoring them to work on it, making performance
       | comparable to glibc-built-SQLite, but they were busy at the time.
        
         | raggi wrote:
         | it was the intrinsics, sometime ago zig "imported" compiler-rt
         | and wrote pure-zig variants that are lacking machine level
         | optimizations and a lot of vectorization and so on. SQLite
         | performance is highly dependent on them.
        
       ___________________________________________________________________
       (page generated 2025-03-28 23:00 UTC)