1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-09-16 09:26:52 +02:00

refactoring buildtarget

This commit is contained in:
Carlos Alexandro Becker
2017-07-06 19:49:21 -03:00
parent 7f2b04f16a
commit 2e0e05134d
11 changed files with 159 additions and 92 deletions

View File

@@ -0,0 +1,37 @@
package buildtarget
import (
"fmt"
"runtime"
)
// Runtime is the current runtime buildTarget
var Runtime = Target{runtime.GOOS, runtime.GOARCH, ""}
// New builtarget
func New(goos, goarch, goarm string) Target {
return Target{goos, goarch, goarm}
}
// Target is a build target
type Target struct {
OS, Arch, Arm string
}
// Env returns the current Target as environment variables
func (t Target) Env() []string {
return []string{
"GOOS=" + t.OS,
"GOARCH=" + t.Arch,
"GOARM=" + t.Arm,
}
}
func (t Target) String() string {
return fmt.Sprintf("%v%v%v", t.OS, t.Arch, t.Arm)
}
// PrettyString is a prettier version of the String method.
func (t Target) PrettyString() string {
return fmt.Sprintf("%v/%v%v", t.OS, t.Arch, t.Arm)
}

View File

@@ -0,0 +1,31 @@
package buildtarget
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestEnv(t *testing.T) {
var assert = assert.New(t)
assert.Equal(
[]string{"GOOS=linux", "GOARCH=arm64", "GOARM=6"},
New("linux", "arm64", "6").Env(),
)
}
func TestString(t *testing.T) {
var assert = assert.New(t)
assert.Equal(
"linuxarm7",
New("linux", "arm", "7").String(),
)
}
func TestPrettyString(t *testing.T) {
var assert = assert.New(t)
assert.Equal(
"linux/arm646",
New("linux", "arm64", "6").PrettyString(),
)
}

View File

@@ -1,10 +1,10 @@
package ext package ext
import "strings" import "github.com/goreleaser/goreleaser/internal/buildtarget"
// For returns the binary extension for the given platform // For returns the binary extension for the given platform
func For(platform string) (ext string) { func For(target buildtarget.Target) (ext string) {
if strings.HasPrefix(platform, "windows") { if target.OS == "windows" {
ext = ".exe" ext = ".exe"
} }
return return

View File

@@ -3,16 +3,17 @@ package ext
import ( import (
"testing" "testing"
"github.com/goreleaser/goreleaser/internal/buildtarget"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestExtWindows(t *testing.T) { func TestExtWindows(t *testing.T) {
assert.Equal(t, ".exe", For("windows")) assert.Equal(t, ".exe", For(buildtarget.New("windows", "", "")))
assert.Equal(t, ".exe", For("windowsamd64")) assert.Equal(t, ".exe", For(buildtarget.New("windows", "adm64", "")))
} }
func TestExtOthers(t *testing.T) { func TestExtOthers(t *testing.T) {
assert.Empty(t, "", For("linux")) assert.Empty(t, "", For(buildtarget.New("linux", "", "")))
assert.Empty(t, "", For("linuxwin")) assert.Empty(t, "", For(buildtarget.New("linuxwin", "", "")))
assert.Empty(t, "", For("winasdasd")) assert.Empty(t, "", For(buildtarget.New("winasdasd", "sad", "6")))
} }

View File

@@ -8,6 +8,7 @@ import (
"github.com/goreleaser/goreleaser/config" "github.com/goreleaser/goreleaser/config"
"github.com/goreleaser/goreleaser/context" "github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/internal/buildtarget"
) )
type nameData struct { type nameData struct {
@@ -22,12 +23,12 @@ type nameData struct {
// ForBuild return the name for the given context, goos, goarch, goarm and // ForBuild return the name for the given context, goos, goarch, goarm and
// build, using the build.Binary property instead of project_name. // build, using the build.Binary property instead of project_name.
func ForBuild(ctx *context.Context, build config.Build, goos, goarch, goarm string) (string, error) { func ForBuild(ctx *context.Context, build config.Build, target buildtarget.Target) (string, error) {
return apply( return apply(
nameData{ nameData{
Os: replace(ctx.Config.Archive.Replacements, goos), Os: replace(ctx.Config.Archive.Replacements, target.OS),
Arch: replace(ctx.Config.Archive.Replacements, goarch), Arch: replace(ctx.Config.Archive.Replacements, target.Arch),
Arm: replace(ctx.Config.Archive.Replacements, goarm), Arm: replace(ctx.Config.Archive.Replacements, target.Arm),
Version: ctx.Version, Version: ctx.Version,
Tag: ctx.Git.CurrentTag, Tag: ctx.Git.CurrentTag,
Binary: build.Binary, Binary: build.Binary,
@@ -38,12 +39,12 @@ func ForBuild(ctx *context.Context, build config.Build, goos, goarch, goarm stri
} }
// For returns the name for the given context, goos, goarch and goarm. // For returns the name for the given context, goos, goarch and goarm.
func For(ctx *context.Context, goos, goarch, goarm string) (string, error) { func For(ctx *context.Context, target buildtarget.Target) (string, error) {
return apply( return apply(
nameData{ nameData{
Os: replace(ctx.Config.Archive.Replacements, goos), Os: replace(ctx.Config.Archive.Replacements, target.OS),
Arch: replace(ctx.Config.Archive.Replacements, goarch), Arch: replace(ctx.Config.Archive.Replacements, target.Arch),
Arm: replace(ctx.Config.Archive.Replacements, goarm), Arm: replace(ctx.Config.Archive.Replacements, target.Arm),
Version: ctx.Version, Version: ctx.Version,
Tag: ctx.Git.CurrentTag, Tag: ctx.Git.CurrentTag,
Binary: ctx.Config.ProjectName, Binary: ctx.Config.ProjectName,

View File

@@ -5,6 +5,7 @@ import (
"github.com/goreleaser/goreleaser/config" "github.com/goreleaser/goreleaser/config"
"github.com/goreleaser/goreleaser/context" "github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/internal/buildtarget"
"github.com/goreleaser/goreleaser/pipeline/defaults" "github.com/goreleaser/goreleaser/pipeline/defaults"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@@ -30,7 +31,7 @@ func TestNameFor(t *testing.T) {
}, },
} }
name, err := For(ctx, "darwin", "amd64", "") name, err := For(ctx, buildtarget.New("darwin", "amd64", ""))
assert.NoError(err) assert.NoError(err)
assert.Equal("test_Darwin_x86_64_v1.2.3_1.2.3", name) assert.Equal("test_Darwin_x86_64_v1.2.3_1.2.3", name)
} }
@@ -55,7 +56,11 @@ func TestNameForBuild(t *testing.T) {
}, },
} }
name, err := ForBuild(ctx, config.Build{Binary: "foo"}, "darwin", "amd64", "") name, err := ForBuild(
ctx,
config.Build{Binary: "foo"},
buildtarget.New("darwin", "amd64", ""),
)
assert.NoError(err) assert.NoError(err)
assert.Equal("foo_Darwin_x86_64_v1.2.3_1.2.3", name) assert.Equal("foo_Darwin_x86_64_v1.2.3_1.2.3", name)
} }
@@ -74,7 +79,7 @@ func TestInvalidNameTemplate(t *testing.T) {
}, },
} }
_, err := For(ctx, "darwin", "amd64", "") _, err := For(ctx, buildtarget.New("darwin", "amd64", ""))
assert.Error(err) assert.Error(err)
} }
@@ -92,13 +97,13 @@ func TestNameDefaltTemplate(t *testing.T) {
type buildTarget struct { type buildTarget struct {
goos, goarch, goarm string goos, goarch, goarm string
} }
for key, target := range map[string]buildTarget{ for key, target := range map[string]buildtarget.Target{
"test_1.2.3_darwin_amd64": {"darwin", "amd64", ""}, "test_1.2.3_darwin_amd64": buildtarget.New("darwin", "amd64", ""),
"test_1.2.3_linux_arm64": {"linux", "arm64", ""}, "test_1.2.3_linux_arm64": buildtarget.New("linux", "arm64", ""),
"test_1.2.3_linux_armv7": {"linux", "arm", "7"}, "test_1.2.3_linux_armv7": buildtarget.New("linux", "arm", "7"),
} { } {
t.Run(key, func(t *testing.T) { t.Run(key, func(t *testing.T) {
name, err := For(ctx, target.goos, target.goarch, target.goarm) name, err := For(ctx, target)
assert.NoError(err) assert.NoError(err)
assert.Equal(key, name) assert.Equal(key, name)
}) })

View File

@@ -61,13 +61,14 @@ func create(ctx *context.Context, platform, name string) error {
return err return err
} }
} }
var path = filepath.Join(ctx.Config.Dist, name) var basepath = filepath.Join(ctx.Config.Dist, name)
binaries, err := ioutil.ReadDir(path) binaries, err := ioutil.ReadDir(basepath)
if err != nil { if err != nil {
return err return err
} }
for _, binary := range binaries { for _, binary := range binaries {
if err := archive.Add(binary.Name(), filepath.Join(path, binary.Name())); err != nil { var path = filepath.Join(basepath, binary.Name())
if err := archive.Add(binary.Name(), path); err != nil {
return err return err
} }
} }

View File

@@ -12,6 +12,7 @@ import (
"github.com/apex/log" "github.com/apex/log"
"github.com/goreleaser/goreleaser/config" "github.com/goreleaser/goreleaser/config"
"github.com/goreleaser/goreleaser/context" "github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/internal/buildtarget"
"github.com/goreleaser/goreleaser/internal/ext" "github.com/goreleaser/goreleaser/internal/ext"
"github.com/goreleaser/goreleaser/internal/name" "github.com/goreleaser/goreleaser/internal/name"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
@@ -65,30 +66,18 @@ func runHook(env []string, hook string) error {
} }
log.WithField("hook", hook).Info("running hook") log.WithField("hook", hook).Info("running hook")
cmd := strings.Fields(hook) cmd := strings.Fields(hook)
return run(runtimeTarget, cmd, env) return run(buildtarget.Runtime, cmd, env)
} }
func doBuild(ctx *context.Context, build config.Build, target buildTarget) error { func doBuild(ctx *context.Context, build config.Build, target buildtarget.Target) error {
folder, err := name.For(ctx, target.goos, target.goarch, target.goarm) folder, err := name.For(ctx, target)
if err != nil { if err != nil {
return err return err
} }
ctx.AddFolder(target.String(), folder) ctx.AddFolder(target.String(), folder)
var binary = filepath.Join( binary, err := binaryName(ctx, build, target, folder)
ctx.Config.Dist, if err != nil {
folder, return err
build.Binary+ext.For(target.goos),
)
if ctx.Config.Archive.Format == "binary" {
bin, err := name.ForBuild(ctx, build, target.goos, target.goarch, target.goarm)
if err != nil {
return err
}
binary = filepath.Join(
ctx.Config.Dist,
folder,
bin+ext.For(target.goos),
)
} }
log.WithField("binary", binary).Info("building") log.WithField("binary", binary).Info("building")
cmd := []string{"go", "build"} cmd := []string{"go", "build"}
@@ -103,10 +92,27 @@ func doBuild(ctx *context.Context, build config.Build, target buildTarget) error
return run(target, cmd, build.Env) return run(target, cmd, build.Env)
} }
func run(target buildTarget, command, env []string) error { func binaryName(
ctx *context.Context,
build config.Build,
target buildtarget.Target,
folder string,
) (binary string, err error) {
if ctx.Config.Archive.Format == "binary" {
binary, err = name.ForBuild(ctx, build, target)
if err != nil {
return
}
binary = binary + ext.For(target)
}
binary = build.Binary + ext.For(target)
return filepath.Join(ctx.Config.Dist, folder, binary), nil
}
func run(target buildtarget.Target, command, env []string) error {
var cmd = exec.Command(command[0], command[1:]...) var cmd = exec.Command(command[0], command[1:]...)
env = append(env, "GOOS="+target.goos, "GOARCH="+target.goarch, "GOARM="+target.goarm) env = append(env, target.Env()...)
var log = log.WithField("target", target.PrettyString()). var log = log.WithField("target", target.String()).
WithField("env", env). WithField("env", env).
WithField("cmd", command) WithField("cmd", command)
cmd.Env = append(cmd.Env, os.Environ()...) cmd.Env = append(cmd.Env, os.Environ()...)
@@ -114,7 +120,7 @@ func run(target buildTarget, command, env []string) error {
log.Debug("running") log.Debug("running")
if out, err := cmd.CombinedOutput(); err != nil { if out, err := cmd.CombinedOutput(); err != nil {
log.WithError(err).Debug("failed") log.WithError(err).Debug("failed")
return fmt.Errorf("build failed for %s:\n%v", target.PrettyString(), string(out)) return fmt.Errorf("build failed for %s:\n%v", target.String(), string(out))
} }
return nil return nil
} }

View File

@@ -9,6 +9,7 @@ import (
"github.com/goreleaser/goreleaser/config" "github.com/goreleaser/goreleaser/config"
"github.com/goreleaser/goreleaser/context" "github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/internal/buildtarget"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@@ -19,11 +20,11 @@ func TestPipeDescription(t *testing.T) {
} }
func TestRun(t *testing.T) { func TestRun(t *testing.T) {
assert.NoError(t, run(runtimeTarget, []string{"go", "list", "./..."}, emptyEnv)) assert.NoError(t, run(buildtarget.Runtime, []string{"go", "list", "./..."}, emptyEnv))
} }
func TestRunInvalidCommand(t *testing.T) { func TestRunInvalidCommand(t *testing.T) {
assert.Error(t, run(runtimeTarget, []string{"gggggo", "nope"}, emptyEnv)) assert.Error(t, run(buildtarget.Runtime, []string{"gggggo", "nope"}, emptyEnv))
} }
func TestBuild(t *testing.T) { func TestBuild(t *testing.T) {
@@ -41,7 +42,7 @@ func TestBuild(t *testing.T) {
Config: config, Config: config,
Folders: map[string]string{}, Folders: map[string]string{},
} }
assert.NoError(doBuild(ctx, ctx.Config.Builds[0], runtimeTarget)) assert.NoError(doBuild(ctx, ctx.Config.Builds[0], buildtarget.Runtime))
} }
func TestRunFullPipe(t *testing.T) { func TestRunFullPipe(t *testing.T) {

View File

@@ -1,37 +1,20 @@
package build package build
import ( import (
"fmt"
"runtime"
"github.com/apex/log" "github.com/apex/log"
"github.com/goreleaser/goreleaser/config" "github.com/goreleaser/goreleaser/config"
"github.com/goreleaser/goreleaser/internal/buildtarget"
) )
var runtimeTarget = buildTarget{runtime.GOOS, runtime.GOARCH, ""} func buildTargets(build config.Build) (targets []buildtarget.Target) {
// a build target
type buildTarget struct {
goos, goarch, goarm string
}
func (t buildTarget) String() string {
return fmt.Sprintf("%v%v%v", t.goos, t.goarch, t.goarm)
}
func (t buildTarget) PrettyString() string {
return fmt.Sprintf("%v/%v%v", t.goos, t.goarch, t.goarm)
}
func buildTargets(build config.Build) (targets []buildTarget) {
for _, target := range allBuildTargets(build) { for _, target := range allBuildTargets(build) {
if !valid(target) { if !valid(target) {
log.WithField("target", target.PrettyString()). log.WithField("target", target.String()).
Warn("skipped invalid build") Warn("skipped invalid build")
continue continue
} }
if ignored(build, target) { if ignored(build, target) {
log.WithField("target", target.PrettyString()). log.WithField("target", target.String()).
Warn("skipped ignored build") Warn("skipped ignored build")
continue continue
} }
@@ -40,24 +23,24 @@ func buildTargets(build config.Build) (targets []buildTarget) {
return return
} }
func allBuildTargets(build config.Build) (targets []buildTarget) { func allBuildTargets(build config.Build) (targets []buildtarget.Target) {
for _, goos := range build.Goos { for _, goos := range build.Goos {
for _, goarch := range build.Goarch { for _, goarch := range build.Goarch {
if goarch == "arm" { if goarch == "arm" {
for _, goarm := range build.Goarm { for _, goarm := range build.Goarm {
targets = append(targets, buildTarget{goos, goarch, goarm}) targets = append(targets, buildtarget.New(goos, goarch, goarm))
} }
continue continue
} }
targets = append(targets, buildTarget{goos, goarch, ""}) targets = append(targets, buildtarget.New(goos, goarch, ""))
} }
} }
return return
} }
func ignored(build config.Build, target buildTarget) bool { func ignored(build config.Build, target buildtarget.Target) bool {
for _, ig := range build.Ignore { for _, ig := range build.Ignore {
var ignored = buildTarget{ig.Goos, ig.Goarch, ig.Goarm} var ignored = buildtarget.New(ig.Goos, ig.Goarch, ig.Goarm)
if ignored == target { if ignored == target {
return true return true
} }
@@ -65,8 +48,8 @@ func ignored(build config.Build, target buildTarget) bool {
return false return false
} }
func valid(target buildTarget) bool { func valid(target buildtarget.Target) bool {
var s = target.goos + target.goarch var s = target.OS + target.Arch
for _, a := range valids { for _, a := range valids {
if a == s { if a == s {
return true return true

View File

@@ -5,6 +5,7 @@ import (
"testing" "testing"
"github.com/goreleaser/goreleaser/config" "github.com/goreleaser/goreleaser/config"
"github.com/goreleaser/goreleaser/internal/buildtarget"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@@ -37,16 +38,16 @@ func TestAllBuildTargets(t *testing.T) {
}, },
}, },
} }
assert.Equal([]buildTarget{ assert.Equal([]buildtarget.Target{
{"linux", "386", ""}, buildtarget.New("linux", "386", ""),
{"linux", "amd64", ""}, buildtarget.New("linux", "amd64", ""),
{"linux", "arm", "6"}, buildtarget.New("linux", "arm", "6"),
{"linux", "arm64", ""}, buildtarget.New("linux", "arm64", ""),
{"darwin", "amd64", ""}, buildtarget.New("darwin", "amd64", ""),
{"freebsd", "386", ""}, buildtarget.New("freebsd", "386", ""),
{"freebsd", "amd64", ""}, buildtarget.New("freebsd", "amd64", ""),
{"freebsd", "arm", "6"}, buildtarget.New("freebsd", "arm", "6"),
{"freebsd", "arm", "7"}, buildtarget.New("freebsd", "arm", "7"),
}, buildTargets(build)) }, buildTargets(build))
} }
@@ -85,7 +86,7 @@ func TestValidGoosGoarchCombos(t *testing.T) {
} }
for _, p := range platforms { for _, p := range platforms {
t.Run(fmt.Sprintf("%v %v is valid", p.os, p.arch), func(t *testing.T) { t.Run(fmt.Sprintf("%v %v is valid", p.os, p.arch), func(t *testing.T) {
assert.True(t, valid(buildTarget{p.os, p.arch, ""})) assert.True(t, valid(buildtarget.New(p.os, p.arch, "")))
}) })
} }
} }
@@ -101,7 +102,7 @@ func TestInvalidGoosGoarchCombos(t *testing.T) {
} }
for _, p := range platforms { for _, p := range platforms {
t.Run(fmt.Sprintf("%v %v is invalid", p.os, p.arch), func(t *testing.T) { t.Run(fmt.Sprintf("%v %v is invalid", p.os, p.arch), func(t *testing.T) {
assert.False(t, valid(buildTarget{p.os, p.arch, ""})) assert.False(t, valid(buildtarget.New(p.os, p.arch, "")))
}) })
} }
} }