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  ```