From 0525e9014cb4cd7688749605b95da64641d6d371 Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Mon, 24 Apr 2017 14:27:21 -0300 Subject: [PATCH] added goarch option to build section --- README.md | 6 +++- config/config.go | 1 + pipeline/build/build.go | 52 +++++++++++++++++------------------ pipeline/build/build_test.go | 37 +++++++++++++++++++++++-- pipeline/build/name.go | 8 ++++-- pipeline/build/name_test.go | 32 +++++++++++++++++++-- pipeline/build/target.go | 39 ++++++++++++++++++++++++++ pipeline/defaults/defaults.go | 8 +++++- 8 files changed, 146 insertions(+), 37 deletions(-) create mode 100644 pipeline/build/target.go diff --git a/README.md b/README.md index 47d590c6b..3d677557a 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,9 @@ build: - linux goarch: - amd64 + goarm: + - 6 + - 7 # Archive customization archive: format: tar.gz @@ -246,7 +249,8 @@ archive: # - Version (Tag with the `v` prefix stripped) # - Os # - Arch - # The default is `{{.Binary}}_{{.Os}}_{{.Arch}}` + # - Arm (ARM version) + # The default is `{{ .Binary }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}` name_template: "{{.Binary}}_{{.Version}}_{{.Os}}_{{.Arch}}" # Archive format. Valid options are `tar.gz` and `zip`. diff --git a/config/config.go b/config/config.go index e214905ee..acda4c87e 100644 --- a/config/config.go +++ b/config/config.go @@ -42,6 +42,7 @@ type Hooks struct { type Build struct { Goos []string Goarch []string + Goarm []string Main string Ldflags string Flags string diff --git a/pipeline/build/build.go b/pipeline/build/build.go index 79fd7a692..3138f4afe 100644 --- a/pipeline/build/build.go +++ b/pipeline/build/build.go @@ -8,7 +8,6 @@ import ( "os" "os/exec" "path/filepath" - "runtime" "strings" "github.com/goreleaser/goreleaser/context" @@ -30,27 +29,21 @@ func (Pipe) Run(ctx *context.Context) error { } sem := make(chan bool, 4) var g errgroup.Group - for _, goos := range ctx.Config.Build.Goos { - for _, goarch := range ctx.Config.Build.Goarch { - goos := goos - goarch := goarch - if !valid(goos, goarch) { - log.Printf("Skipped build for %v/%v\n", goos, goarch) - continue - } - sem <- true - name, err := nameFor(ctx, goos, goarch) - if err != nil { - return err - } - ctx.Archives[goos+goarch] = name - g.Go(func() error { - defer func() { - <-sem - }() - return build(name, goos, goarch, ctx) - }) + for _, target := range allBuildTargets(ctx) { + name, err := nameFor(ctx, target) + if err != nil { + return err } + ctx.Archives[target.String()] = name + + sem <- true + target := target + g.Go(func() error { + defer func() { + <-sem + }() + return build(ctx, name, target) + }) } if err := g.Wait(); err != nil { return err @@ -64,14 +57,14 @@ func runHook(hook string) error { } log.Println("Running hook", hook) cmd := strings.Fields(hook) - return run(runtime.GOOS, runtime.GOARCH, cmd) + return run(runtimeTarget, cmd) } -func build(name, goos, goarch string, ctx *context.Context) error { +func build(ctx *context.Context, name string, target buildTarget) error { output := filepath.Join( ctx.Config.Dist, name, - ctx.Config.Build.Binary+extFor(goos), + ctx.Config.Build.Binary+extFor(target.goos), ) log.Println("Building", output) cmd := []string{"go", "build"} @@ -83,13 +76,18 @@ func build(name, goos, goarch string, ctx *context.Context) error { return err } cmd = append(cmd, "-ldflags="+flags, "-o", output, ctx.Config.Build.Main) - return run(goos, goarch, cmd) + return run(target, cmd) } -func run(goos, goarch string, command []string) error { +func run(target buildTarget, command []string) error { cmd := exec.Command(command[0], command[1:]...) cmd.Env = append(cmd.Env, os.Environ()...) - cmd.Env = append(cmd.Env, "GOOS="+goos, "GOARCH="+goarch) + cmd.Env = append( + cmd.Env, + "GOOS="+target.goos, + "GOARCH="+target.goarch, + "GOARM="+target.goarm, + ) if out, err := cmd.CombinedOutput(); err != nil { return errors.New(string(out)) } diff --git a/pipeline/build/build_test.go b/pipeline/build/build_test.go index 64b809ea6..2e95bc3c7 100644 --- a/pipeline/build/build_test.go +++ b/pipeline/build/build_test.go @@ -17,11 +17,11 @@ func TestPipeDescription(t *testing.T) { } func TestRun(t *testing.T) { - assert.NoError(t, run(runtime.GOOS, runtime.GOARCH, []string{"go", "list", "./..."})) + assert.NoError(t, run(runtimeTarget, []string{"go", "list", "./..."})) } func TestRunInvalidCommand(t *testing.T) { - assert.Error(t, run(runtime.GOOS, runtime.GOARCH, []string{"gggggo", "nope"})) + assert.Error(t, run(runtimeTarget, []string{"gggggo", "nope"})) } func TestBuild(t *testing.T) { @@ -35,7 +35,7 @@ func TestBuild(t *testing.T) { var ctx = &context.Context{ Config: config, } - assert.NoError(build("build_test", runtime.GOOS, runtime.GOARCH, ctx)) + assert.NoError(build(ctx, "build_test", runtimeTarget)) } func TestRunFullPipe(t *testing.T) { @@ -73,6 +73,37 @@ func TestRunFullPipe(t *testing.T) { assert.True(exists(post), post) } +func TestRunArmFullPipe(t *testing.T) { + assert := assert.New(t) + folder, err := ioutil.TempDir("", "goreleasertest") + assert.NoError(err) + var binary = filepath.Join(folder, "armtesting") + var config = config.Project{ + Dist: folder, + Build: config.Build{ + Binary: "armtesting", + Flags: "-v", + Ldflags: "-X main.test=armtesting", + Goos: []string{ + "linux", + }, + Goarch: []string{ + "arm", + "arm64", + }, + Goarm: []string{ + "6", + }, + }, + } + var ctx = &context.Context{ + Config: config, + Archives: map[string]string{}, + } + assert.NoError(Pipe{}.Run(ctx)) + assert.True(exists(binary), binary) +} + func TestBuildFailed(t *testing.T) { assert := assert.New(t) var config = config.Project{ diff --git a/pipeline/build/name.go b/pipeline/build/name.go index 3fb75c519..e1549fd64 100644 --- a/pipeline/build/name.go +++ b/pipeline/build/name.go @@ -10,15 +10,17 @@ import ( type nameData struct { Os string Arch string + Arm string Version string Tag string Binary string } -func nameFor(ctx *context.Context, goos, goarch string) (string, error) { +func nameFor(ctx *context.Context, target buildTarget) (string, error) { var data = nameData{ - Os: replace(ctx.Config.Archive.Replacements, goos), - Arch: replace(ctx.Config.Archive.Replacements, goarch), + Os: replace(ctx.Config.Archive.Replacements, target.goos), + Arch: replace(ctx.Config.Archive.Replacements, target.goarch), + Arm: replace(ctx.Config.Archive.Replacements, target.goarm), Version: ctx.Version, Tag: ctx.Git.CurrentTag, Binary: ctx.Config.Build.Binary, diff --git a/pipeline/build/name_test.go b/pipeline/build/name_test.go index 016fdb406..34ab441cb 100644 --- a/pipeline/build/name_test.go +++ b/pipeline/build/name_test.go @@ -5,6 +5,7 @@ import ( "github.com/goreleaser/goreleaser/config" "github.com/goreleaser/goreleaser/context" + "github.com/goreleaser/goreleaser/pipeline/defaults" "github.com/stretchr/testify/assert" ) @@ -39,7 +40,7 @@ func TestNameFor(t *testing.T) { }, } - name, err := nameFor(ctx, "darwin", "amd64") + name, err := nameFor(ctx, buildTarget{"darwin", "amd64", ""}) assert.NoError(err) assert.Equal("test_Darwin_x86_64_v1.2.3_1.2.3", name) } @@ -62,6 +63,33 @@ func TestInvalidNameTemplate(t *testing.T) { }, } - _, err := nameFor(ctx, "darwin", "amd64") + _, err := nameFor(ctx, buildTarget{"darwin", "amd64", ""}) assert.Error(err) } + +func TestNameDefaltTemplate(t *testing.T) { + assert := assert.New(t) + var ctx = &context.Context{ + Config: config.Project{ + Archive: config.Archive{ + NameTemplate: defaults.NameTemplate, + }, + Build: config.Build{ + Binary: "test", + }, + }, + Version: "1.2.3", + } + for key, target := range map[string]buildTarget{ + "test_darwin_amd64": buildTarget{"darwin", "amd64", ""}, + "test_linux_arm64": buildTarget{"linux", "arm64", ""}, + "test_linux_armv7": buildTarget{"linux", "arm", "7"}, + } { + t.Run(key, func(t *testing.T) { + name, err := nameFor(ctx, target) + assert.NoError(err) + assert.Equal(key, name) + }) + } + +} diff --git a/pipeline/build/target.go b/pipeline/build/target.go new file mode 100644 index 000000000..e71ad899a --- /dev/null +++ b/pipeline/build/target.go @@ -0,0 +1,39 @@ +package build + +import ( + "fmt" + "log" + "runtime" + + "github.com/goreleaser/goreleaser/context" +) + +var runtimeTarget = buildTarget{runtime.GOOS, runtime.GOARCH, ""} + +// 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 allBuildTargets(ctx *context.Context) (t []buildTarget) { + for _, goos := range ctx.Config.Build.Goos { + for _, goarch := range ctx.Config.Build.Goarch { + if !valid(goos, goarch) { + log.Printf("Skipped build for %v/%v\n", goos, goarch) + continue + } + if goarch == "arm" { + for _, goarm := range ctx.Config.Build.Goarm { + t = append(t, buildTarget{goos, goarch, goarm}) + } + continue + } + t = append(t, buildTarget{goos, goarch, ""}) + } + } + return +} diff --git a/pipeline/defaults/defaults.go b/pipeline/defaults/defaults.go index b0dfe9e99..2ad854c98 100644 --- a/pipeline/defaults/defaults.go +++ b/pipeline/defaults/defaults.go @@ -12,6 +12,9 @@ import ( var defaultFiles = []string{"licence", "license", "readme", "changelog"} +// NameTemplate default name_template for the archive. +const NameTemplate = "{{ .Binary }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" + // Pipe for brew deployment type Pipe struct{} @@ -41,12 +44,15 @@ func (Pipe) Run(ctx *context.Context) error { if len(ctx.Config.Build.Goarch) == 0 { ctx.Config.Build.Goarch = []string{"amd64", "386"} } + if len(ctx.Config.Build.Goarm) == 0 { + ctx.Config.Build.Goarm = []string{"6"} + } if ctx.Config.Build.Ldflags == "" { ctx.Config.Build.Ldflags = "-s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}" } if ctx.Config.Archive.NameTemplate == "" { - ctx.Config.Archive.NameTemplate = "{{.Binary}}_{{.Os}}_{{.Arch}}" + ctx.Config.Archive.NameTemplate = NameTemplate } if ctx.Config.Archive.Format == "" { ctx.Config.Archive.Format = "tar.gz"