github.com/goreleaser/goreleaser@v1.25.1/www/docs/customization/builds.md (about) 1 # Builds 2 3 Builds can be customized in multiple ways. 4 You can specify for which `GOOS`, `GOARCH` and `GOARM` binaries are built 5 (GoReleaser will generate a matrix of all combinations), and you can change 6 the name of the binary, flags, environment variables, hooks and more. 7 8 Here is a commented `builds` section with all fields specified: 9 10 ```yaml 11 # .goreleaser.yaml 12 builds: 13 # You can have multiple builds defined as a yaml list 14 - # 15 # ID of the build. 16 # 17 # Default: Project directory name 18 id: "my-build" 19 20 # Path to main.go file or main package. 21 # Notice: when used with `gomod.proxy`, this must be a package. 22 # 23 # Default is `.`. 24 main: ./cmd/my-app 25 26 # Binary name. 27 # Can be a path (e.g. `bin/app`) to wrap the binary in a directory. 28 # 29 # Default: Project directory name 30 binary: program 31 32 # Custom flags. 33 # 34 # Templates: allowed 35 flags: 36 - -tags=dev 37 - -v 38 39 # Custom asmflags. 40 # 41 # Templates: allowed 42 asmflags: 43 - -D mysymbol 44 - all=-trimpath={{.Env.GOPATH}} 45 46 # Custom gcflags. 47 # 48 # Templates: allowed 49 gcflags: 50 - all=-trimpath={{.Env.GOPATH}} 51 - ./dontoptimizeme=-N 52 53 # Custom ldflags. 54 # 55 # Default: '-s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}} -X main.builtBy=goreleaser' 56 # Templates: allowed 57 ldflags: 58 - -s -w -X main.build={{.Version}} 59 - ./usemsan=-msan 60 61 # Custom Go build mode. 62 # 63 # Valid options: 64 # - `c-shared` 65 # - `c-archive` 66 # - `pie` 67 # 68 # Since: v1.13 69 buildmode: c-shared 70 71 # Custom build tags templates. 72 tags: 73 - osusergo 74 - netgo 75 - static_build 76 - feature 77 78 # Custom environment variables to be set during the builds. 79 # Invalid environment variables will be ignored. 80 # 81 # Default: os.Environ() ++ env config section 82 # Templates: allowed (since v1.14) 83 env: 84 - CGO_ENABLED=0 85 # complex, templated envs (v1.14+): 86 - >- 87 {{- if eq .Os "darwin" }} 88 {{- if eq .Arch "amd64"}}CC=o64-clang{{- end }} 89 {{- if eq .Arch "arm64"}}CC=aarch64-apple-darwin20.2-clang{{- end }} 90 {{- end }} 91 {{- if eq .Os "windows" }} 92 {{- if eq .Arch "amd64" }}CC=x86_64-w64-mingw32-gcc{{- end }} 93 {{- end }} 94 95 # GOOS list to build for. 96 # For more info refer to: https://golang.org/doc/install/source#environment 97 # 98 # Default: [ 'darwin', 'linux', 'windows' ] 99 goos: 100 - freebsd 101 - windows 102 103 # GOARCH to build for. 104 # For more info refer to: https://golang.org/doc/install/source#environment 105 # 106 # Default: [ '386', 'amd64', 'arm64' ] 107 goarch: 108 - amd64 109 - arm 110 - arm64 111 112 # GOARM to build for when GOARCH is arm. 113 # For more info refer to: https://golang.org/doc/install/source#environment 114 # 115 # Default: [ 6 ] 116 goarm: 117 - 6 118 - 7 119 120 # GOAMD64 to build when GOARCH is amd64. 121 # For more info refer to: https://golang.org/doc/install/source#environment 122 # 123 # Default: [ 'v1' ] 124 goamd64: 125 - v2 126 - v3 127 128 # GOMIPS and GOMIPS64 to build when GOARCH is mips, mips64, mipsle or mips64le. 129 # For more info refer to: https://golang.org/doc/install/source#environment 130 # 131 # Default: [ 'hardfloat' ] 132 gomips: 133 - hardfloat 134 - softfloat 135 136 # List of combinations of GOOS + GOARCH + GOARM to ignore. 137 ignore: 138 - goos: darwin 139 goarch: 386 140 - goos: linux 141 goarch: arm 142 goarm: 7 143 - goarm: mips64 144 - gomips: hardfloat 145 - goamd64: v4 146 147 # Optionally override the matrix generation and specify only the final list 148 # of targets. 149 # 150 # Format is `{goos}_{goarch}` with their respective suffixes when 151 # applicable: `_{goarm}`, `_{goamd64}`, `_{gomips}`. 152 # 153 # Special values: 154 # - go_118_first_class: evaluates to the first-class ports of go1.18. 155 # - go_first_class: evaluates to latest stable go first-class ports, 156 # currently same as 1.18. 157 # 158 # This overrides `goos`, `goarch`, `goarm`, `gomips`, `goamd64` and 159 # `ignores`. 160 targets: 161 # Since: v1.9 162 - go_first_class 163 # Since: v1.9 164 - go_118_first_class 165 - linux_amd64_v1 166 - darwin_arm64 167 - linux_arm_6 168 169 # Set a specific go binary to use when building. 170 # It is safe to ignore this option in most cases. 171 # 172 # Default is "go" 173 # Templates: allowed (since v1.23). 174 gobinary: "go1.13.4" 175 176 # Sets the command to run to build. 177 # Can be useful if you want to build tests, for example, 178 # in which case you can set this to "test". 179 # It is safe to ignore this option in most cases. 180 # 181 # Default: build. 182 # Since: v1.9 183 command: test 184 185 # Set the modified timestamp on the output binary, typically 186 # you would do this to ensure a build was reproducible. 187 # Pass an empty string to skip modifying the output. 188 # 189 # Templates: allowed 190 mod_timestamp: "{{ .CommitTimestamp }}" 191 192 # Hooks can be used to customize the final binary, 193 # for example, to run generators. 194 # 195 # Templates: allowed 196 hooks: 197 pre: rice embed-go 198 post: ./script.sh {{ .Path }} 199 200 # If true, skip the build. 201 # Useful for library projects. 202 skip: false 203 204 # By default, GoReleaser will create your binaries inside 205 # `dist/${BuildID}_${BuildTarget}`, which is a unique directory per build 206 # target in the matrix. 207 # You can set subdirs within that directory using the `binary` property. 208 # 209 # However, if for some reason you don't want that unique directory to be 210 # created, you can set this property. 211 # If you do, you are responsible for keeping different builds from 212 # overriding each other. 213 no_unique_dist_dir: true 214 215 # By default, GoReleaser will check if the main filepath has a main 216 # function. 217 # This can be used to skip that check, in case you're building tests, for 218 # example. 219 # 220 # Since: v1.9 221 no_main_check: true 222 223 # Path to project's (sub)directory containing Go code. 224 # This is the working directory for the Go build command(s). 225 # If dir does not contain a `go.mod` file, and you are using `gomod.proxy`, 226 # produced binaries will be invalid. 227 # You would likely want to use `main` instead of this. 228 # 229 # Default: '.' 230 dir: go 231 232 # Builder allows you to use a different build implementation. 233 # This is a GoReleaser Pro feature. 234 # Valid options are: `go` and `prebuilt`. 235 # 236 # Default: 'go' 237 builder: prebuilt 238 239 # Overrides allows to override some fields for specific targets. 240 # This can be specially useful when using CGO. 241 # Note: it'll only match if the full target matches. 242 # 243 # Since: v1.5 244 overrides: 245 - goos: darwin 246 goarch: arm64 247 goamd64: v1 248 goarm: "" 249 gomips: "" 250 ldflags: 251 - foo 252 tags: 253 - bar 254 asmflags: 255 - foobar 256 gcflags: 257 - foobaz 258 env: 259 - CGO_ENABLED=1 260 ``` 261 262 !!! tip 263 264 Learn more about the [name template engine](/customization/templates/). 265 266 !!! info 267 268 First-class build targets are gathered by running: 269 ```sh 270 go tool dist list -json | jq -r '.[] | select(.FirstClass) | [.GOOS, .GOARCH] | @tsv' 271 ``` 272 We also recommend reading the [official wiki about Go ports](https://go.dev/wiki/PortingPolicy#first-class-ports). 273 274 Here is an example with multiple binaries: 275 276 ```yaml 277 # .goreleaser.yaml 278 builds: 279 - main: ./cmd/cli 280 id: "cli" 281 binary: cli 282 goos: 283 - linux 284 - darwin 285 - windows 286 287 - main: ./cmd/worker 288 id: "worker" 289 binary: worker 290 goos: 291 - linux 292 - darwin 293 - windows 294 295 - main: ./cmd/tracker 296 id: "tracker" 297 binary: tracker 298 goos: 299 - linux 300 - darwin 301 - windows 302 ``` 303 304 The binary name field supports [templating](/customization/templates/). The 305 following build details are exposed: 306 307 <!-- to format the tables, use: https://tabletomarkdown.com/format-markdown-table/ --> 308 309 | Key | Description | 310 | ------- | --------------------------------- | 311 | .Os | `GOOS` | 312 | .Arch | `GOARCH` | 313 | .Arm | `GOARM` | 314 | .Ext | Extension, e.g. `.exe` | 315 | .Target | Build target, e.g. `darwin_amd64` | 316 317 ## Passing environment variables to ldflags 318 319 You can do that by using `{{ .Env.VARIABLE_NAME }}` in the template, for 320 example: 321 322 ```yaml 323 # .goreleaser.yaml 324 builds: 325 - ldflags: 326 - -s -w -X "main.goversion={{.Env.GOVERSION}}" 327 ``` 328 329 Then you can run: 330 331 ```sh 332 GOVERSION=$(go version) goreleaser 333 ``` 334 335 ## Build Hooks 336 337 Both pre and post hooks run **for each build target**, regardless of whether 338 these targets are generated via a matrix of OSes and architectures or defined 339 explicitly. 340 341 In addition to simple declarations as shown above _multiple_ hooks can be 342 declared to help retaining reusability of config between different build 343 environments. 344 345 ```yaml 346 # .goreleaser.yaml 347 builds: 348 - id: "with-hooks" 349 targets: 350 - "darwin_amd64" 351 - "windows_amd64" 352 hooks: 353 pre: 354 - first-script.sh 355 - second-script.sh 356 post: 357 - upx "{{ .Path }}" 358 - codesign -project="{{ .ProjectName }}" "{{ .Path }}" 359 ``` 360 361 Each hook can also have its own work directory and environment variables: 362 363 ```yaml 364 # .goreleaser.yaml 365 builds: 366 - id: "with-hooks" 367 targets: 368 - "darwin_amd64" 369 - "windows_amd64" 370 hooks: 371 pre: 372 - cmd: first-script.sh 373 dir: 374 "{{ dir .Dist}}" 375 # Always print command output, otherwise only visible in debug mode. 376 # Since: v1.5 377 output: true 378 env: 379 - HOOK_SPECIFIC_VAR={{ .Env.GLOBAL_VAR }} 380 - second-script.sh 381 ``` 382 383 All properties of a hook (`cmd`, `dir` and `env`) support 384 [templating](/customization/templates/) with `post` hooks having binary artifact 385 available (as these run _after_ the build). 386 Additionally the following build details are exposed to both `pre` and `post` 387 hooks: 388 389 <!-- to format the tables, use: https://tabletomarkdown.com/format-markdown-table/ --> 390 391 | Key | Description | 392 | ------- | -------------------------------------- | 393 | .Name | Filename of the binary, e.g. `bin.exe` | 394 | .Ext | Extension, e.g. `.exe` | 395 | .Path | Absolute path to the binary | 396 | .Target | Build target, e.g. `darwin_amd64` | 397 398 Environment variables are inherited and overridden in the following order: 399 400 - global (`env`) 401 - build (`builds[].env`) 402 - hook (`builds[].hooks.pre[].env` and `builds[].hooks.post[].env`) 403 404 ## Go Modules 405 406 If you use Go 1.11+ with go modules or vgo, when GoReleaser runs it may try to 407 download the dependencies. Since several builds run in parallel, it is very 408 likely to fail. 409 410 You can solve this by running `go mod tidy` before calling `goreleaser` or 411 by adding a [hook][] doing that on your `.goreleaser.yaml` file: 412 413 ```yaml 414 # .goreleaser.yaml 415 before: 416 hooks: 417 - go mod tidy 418 # rest of the file... 419 ``` 420 421 [hook]: /customization/hooks 422 423 ## Define Build Tag 424 425 GoReleaser uses `git describe` to get the build tag. You can set 426 a different build tag using the environment variable `GORELEASER_CURRENT_TAG`. 427 This is useful in scenarios where two tags point to the same commit. 428 429 ## Reproducible Builds 430 431 To make your releases, checksums and signatures reproducible, you will need to 432 make some (if not all) of the following modifications to the build defaults in 433 GoReleaser: 434 435 - Modify `ldflags`: by default `main.Date` is set to the time GoReleaser is run 436 (`{{.Date}}`), you can set this to `{{.CommitDate}}` or just not pass the 437 variable. 438 - Modify `mod_timestamp`: by default this is empty string — which means it'll be 439 the compilation time, set to `{{.CommitTimestamp}}` or a constant value 440 instead. 441 - If you do not run your builds from a consistent directory structure, pass 442 `-trimpath` to `flags`. 443 - Remove uses of the `time` template function. This function returns a new value 444 on every call and is not deterministic. 445 446 ## Import pre-built binaries 447 448 !!! success "GoReleaser Pro" 449 450 The prebuilt builder is a [GoReleaser Pro feature](/pro/). 451 452 It is also possible to import pre-built binaries into the GoReleaser lifecycle. 453 454 Reasons you might want to do that include: 455 456 - You want to build your binaries in different machines due to CGO 457 - You want to build using a pre-existing `Makefile` or other tool 458 - You want to speed up the build by running several builds in parallel in 459 different machines 460 461 In any case, its pretty easy to do that now: 462 463 ```yaml 464 # .goreleaser.yaml 465 builds: 466 - # Set the builder to prebuilt 467 builder: prebuilt 468 469 # When builder is `prebuilt` there are no defaults for goos, goarch, 470 # goarm, gomips, goamd64 and targets, so you always have to specify them: 471 goos: 472 - linux 473 - darwin 474 goarch: 475 - amd64 476 - arm64 477 goamd64: 478 - v1 479 480 # prebuilt specific options 481 prebuilt: 482 # Path must be the template path to the binaries. 483 # GoReleaser removes the `dist` directory before running, so you will likely 484 # want to put the binaries elsewhere. 485 # This field is required when using the `prebuilt` builder. 486 path: output/mybin_{{ .Os }}_{{ .Arch }}{{ with .Amd64 }}_{{ . }}{{ end }}/mybin 487 488 # Use 'binary' to set the final name of your binary. 489 # This is the name that will be used in archives et al. 490 binary: bin/mybin 491 ``` 492 493 !!! tip 494 495 You can think of `prebuilt.path` as being the "external path" and the 496 `binary` as being the "internal path to binary". 497 498 This example config will import into your release pipeline the following 499 binaries: 500 501 - `output/mybin_linux_amd64_v1` 502 - `output/mybin_linux_arm64` 503 - `output/mybin_darwin_amd64_v1` 504 - `output/mybin_darwin_arm64` 505 506 The other steps of the pipeline will act as if those were built by GoReleaser 507 itself. 508 There is no difference in how the binaries are handled. 509 510 !!! tip 511 512 A cool tip here, specially when using CGO, is that you can have one 513 `.goreleaser.yaml` file just for the builds, build each in its own machine 514 with [`goreleaser build --single-target`](/cmd/goreleaser_build/) and 515 have a second `.goreleaser.yaml` file that imports those binaries 516 and release them. 517 This tip can also be used to speed up the build process if you run all the 518 builds in different machines in parallel. 519 520 !!! warning 521 522 GoReleaser will try to stat the final path, if any error happens while 523 doing that (e.g. file does not exist or permission issues), 524 GoReleaser will fail. 525 526 !!! warning 527 528 When using the `prebuilt` binary, there are no defaults for `goos`, 529 `goarch`, `goarm`, `gomips` and `goamd64`. 530 You'll need to either provide them or the final `targets` matrix. 531 532 If you'd like to see this in action, check [this example on GitHub](https://github.com/caarlos0/goreleaser-pro-prebuilt-example). 533 534 ## A note about directory names inside `dist` 535 536 By default, GoReleaser will create your binaries inside 537 `dist/${BuildID}_${BuildTarget}`, which is a unique directory per build target 538 in the matrix. 539 540 Those names have no guarantees of remaining the same from one version to 541 another. If you really need to access them from outside GoReleaser, you should 542 be able to consistently get the path of a binary by parsing 543 `dist/artifacts.json`. 544 545 You can also set `builds.no_unique_dist_dir` (as documented earlier in this 546 page), but in that case you are responsible for preventing name conflicts. 547 548 ### Why is there a `_v1` suffix on `amd64` builds? 549 550 Go 1.18 introduced the `GOAMD64` option, and `v1` is the default value for that 551 option. 552 553 Since you can have GoReleaser build for multiple different `GOAMD64` targets, it 554 adds that suffix to prevent name conflicts. The same thing happens for `arm` and 555 `GOARM`, `mips` and `GOMIPS` and others. 556 557 ### Go's first class ports 558 559 The `targets` option can take a `go_first_class` special value as target, which 560 will evaluate to the list of first class ports as defined in the Go wiki. 561 562 You can read more about it 563 [here](https://go.dev/wiki/PortingPolicy#first-class-ports). 564 565 ## Building shared or static libraries 566 567 > Since: v1.13 568 569 GoReleaser supports compiling and releasing C shared or static libraries, by 570 configuring the [Go build mode](https://pkg.go.dev/cmd/go#hdr-Build_modes). 571 572 This can be set with `buildmode` in your build. 573 It now supports `c-shared` and `c-archive`. Other values will transparently be 574 applied to the build line (via the `-buildmode` flag), but GoReleaser will not 575 attempt to configure any additional logic. 576 577 GoReleaser will: 578 579 - set the correct file extension for the target OS. 580 - package the generated header file (`.h`) in the release bundle. 581 582 Example usage: 583 584 ```yaml 585 # .goreleaser.yaml 586 builds: 587 - id: "my-library" 588 589 # Configure the buildmode flag to output a shared library 590 buildmode: "c-shared" # or "c-archive" for a static library 591 ``` 592 593 ## Complex template environment variables 594 595 > Since v1.14 596 597 Builds environment variables accept templates. 598 599 You can leverage that to have a single build configuration with different 600 environment variables for each platform, for example. 601 602 A common example of this is the variables `CC` and `CXX`. 603 604 Here are two different examples: 605 606 ### Using multiple envs 607 608 This example creates once `CC_` and `CXX_` variable for each platform, and then 609 set `CC` and `CXX` to the right one: 610 611 ```yaml 612 # .goreleaser.yml 613 builds: 614 - id: mybin 615 binary: mybin 616 main: . 617 goos: 618 - linux 619 - darwin 620 - windows 621 goarch: 622 - amd64 623 - arm64 624 env: 625 - CGO_ENABLED=0 626 - CC_darwin_amd64=o64-clang 627 - CXX_darwin_amd64=o64-clang+ 628 - CC_darwin_arm64=aarch64-apple-darwin20.2-clang 629 - CXX_darwin_arm64=aarch64-apple-darwin20.2-clang++ 630 - CC_windows_amd64=x86_64-w64-mingw32-gc 631 - CXX_windows_amd64=x86_64-w64-mingw32-g++ 632 - 'CC={{ index .Env (print "CC_" .Os "_" .Arch) }}' 633 - 'CXX={{ index .Env (print "CXX_" .Os "_" .Arch) }}' 634 ``` 635 636 ### Using `if` statements 637 638 This example uses `if` statements to set `CC` and `CXX`: 639 640 ```yaml 641 # .goreleaser.yml 642 builds: 643 - id: mybin 644 binary: mybin 645 main: . 646 goos: 647 - linux 648 - darwin 649 - windows 650 goarch: 651 - amd64 652 - arm64 653 env: 654 - CGO_ENABLED=0 655 - >- 656 {{- if eq .Os "darwin" }} 657 {{- if eq .Arch "amd64"}}CC=o64-clang{{- end }} 658 {{- if eq .Arch "arm64"}}CC=aarch64-apple-darwin20.2-clang{{- end }} 659 {{- end }} 660 {{- if eq .Os "windows" }} 661 {{- if eq .Arch "amd64" }}CC=x86_64-w64-mingw32-gcc{{- end }} 662 {{- end }} 663 - >- 664 {{- if eq .Os "darwin" }} 665 {{- if eq .Arch "amd64"}}CXX=o64-clang+{{- end }} 666 {{- if eq .Arch "arm64"}}CXX=aarch64-apple-darwin20.2-clang++{{- end }} 667 {{- end }} 668 {{- if eq .Os "windows" }} 669 {{- if eq .Arch "amd64" }}CXX=x86_64-w64-mingw32-g++{{- end }} 670 {{- end }} 671 ```