Skip to content

Commit

Permalink
Use ghcr.io/goreleaser/goreleaser-cross as an image for the go build …
Browse files Browse the repository at this point in the history
…in the docker (#415)

* Use ghcr.io/goreleaser/goreleaser-cross as an image for the go build in the docker

* Use ghcr.io/goreleaser/goreleaser-cross image
* Update the build config to allow the passing of tags,ldFlags and docker volumes
* Remove redundant code
* Add muslcc tool
  • Loading branch information
dzmitryhil authored Jun 14, 2024
1 parent afb494a commit cf038db
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 149 deletions.
7 changes: 0 additions & 7 deletions build/golang/Dockerfile.tmpl

This file was deleted.

159 changes: 51 additions & 108 deletions build/golang/go.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (
"bytes"
"context"
"crypto/rand"
"crypto/sha256"
_ "embed"
"encoding/hex"
"encoding/json"
"fmt"
Expand All @@ -17,7 +15,6 @@ import (
"regexp"
"runtime"
"strings"
"text/template"

"github.com/pkg/errors"
"go.uber.org/zap"
Expand All @@ -32,29 +29,37 @@ import (
)

const (
repoPath = "."
goAlpineVersion = "3.18"
repoPath = "."
)

// BinaryBuildConfig is the configuration for `go build`.
type BinaryBuildConfig struct {
// TargetPlatform is the platform to build the binary for
// TargetPlatform is the platform to build the binary for.
TargetPlatform tools.TargetPlatform

// PackagePath is the path to package to build relative to the ModulePath
// PackagePath is the path to package to build relative to the ModulePath.
PackagePath string

// BinOutputPath is the path for compiled binary file
// BinOutputPath is the path for compiled binary file.
BinOutputPath string

// CGOEnabled builds cgo binary
// CGOEnabled builds cgo binary.
CGOEnabled bool

// Flags is a slice of additional flags to pass to `go build`. E.g -cover, -compiler, -ldflags=... etc.
// Tags is go build tags.
Tags []string

// Flags is a slice of additional ldflags to pass to `go build`. E.g -w, -s ... etc.
LDFlags []string

// Flags is a slice of additional flags to pass to `go build`. E.g -cover, -compiler ... etc.
Flags []string

// Envs is a slice of additional environment variables to pass to `go build`.
Envs []string

// DockerVolumes list of the volumes to use for the docker build.
DockerVolumes []string
}

// TestConfig is the configuration for `go test -c`.
Expand Down Expand Up @@ -104,6 +109,10 @@ func Build(ctx context.Context, deps types.DepsFunc, config BinaryBuildConfig) e
}

func buildLocally(ctx context.Context, config BinaryBuildConfig) error {
if len(config.DockerVolumes) != 0 {
return errors.New("the usage of the `DockerVolumes` config is prohibited for the local build")
}

if config.TargetPlatform != tools.TargetPlatformLocal {
return errors.Errorf("building requested for platform %s while only %s is supported",
config.TargetPlatform, tools.TargetPlatformLocal)
Expand All @@ -113,7 +122,7 @@ func buildLocally(ctx context.Context, config BinaryBuildConfig) error {
if err := os.MkdirAll(libDir, 0o700); err != nil {
return errors.WithStack(err)
}
args, envs, err := buildArgsAndEnvs(ctx, config, libDir)
args, envs, err := buildArgsAndEnvs(config, libDir)
if err != nil {
return err
}
Expand Down Expand Up @@ -152,11 +161,14 @@ func buildInDocker(ctx context.Context, config BinaryBuildConfig) error {
return err
}

image, err := ensureBuildDockerImage(ctx)
goTool, err := tools.Get(tools.Go)
if err != nil {
return err
}

// use goreleaser-cross with pre-installed cross-compilers
image := fmt.Sprintf("ghcr.io/goreleaser/goreleaser-cross:v%s", goTool.GetVersion())

srcDir := must.String(filepath.Abs(".."))
dockerRepoDir := filepath.Join("/src", filepath.Base(modulePath)+"-tmp")

Expand All @@ -180,7 +192,7 @@ func buildInDocker(ctx context.Context, config BinaryBuildConfig) error {
return errors.WithStack(err)
}

args, envs, err := buildArgsAndEnvs(ctx, config, filepath.Join("/crust-cache", tools.Version(), "lib"))
args, envs, err := buildArgsAndEnvs(config, filepath.Join("/crust-cache", tools.Version(), "lib"))
if err != nil {
return err
}
Expand All @@ -197,22 +209,17 @@ func buildInDocker(ctx context.Context, config BinaryBuildConfig) error {
"--workdir", workDir,
"--user", fmt.Sprintf("%d:%d", os.Getuid(), os.Getgid()),
"--name", "crust-build-" + filepath.Base(config.PackagePath) + "-" + hex.EncodeToString(nameSuffix),
"--entrypoint", "go", // override default goreleaser
}
if config.CGOEnabled &&
tools.TargetPlatformLocal == tools.TargetPlatformLinuxAMD64 &&
config.TargetPlatform == tools.TargetPlatformLinuxARM64InDocker {
crossCompilerPath := filepath.Dir(
filepath.Dir(tools.Path("bin/aarch64-linux-musl-gcc", tools.TargetPlatformLinuxAMD64InDocker)),
)
libWasmVMPath := tools.Path("lib/libwasmvm_muslc.a", tools.TargetPlatformLinuxARM64InDocker)
runArgs = append(runArgs,
"-v", crossCompilerPath+":/aarch64-linux-musl-cross",
"-v", libWasmVMPath+":/aarch64-linux-musl-cross/aarch64-linux-musl/lib/libwasmvm_muslc.a",
)
}

for _, env := range envs {
runArgs = append(runArgs, "--env", env)
}

for _, v := range config.DockerVolumes {
runArgs = append(runArgs, "-v", v)
}

runArgs = append(runArgs, image)
runArgs = append(runArgs, args...)
runArgs = append(runArgs, "-o", filepath.Join("/out", filepath.Base(config.BinOutputPath)), ".")
Expand Down Expand Up @@ -250,94 +257,37 @@ func RunTests(ctx context.Context, deps types.DepsFunc, config TestConfig) error
return nil
}

//go:embed Dockerfile.tmpl
var dockerfileTemplate string

var dockerfileTemplateParsed = template.Must(template.New("Dockerfile").Parse(dockerfileTemplate))

func ensureBuildDockerImage(ctx context.Context) (string, error) {
goTool, err := tools.Get(tools.Go)
if err != nil {
return "", err
}
dockerfileBuf := &bytes.Buffer{}
err = dockerfileTemplateParsed.Execute(dockerfileBuf, struct {
GOVersion string
AlpineVersion string
}{
GOVersion: goTool.GetVersion(),
AlpineVersion: goAlpineVersion,
})
if err != nil {
return "", errors.Wrap(err, "executing Dockerfile template failed")
}
dockerfileChecksum := sha256.Sum256(dockerfileBuf.Bytes())
image := "crust-go-build:" + hex.EncodeToString(dockerfileChecksum[:4])

imageBuf := &bytes.Buffer{}
imageCmd := exec.Command("docker", "images", "-q", image)
imageCmd.Stdout = imageBuf
if err := libexec.Exec(ctx, imageCmd); err != nil {
return "", errors.Wrapf(err, "failed to list image '%s'", image)
}
if imageBuf.Len() > 0 {
return image, nil
}

buildCmd := exec.Command(
"docker",
"build",
"--label", docker.LabelKey+"="+docker.LabelValue,
"--tag", image,
"--tag", "crust-go-build:latest",
"-",
)
buildCmd.Stdin = dockerfileBuf

if err := libexec.Exec(ctx, buildCmd); err != nil {
return "", errors.Wrapf(err, "failed to build image '%s'", image)
}
return image, nil
}

func buildArgsAndEnvs(
ctx context.Context,
config BinaryBuildConfig,
libDir string,
) (args, envs []string, err error) {
var crossCompileARM64 bool

switch config.TargetPlatform {
case tools.TargetPlatformLocal,
tools.TargetPlatformLinuxLocalArchInDocker,
tools.TargetPlatformDarwinAMD64InDocker,
tools.TargetPlatformDarwinARM64InDocker:
case tools.TargetPlatformLinuxARM64InDocker:
if config.CGOEnabled {
if tools.TargetPlatformLocal != tools.TargetPlatformLinuxAMD64 {
return nil, nil, errors.Errorf(
"crosscompiling for %s is possible only on platform %s",
config.TargetPlatform,
tools.TargetPlatformLinuxAMD64,
)
}
crossCompileARM64 = true
ldFlags := []string{"-w", "-s"}
for _, flag := range config.Flags {
if strings.Contains(flag, "-ldflags") {
return nil, nil, errors.Errorf(
"it's prohibited to use `-ldflags` in the Flags config, use LDFlags instead",
)
}
default:
return nil, nil,
errors.Errorf(
"building is not possible for platform %s on platform %s",
config.TargetPlatform,
tools.TargetPlatformLocal,
if strings.Contains(flag, "-tags") {
return nil, nil, errors.Errorf(
"it's prohibited to use `-tags` in the Flags config, use Tags instead",
)
}
}
ldFlags = append(ldFlags, config.LDFlags...)

ldFlags := []string{"-w", "-s"}
args = []string{
"build",
"-trimpath",
"-ldflags=" + strings.Join(ldFlags, " "),
"-buildvcs=false",
}
if len(ldFlags) != 0 {
args = append(args, "-ldflags="+strings.Join(ldFlags, " "))
}
if len(config.Tags) != 0 {
args = append(args, "-tags="+strings.Join(config.Tags, ","))
}

args = append(args, config.Flags...)

cgoEnabled := "0"
Expand All @@ -350,13 +300,6 @@ func buildArgsAndEnvs(
"GOOS=" + config.TargetPlatform.OS,
"GOARCH=" + config.TargetPlatform.Arch,
}
if crossCompileARM64 {
if err := tools.Ensure(ctx, tools.Aarch64LinuxMuslCross, tools.TargetPlatformLinuxAMD64InDocker); err != nil {
return nil, nil, err
}

envs = append(envs, "CC=/aarch64-linux-musl-cross/bin/aarch64-linux-musl-gcc")
}
envs = append(envs, config.Envs...)

return args, envs, nil
Expand Down
89 changes: 55 additions & 34 deletions build/tools/tools.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,27 +30,27 @@ import (

// Tool names.
const (
Go Name = "go"
GolangCI Name = "golangci"
Cosmovisor Name = "cosmovisor"
Aarch64LinuxMuslCross Name = "aarch64-linux-musl-cross"
LibWASMMuslC Name = "libwasmvm_muslc"
Gaia Name = "gaia"
Osmosis Name = "osmosis"
Hermes Name = "hermes"
CoredV303 Name = "cored-v3.0.3"
Mockgen = "mockgen"
Buf Name = "buf"
Protoc Name = "protoc"
ProtocGenDoc Name = "protoc-gen-doc"
ProtocGenGRPCGateway Name = "protoc-gen-grpc-gateway"
ProtocGenOpenAPIV2 Name = "protoc-gen-openapiv2"
ProtocGenGoCosmos Name = "protoc-gen-gocosmos"
ProtocGenBufLint Name = "protoc-gen-buf-lint"
ProtocGenBufBreaking Name = "protoc-gen-buf-breaking"
RustUpInit Name = "rustup-init"
Rust Name = "rust"
WASMOpt Name = "wasm-opt"
Go Name = "go"
GolangCI Name = "golangci"
Cosmovisor Name = "cosmovisor"
MuslCC Name = "muslcc"
LibWASM Name = "libwasmvm"
Gaia Name = "gaia"
Osmosis Name = "osmosis"
Hermes Name = "hermes"
CoredV303 Name = "cored-v3.0.3"
Mockgen = "mockgen"
Buf Name = "buf"
Protoc Name = "protoc"
ProtocGenDoc Name = "protoc-gen-doc"
ProtocGenGRPCGateway Name = "protoc-gen-grpc-gateway"
ProtocGenOpenAPIV2 Name = "protoc-gen-openapiv2"
ProtocGenGoCosmos Name = "protoc-gen-gocosmos"
ProtocGenBufLint Name = "protoc-gen-buf-lint"
ProtocGenBufBreaking Name = "protoc-gen-buf-breaking"
RustUpInit Name = "rustup-init"
Rust Name = "rust"
WASMOpt Name = "wasm-opt"
)

func init() {
Expand Down Expand Up @@ -134,38 +134,59 @@ var tools = []Tool{

// http://musl.cc/#binaries
BinaryTool{
Name: Aarch64LinuxMuslCross,
Name: MuslCC,
// update GCP bin source when update the version
Version: "11.2.1",
Sources: Sources{
TargetPlatformLinuxAMD64InDocker: {
URL: "https://storage.googleapis.com/cored-build-process-binaries/aarch64-linux-musl-cross/11.2.1/aarch64-linux-musl-cross.tgz", //nolint:lll // breaking down urls is not beneficial
URL: "https://storage.googleapis.com/cored-build-process-binaries/muslcc/11.2.1/x86_64-linux-musl-cross.tgz", //nolint:lll // breaking down urls is not beneficial
Hash: "sha256:c5d410d9f82a4f24c549fe5d24f988f85b2679b452413a9f7e5f7b956f2fe7ea",
Binaries: map[string]string{
"bin/x86_64-linux-musl-gcc": "x86_64-linux-musl-cross/bin/x86_64-linux-musl-gcc",
},
},
TargetPlatformLinuxARM64InDocker: {
URL: "https://storage.googleapis.com/cored-build-process-binaries/muslcc/11.2.1/aarch64-linux-musl-cross.tgz", //nolint:lll // breaking down urls is not beneficial
Hash: "sha256:c909817856d6ceda86aa510894fa3527eac7989f0ef6e87b5721c58737a06c38",
Binaries: map[string]string{
"bin/aarch64-linux-musl-gcc": "aarch64-linux-musl-cross/bin/aarch64-linux-musl-gcc",
},
},
},
Binaries: map[string]string{
"bin/aarch64-linux-musl-gcc": "aarch64-linux-musl-cross/bin/aarch64-linux-musl-gcc",
},
},

// https://github.com/CosmWasm/wasmvm/releases
// Check compatibility with wasmd beore upgrading: https://github.com/CosmWasm/wasmd
BinaryTool{
Name: LibWASMMuslC,
Version: "v1.5.1",
Name: LibWASM,
Version: "v1.5.2",
Sources: Sources{
TargetPlatformLinuxAMD64InDocker: {
URL: "https://github.com/CosmWasm/wasmvm/releases/download/v1.5.1/libwasmvm_muslc.x86_64.a",
Hash: "sha256:c0f4614d0835be78ac8f3d647a70ccd7ed9f48632bc1374db04e4df2245cb467",
URL: "https://github.com/CosmWasm/wasmvm/releases/download/v1.5.2/libwasmvm_muslc.x86_64.a",
Hash: "sha256:e660a38efb2930b34ee6f6b0bb12730adccb040b6ab701b8f82f34453a426ae7",
Binaries: map[string]string{
"lib/libwasmvm_muslc.a": "libwasmvm_muslc.x86_64.a",
"lib/libwasmvm_muslc.x86_64.a": "libwasmvm_muslc.x86_64.a",
},
},
TargetPlatformLinuxARM64InDocker: {
URL: "https://github.com/CosmWasm/wasmvm/releases/download/v1.5.1/libwasmvm_muslc.aarch64.a",
Hash: "sha256:b89c242ffe2c867267621a6469f07ab70fc204091809d9c6f482c3fdf9293830",
URL: "https://github.com/CosmWasm/wasmvm/releases/download/v1.5.2/libwasmvm_muslc.aarch64.a",
Hash: "sha256:e78b224c15964817a3b75a40e59882b4d0e06fd055b39514d61646689cef8c6e",
Binaries: map[string]string{
"lib/libwasmvm_muslc.aarch64.a": "libwasmvm_muslc.aarch64.a",
},
},
TargetPlatformDarwinAMD64InDocker: {
URL: "https://github.com/CosmWasm/wasmvm/releases/download/v1.5.2/libwasmvmstatic_darwin.a",
Hash: "sha256:78dd3f7c1512eca76ac9665021601ca87ee4956f1b9de9a86283d89a84bf37d4",
Binaries: map[string]string{
"lib/libwasmvmstatic_darwin.a": "libwasmvmstatic_darwin.a",
},
},
TargetPlatformDarwinARM64InDocker: {
URL: "https://github.com/CosmWasm/wasmvm/releases/download/v1.5.2/libwasmvmstatic_darwin.a",
Hash: "sha256:78dd3f7c1512eca76ac9665021601ca87ee4956f1b9de9a86283d89a84bf37d4",
Binaries: map[string]string{
"lib/libwasmvm_muslc.a": "libwasmvm_muslc.aarch64.a",
"lib/libwasmvmstatic_darwin.a": "libwasmvmstatic_darwin.a",
},
},
},
Expand Down

0 comments on commit cf038db

Please sign in to comment.