build: add static linking support (#25492)
This adds support for building statically-linked executables using ci.go. Static linking is enabled by default in Docker builds, making it possible to use the geth executable in any Docker image, regardless of the Linux distribution the Dockerfile is based on. Co-authored-by: Felix Lange <fjl@twurst.com>
This commit is contained in:
parent
c4cd632f47
commit
c0cc6f6362
@ -14,7 +14,7 @@ COPY go.sum /go-ethereum/
|
||||
RUN cd /go-ethereum && go mod download
|
||||
|
||||
ADD . /go-ethereum
|
||||
RUN cd /go-ethereum && go run build/ci.go install ./cmd/geth
|
||||
RUN cd /go-ethereum && go run build/ci.go install -static ./cmd/geth
|
||||
|
||||
# Pull Geth into a second stage deploy alpine container
|
||||
FROM alpine:latest
|
||||
|
@ -14,7 +14,7 @@ COPY go.sum /go-ethereum/
|
||||
RUN cd /go-ethereum && go mod download
|
||||
|
||||
ADD . /go-ethereum
|
||||
RUN cd /go-ethereum && go run build/ci.go install
|
||||
RUN cd /go-ethereum && go run build/ci.go install -static
|
||||
|
||||
# Pull all binaries into a second stage deploy alpine container
|
||||
FROM alpine:latest
|
||||
|
25
build/ci.go
25
build/ci.go
@ -203,6 +203,7 @@ func doInstall(cmdline []string) {
|
||||
dlgo = flag.Bool("dlgo", false, "Download Go and build with it")
|
||||
arch = flag.String("arch", "", "Architecture to cross build for")
|
||||
cc = flag.String("cc", "", "C compiler to cross build with")
|
||||
staticlink = flag.Bool("static", false, "Create statically-linked executable")
|
||||
)
|
||||
flag.CommandLine.Parse(cmdline)
|
||||
|
||||
@ -213,9 +214,12 @@ func doInstall(cmdline []string) {
|
||||
tc.Root = build.DownloadGo(csdb, dlgoVersion)
|
||||
}
|
||||
|
||||
// Disable CLI markdown doc generation in release builds.
|
||||
buildTags := []string{"urfave_cli_no_docs"}
|
||||
|
||||
// Configure the build.
|
||||
env := build.Env()
|
||||
gobuild := tc.Go("build", buildFlags(env)...)
|
||||
gobuild := tc.Go("build", buildFlags(env, *staticlink, buildTags)...)
|
||||
|
||||
// arm64 CI builders are memory-constrained and can't handle concurrent builds,
|
||||
// better disable it. This check isn't the best, it should probably
|
||||
@ -224,9 +228,6 @@ func doInstall(cmdline []string) {
|
||||
gobuild.Args = append(gobuild.Args, "-p", "1")
|
||||
}
|
||||
|
||||
// Disable CLI markdown doc generation in release builds.
|
||||
gobuild.Args = append(gobuild.Args, "-tags", "urfave_cli_no_docs")
|
||||
|
||||
// We use -trimpath to avoid leaking local paths into the built executables.
|
||||
gobuild.Args = append(gobuild.Args, "-trimpath")
|
||||
|
||||
@ -251,7 +252,7 @@ func doInstall(cmdline []string) {
|
||||
}
|
||||
|
||||
// buildFlags returns the go tool flags for building.
|
||||
func buildFlags(env build.Environment) (flags []string) {
|
||||
func buildFlags(env build.Environment, staticLinking bool, buildTags []string) (flags []string) {
|
||||
var ld []string
|
||||
if env.Commit != "" {
|
||||
ld = append(ld, "-X", "main.gitCommit="+env.Commit)
|
||||
@ -262,14 +263,24 @@ func buildFlags(env build.Environment) (flags []string) {
|
||||
if runtime.GOOS == "darwin" {
|
||||
ld = append(ld, "-s")
|
||||
}
|
||||
if runtime.GOOS == "linux" {
|
||||
// Enforce the stacksize to 8M, which is the case on most platforms apart from
|
||||
// alpine Linux.
|
||||
if runtime.GOOS == "linux" {
|
||||
ld = append(ld, "-extldflags", "-Wl,-z,stack-size=0x800000")
|
||||
extld := []string{"-Wl,-z,stack-size=0x800000"}
|
||||
if staticLinking {
|
||||
extld = append(extld, "-static")
|
||||
// Under static linking, use of certain glibc features must be
|
||||
// disabled to avoid shared library dependencies.
|
||||
buildTags = append(buildTags, "osusergo", "netgo")
|
||||
}
|
||||
ld = append(ld, "-extldflags", "'"+strings.Join(extld, " ")+"'")
|
||||
}
|
||||
if len(ld) > 0 {
|
||||
flags = append(flags, "-ldflags", strings.Join(ld, " "))
|
||||
}
|
||||
if len(buildTags) > 0 {
|
||||
flags = append(flags, "-tags", strings.Join(buildTags, ","))
|
||||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@ import (
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
@ -39,7 +40,7 @@ var DryRunFlag = flag.Bool("n", false, "dry run, don't execute commands")
|
||||
// MustRun executes the given command and exits the host process for
|
||||
// any error.
|
||||
func MustRun(cmd *exec.Cmd) {
|
||||
fmt.Println(">>>", strings.Join(cmd.Args, " "))
|
||||
fmt.Println(">>>", printArgs(cmd.Args))
|
||||
if !*DryRunFlag {
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdout = os.Stdout
|
||||
@ -49,6 +50,20 @@ func MustRun(cmd *exec.Cmd) {
|
||||
}
|
||||
}
|
||||
|
||||
func printArgs(args []string) string {
|
||||
var s strings.Builder
|
||||
for i, arg := range args {
|
||||
if i > 0 {
|
||||
s.WriteByte(' ')
|
||||
}
|
||||
if strings.IndexByte(arg, ' ') >= 0 {
|
||||
arg = strconv.QuoteToASCII(arg)
|
||||
}
|
||||
s.WriteString(arg)
|
||||
}
|
||||
return s.String()
|
||||
}
|
||||
|
||||
func MustRunCommand(cmd string, args ...string) {
|
||||
MustRun(exec.Command(cmd, args...))
|
||||
}
|
||||
@ -121,7 +136,7 @@ func UploadSFTP(identityFile, host, dir string, files []string) error {
|
||||
sftp.Args = append(sftp.Args, "-i", identityFile)
|
||||
}
|
||||
sftp.Args = append(sftp.Args, host)
|
||||
fmt.Println(">>>", strings.Join(sftp.Args, " "))
|
||||
fmt.Println(">>>", printArgs(sftp.Args))
|
||||
if *DryRunFlag {
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user