diff --git a/internal/pipe/upx/upx.go b/internal/pipe/upx/upx.go index d88796fe6..faaf66caa 100644 --- a/internal/pipe/upx/upx.go +++ b/internal/pipe/upx/upx.go @@ -101,12 +101,35 @@ func findBinaries(ctx *context.Context, upx config.UPX) []*artifact.Artifact { artifact.ByType(artifact.UniversalBinary), ), } + if f := orBy(artifact.ByGoos, upx.Goos); f != nil { + filters = append(filters, f) + } + if f := orBy(artifact.ByGoarch, upx.Goarch); f != nil { + filters = append(filters, f) + } + if f := orBy(artifact.ByGoarm, upx.Goarm); f != nil { + filters = append(filters, f) + } + if f := orBy(artifact.ByGoamd64, upx.Goamd64); f != nil { + filters = append(filters, f) + } if len(upx.IDs) > 0 { filters = append(filters, artifact.ByIDs(upx.IDs...)) } return ctx.Artifacts.Filter(artifact.And(filters...)).List() } +func orBy(fn func(string) artifact.Filter, items []string) artifact.Filter { + var result []artifact.Filter + for _, f := range items { + result = append(result, fn(f)) + } + if len(result) == 0 { + return nil + } + return artifact.Or(result...) +} + func sizeOf(name string) int64 { st, err := os.Stat(name) if err != nil { diff --git a/internal/pipe/upx/upx_test.go b/internal/pipe/upx/upx_test.go index 3912aae87..f4e109707 100644 --- a/internal/pipe/upx/upx_test.go +++ b/internal/pipe/upx/upx_test.go @@ -139,3 +139,133 @@ func TestUpxNotInstalled(t *testing.T) { }) testlib.AssertSkipped(t, Pipe{}.Run(ctx)) } + +func TestFindBinaries(t *testing.T) { + ctx := testctx.New() + tmp := t.TempDir() + main := filepath.Join(tmp, "main.go") + require.NoError(t, os.WriteFile(main, []byte("package main\nfunc main(){ println(1) }"), 0o644)) + for _, goos := range []string{"linux", "windows", "darwin"} { + for _, goarch := range []string{"386", "amd64", "arm64", "arm", "mips"} { + ext := "" + goarm := "" + gomips := "" + goamd64 := "" + switch goos { + case "windows": + ext = ".exe" + } + if goos == "windows" { + ext = ".exe" + } + switch goarch { + case "arm": + goarm = "7" + if goos != "linux" { + continue + } + case "mips": + gomips = "softfloat" + if goos != "linux" { + continue + } + case "arm64": + if goos == "windows" { + continue + } + case "amd64": + goamd64 = "v1" + case "386": + if goos == "darwin" { + continue + } + } + path := filepath.Join(tmp, fmt.Sprintf("bin_%s_%s%s", goos, goarch, ext)) + cmd := exec.Command("go", "build", "-o", path, main) + cmd.Env = append([]string{ + "CGO_ENABLED=0", + "GOOS=" + goos, + "GOARCH=" + goarch, + "GOAMD64=" + goamd64, + "GOARM=" + goarm, + "GOMIPS=" + gomips, + }, cmd.Environ()...) + if cmd.Run() != nil { + // ignore unsupported arches + continue + } + + for i := 1; i <= 5; i++ { + ctx.Artifacts.Add(&artifact.Artifact{ + Name: "bin", + Path: path, + Goos: goos, + Goarch: goarch, + Goarm: goarm, + Gomips: gomips, + Goamd64: goamd64, + Type: artifact.Binary, + Extra: map[string]any{ + artifact.ExtraID: fmt.Sprintf("%d", i), + }, + }) + } + + } + } + + t.Run("only ids", func(t *testing.T) { + require.Len(t, findBinaries(ctx, config.UPX{ + IDs: []string{"1", "2", "3"}, + }), 27) + }) + + t.Run("id and goos", func(t *testing.T) { + require.Len(t, findBinaries(ctx, config.UPX{ + IDs: []string{"4"}, + Goos: []string{"windows", "darwin"}, + }), 4) // amd64, 386 + }) + + t.Run("id, goos goarch", func(t *testing.T) { + require.Len(t, findBinaries(ctx, config.UPX{ + IDs: []string{"3"}, + Goos: []string{"windows"}, + Goarch: []string{"386", "amd64"}, + }), 2) + }) + + t.Run("goamd64", func(t *testing.T) { + require.Len(t, findBinaries(ctx, config.UPX{ + IDs: []string{"2"}, + Goos: []string{"linux"}, + Goarch: []string{"amd64"}, + Goamd64: []string{"v3"}, + }), 0) + require.Len(t, findBinaries(ctx, config.UPX{ + IDs: []string{"2"}, + Goos: []string{"linux"}, + Goarch: []string{"amd64"}, + Goamd64: []string{"v1", "v2", "v3", "v4"}, + }), 1) + }) + + t.Run("goarm", func(t *testing.T) { + require.Len(t, findBinaries(ctx, config.UPX{ + IDs: []string{"2"}, + Goos: []string{"linux"}, + Goarch: []string{"arm"}, + Goarm: []string{"6"}, + }), 0) + require.Len(t, findBinaries(ctx, config.UPX{ + IDs: []string{"2"}, + Goos: []string{"linux"}, + Goarch: []string{"arm"}, + Goarm: []string{"7"}, + }), 1) + require.Len(t, findBinaries(ctx, config.UPX{ + IDs: []string{"2"}, + Goarm: []string{"6", "7"}, + }), 1) + }) +} diff --git a/pkg/config/config.go b/pkg/config/config.go index 2c1d57ac4..3d280710a 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -584,6 +584,10 @@ type UniversalBinary struct { type UPX struct { Enabled bool `yaml:"enabled,omitempty" json:"enabled,omitempty"` IDs []string `yaml:"ids,omitempty" json:"ids,omitempty"` + Goos []string `yaml:"goos,omitempty" json:"goos,omitempty"` + Goarch []string `yaml:"goarch,omitempty" json:"goarch,omitempty"` + Goarm []string `yaml:"goarm,omitempty" json:"goarm,omitempty"` + Goamd64 []string `yaml:"goamd64,omitempty" json:"goamd64,omitempty"` Binary string `yaml:"binary,omitempty" json:"binary,omitempty"` Compress string `yaml:"compress,omitempty" json:"compress,omitempty" jsonschema:"enum=1,enum=2,enum=3,enum=4,enum=5,enum=6,enum=7,enum=8,enum=9,enum=best,enum=,default="` LZMA bool `yaml:"lzma,omitempty" json:"lzma,omitempty"` diff --git a/www/docs/customization/upx.md b/www/docs/customization/upx.md index 284fb2f2a..ac5ac30dc 100644 --- a/www/docs/customization/upx.md +++ b/www/docs/customization/upx.md @@ -9,8 +9,6 @@ GoReleaser has had `-s -w` as default `ldflags` since the beginning, which help shaving off some bytes, but if you want to shave it even more, [`upx`][upx] is the _de facto_ tool for the job. -[upx]: https://upx.github.io/ - GoReleaser has been able to integrate with it via custom [build hooks][bhooks], and now UPX has its own configuration section: @@ -33,6 +31,26 @@ upx: # Filter by build ID. ids: [ build1, build2 ] + # Filter by GOOS. + # + # Since: v1.19 + goos: [ linux , darwin ] + + # Filter by GOARCH. + # + # Since: v1.19 + goarch: [ arm, amd64 ] + + # Filter by GOARM. + # + # Since: v1.19 + goarm: [ 8 ] + + # Filter by GOAMD64. + # + # Since: v1.19 + goamd64: [ v1 ] + # Compress argument. # Valid options are from '1' (faster) to '9' (better), and 'best'. compress: best @@ -44,7 +62,13 @@ upx: brute: true ``` +Notice you can define multiple `upx` definitions, filtering by various fields. +You can use that to have different compression options depending on the target +OS, for instance - or even to run it only on a few selected platforms. + !!! info If `upx` is not in `$PATH`, GoReleaser will automatically avoid running it. +[upx]: https://upx.github.io/ [upx-issues]: https://github.com/upx/upx/issues +[bhooks]: /customization/builds/#build-hooks