mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-03-17 20:47:50 +02:00
refactor(build): preparing to support multiple languages (#5307)
This starts laying the foundation for supporting more languages, the first of which will probably be Zig, and then Rust. I already have a zig prototype working in another branch, just raw dogged it to see if it would work, and since it does, now I'll do it piece by piece but with hopefully slightly better code.
This commit is contained in:
parent
f061ae92ad
commit
d43f84aa3f
@ -38,6 +38,46 @@ func init() {
|
||||
// Builder is golang builder.
|
||||
type Builder struct{}
|
||||
|
||||
// Parse implements build.Builder.
|
||||
func (b *Builder) Parse(target string) (api.Target, error) {
|
||||
target = fixTarget(target)
|
||||
parts := strings.Split(target, "_")
|
||||
if len(parts) < 2 {
|
||||
return nil, fmt.Errorf("%s is not a valid build target", target)
|
||||
}
|
||||
|
||||
goos := parts[0]
|
||||
goarch := parts[1]
|
||||
|
||||
t := Target{
|
||||
Target: target,
|
||||
Goos: goos,
|
||||
Goarch: goarch,
|
||||
}
|
||||
|
||||
if len(parts) > 2 {
|
||||
extra := parts[2]
|
||||
switch goarch {
|
||||
case "amd64":
|
||||
t.Goamd64 = extra
|
||||
case "arm64":
|
||||
t.Goarm64 = extra
|
||||
case "386":
|
||||
t.Go386 = extra
|
||||
case "arm":
|
||||
t.Goarm = extra
|
||||
case "mips", "mipsle", "mips64", "mips64le":
|
||||
t.Gomips = extra
|
||||
case "ppc64":
|
||||
t.Goppc64 = extra
|
||||
case "riscv":
|
||||
t.Goriscv64 = extra
|
||||
}
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// WithDefaults sets the defaults for a golang build and returns it.
|
||||
func (*Builder) WithDefaults(build config.Build) (config.Build, error) {
|
||||
if build.GoBinary == "" {
|
||||
@ -187,19 +227,21 @@ func (*Builder) Build(ctx *context.Context, build config.Build, options api.Opti
|
||||
return err
|
||||
}
|
||||
|
||||
t := options.Target.(Target)
|
||||
|
||||
a := &artifact.Artifact{
|
||||
Type: artifact.Binary,
|
||||
Path: options.Path,
|
||||
Name: options.Name,
|
||||
Goos: options.Goos,
|
||||
Goarch: options.Goarch,
|
||||
Goamd64: options.Goamd64,
|
||||
Go386: options.Go386,
|
||||
Goarm: options.Goarm,
|
||||
Goarm64: options.Goarm64,
|
||||
Gomips: options.Gomips,
|
||||
Goppc64: options.Goppc64,
|
||||
Goriscv64: options.Goriscv64,
|
||||
Goos: t.Goos,
|
||||
Goarch: t.Goarch,
|
||||
Goamd64: t.Goamd64,
|
||||
Go386: t.Go386,
|
||||
Goarm: t.Goarm,
|
||||
Goarm64: t.Goarm64,
|
||||
Gomips: t.Gomips,
|
||||
Goppc64: t.Goppc64,
|
||||
Goriscv64: t.Goriscv64,
|
||||
Extra: map[string]interface{}{
|
||||
artifact.ExtraBinary: strings.TrimSuffix(filepath.Base(options.Path), options.Ext),
|
||||
artifact.ExtraExt: options.Ext,
|
||||
@ -211,12 +253,12 @@ func (*Builder) Build(ctx *context.Context, build config.Build, options api.Opti
|
||||
a.Type = artifact.CArchive
|
||||
ctx.Artifacts.Add(getHeaderArtifactForLibrary(build, options))
|
||||
}
|
||||
if build.Buildmode == "c-shared" && !strings.Contains(options.Target, "wasm") {
|
||||
if build.Buildmode == "c-shared" && !strings.Contains(t.Target, "wasm") {
|
||||
a.Type = artifact.CShared
|
||||
ctx.Artifacts.Add(getHeaderArtifactForLibrary(build, options))
|
||||
}
|
||||
|
||||
details, err := withOverrides(ctx, build, options)
|
||||
details, err := withOverrides(ctx, build, t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -238,20 +280,8 @@ func (*Builder) Build(ctx *context.Context, build config.Build, options api.Opti
|
||||
}
|
||||
}
|
||||
}
|
||||
env = append(
|
||||
env,
|
||||
"GOOS="+options.Goos,
|
||||
"GOARCH="+options.Goarch,
|
||||
"GOAMD64="+options.Goamd64,
|
||||
"GO386="+options.Go386,
|
||||
"GOARM="+options.Goarm,
|
||||
"GOARM64="+options.Goarm64,
|
||||
"GOMIPS="+options.Gomips,
|
||||
"GOMIPS64="+options.Gomips,
|
||||
"GOPPC64="+options.Goppc64,
|
||||
"GORISCV64="+options.Goriscv64,
|
||||
)
|
||||
|
||||
env = append(env, t.env()...)
|
||||
if v := os.Getenv("GOCACHEPROG"); v != "" {
|
||||
env = append(env, "GOCACHEPROG="+v)
|
||||
}
|
||||
@ -281,18 +311,10 @@ 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
|
||||
if extra := options.Goamd64 + options.Go386 + options.Goarm + options.Goarm64 + options.Gomips + options.Goppc64 + options.Goriscv64; extra != "" {
|
||||
optsTarget += "_" + extra
|
||||
}
|
||||
optsTarget = fixTarget(optsTarget)
|
||||
func withOverrides(ctx *context.Context, build config.Build, target Target) (config.BuildDetails, error) {
|
||||
optsTarget := target.Target
|
||||
for _, o := range build.BuildDetailsOverrides {
|
||||
s := o.Goos + "_" + o.Goarch
|
||||
if extra := o.Goamd64 + o.Go386 + o.Goarm + o.Goarm64 + o.Gomips + o.Goppc64 + o.Goriscv64; extra != "" {
|
||||
s += "_" + extra
|
||||
}
|
||||
overrideTarget, err := tmpl.New(ctx).Apply(s)
|
||||
overrideTarget, err := tmpl.New(ctx).Apply(formatTarget(o))
|
||||
if err != nil {
|
||||
return build.BuildDetails, err
|
||||
}
|
||||
@ -521,20 +543,21 @@ func getHeaderArtifactForLibrary(build config.Build, options api.Options) *artif
|
||||
basePath := filepath.Base(fullPathWithoutExt)
|
||||
fullPath := fullPathWithoutExt + ".h"
|
||||
headerName := basePath + ".h"
|
||||
t := options.Target.(Target)
|
||||
|
||||
return &artifact.Artifact{
|
||||
Type: artifact.Header,
|
||||
Path: fullPath,
|
||||
Name: headerName,
|
||||
Goos: options.Goos,
|
||||
Goarch: options.Goarch,
|
||||
Goamd64: options.Goamd64,
|
||||
Go386: options.Go386,
|
||||
Goarm: options.Goarm,
|
||||
Goarm64: options.Goarm64,
|
||||
Gomips: options.Gomips,
|
||||
Goppc64: options.Goppc64,
|
||||
Goriscv64: options.Goriscv64,
|
||||
Goos: t.Goos,
|
||||
Goarch: t.Goarch,
|
||||
Goamd64: t.Goamd64,
|
||||
Go386: t.Go386,
|
||||
Goarm: t.Goarm,
|
||||
Goarm64: t.Goarm64,
|
||||
Gomips: t.Gomips,
|
||||
Goppc64: t.Goppc64,
|
||||
Goriscv64: t.Goriscv64,
|
||||
Extra: map[string]interface{}{
|
||||
artifact.ExtraBinary: headerName,
|
||||
artifact.ExtraExt: ".h",
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/goreleaser/goreleaser/v2/internal/artifact"
|
||||
"github.com/goreleaser/goreleaser/v2/internal/experimental"
|
||||
"github.com/goreleaser/goreleaser/v2/internal/testctx"
|
||||
"github.com/goreleaser/goreleaser/v2/internal/testlib"
|
||||
"github.com/goreleaser/goreleaser/v2/internal/tmpl"
|
||||
@ -33,6 +34,78 @@ var go118FirstClassAdjustedTargets = []string{
|
||||
"windows_amd64_v1",
|
||||
}
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
for target, dst := range map[string]Target{
|
||||
"linux_amd64": {
|
||||
Target: "linux_amd64_v1",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Goamd64: "v1",
|
||||
},
|
||||
"linux_amd64_v2": {
|
||||
Target: "linux_amd64_v2",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Goamd64: "v2",
|
||||
},
|
||||
"linux_arm": {
|
||||
Target: "linux_arm_" + experimental.DefaultGOARM(),
|
||||
Goos: "linux",
|
||||
Goarch: "arm",
|
||||
Goarm: experimental.DefaultGOARM(),
|
||||
},
|
||||
"linux_arm_7": {
|
||||
Target: "linux_arm_7",
|
||||
Goos: "linux",
|
||||
Goarch: "arm",
|
||||
Goarm: "7",
|
||||
},
|
||||
"linux_mips": {
|
||||
Target: "linux_mips_hardfloat",
|
||||
Goos: "linux",
|
||||
Goarch: "mips",
|
||||
Gomips: "hardfloat",
|
||||
},
|
||||
"linux_mips_softfloat": {
|
||||
Target: "linux_mips_softfloat",
|
||||
Goos: "linux",
|
||||
Goarch: "mips",
|
||||
Gomips: "softfloat",
|
||||
},
|
||||
"linux_386": {
|
||||
Target: "linux_386_sse2",
|
||||
Goos: "linux",
|
||||
Goarch: "386",
|
||||
Go386: "sse2",
|
||||
},
|
||||
"linux_386_hardfloat": {
|
||||
Target: "linux_386_hardfloat",
|
||||
Goos: "linux",
|
||||
Goarch: "386",
|
||||
Go386: "hardfloat",
|
||||
},
|
||||
"linux_arm64": {
|
||||
Target: "linux_arm64_v8.0",
|
||||
Goos: "linux",
|
||||
Goarch: "arm64",
|
||||
Goarm64: "v8.0",
|
||||
},
|
||||
"linux_arm64_v9.0": {
|
||||
Target: "linux_arm64_v9.0",
|
||||
Goos: "linux",
|
||||
Goarch: "arm64",
|
||||
Goarm64: "v9.0",
|
||||
},
|
||||
} {
|
||||
t.Run(target, func(t *testing.T) {
|
||||
got, err := Default.Parse(target)
|
||||
require.NoError(t, err)
|
||||
require.IsType(t, Target{}, got)
|
||||
require.Equal(t, dst, got.(Target))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithDefaults(t *testing.T) {
|
||||
for name, testcase := range map[string]struct {
|
||||
build config.Build
|
||||
@ -429,30 +502,14 @@ func TestBuild(t *testing.T) {
|
||||
// injecting some delay here to force inconsistent mod times on bins
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
parts := strings.Split(target, "_")
|
||||
goos := parts[0]
|
||||
goarch := parts[1]
|
||||
goarm := ""
|
||||
gomips := ""
|
||||
if len(parts) > 2 {
|
||||
if strings.Contains(goarch, "arm") {
|
||||
goarm = parts[2]
|
||||
}
|
||||
if strings.Contains(goarch, "mips") {
|
||||
gomips = parts[2]
|
||||
}
|
||||
}
|
||||
err := Default.Build(ctx, build, api.Options{
|
||||
Target: target,
|
||||
gtarget, err := Default.Parse(target)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, Default.Build(ctx, build, api.Options{
|
||||
Target: gtarget,
|
||||
Name: bin + ext,
|
||||
Path: filepath.Join(folder, "dist", target, bin+ext),
|
||||
Goos: goos,
|
||||
Goarch: goarch,
|
||||
Goarm: goarm,
|
||||
Gomips: gomips,
|
||||
Ext: ext,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}))
|
||||
}
|
||||
list := ctx.Artifacts
|
||||
require.NoError(t, list.Visit(func(a *artifact.Artifact) error {
|
||||
@ -462,13 +519,14 @@ func TestBuild(t *testing.T) {
|
||||
}
|
||||
return nil
|
||||
}))
|
||||
require.ElementsMatch(t, list.List(), []*artifact.Artifact{
|
||||
expected := []*artifact.Artifact{
|
||||
{
|
||||
Name: "bin/foo-v5.6.7",
|
||||
Path: filepath.ToSlash(filepath.Join("dist", "linux_amd64", "bin", "foo-v5.6.7")),
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Type: artifact.Binary,
|
||||
Name: "bin/foo-v5.6.7",
|
||||
Path: filepath.ToSlash(filepath.Join("dist", "linux_amd64", "bin", "foo-v5.6.7")),
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Goamd64: "v1",
|
||||
Type: artifact.Binary,
|
||||
Extra: map[string]interface{}{
|
||||
artifact.ExtraExt: "",
|
||||
artifact.ExtraBinary: "foo-v5.6.7",
|
||||
@ -505,11 +563,12 @@ func TestBuild(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "bin/foo-v5.6.7",
|
||||
Path: filepath.ToSlash(filepath.Join("dist", "darwin_amd64", "bin", "foo-v5.6.7")),
|
||||
Goos: "darwin",
|
||||
Goarch: "amd64",
|
||||
Type: artifact.Binary,
|
||||
Name: "bin/foo-v5.6.7",
|
||||
Path: filepath.ToSlash(filepath.Join("dist", "darwin_amd64", "bin", "foo-v5.6.7")),
|
||||
Goos: "darwin",
|
||||
Goarch: "amd64",
|
||||
Goamd64: "v1",
|
||||
Type: artifact.Binary,
|
||||
Extra: map[string]interface{}{
|
||||
artifact.ExtraExt: "",
|
||||
artifact.ExtraBinary: "foo-v5.6.7",
|
||||
@ -532,11 +591,12 @@ func TestBuild(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "bin/foo-v5.6.7.exe",
|
||||
Path: filepath.ToSlash(filepath.Join("dist", "windows_amd64", "bin", "foo-v5.6.7.exe")),
|
||||
Goos: "windows",
|
||||
Goarch: "amd64",
|
||||
Type: artifact.Binary,
|
||||
Name: "bin/foo-v5.6.7.exe",
|
||||
Path: filepath.ToSlash(filepath.Join("dist", "windows_amd64", "bin", "foo-v5.6.7.exe")),
|
||||
Goos: "windows",
|
||||
Goarch: "amd64",
|
||||
Goamd64: "v1",
|
||||
Type: artifact.Binary,
|
||||
Extra: map[string]interface{}{
|
||||
artifact.ExtraExt: ".exe",
|
||||
artifact.ExtraBinary: "foo-v5.6.7",
|
||||
@ -557,7 +617,10 @@ func TestBuild(t *testing.T) {
|
||||
"testEnvs": []string{"TEST_T="},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
got := list.List()
|
||||
testlib.RequireEqualArtifacts(t, expected, got)
|
||||
|
||||
modTimes := map[int64]bool{}
|
||||
for _, bin := range ctx.Artifacts.List() {
|
||||
@ -599,7 +662,7 @@ func TestBuildInvalidEnv(t *testing.T) {
|
||||
}, testctx.WithCurrentTag("5.6.7"))
|
||||
build := ctx.Config.Builds[0]
|
||||
err := Default.Build(ctx, build, api.Options{
|
||||
Target: runtimeTarget,
|
||||
Target: mustParse(t, runtimeTarget),
|
||||
Name: build.Binary,
|
||||
Path: filepath.Join("dist", runtimeTarget, build.Binary),
|
||||
Ext: "",
|
||||
@ -632,7 +695,7 @@ func TestBuildCodeInSubdir(t *testing.T) {
|
||||
}, testctx.WithCurrentTag("5.6.7"))
|
||||
build := ctx.Config.Builds[0]
|
||||
err = Default.Build(ctx, build, api.Options{
|
||||
Target: runtimeTarget,
|
||||
Target: mustParse(t, runtimeTarget),
|
||||
Name: build.Binary,
|
||||
Path: filepath.Join("dist", runtimeTarget, build.Binary),
|
||||
Ext: "",
|
||||
@ -660,7 +723,7 @@ func TestBuildWithDotGoDir(t *testing.T) {
|
||||
}, testctx.WithCurrentTag("5.6.7"))
|
||||
build := ctx.Config.Builds[0]
|
||||
require.NoError(t, Default.Build(ctx, build, api.Options{
|
||||
Target: runtimeTarget,
|
||||
Target: mustParse(t, runtimeTarget),
|
||||
Name: build.Binary,
|
||||
Path: filepath.Join("dist", runtimeTarget, build.Binary),
|
||||
Ext: "",
|
||||
@ -686,7 +749,7 @@ func TestBuildFailed(t *testing.T) {
|
||||
},
|
||||
}, testctx.WithCurrentTag("5.6.7"))
|
||||
err := Default.Build(ctx, ctx.Config.Builds[0], api.Options{
|
||||
Target: "darwin_amd64",
|
||||
Target: mustParse(t, "darwin_amd64"),
|
||||
})
|
||||
require.ErrorContains(t, err, `flag provided but not defined: -flag-that-dont-exists-to-force-failure`)
|
||||
require.Empty(t, ctx.Artifacts.List())
|
||||
@ -709,7 +772,7 @@ func TestRunInvalidAsmflags(t *testing.T) {
|
||||
},
|
||||
}, testctx.WithCurrentTag("5.6.7"))
|
||||
err := Default.Build(ctx, ctx.Config.Builds[0], api.Options{
|
||||
Target: runtimeTarget,
|
||||
Target: mustParse(t, runtimeTarget),
|
||||
})
|
||||
testlib.RequireTemplateError(t, err)
|
||||
}
|
||||
@ -731,7 +794,7 @@ func TestRunInvalidGcflags(t *testing.T) {
|
||||
},
|
||||
}, testctx.WithCurrentTag("5.6.7"))
|
||||
err := Default.Build(ctx, ctx.Config.Builds[0], api.Options{
|
||||
Target: runtimeTarget,
|
||||
Target: mustParse(t, runtimeTarget),
|
||||
})
|
||||
testlib.RequireTemplateError(t, err)
|
||||
}
|
||||
@ -754,7 +817,7 @@ func TestRunInvalidLdflags(t *testing.T) {
|
||||
},
|
||||
}, testctx.WithCurrentTag("5.6.7"))
|
||||
err := Default.Build(ctx, ctx.Config.Builds[0], api.Options{
|
||||
Target: runtimeTarget,
|
||||
Target: mustParse(t, runtimeTarget),
|
||||
})
|
||||
testlib.RequireTemplateError(t, err)
|
||||
}
|
||||
@ -776,7 +839,7 @@ func TestRunInvalidFlags(t *testing.T) {
|
||||
},
|
||||
})
|
||||
err := Default.Build(ctx, ctx.Config.Builds[0], api.Options{
|
||||
Target: runtimeTarget,
|
||||
Target: mustParse(t, runtimeTarget),
|
||||
})
|
||||
testlib.RequireTemplateError(t, err)
|
||||
}
|
||||
@ -795,28 +858,28 @@ func TestRunPipeWithoutMainFunc(t *testing.T) {
|
||||
ctx := newCtx(t)
|
||||
ctx.Config.Builds[0].Main = ""
|
||||
require.EqualError(t, Default.Build(ctx, ctx.Config.Builds[0], api.Options{
|
||||
Target: runtimeTarget,
|
||||
Target: mustParse(t, runtimeTarget),
|
||||
}), errNoMain{"no-main"}.Error())
|
||||
})
|
||||
t.Run("not main.go", func(t *testing.T) {
|
||||
ctx := newCtx(t)
|
||||
ctx.Config.Builds[0].Main = "foo.go"
|
||||
require.ErrorIs(t, Default.Build(ctx, ctx.Config.Builds[0], api.Options{
|
||||
Target: runtimeTarget,
|
||||
Target: mustParse(t, runtimeTarget),
|
||||
}), os.ErrNotExist)
|
||||
})
|
||||
t.Run("glob", func(t *testing.T) {
|
||||
ctx := newCtx(t)
|
||||
ctx.Config.Builds[0].Main = "."
|
||||
require.EqualError(t, Default.Build(ctx, ctx.Config.Builds[0], api.Options{
|
||||
Target: runtimeTarget,
|
||||
Target: mustParse(t, runtimeTarget),
|
||||
}), errNoMain{"no-main"}.Error())
|
||||
})
|
||||
t.Run("fixed main.go", func(t *testing.T) {
|
||||
ctx := newCtx(t)
|
||||
ctx.Config.Builds[0].Main = "main.go"
|
||||
require.EqualError(t, Default.Build(ctx, ctx.Config.Builds[0], api.Options{
|
||||
Target: runtimeTarget,
|
||||
Target: mustParse(t, runtimeTarget),
|
||||
}), errNoMain{"no-main"}.Error())
|
||||
})
|
||||
t.Run("using gomod.proxy", func(t *testing.T) {
|
||||
@ -827,7 +890,7 @@ func TestRunPipeWithoutMainFunc(t *testing.T) {
|
||||
ctx.Config.Builds[0].UnproxiedDir = "."
|
||||
ctx.Config.Builds[0].UnproxiedMain = "."
|
||||
require.EqualError(t, Default.Build(ctx, ctx.Config.Builds[0], api.Options{
|
||||
Target: runtimeTarget,
|
||||
Target: mustParse(t, runtimeTarget),
|
||||
}), errNoMain{"no-main"}.Error())
|
||||
})
|
||||
}
|
||||
@ -848,7 +911,7 @@ func TestBuildTests(t *testing.T) {
|
||||
build, err := Default.WithDefaults(ctx.Config.Builds[0])
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, Default.Build(ctx, build, api.Options{
|
||||
Target: runtimeTarget,
|
||||
Target: mustParse(t, runtimeTarget),
|
||||
}))
|
||||
}
|
||||
|
||||
@ -899,7 +962,7 @@ import _ "github.com/goreleaser/goreleaser"
|
||||
})
|
||||
|
||||
require.NoError(t, Default.Build(ctx, ctx.Config.Builds[0], api.Options{
|
||||
Target: runtimeTarget,
|
||||
Target: mustParse(t, runtimeTarget),
|
||||
}))
|
||||
}
|
||||
|
||||
@ -929,19 +992,19 @@ func TestRunPipeWithMainFuncNotInMainGoFile(t *testing.T) {
|
||||
t.Run("empty", func(t *testing.T) {
|
||||
ctx.Config.Builds[0].Main = ""
|
||||
require.NoError(t, Default.Build(ctx, ctx.Config.Builds[0], api.Options{
|
||||
Target: runtimeTarget,
|
||||
Target: mustParse(t, runtimeTarget),
|
||||
}))
|
||||
})
|
||||
t.Run("foo.go", func(t *testing.T) {
|
||||
ctx.Config.Builds[0].Main = "foo.go"
|
||||
require.NoError(t, Default.Build(ctx, ctx.Config.Builds[0], api.Options{
|
||||
Target: runtimeTarget,
|
||||
Target: mustParse(t, runtimeTarget),
|
||||
}))
|
||||
})
|
||||
t.Run("glob", func(t *testing.T) {
|
||||
ctx.Config.Builds[0].Main = "."
|
||||
require.NoError(t, Default.Build(ctx, ctx.Config.Builds[0], api.Options{
|
||||
Target: runtimeTarget,
|
||||
Target: mustParse(t, runtimeTarget),
|
||||
}))
|
||||
})
|
||||
}
|
||||
@ -1099,7 +1162,7 @@ func TestBuildModTimestamp(t *testing.T) {
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
err := Default.Build(ctx, build, api.Options{
|
||||
Target: target,
|
||||
Target: mustParse(t, runtimeTarget),
|
||||
Name: bin + ext,
|
||||
Path: filepath.Join(folder, "dist", target, bin+ext),
|
||||
Ext: ext,
|
||||
@ -1131,11 +1194,10 @@ func TestBuildGoBuildLine(t *testing.T) {
|
||||
)
|
||||
options := api.Options{
|
||||
Path: ctx.Config.Builds[0].Binary,
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Target: mustParse(t, "linux_amd64"),
|
||||
}
|
||||
|
||||
dets, err := withOverrides(ctx, build, options)
|
||||
dets, err := withOverrides(ctx, build, options.Target.(Target))
|
||||
require.NoError(t, err)
|
||||
|
||||
line, err := buildGoBuildLine(
|
||||
@ -1298,10 +1360,7 @@ func TestOverrides(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, api.Options{
|
||||
Goos: "linux",
|
||||
Goarch: arch,
|
||||
},
|
||||
}, mustParse(t, "linux_"+arch),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.ElementsMatch(t, dets.Ldflags, []string{"overridden"})
|
||||
@ -1326,10 +1385,7 @@ func TestOverrides(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, api.Options{
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
},
|
||||
}, mustParse(t, "linux_amd64"),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, config.BuildDetails{
|
||||
@ -1358,10 +1414,7 @@ func TestOverrides(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, api.Options{
|
||||
Goos: runtime.GOOS,
|
||||
Goarch: runtime.GOARCH,
|
||||
},
|
||||
}, mustParse(t, runtimeTarget),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, config.BuildDetails{
|
||||
@ -1380,10 +1433,7 @@ func TestOverrides(t *testing.T) {
|
||||
Goos: "{{ .Runtime.Goos }",
|
||||
},
|
||||
},
|
||||
}, api.Options{
|
||||
Goos: runtime.GOOS,
|
||||
Goarch: runtime.GOARCH,
|
||||
},
|
||||
}, mustParse(t, runtimeTarget),
|
||||
)
|
||||
testlib.RequireTemplateError(t, err)
|
||||
})
|
||||
@ -1405,11 +1455,7 @@ func TestOverrides(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, api.Options{
|
||||
Goos: "linux",
|
||||
Goarch: "arm64",
|
||||
Goarm64: "v8.0",
|
||||
},
|
||||
}, mustParse(t, "linux_arm64_v8.0"),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, config.BuildDetails{
|
||||
@ -1434,11 +1480,7 @@ func TestOverrides(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, api.Options{
|
||||
Goos: "linux",
|
||||
Goarch: "arm64",
|
||||
Goarm64: "v8.0",
|
||||
},
|
||||
}, mustParse(t, "linux_arm64_v8.0"),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, config.BuildDetails{
|
||||
@ -1464,11 +1506,7 @@ func TestOverrides(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, api.Options{
|
||||
Goos: "linux",
|
||||
Goarch: "arm",
|
||||
Goarm: "6",
|
||||
},
|
||||
}, mustParse(t, "linux_arm_6"),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, config.BuildDetails{
|
||||
@ -1493,11 +1531,7 @@ func TestOverrides(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, api.Options{
|
||||
Goos: "linux",
|
||||
Goarch: "arm",
|
||||
Goarm: "6",
|
||||
},
|
||||
}, mustParse(t, "linux_arm_6"),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, config.BuildDetails{
|
||||
@ -1523,11 +1557,7 @@ func TestOverrides(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, api.Options{
|
||||
Goos: "linux",
|
||||
Goarch: "mips",
|
||||
Gomips: "softfloat",
|
||||
},
|
||||
}, mustParse(t, "linux_mips_softfloat"),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, config.BuildDetails{
|
||||
@ -1552,11 +1582,7 @@ func TestOverrides(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, api.Options{
|
||||
Goos: "linux",
|
||||
Goarch: "mips",
|
||||
Gomips: "hardfloat",
|
||||
},
|
||||
}, mustParse(t, "linux_mips_hardfloat"),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, config.BuildDetails{
|
||||
@ -1582,11 +1608,7 @@ func TestOverrides(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, api.Options{
|
||||
Goos: "linux",
|
||||
Goarch: "riscv64",
|
||||
Goriscv64: "rva22u64",
|
||||
},
|
||||
}, mustParse(t, "linux_riscv64_rva22u64"),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, config.BuildDetails{
|
||||
@ -1612,11 +1634,7 @@ func TestOverrides(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, api.Options{
|
||||
Goos: "linux",
|
||||
Goarch: "riscv64",
|
||||
Goriscv64: "rva22u64",
|
||||
},
|
||||
}, mustParse(t, "linux_riscv64_rva22u64"),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, config.BuildDetails{
|
||||
@ -1642,11 +1660,7 @@ func TestOverrides(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, api.Options{
|
||||
Goos: "linux",
|
||||
Goarch: "386",
|
||||
Go386: "sse2",
|
||||
},
|
||||
}, mustParse(t, "linux_386_sse2"),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, config.BuildDetails{
|
||||
@ -1672,11 +1686,7 @@ func TestOverrides(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, api.Options{
|
||||
Goos: "linux",
|
||||
Goarch: "386",
|
||||
Go386: "sse2",
|
||||
},
|
||||
}, mustParse(t, "linux_386_sse2"),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, config.BuildDetails{
|
||||
@ -1733,7 +1743,7 @@ func TestInvalidGoBinaryTpl(t *testing.T) {
|
||||
})
|
||||
build := ctx.Config.Builds[0]
|
||||
testlib.RequireTemplateError(t, Default.Build(ctx, build, api.Options{
|
||||
Target: runtimeTarget,
|
||||
Target: mustParse(t, runtimeTarget),
|
||||
Name: build.Binary,
|
||||
Path: filepath.Join("dist", runtimeTarget, build.Binary),
|
||||
Ext: "",
|
||||
@ -1794,3 +1804,10 @@ func writeTest(t *testing.T, folder string) {
|
||||
0o666,
|
||||
))
|
||||
}
|
||||
|
||||
func mustParse(tb testing.TB, target string) Target {
|
||||
tb.Helper()
|
||||
got, err := Default.Parse(target)
|
||||
require.NoError(tb, err)
|
||||
return got.(Target)
|
||||
}
|
||||
|
63
internal/builders/golang/targets.go
Normal file
63
internal/builders/golang/targets.go
Normal file
@ -0,0 +1,63 @@
|
||||
package golang
|
||||
|
||||
import (
|
||||
"github.com/goreleaser/goreleaser/v2/internal/tmpl"
|
||||
"github.com/goreleaser/goreleaser/v2/pkg/config"
|
||||
)
|
||||
|
||||
func formatTarget(o config.BuildDetailsOverride) string {
|
||||
target := o.Goos + "_" + o.Goarch
|
||||
if extra := o.Goamd64 + o.Go386 + o.Goarm + o.Goarm64 + o.Gomips + o.Goppc64 + o.Goriscv64; extra != "" {
|
||||
target += "_" + extra
|
||||
}
|
||||
return target
|
||||
}
|
||||
|
||||
// Target is a Go build target.
|
||||
type Target struct {
|
||||
Target string
|
||||
Goos string
|
||||
Goarch string
|
||||
Goamd64 string
|
||||
Go386 string
|
||||
Goarm string
|
||||
Goarm64 string
|
||||
Gomips string
|
||||
Goppc64 string
|
||||
Goriscv64 string
|
||||
}
|
||||
|
||||
// Fields implements build.Target.
|
||||
func (t Target) Fields() map[string]string {
|
||||
return map[string]string{
|
||||
tmpl.KeyOS: t.Goos,
|
||||
tmpl.KeyArch: t.Goarch,
|
||||
tmpl.KeyAmd64: t.Goamd64,
|
||||
tmpl.Key386: t.Go386,
|
||||
tmpl.KeyArm: t.Goarm,
|
||||
tmpl.KeyArm64: t.Goarm64,
|
||||
tmpl.KeyMips: t.Gomips,
|
||||
tmpl.KeyPpc64: t.Goppc64,
|
||||
tmpl.KeyRiscv64: t.Goriscv64,
|
||||
}
|
||||
}
|
||||
|
||||
// String implements fmt.Stringer.
|
||||
func (t Target) String() string {
|
||||
return t.Target
|
||||
}
|
||||
|
||||
func (t Target) env() []string {
|
||||
return []string{
|
||||
"GOOS=" + t.Goos,
|
||||
"GOARCH=" + t.Goarch,
|
||||
"GOAMD64=" + t.Goamd64,
|
||||
"GO386=" + t.Go386,
|
||||
"GOARM=" + t.Goarm,
|
||||
"GOARM64=" + t.Goarm64,
|
||||
"GOMIPS=" + t.Gomips,
|
||||
"GOMIPS64=" + t.Gomips,
|
||||
"GOPPC64=" + t.Goppc64,
|
||||
"GORISCV64=" + t.Goriscv64,
|
||||
}
|
||||
}
|
@ -165,34 +165,15 @@ func buildOptionsForTarget(ctx *context.Context, build config.Build, target stri
|
||||
return nil, fmt.Errorf("%s is not a valid build target", target)
|
||||
}
|
||||
|
||||
goos := parts[0]
|
||||
goarch := parts[1]
|
||||
|
||||
buildOpts := builders.Options{
|
||||
Target: target,
|
||||
Ext: ext,
|
||||
Goos: goos,
|
||||
Goarch: goarch,
|
||||
Ext: ext,
|
||||
}
|
||||
|
||||
if len(parts) > 2 {
|
||||
//nolint:gocritic
|
||||
if strings.HasPrefix(goarch, "amd64") {
|
||||
buildOpts.Goamd64 = parts[2]
|
||||
} else if goarch == "386" {
|
||||
buildOpts.Go386 = parts[2]
|
||||
} else if strings.HasPrefix(goarch, "arm64") {
|
||||
buildOpts.Goarm64 = parts[2]
|
||||
} else if strings.HasPrefix(goarch, "arm") {
|
||||
buildOpts.Goarm = parts[2]
|
||||
} else if strings.HasPrefix(goarch, "mips") {
|
||||
buildOpts.Gomips = parts[2]
|
||||
} else if strings.HasPrefix(goarch, "ppc64") {
|
||||
buildOpts.Goppc64 = parts[2]
|
||||
} else if goarch == "riscv64" {
|
||||
buildOpts.Goriscv64 = parts[2]
|
||||
}
|
||||
t, err := builders.For(build.Builder).Parse(target)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buildOpts.Target = t
|
||||
|
||||
bin, err := tmpl.New(ctx).WithBuildOptions(buildOpts).Apply(build.Binary)
|
||||
if err != nil {
|
||||
@ -200,7 +181,7 @@ func buildOptionsForTarget(ctx *context.Context, build config.Build, target stri
|
||||
}
|
||||
|
||||
name := bin + ext
|
||||
dir := fmt.Sprintf("%s_%s", build.ID, target)
|
||||
dir := fmt.Sprintf("%s_%s", build.ID, t)
|
||||
noUnique, err := tmpl.New(ctx).Bool(build.NoUniqueDistDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/goreleaser/goreleaser/v2/internal/artifact"
|
||||
@ -24,11 +25,34 @@ var (
|
||||
errFailedDefault = errors.New("fake builder defaults failed")
|
||||
)
|
||||
|
||||
type fakeTarget struct {
|
||||
target string
|
||||
}
|
||||
|
||||
// String implements build.Target.
|
||||
func (f fakeTarget) String() string {
|
||||
return f.target
|
||||
}
|
||||
|
||||
// Fields implements build.Target.
|
||||
func (f fakeTarget) Fields() map[string]string {
|
||||
os, arch, _ := strings.Cut(f.target, "_")
|
||||
return map[string]string{
|
||||
tmpl.KeyOS: os,
|
||||
tmpl.KeyArch: arch,
|
||||
}
|
||||
}
|
||||
|
||||
type fakeBuilder struct {
|
||||
fail bool
|
||||
failDefault bool
|
||||
}
|
||||
|
||||
// Parse implements build.Builder.
|
||||
func (f *fakeBuilder) Parse(target string) (api.Target, error) {
|
||||
return fakeTarget{target}, nil
|
||||
}
|
||||
|
||||
func (f *fakeBuilder) WithDefaults(build config.Build) (config.Build, error) {
|
||||
if f.failDefault {
|
||||
return build, errFailedDefault
|
||||
@ -585,7 +609,7 @@ func TestBuildOptionsForTarget(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
build config.Build
|
||||
expectedOpts *api.Options
|
||||
expectedOpts api.Options
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
@ -597,13 +621,9 @@ func TestBuildOptionsForTarget(t *testing.T) {
|
||||
"linux_amd64",
|
||||
},
|
||||
},
|
||||
expectedOpts: &api.Options{
|
||||
Name: "testbinary",
|
||||
Path: filepath.Join(tmpDir, "testid_linux_amd64_v1", "testbinary"),
|
||||
Target: "linux_amd64_v1",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Goamd64: "v1",
|
||||
expectedOpts: api.Options{
|
||||
Name: "testbinary",
|
||||
Path: filepath.Join(tmpDir, "testid_linux_amd64_v1", "testbinary"),
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -615,13 +635,9 @@ func TestBuildOptionsForTarget(t *testing.T) {
|
||||
"linux_amd64",
|
||||
},
|
||||
},
|
||||
expectedOpts: &api.Options{
|
||||
Name: "testbinary_linux_amd64",
|
||||
Path: filepath.Join(tmpDir, "testid_linux_amd64_v1", "testbinary_linux_amd64"),
|
||||
Target: "linux_amd64_v1",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Goamd64: "v1",
|
||||
expectedOpts: api.Options{
|
||||
Name: "testbinary_linux_amd64",
|
||||
Path: filepath.Join(tmpDir, "testid_linux_amd64_v1", "testbinary_linux_amd64"),
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -634,13 +650,9 @@ func TestBuildOptionsForTarget(t *testing.T) {
|
||||
},
|
||||
NoUniqueDistDir: `{{ printf "true"}}`,
|
||||
},
|
||||
expectedOpts: &api.Options{
|
||||
Name: "distpath/linux/amd64/testbinary",
|
||||
Path: filepath.Join(tmpDir, "distpath", "linux", "amd64", "testbinary"),
|
||||
Target: "linux_amd64_v1",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Goamd64: "v1",
|
||||
expectedOpts: api.Options{
|
||||
Name: "distpath/linux/amd64/testbinary",
|
||||
Path: filepath.Join(tmpDir, "distpath", "linux", "amd64", "testbinary"),
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -653,13 +665,9 @@ func TestBuildOptionsForTarget(t *testing.T) {
|
||||
},
|
||||
NoUniqueDistDir: `{{ printf "false"}}`,
|
||||
},
|
||||
expectedOpts: &api.Options{
|
||||
Name: "testbinary",
|
||||
Path: filepath.Join(tmpDir, "testid_linux_amd64_v1", "testbinary"),
|
||||
Target: "linux_amd64_v1",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Goamd64: "v1",
|
||||
expectedOpts: api.Options{
|
||||
Name: "testbinary",
|
||||
Path: filepath.Join(tmpDir, "testid_linux_amd64_v1", "testbinary"),
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -671,13 +679,9 @@ func TestBuildOptionsForTarget(t *testing.T) {
|
||||
"linux_arm_6",
|
||||
},
|
||||
},
|
||||
expectedOpts: &api.Options{
|
||||
Name: "testbinary",
|
||||
Path: filepath.Join(tmpDir, "testid_linux_arm_6", "testbinary"),
|
||||
Target: "linux_arm_6",
|
||||
Goos: "linux",
|
||||
Goarch: "arm",
|
||||
Goarm: "6",
|
||||
expectedOpts: api.Options{
|
||||
Name: "testbinary",
|
||||
Path: filepath.Join(tmpDir, "testid_linux_arm_6", "testbinary"),
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -689,13 +693,9 @@ func TestBuildOptionsForTarget(t *testing.T) {
|
||||
"linux_mips_softfloat",
|
||||
},
|
||||
},
|
||||
expectedOpts: &api.Options{
|
||||
Name: "testbinary",
|
||||
Path: filepath.Join(tmpDir, "testid_linux_mips_softfloat", "testbinary"),
|
||||
Target: "linux_mips_softfloat",
|
||||
Goos: "linux",
|
||||
Goarch: "mips",
|
||||
Gomips: "softfloat",
|
||||
expectedOpts: api.Options{
|
||||
Name: "testbinary",
|
||||
Path: filepath.Join(tmpDir, "testid_linux_mips_softfloat", "testbinary"),
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -707,13 +707,9 @@ func TestBuildOptionsForTarget(t *testing.T) {
|
||||
"linux_amd64_v3",
|
||||
},
|
||||
},
|
||||
expectedOpts: &api.Options{
|
||||
Name: "testbinary",
|
||||
Path: filepath.Join(tmpDir, "testid_linux_amd64_v3", "testbinary"),
|
||||
Target: "linux_amd64_v3",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Goamd64: "v3",
|
||||
expectedOpts: api.Options{
|
||||
Name: "testbinary",
|
||||
Path: filepath.Join(tmpDir, "testid_linux_amd64_v3", "testbinary"),
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -728,7 +724,8 @@ func TestBuildOptionsForTarget(t *testing.T) {
|
||||
opts, err := buildOptionsForTarget(ctx, ctx.Config.Builds[0], ctx.Config.Builds[0].Targets[0])
|
||||
if tc.expectedErr == "" {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.expectedOpts, opts)
|
||||
opts.Target = nil
|
||||
require.Equal(t, tc.expectedOpts, *opts)
|
||||
} else {
|
||||
require.EqualError(t, err, tc.expectedErr)
|
||||
}
|
||||
|
14
internal/pipe/universalbinary/targets.go
Normal file
14
internal/pipe/universalbinary/targets.go
Normal file
@ -0,0 +1,14 @@
|
||||
package universalbinary
|
||||
|
||||
import "github.com/goreleaser/goreleaser/v2/internal/tmpl"
|
||||
|
||||
type unitarget struct{}
|
||||
|
||||
func (unitarget) String() string { return "darwin_all" }
|
||||
|
||||
func (unitarget) Fields() map[string]string {
|
||||
return map[string]string{
|
||||
tmpl.KeyOS: "darwin",
|
||||
tmpl.KeyArch: "all",
|
||||
}
|
||||
}
|
@ -55,9 +55,7 @@ func (Pipe) Run(ctx *context.Context) error {
|
||||
for _, unibin := range ctx.Config.UniversalBinaries {
|
||||
g.Go(func() error {
|
||||
opts := build.Options{
|
||||
Target: "darwin_all",
|
||||
Goos: "darwin",
|
||||
Goarch: "all",
|
||||
Target: unitarget{},
|
||||
}
|
||||
if !skips.Any(ctx, skips.PreBuildHooks) {
|
||||
if err := runHook(ctx, &opts, unibin.Hooks.Pre); err != nil {
|
||||
|
@ -179,7 +179,7 @@ func TestRun(t *testing.T) {
|
||||
},
|
||||
Post: []config.Hook{
|
||||
{Cmd: testlib.Touch(post)},
|
||||
{Cmd: testlib.ShC(`echo "{{ .Name }} {{ .Os }} {{ .Arch }} {{ .Arm }} {{ .Target }} {{ .Ext }}" > {{ .Path }}.post`), Output: true},
|
||||
{Cmd: testlib.ShC(`echo "{{ .Name }} {{ .Os }} {{ .Arch }} {{ .Target }} {{ .Ext }}" > {{ .Path }}.post`), Output: true},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -213,7 +213,7 @@ func TestRun(t *testing.T) {
|
||||
Post: []config.Hook{
|
||||
{Cmd: testlib.Touch(post)},
|
||||
{
|
||||
Cmd: testlib.ShC(`echo "{{ .Name }} {{ .Os }} {{ .Arch }} {{ .Arm }} {{ .Target }} {{ .Ext }}" > {{ .Path }}.post`),
|
||||
Cmd: testlib.ShC(`echo "{{ .Name }} {{ .Os }} {{ .Arch }} {{ .Target }} {{ .Ext }}" > {{ .Path }}.post`),
|
||||
Output: true,
|
||||
},
|
||||
},
|
||||
@ -312,7 +312,7 @@ func TestRun(t *testing.T) {
|
||||
require.FileExists(t, post)
|
||||
bts, err := os.ReadFile(post)
|
||||
require.NoError(t, err)
|
||||
require.Contains(t, string(bts), "foo darwin all darwin_all")
|
||||
require.Contains(t, string(bts), "foo darwin all darwin_all")
|
||||
})
|
||||
|
||||
t.Run("failing pre-hook", func(t *testing.T) {
|
||||
|
30
internal/testlib/artifacts.go
Normal file
30
internal/testlib/artifacts.go
Normal file
@ -0,0 +1,30 @@
|
||||
package testlib
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/goreleaser/goreleaser/v2/internal/artifact"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func RequireEqualArtifacts(tb testing.TB, expected, got []*artifact.Artifact) {
|
||||
tb.Helper()
|
||||
slices.SortFunc(expected, artifactSort)
|
||||
slices.SortFunc(got, artifactSort)
|
||||
require.Equal(tb, filenames(expected), filenames(got))
|
||||
require.Equal(tb, expected, got)
|
||||
}
|
||||
|
||||
func artifactSort(a, b *artifact.Artifact) int {
|
||||
return strings.Compare(a.Path, b.Path)
|
||||
}
|
||||
|
||||
func filenames(ts []*artifact.Artifact) []string {
|
||||
result := make([]string, len(ts))
|
||||
for i, t := range ts {
|
||||
result[i] = t.Path
|
||||
}
|
||||
return result
|
||||
}
|
@ -28,8 +28,21 @@ type Template struct {
|
||||
// Fields that will be available to the template engine.
|
||||
type Fields map[string]interface{}
|
||||
|
||||
// Template fields names used in build targets and more.
|
||||
const (
|
||||
KeyOS = "Os"
|
||||
KeyArch = "Arch"
|
||||
KeyAmd64 = "Amd64"
|
||||
Key386 = "I386"
|
||||
KeyArm = "Arm"
|
||||
KeyArm64 = "Arm64"
|
||||
KeyMips = "Mips"
|
||||
KeyPpc64 = "Ppc64"
|
||||
KeyRiscv64 = "Riscv64"
|
||||
)
|
||||
|
||||
// general keys.
|
||||
const (
|
||||
// general keys.
|
||||
projectName = "ProjectName"
|
||||
version = "Version"
|
||||
rawVersion = "RawVersion"
|
||||
@ -65,23 +78,18 @@ const (
|
||||
modulePath = "ModulePath"
|
||||
releaseNotes = "ReleaseNotes"
|
||||
runtimeK = "Runtime"
|
||||
)
|
||||
|
||||
// artifact-only keys.
|
||||
osKey = "Os"
|
||||
arch = "Arch"
|
||||
amd64 = "Amd64"
|
||||
go386 = "I386"
|
||||
arm = "Arm"
|
||||
arm64 = "Arm64"
|
||||
mips = "Mips"
|
||||
ppc64 = "Ppc64"
|
||||
riscv64 = "Riscv64"
|
||||
// artifact-only keys.
|
||||
const (
|
||||
binary = "Binary"
|
||||
artifactName = "ArtifactName"
|
||||
artifactExt = "ArtifactExt"
|
||||
artifactPath = "ArtifactPath"
|
||||
)
|
||||
|
||||
// build keys.
|
||||
// build keys.
|
||||
const (
|
||||
name = "Name"
|
||||
ext = "Ext"
|
||||
path = "Path"
|
||||
@ -177,15 +185,15 @@ func (t *Template) WithEnv(e map[string]string) *Template {
|
||||
// WithArtifact populates Fields from the artifact.
|
||||
func (t *Template) WithArtifact(a *artifact.Artifact) *Template {
|
||||
return t.WithExtraFields(Fields{
|
||||
osKey: a.Goos,
|
||||
arch: a.Goarch,
|
||||
amd64: a.Goamd64,
|
||||
go386: a.Go386,
|
||||
arm: a.Goarm,
|
||||
arm64: a.Goarm64,
|
||||
mips: a.Gomips,
|
||||
ppc64: a.Goppc64,
|
||||
riscv64: a.Goriscv64,
|
||||
KeyOS: a.Goos,
|
||||
KeyArch: a.Goarch,
|
||||
KeyAmd64: a.Goamd64,
|
||||
Key386: a.Go386,
|
||||
KeyArm: a.Goarm,
|
||||
KeyArm64: a.Goarm64,
|
||||
KeyMips: a.Gomips,
|
||||
KeyPpc64: a.Goppc64,
|
||||
KeyRiscv64: a.Goriscv64,
|
||||
binary: artifact.ExtraOr(*a, binary, t.fields[projectName].(string)),
|
||||
artifactName: a.Name,
|
||||
artifactExt: artifact.ExtraOr(*a, artifact.ExtraExt, ""),
|
||||
@ -198,21 +206,29 @@ func (t *Template) WithBuildOptions(opts build.Options) *Template {
|
||||
}
|
||||
|
||||
func buildOptsToFields(opts build.Options) Fields {
|
||||
return Fields{
|
||||
target: opts.Target,
|
||||
ext: opts.Ext,
|
||||
name: opts.Name,
|
||||
path: opts.Path,
|
||||
osKey: opts.Goos,
|
||||
arch: opts.Goarch,
|
||||
amd64: opts.Goamd64,
|
||||
go386: opts.Go386,
|
||||
arm: opts.Goarm,
|
||||
arm64: opts.Goarm64,
|
||||
mips: opts.Gomips,
|
||||
ppc64: opts.Goppc64,
|
||||
riscv64: opts.Goriscv64,
|
||||
f := Fields{
|
||||
target: opts.Target.String(),
|
||||
ext: opts.Ext,
|
||||
name: opts.Name,
|
||||
path: opts.Path,
|
||||
|
||||
// set them all to empty, which should prevent breaking templates.
|
||||
// the .Fields() call will override whichever values are actually
|
||||
// available.
|
||||
KeyOS: "",
|
||||
KeyArch: "",
|
||||
KeyAmd64: "",
|
||||
Key386: "",
|
||||
KeyArm: "",
|
||||
KeyArm64: "",
|
||||
KeyMips: "",
|
||||
KeyPpc64: "",
|
||||
KeyRiscv64: "",
|
||||
}
|
||||
for k, v := range opts.Target.Fields() {
|
||||
f[k] = v
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// Bool Apply the given string, and converts it to a bool.
|
||||
|
@ -460,17 +460,21 @@ func TestInvalidMap(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithBuildOptions(t *testing.T) {
|
||||
// testtarget doesn ot set riscv64, it still should not fail to compile the template
|
||||
ts := "{{.Name}}_{{.Path}}_{{.Ext}}_{{.Target}}_{{.Os}}_{{.Arch}}_{{.Amd64}}_{{.Arm}}_{{.Mips}}{{with .Riscv64}}{{.}}{{end}}"
|
||||
out, err := New(testctx.New()).WithBuildOptions(build.Options{
|
||||
Name: "name",
|
||||
Path: "./path",
|
||||
Ext: ".ext",
|
||||
Target: "target",
|
||||
Goos: "os",
|
||||
Goarch: "arch",
|
||||
Goamd64: "amd64",
|
||||
Goarm: "arm",
|
||||
Gomips: "mips",
|
||||
}).Apply("{{.Name}}_{{.Path}}_{{.Ext}}_{{.Target}}_{{.Os}}_{{.Arch}}_{{.Amd64}}_{{.Arm}}_{{.Mips}}")
|
||||
Name: "name",
|
||||
Path: "./path",
|
||||
Ext: ".ext",
|
||||
Target: testTarget{
|
||||
Target: "target",
|
||||
Goos: "os",
|
||||
Goarch: "arch",
|
||||
Goamd64: "amd64",
|
||||
Goarm: "arm",
|
||||
Gomips: "mips",
|
||||
},
|
||||
}).Apply(ts)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "name_./path_.ext_target_os_arch_amd64_arm_mips", out)
|
||||
}
|
||||
@ -491,3 +495,25 @@ func TestReuseTpl(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "bar", s3)
|
||||
}
|
||||
|
||||
type testTarget struct {
|
||||
Target string
|
||||
Goos string
|
||||
Goarch string
|
||||
Goamd64 string
|
||||
Goarm string
|
||||
Gomips string
|
||||
}
|
||||
|
||||
func (t testTarget) String() string { return t.Target }
|
||||
|
||||
func (t testTarget) Fields() map[string]string {
|
||||
return map[string]string{
|
||||
target: t.Target,
|
||||
KeyOS: t.Goos,
|
||||
KeyArch: t.Goarch,
|
||||
KeyAmd64: t.Goamd64,
|
||||
KeyArm: t.Goarm,
|
||||
KeyMips: t.Gomips,
|
||||
}
|
||||
}
|
||||
|
@ -28,23 +28,27 @@ func For(name string) Builder {
|
||||
|
||||
// Options to be passed down to a builder.
|
||||
type Options struct {
|
||||
Name string
|
||||
Path string
|
||||
Ext string // with the leading `.`.
|
||||
Target string
|
||||
Goos string
|
||||
Goarch string
|
||||
Goamd64 string
|
||||
Go386 string
|
||||
Goarm string
|
||||
Goarm64 string
|
||||
Gomips string
|
||||
Goppc64 string
|
||||
Goriscv64 string
|
||||
Name string
|
||||
Path string
|
||||
Ext string // with the leading `.`.
|
||||
Target Target
|
||||
}
|
||||
|
||||
// Target represents a build target.
|
||||
//
|
||||
// Each Builder implementation can implement its own.
|
||||
type Target interface {
|
||||
// String returns the original target.
|
||||
String() string
|
||||
|
||||
// Fields returns the template fields that will be available for this
|
||||
// target (e.g. Os, Arch, etc).
|
||||
Fields() map[string]string
|
||||
}
|
||||
|
||||
// Builder defines a builder.
|
||||
type Builder interface {
|
||||
WithDefaults(build config.Build) (config.Build, error)
|
||||
Build(ctx *context.Context, build config.Build, options Options) error
|
||||
Parse(target string) (Target, error)
|
||||
}
|
||||
|
@ -8,8 +8,25 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type dummyTarget struct{}
|
||||
|
||||
// String implements Target.
|
||||
func (d dummyTarget) String() string {
|
||||
return "dummy"
|
||||
}
|
||||
|
||||
// Fields implements Target.
|
||||
func (d dummyTarget) Fields() map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
type dummy struct{}
|
||||
|
||||
// Parse implements Builder.
|
||||
func (d *dummy) Parse(string) (Target, error) {
|
||||
return dummyTarget{}, nil
|
||||
}
|
||||
|
||||
func (*dummy) WithDefaults(build config.Build) (config.Build, error) {
|
||||
return build, nil
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user