From 11c5cedfe325ab6f65006b1e449131889aec0d16 Mon Sep 17 00:00:00 2001 From: 0xe3b0c4 <0xe3b0c4@proton.me> Date: Mon, 8 Aug 2022 15:08:59 +0800 Subject: [PATCH 1/6] static linking (improve from #17247) --- Dockerfile | 2 +- Dockerfile.alltools | 2 +- build/ci.go | 16 ++++++++++++---- internal/build/env.go | 9 +++++++-- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/Dockerfile b/Dockerfile index 70299190f90f5..143c92f27f505 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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 diff --git a/Dockerfile.alltools b/Dockerfile.alltools index b11492cabc9c0..176c4592206d5 100644 --- a/Dockerfile.alltools +++ b/Dockerfile.alltools @@ -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 diff --git a/build/ci.go b/build/ci.go index 526e76f38132c..86491ab962bd3 100644 --- a/build/ci.go +++ b/build/ci.go @@ -200,9 +200,10 @@ func main() { func doInstall(cmdline []string) { var ( - 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") + 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, "Static link build with") ) flag.CommandLine.Parse(cmdline) @@ -215,6 +216,9 @@ func doInstall(cmdline []string) { // Configure the build. env := build.Env() + if *staticlink { + env.StaticLink = true + } gobuild := tc.Go("build", buildFlags(env)...) // arm64 CI builders are memory-constrained and can't handle concurrent builds, @@ -265,7 +269,11 @@ func buildFlags(env build.Environment) (flags []string) { // 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") + staticlinkflag := "" + if env.StaticLink { + staticlinkflag = "-static" + } + ld = append(ld, "-extldflags", fmt.Sprintf("'-Wl,-z,stack-size=0x800000 %s'", staticlinkflag)) } if len(ld) > 0 { flags = append(flags, "-ldflags", strings.Join(ld, " ")) diff --git a/internal/build/env.go b/internal/build/env.go index d70c0d50a4999..714aa3d6c566b 100644 --- a/internal/build/env.go +++ b/internal/build/env.go @@ -34,6 +34,7 @@ var ( BuildnumFlag = flag.String("buildnum", "", `Overrides CI build number`) PullRequestFlag = flag.Bool("pull-request", false, `Overrides pull request status of the build`) CronJobFlag = flag.Bool("cron-job", false, `Overrides cron job status of the build`) + StaticLink = flag.Bool("static-link", false, `Overrides static link status of the build`) ) // Environment contains metadata provided by the build environment. @@ -45,11 +46,12 @@ type Environment struct { Buildnum string IsPullRequest bool IsCronJob bool + StaticLink bool } func (env Environment) String() string { - return fmt.Sprintf("%s env (commit:%s date:%s branch:%s tag:%s buildnum:%s pr:%t)", - env.Name, env.Commit, env.Date, env.Branch, env.Tag, env.Buildnum, env.IsPullRequest) + return fmt.Sprintf("%s env (commit:%s date:%s branch:%s tag:%s buildnum:%s pr:%t static:%t)", + env.Name, env.Commit, env.Date, env.Branch, env.Tag, env.Buildnum, env.IsPullRequest, env.StaticLink) } // Env returns metadata about the current CI environment, falling back to LocalEnv @@ -168,5 +170,8 @@ func applyEnvFlags(env Environment) Environment { if *CronJobFlag { env.IsCronJob = true } + if *StaticLink { + env.StaticLink = true + } return env } From ce1e267519824a256c21bdf5b8f0d21e7dfa1fc0 Mon Sep 17 00:00:00 2001 From: 0xe3b0c4 <0xe3b0c4@proton.me> Date: Mon, 8 Aug 2022 17:30:30 +0800 Subject: [PATCH 2/6] remove StaticLink flag from Environment --- build/ci.go | 9 +++------ internal/build/env.go | 9 ++------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/build/ci.go b/build/ci.go index 86491ab962bd3..7d324b5df7872 100644 --- a/build/ci.go +++ b/build/ci.go @@ -216,10 +216,7 @@ func doInstall(cmdline []string) { // Configure the build. env := build.Env() - if *staticlink { - env.StaticLink = true - } - gobuild := tc.Go("build", buildFlags(env)...) + gobuild := tc.Go("build", buildFlags(env, *staticlink)...) // arm64 CI builders are memory-constrained and can't handle concurrent builds, // better disable it. This check isn't the best, it should probably @@ -255,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, staticlink bool) (flags []string) { var ld []string if env.Commit != "" { ld = append(ld, "-X", "main.gitCommit="+env.Commit) @@ -270,7 +267,7 @@ func buildFlags(env build.Environment) (flags []string) { // alpine Linux. if runtime.GOOS == "linux" { staticlinkflag := "" - if env.StaticLink { + if staticlink { staticlinkflag = "-static" } ld = append(ld, "-extldflags", fmt.Sprintf("'-Wl,-z,stack-size=0x800000 %s'", staticlinkflag)) diff --git a/internal/build/env.go b/internal/build/env.go index 714aa3d6c566b..d70c0d50a4999 100644 --- a/internal/build/env.go +++ b/internal/build/env.go @@ -34,7 +34,6 @@ var ( BuildnumFlag = flag.String("buildnum", "", `Overrides CI build number`) PullRequestFlag = flag.Bool("pull-request", false, `Overrides pull request status of the build`) CronJobFlag = flag.Bool("cron-job", false, `Overrides cron job status of the build`) - StaticLink = flag.Bool("static-link", false, `Overrides static link status of the build`) ) // Environment contains metadata provided by the build environment. @@ -46,12 +45,11 @@ type Environment struct { Buildnum string IsPullRequest bool IsCronJob bool - StaticLink bool } func (env Environment) String() string { - return fmt.Sprintf("%s env (commit:%s date:%s branch:%s tag:%s buildnum:%s pr:%t static:%t)", - env.Name, env.Commit, env.Date, env.Branch, env.Tag, env.Buildnum, env.IsPullRequest, env.StaticLink) + return fmt.Sprintf("%s env (commit:%s date:%s branch:%s tag:%s buildnum:%s pr:%t)", + env.Name, env.Commit, env.Date, env.Branch, env.Tag, env.Buildnum, env.IsPullRequest) } // Env returns metadata about the current CI environment, falling back to LocalEnv @@ -170,8 +168,5 @@ func applyEnvFlags(env Environment) Environment { if *CronJobFlag { env.IsCronJob = true } - if *StaticLink { - env.StaticLink = true - } return env } From 6d96af57757d2365d2f52d4e29af38f9f964947b Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 9 Aug 2022 01:00:11 +0200 Subject: [PATCH 3/6] Update ci.go --- build/ci.go | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/build/ci.go b/build/ci.go index 7d324b5df7872..05da8ef0453d8 100644 --- a/build/ci.go +++ b/build/ci.go @@ -214,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, *staticlink)...) + env := build.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 @@ -225,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") @@ -252,7 +252,7 @@ func doInstall(cmdline []string) { } // buildFlags returns the go tool flags for building. -func buildFlags(env build.Environment, staticlink bool) (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) @@ -263,18 +263,25 @@ func buildFlags(env build.Environment, staticlink bool) (flags []string) { if runtime.GOOS == "darwin" { ld = append(ld, "-s") } - // Enforce the stacksize to 8M, which is the case on most platforms apart from - // alpine Linux. if runtime.GOOS == "linux" { - staticlinkflag := "" - if staticlink { - staticlinkflag = "-static" + staticflag := "" + if staticLinking { + staticflag = " -static" + // Under static linking, use of certain glibc features must be + // disable to avoid shared library dependencies. + buildTags = append(buildTags, "osusergo", "netgo") } - ld = append(ld, "-extldflags", fmt.Sprintf("'-Wl,-z,stack-size=0x800000 %s'", staticlinkflag)) + // Enforce the stacksize to 8M, which is the case on most platforms apart from + // alpine Linux. + extflag := "'-Wl,-z,stack-size=0x800000" + staticflag + "'" + ld = append(ld, "-extldflags", extflag) } if len(ld) > 0 { flags = append(flags, "-ldflags", strings.Join(ld, " ")) } + + // Set build tags. + flags = append(flags, "-tags", strings.Join(buildTags, ",")) return flags } From 0ac7239f8dd78624132b09059207b65c3986ff29 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 9 Aug 2022 01:13:19 +0200 Subject: [PATCH 4/6] Update ci.go --- build/ci.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build/ci.go b/build/ci.go index 05da8ef0453d8..1763454d3be52 100644 --- a/build/ci.go +++ b/build/ci.go @@ -218,7 +218,7 @@ func doInstall(cmdline []string) { buildTags := []string{"urfave_cli_no_docs"} // Configure the build. - env := build.Env() + env := build.Env() gobuild := tc.Go("build", buildFlags(env, *staticlink, buildTags)...) // arm64 CI builders are memory-constrained and can't handle concurrent builds, @@ -268,7 +268,7 @@ func buildFlags(env build.Environment, staticLinking bool, buildTags []string) ( if staticLinking { staticflag = " -static" // Under static linking, use of certain glibc features must be - // disable to avoid shared library dependencies. + // disabled to avoid shared library dependencies. buildTags = append(buildTags, "osusergo", "netgo") } // Enforce the stacksize to 8M, which is the case on most platforms apart from @@ -279,9 +279,9 @@ func buildFlags(env build.Environment, staticLinking bool, buildTags []string) ( if len(ld) > 0 { flags = append(flags, "-ldflags", strings.Join(ld, " ")) } - - // Set build tags. - flags = append(flags, "-tags", strings.Join(buildTags, ",")) + if len(buildTags) > 0 { + flags = append(flags, "-tags", strings.Join(buildTags, ",")) + } return flags } From 26601961f9e42117acb916a46d5d77a359232e23 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 9 Aug 2022 10:45:19 +0000 Subject: [PATCH 5/6] build: clean up ldflags handling --- build/ci.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/build/ci.go b/build/ci.go index 1763454d3be52..f91de328bebc2 100644 --- a/build/ci.go +++ b/build/ci.go @@ -203,7 +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, "Static link build with") + staticlink = flag.Bool("static", false, "Create statically-linked executable") ) flag.CommandLine.Parse(cmdline) @@ -264,17 +264,16 @@ func buildFlags(env build.Environment, staticLinking bool, buildTags []string) ( ld = append(ld, "-s") } if runtime.GOOS == "linux" { - staticflag := "" + // Enforce the stacksize to 8M, which is the case on most platforms apart from + // alpine Linux. + extld := []string{"-Wl,-z,stack-size=0x800000"} if staticLinking { - staticflag = " -static" + 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") } - // Enforce the stacksize to 8M, which is the case on most platforms apart from - // alpine Linux. - extflag := "'-Wl,-z,stack-size=0x800000" + staticflag + "'" - ld = append(ld, "-extldflags", extflag) + ld = append(ld, "-extldflags", "'"+strings.Join(extld, " ")+"'") } if len(ld) > 0 { flags = append(flags, "-ldflags", strings.Join(ld, " ")) From 41f64dcc704e53c440a0d0617ba4e711f07d935d Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 9 Aug 2022 10:45:38 +0000 Subject: [PATCH 6/6] internal/build: escape printed command-line args --- internal/build/util.go | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/internal/build/util.go b/internal/build/util.go index 654349fac307c..9a721e9b83b16 100644 --- a/internal/build/util.go +++ b/internal/build/util.go @@ -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 }