index.html :: rss :: github :: telegram :: email

go+musl: building static binaries

08 Sep 2024

tldr: build command example, works on both Linux and macOS, CC and CXX wrappers are from musl package on both platfroms:

CC=x86_64-linux-musl-gcc \
    CXX=x86_64-linux-musl-g++ \
    GOARCH=amd64
    GOOS=linux
    CGO_ENABLED=1
    go build -o app \
    -ldflags "-linkmode external -extldflags -static" \
    ./cmd/main.go

Works perfectly to cross-compile sqlite apps.


Go code example:

package main

// #include <stdio.h>
// void helloworld() { printf("hello, world\n"); }
import "C"

import (
	"log"
	"net"
)

func main() {
	log.Println(net.LookupHost("google.com"))
	C.helloworld()
}

Building:

$ CC=/usr/local/musl/bin/musl-gcc go build --ldflags '-linkmode external -extldflags "-static"' hello.go
  1. use musl-gcc wrapper as a C compiler;

  2. set -linkmode external to always use the external linter;

  3. -extldflags "-static" passed -static to an external linker.

Checking produced binaries:

$ file hello
hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
$ ./hello
2015/06/22 06:01:40 [216.58.211.14 2a00:1450:4016:804::200e] <nil>
hello, world

source.