Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: first class build targets #3062

Merged
merged 1 commit into from Apr 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
48 changes: 43 additions & 5 deletions internal/builders/golang/build.go
Expand Up @@ -65,29 +65,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 @@ -187,6 +194,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 @@ -335,7 +349,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 @@ -407,5 +421,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.