Skip to content

Commit

Permalink
feat: first class build targets (#3062)
Browse files Browse the repository at this point in the history
Adds the ability to tell goreleaser to use the first-class Go ports as
targets.

Closes #3053

Signed-off-by: Carlos A Becker <caarlos0@gmail.com>
  • Loading branch information
caarlos0 committed Apr 26, 2022
1 parent 5aeb8ac commit 69cf1aa
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 11 deletions.
48 changes: 43 additions & 5 deletions internal/builders/golang/build.go
Expand Up @@ -68,29 +68,67 @@ func (*Builder) WithDefaults(build config.Build) (config.Build, error) {
build.Goamd64 = []string{"v1"}
}
targets, err := buildtarget.List(build)
build.Targets = targets
if err != nil {
return build, err
}
build.Targets = targets
} else {
for i, target := range build.Targets {
targets := map[string]bool{}
for _, target := range build.Targets {
if target == go118FirstClassTargetsName ||
target == goStableFirstClassTargetsName {
for _, t := range go118FirstClassTargets {
targets[t] = true
}
continue
}
if strings.HasSuffix(target, "_amd64") {
build.Targets[i] = target + "_v1"
targets[target+"_v1"] = true
continue
}
if strings.HasSuffix(target, "_arm") {
build.Targets[i] = target + "_6"
targets[target+"_6"] = true
continue
}
if strings.HasSuffix(target, "_mips") ||
strings.HasSuffix(target, "_mips64") ||
strings.HasSuffix(target, "_mipsle") ||
strings.HasSuffix(target, "_mips64le") {
build.Targets[i] = target + "_hardfloat"
targets[target+"_hardfloat"] = true
continue
}
targets[target] = true
}
build.Targets = keys(targets)
}
return build, nil
}

func keys(m map[string]bool) []string {
result := make([]string, 0, len(m))
for k := range m {
result = append(result, k)
}
return result
}

const (
go118FirstClassTargetsName = "go_118_first_class"
goStableFirstClassTargetsName = "go_first_class"
)

// go tool dist list -json | jq -r '.[] | select(.FirstClass) | [.GOOS, .GOARCH] | @tsv'
var go118FirstClassTargets = []string{
"darwin_amd64_v1",
"darwin_arm64",
"linux_386",
"linux_amd64_v1",
"linux_arm_6",
"linux_arm64",
"windows_386",
"windows_amd64_v1",
}

// Build builds a golang build.
func (*Builder) Build(ctx *context.Context, build config.Build, options api.Options) error {
if err := checkMain(build); err != nil {
Expand Down
36 changes: 36 additions & 0 deletions internal/builders/golang/build_test.go
Expand Up @@ -185,6 +185,42 @@ func TestWithDefaults(t *testing.T) {
},
goBinary: "go",
},
"go first class targets": {
build: config.Build{
ID: "foo3",
Binary: "foo",
Targets: []string{goStableFirstClassTargetsName},
},
targets: go118FirstClassTargets,
goBinary: "go",
},
"go 1.18 first class targets": {
build: config.Build{
ID: "foo3",
Binary: "foo",
Targets: []string{go118FirstClassTargetsName},
},
targets: go118FirstClassTargets,
goBinary: "go",
},
"go 1.18 first class targets plus custom": {
build: config.Build{
ID: "foo3",
Binary: "foo",
Targets: []string{"linux_amd64_v1", go118FirstClassTargetsName, "darwin_amd64_v2"},
},
targets: append(go118FirstClassTargets, "darwin_amd64_v2"),
goBinary: "go",
},
"repeatin targets": {
build: config.Build{
ID: "foo3",
Binary: "foo",
Targets: []string{go118FirstClassTargetsName, go118FirstClassTargetsName, goStableFirstClassTargetsName},
},
targets: go118FirstClassTargets,
goBinary: "go",
},
} {
t.Run(name, func(t *testing.T) {
if testcase.build.GoBinary != "" && testcase.build.GoBinary != "go" {
Expand Down
27 changes: 21 additions & 6 deletions www/docs/customization/build.md
Expand Up @@ -2,8 +2,8 @@

Builds can be customized in multiple ways.
You can specify for which `GOOS`, `GOARCH` and `GOARM` binaries are built
(goreleaser will generate a matrix of all combinations), and you can change
the name of the binary, flags, environment variables, hooks and etc.
(GoReleaser will generate a matrix of all combinations), and you can change
the name of the binary, flags, environment variables, hooks and more.

Here is a commented `builds` section with all fields specified:

Expand Down Expand Up @@ -119,9 +119,16 @@ builds:

# Optionally override the matrix generation and specify only the final list of targets.
# Format is `{goos}_{goarch}` with optionally a suffix with `_{goarm}`, `_{goamd64}` or `_{gomips}`.
#
# Special values:
# - go_118_first_class: evaluates to the first-class targets of go1.18
# - go_first_class: evaluates to latest stable go first-class targets, currently same as 1.18.
#
# This overrides `goos`, `goarch`, `goarm`, `gomips`, `goamd64` and `ignores`.
targets:
- linux_amd64
- go_first_class
- go_118_first_class
- linux_amd64_v1
- darwin_arm64
- linux_arm_6

Expand Down Expand Up @@ -202,6 +209,13 @@ builds:
!!! tip
Learn more about the [name template engine](/customization/templates/).

!!! info
First-class build targets are gathered by running:
```sh
go tool dist list -json | jq -r '.[] | select(.FirstClass) | [.GOOS, .GOARCH] | @tsv'
```
We also recommend reading the [official wiki about Go ports](https://github.com/golang/go/wiki/PortingPolicy#first-class-ports).

Here is an example with multiple binaries:

```yaml
Expand Down Expand Up @@ -350,7 +364,7 @@ This is useful in scenarios where two tags point to the same commit.

## Reproducible Builds

To make your releases, checksums, and signatures reproducible, you will need to make some (if not all) of the following modifications to the build defaults in GoReleaser:
To make your releases, checksums and signatures reproducible, you will need to make some (if not all) of the following modifications to the build defaults in GoReleaser:

* Modify `ldflags`: by default `main.Date` is set to the time GoReleaser is run (`{{.Date}}`), you can set this to `{{.CommitDate}}` or just not pass the variable.
* Modify `mod_timestamp`: by default this is empty string, set to `{{.CommitTimestamp}}` or a constant value instead.
Expand Down Expand Up @@ -422,5 +436,6 @@ There is no difference in how the binaries are handled.
GoReleaser will fail.

!!! warning
When using the `prebuilt` binary, there are no defaults for `goos` et al,
so you need to either provide those or the final `targets` matrix.
When using the `prebuilt` binary, there are no defaults for `goos`,
`goarch`, `goarm`, `gomips` and `goamd64`.
You'll need to either provide them or the final `targets` matrix.

0 comments on commit 69cf1aa

Please sign in to comment.