1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-11-06 09:09:29 +02:00

feat: allow to override build flags by goos/goarch/etc (#2860)

* feat: allow to override build flags by goos/goarch/etc

Signed-off-by: Carlos A Becker <caarlos0@gmail.com>

* test: improve

* fix: typos

* feat: templates, merges

Signed-off-by: Carlos A Becker <caarlos0@gmail.com>

* test: fix

Signed-off-by: Carlos A Becker <caarlos0@gmail.com>

* test: one more case

Signed-off-by: Carlos A Becker <caarlos0@gmail.com>

* Update internal/builders/golang/build.go

Co-authored-by: Brian Flad <bflad417@gmail.com>

* Update internal/builders/golang/build.go

Co-authored-by: Brian Flad <bflad417@gmail.com>

* test: more tests

Signed-off-by: Carlos A Becker <caarlos0@gmail.com>

Co-authored-by: Brian Flad <bflad417@gmail.com>
This commit is contained in:
Carlos Alexandro Becker
2022-02-02 00:01:34 -03:00
committed by GitHub
parent df09e16f6d
commit 1bdfc9cdff
5 changed files with 354 additions and 54 deletions

View File

@@ -19,6 +19,7 @@ import (
api "github.com/goreleaser/goreleaser/pkg/build"
"github.com/goreleaser/goreleaser/pkg/config"
"github.com/goreleaser/goreleaser/pkg/context"
"github.com/imdario/mergo"
)
// Default builder instance.
@@ -129,29 +130,60 @@ func (*Builder) Build(ctx *context.Context, build config.Build, options api.Opti
return nil
}
func withOverrides(ctx *context.Context, build config.Build, options api.Options) (config.BuildDetails, error) {
optsTarget := options.Goos + options.Goarch + options.Goarm + options.Gomips
for _, o := range build.BuildDetailsOverrides {
overrideTarget, err := tmpl.New(ctx).Apply(o.Goos + o.Goarch + o.Gomips + o.Goarm)
if err != nil {
return build.BuildDetails, err
}
if optsTarget == overrideTarget {
dets := config.BuildDetails{
Ldflags: build.BuildDetails.Ldflags,
Tags: build.BuildDetails.Tags,
Flags: build.BuildDetails.Flags,
Asmflags: build.BuildDetails.Asmflags,
Gcflags: build.BuildDetails.Gcflags,
}
if err := mergo.Merge(&dets, o.BuildDetails, mergo.WithOverride); err != nil {
return build.BuildDetails, err
}
log.WithField("dets", dets).Info("will use")
return dets, nil
}
}
return build.BuildDetails, nil
}
func buildGoBuildLine(ctx *context.Context, build config.Build, options api.Options, artifact *artifact.Artifact, env []string) ([]string, error) {
cmd := []string{build.GoBinary, "build"}
flags, err := processFlags(ctx, artifact, env, build.Flags, "")
details, err := withOverrides(ctx, build, options)
if err != nil {
return cmd, err
}
flags, err := processFlags(ctx, artifact, env, details.Flags, "")
if err != nil {
return cmd, err
}
cmd = append(cmd, flags...)
asmflags, err := processFlags(ctx, artifact, env, build.Asmflags, "-asmflags=")
asmflags, err := processFlags(ctx, artifact, env, details.Asmflags, "-asmflags=")
if err != nil {
return cmd, err
}
cmd = append(cmd, asmflags...)
gcflags, err := processFlags(ctx, artifact, env, build.Gcflags, "-gcflags=")
gcflags, err := processFlags(ctx, artifact, env, details.Gcflags, "-gcflags=")
if err != nil {
return cmd, err
}
cmd = append(cmd, gcflags...)
// tags is not a repeatable flag
if len(build.Tags) > 0 {
tags, err := processFlags(ctx, artifact, env, build.Tags, "")
if len(details.Tags) > 0 {
tags, err := processFlags(ctx, artifact, env, details.Tags, "")
if err != nil {
return cmd, err
}
@@ -159,9 +191,9 @@ func buildGoBuildLine(ctx *context.Context, build config.Build, options api.Opti
}
// ldflags is not a repeatable flag
if len(build.Ldflags) > 0 {
if len(details.Ldflags) > 0 {
// flag prefix is skipped because ldflags need to output a single string
ldflags, err := processFlags(ctx, artifact, env, build.Ldflags, "")
ldflags, err := processFlags(ctx, artifact, env, details.Ldflags, "")
if err != nil {
return cmd, err
}

View File

@@ -226,11 +226,13 @@ func TestBuild(t *testing.T) {
"linux_mips_softfloat",
"linux_mips64le_softfloat",
},
Asmflags: []string{".=", "all="},
Gcflags: []string{"all="},
Flags: []string{"{{.Env.GO_FLAGS}}"},
Tags: []string{"osusergo", "netgo", "static_build"},
GoBinary: "go",
BuildDetails: config.BuildDetails{
Asmflags: []string{".=", "all="},
Gcflags: []string{"all="},
Flags: []string{"{{.Env.GO_FLAGS}}"},
Tags: []string{"osusergo", "netgo", "static_build"},
},
},
},
}
@@ -450,8 +452,10 @@ func TestBuildFailed(t *testing.T) {
config := config.Project{
Builds: []config.Build{
{
ID: "buildid",
Flags: []string{"-flag-that-dont-exists-to-force-failure"},
ID: "buildid",
BuildDetails: config.BuildDetails{
Flags: []string{"-flag-that-dont-exists-to-force-failure"},
},
Targets: []string{
runtimeTarget,
},
@@ -474,8 +478,10 @@ func TestRunInvalidAsmflags(t *testing.T) {
config := config.Project{
Builds: []config.Build{
{
Binary: "nametest",
Asmflags: []string{"{{.Version}"},
Binary: "nametest",
BuildDetails: config.BuildDetails{
Asmflags: []string{"{{.Version}"},
},
Targets: []string{
runtimeTarget,
},
@@ -496,8 +502,10 @@ func TestRunInvalidGcflags(t *testing.T) {
config := config.Project{
Builds: []config.Build{
{
Binary: "nametest",
Gcflags: []string{"{{.Version}"},
Binary: "nametest",
BuildDetails: config.BuildDetails{
Gcflags: []string{"{{.Version}"},
},
Targets: []string{
runtimeTarget,
},
@@ -518,9 +526,11 @@ func TestRunInvalidLdflags(t *testing.T) {
config := config.Project{
Builds: []config.Build{
{
Binary: "nametest",
Flags: []string{"-v"},
Ldflags: []string{"-s -w -X main.version={{.Version}"},
Binary: "nametest",
BuildDetails: config.BuildDetails{
Flags: []string{"-v"},
Ldflags: []string{"-s -w -X main.version={{.Version}"},
},
Targets: []string{
runtimeTarget,
},
@@ -542,7 +552,9 @@ func TestRunInvalidFlags(t *testing.T) {
Builds: []config.Build{
{
Binary: "nametest",
Flags: []string{"{{.Env.GOOS}"},
BuildDetails: config.BuildDetails{
Flags: []string{"{{.Env.GOOS}"},
},
Targets: []string{
runtimeTarget,
},
@@ -832,9 +844,11 @@ func TestBuildModTimestamp(t *testing.T) {
"linux_mips_softfloat",
"linux_mips64le_softfloat",
},
Asmflags: []string{".=", "all="},
Gcflags: []string{"all="},
Flags: []string{"{{.Env.GO_FLAGS}}"},
BuildDetails: config.BuildDetails{
Asmflags: []string{".=", "all="},
Gcflags: []string{"all="},
Flags: []string{"{{.Env.GO_FLAGS}}"},
},
ModTimestamp: fmt.Sprintf("%d", modTime.Unix()),
GoBinary: "go",
},
@@ -888,19 +902,25 @@ func TestBuildGoBuildLine(t *testing.T) {
ctx.Version = "1.2.3"
ctx.Git.Commit = "aaa"
line, err := buildGoBuildLine(ctx, config.Builds[0], api.Options{Path: "foo"}, &artifact.Artifact{}, []string{})
line, err := buildGoBuildLine(ctx, config.Builds[0], api.Options{
Path: "foo",
Goos: "linux",
Goarch: "amd64",
}, &artifact.Artifact{}, []string{})
require.NoError(t, err)
require.Equal(t, expected, line)
}
t.Run("full", func(t *testing.T) {
requireEqualCmd(t, config.Build{
Main: ".",
Asmflags: []string{"asmflag1", "asmflag2"},
Gcflags: []string{"gcflag1", "gcflag2"},
Flags: []string{"-flag1", "-flag2"},
Tags: []string{"tag1", "tag2"},
Ldflags: []string{"ldflag1", "ldflag2"},
Main: ".",
BuildDetails: config.BuildDetails{
Asmflags: []string{"asmflag1", "asmflag2"},
Gcflags: []string{"gcflag1", "gcflag2"},
Flags: []string{"-flag1", "-flag2"},
Tags: []string{"tag1", "tag2"},
Ldflags: []string{"ldflag1", "ldflag2"},
},
GoBinary: "go",
}, []string{
"go", "build",
@@ -913,6 +933,41 @@ func TestBuildGoBuildLine(t *testing.T) {
})
})
t.Run("with overrides", func(t *testing.T) {
requireEqualCmd(t, config.Build{
Main: ".",
BuildDetails: config.BuildDetails{
Asmflags: []string{"asmflag1", "asmflag2"},
Gcflags: []string{"gcflag1", "gcflag2"},
Flags: []string{"-flag1", "-flag2"},
Tags: []string{"tag1", "tag2"},
Ldflags: []string{"ldflag1", "ldflag2"},
},
BuildDetailsOverrides: []config.BuildDetailsOverride{
{
Goos: "linux",
Goarch: "amd64",
BuildDetails: config.BuildDetails{
Asmflags: []string{"asmflag3"},
Gcflags: []string{"gcflag3"},
Flags: []string{"-flag3"},
Tags: []string{"tag3"},
Ldflags: []string{"ldflag3"},
},
},
},
GoBinary: "go",
}, []string{
"go", "build",
"-flag3",
"-asmflags=asmflag3",
"-gcflags=gcflag3",
"-tags=tag3",
"-ldflags=ldflag3",
"-o", "foo", ".",
})
})
t.Run("simple", func(t *testing.T) {
requireEqualCmd(t, config.Build{
Main: ".",
@@ -922,8 +977,10 @@ func TestBuildGoBuildLine(t *testing.T) {
t.Run("ldflags1", func(t *testing.T) {
requireEqualCmd(t, config.Build{
Main: ".",
Ldflags: []string{"-s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.builtBy=goreleaser"},
Main: ".",
BuildDetails: config.BuildDetails{
Ldflags: []string{"-s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.builtBy=goreleaser"},
},
GoBinary: "go",
}, []string{
"go", "build",
@@ -934,13 +991,179 @@ func TestBuildGoBuildLine(t *testing.T) {
t.Run("ldflags2", func(t *testing.T) {
requireEqualCmd(t, config.Build{
Main: ".",
Ldflags: []string{"-s -w", "-X main.version={{.Version}}"},
Main: ".",
BuildDetails: config.BuildDetails{
Ldflags: []string{"-s -w", "-X main.version={{.Version}}"},
},
GoBinary: "go",
}, []string{"go", "build", "-ldflags=-s -w -X main.version=1.2.3", "-o", "foo", "."})
})
}
func TestOverrides(t *testing.T) {
t.Run("linux amd64", func(t *testing.T) {
dets, err := withOverrides(
context.New(config.Project{}),
config.Build{
BuildDetails: config.BuildDetails{
Ldflags: []string{"original"},
},
BuildDetailsOverrides: []config.BuildDetailsOverride{
{
Goos: "linux",
Goarch: "amd64",
BuildDetails: config.BuildDetails{
Ldflags: []string{"overridden"},
},
},
},
}, api.Options{
Goos: "linux",
Goarch: "amd64",
},
)
require.NoError(t, err)
require.Equal(t, dets, config.BuildDetails{
Ldflags: []string{"overridden"},
})
})
t.Run("single sided", func(t *testing.T) {
dets, err := withOverrides(
context.New(config.Project{}),
config.Build{
BuildDetails: config.BuildDetails{},
BuildDetailsOverrides: []config.BuildDetailsOverride{
{
Goos: "linux",
Goarch: "amd64",
BuildDetails: config.BuildDetails{
Ldflags: []string{"overridden"},
Tags: []string{"tag1"},
Asmflags: []string{"asm1"},
Gcflags: []string{"gcflag1"},
},
},
},
}, api.Options{
Goos: "linux",
Goarch: "amd64",
},
)
require.NoError(t, err)
require.Equal(t, dets, config.BuildDetails{
Ldflags: []string{"overridden"},
Gcflags: []string{"gcflag1"},
Asmflags: []string{"asm1"},
Tags: []string{"tag1"},
})
})
t.Run("with template", func(t *testing.T) {
dets, err := withOverrides(
context.New(config.Project{}),
config.Build{
BuildDetails: config.BuildDetails{
Ldflags: []string{"original"},
Asmflags: []string{"asm1"},
},
BuildDetailsOverrides: []config.BuildDetailsOverride{
{
Goos: "{{ .Runtime.Goos }}",
Goarch: "{{ .Runtime.Goarch }}",
BuildDetails: config.BuildDetails{
Ldflags: []string{"overridden"},
},
},
},
}, api.Options{
Goos: runtime.GOOS,
Goarch: runtime.GOARCH,
},
)
require.NoError(t, err)
require.Equal(t, dets, config.BuildDetails{
Ldflags: []string{"overridden"},
Asmflags: []string{"asm1"},
})
})
t.Run("with invalid template", func(t *testing.T) {
_, err := withOverrides(
context.New(config.Project{}),
config.Build{
BuildDetailsOverrides: []config.BuildDetailsOverride{
{
Goos: "{{ .Runtime.Goos }",
},
},
}, api.Options{
Goos: runtime.GOOS,
Goarch: runtime.GOARCH,
},
)
require.EqualError(t, err, `template: tmpl:1: unexpected "}" in operand`)
})
t.Run("with goarm", func(t *testing.T) {
dets, err := withOverrides(
context.New(config.Project{}),
config.Build{
BuildDetails: config.BuildDetails{
Ldflags: []string{"original"},
},
BuildDetailsOverrides: []config.BuildDetailsOverride{
{
Goos: "linux",
Goarch: "arm",
Goarm: "6",
BuildDetails: config.BuildDetails{
Ldflags: []string{"overridden"},
},
},
},
}, api.Options{
Goos: "linux",
Goarch: "arm",
Goarm: "6",
},
)
require.NoError(t, err)
require.Equal(t, dets, config.BuildDetails{
Ldflags: []string{"overridden"},
})
})
t.Run("with gomips", func(t *testing.T) {
dets, err := withOverrides(
context.New(config.Project{}),
config.Build{
BuildDetails: config.BuildDetails{
Ldflags: []string{"original"},
},
BuildDetailsOverrides: []config.BuildDetailsOverride{
{
Goos: "linux",
Goarch: "mips",
Gomips: "softfloat",
BuildDetails: config.BuildDetails{
Ldflags: []string{"overridden"},
},
},
},
}, api.Options{
Goos: "linux",
Goarch: "mips",
Gomips: "softfloat",
},
)
require.NoError(t, err)
require.Equal(t, dets, config.BuildDetails{
Ldflags: []string{"overridden"},
})
})
}
//
// Helpers
//