Re: [MacPorts] #73086: Go is broken on 10.13–10.15

MacPorts noreply at macports.org
Mon Aug 3 18:39:11 UTC 2026


#73086: Go is broken on 10.13–10.15
---------------------------+------------------------------------------
  Reporter:  barracuda156  |      Owner:  herbygillot
      Type:  defect        |     Status:  closed
  Priority:  High          |  Milestone:
 Component:  ports         |    Version:  2.11.5
Resolution:  fixed         |   Keywords:  catalina, mojave, highsierra
      Port:  go            |
---------------------------+------------------------------------------
Changes (by herbygillot):

 * status:  assigned => closed
 * resolution:   => fixed


Comment:

 == What changed ==

 `go` no longer builds a toolchain. It is a wrapper that depends on a
 versioned `go-1.NN` port and symlinks its `go` and `gofmt`, so each system
 is offered the newest Go release it can actually run:

 ||= macOS =||= darwin =||= `go` provides =||
 || 10.7 – 10.12 || 11–16 || 1.17.13 ||
 || 10.13 – 11 || 17–20 || 1.24.13 ||
 || 12 and later || 21+ || 1.26.5 ||

 The mapping lives in a new `go_toolchain` PortGroup, and `go` asks it
 rather than restating it, so the wrapper cannot drift from the toolchains.
 The toolchains themselves install side by side as `go-1.NN` and
 `gofmt-1.NN` with GOROOT at `${prefix}/lib/go-1.NN`, so a build can depend
 on one directly to pin a series. Currently packaged: 1.17, 1.20, 1.22,
 1.23, 1.24, 1.25, 1.26, plus `go-devel` tracking the prerelease on 13 and
 later.

 '''Root cause of this ticket.''' `make.bash` bootstraps from upstream's
 prebuilt binary. From Go 1.25 that binary imports
 `_SecTrustCopyCertificateChain`, which arrived in macOS 12, and the import
 is non-lazy — so dyld cannot bind it and aborts the process before `main`
 on anything older. That is the `Abort trap: 6` in the report. It was never
 a compiler problem; the bootstrap could not start.

 '''The floors are load-time floors, not upstream's support policy.''' They
 are read from the `//go:cgo_import_dynamic` directives in
 `src/crypto/x509/internal/macos/security.go`. Go 1.20 through 1.24 declare
 an identical symbol set, all of which 10.13 satisfies; 1.25 swaps the
 deprecated `SecTrustGetCertificateAtIndex`/`Count` pair for the macOS 12
 call. That single substitution is the entire cliff. `LC_BUILD_VERSION` is
 not the limit — Go 1.24.8 declares `minos 11.0` and ran on 10.13 through
 11 for the nine months MacPorts shipped it, because macOS dyld loads a
 binary whose minimum is newer than the running system.

 Following upstream's supported-macOS list instead would have capped 10.13
 and 10.14 at Go 1.20 and 10.15 at 1.22, for no reason those systems could
 observe.

 '''Confirmed on hardware, not just from symbol tables.''' The buildbots
 built `go-1.22`, `go-1.23` and `go-1.24` on 10.13 and 10.14, and
 `go-1.23`/`go-1.24` on 10.15 — eight first-time builds, no failures. Each
 had to start `go1.24.13.darwin-amd64` on that machine in order to
 bootstrap. Only once that came back green were those systems moved onto
 1.24.

 == Ports still fail until they are annotated ==

 Fixing the toolchain does not fix a port whose '''source''' needs a newer
 Go than the system can provide. Those still fetch, build and fail on every
 push, and that is the bulk of the remaining noise on older builders.

 The `golang` PortGroup now accepts a declared minimum:

 {{{
 go.offline_build    no
 go.toolchain_min    1.25.0
 }}}

 Where the system cannot provide that series, the port is marked
 `known_fail`, so it is excluded from the build list — and its failcache
 entry cleared — rather than built and failed. Annotating `rclone` alone
 turned ten builders from failing to skipping. 42 ports carry an annotation
 today.

 '''Requirements for annotating a port:'''

  1. '''Module mode only.''' The value belongs in a Portfile only when the
 build sets `go.offline_build no`. In GOPATH mode `go.mod` is not consulted
 at all, so its directive is merely an upper bound on what the source
 needs, and declaring it risks skipping a port that would have built. Of
 the ports using the PortGroup, 354 build in module mode and 234 in GOPATH
 mode.
  1. '''Copy the `go` directive from the project's `go.mod`''' at the
 version the port packages, verbatim. Patch form is fine — only the series
 is compared, since MacPorts ships the newest patch release of each series
 it packages.
  1. '''It cannot name a series newer than `go_toolchain` records.'''
 Anything above the newest recorded series is refused with an error,
 because it is either a typo — which would otherwise skip the port
 everywhere without a word — or a real release whose macOS floor has not
 been recorded yet.
  1. '''Recheck it on version updates.''' `go.mod` directives move; an
 annotation that was right at 1.2.3 can be wrong at 1.3.0.

 No annotation is needed for 10.6, where no Go runs at all — anything using
 the `golang` PortGroup is skipped there automatically.

 === `go.vendors` and why it blocks this ===

 185 of the GOPATH-mode ports use `go.vendors`, which fetches each
 dependency as a separate MacPorts distfile and stakes them out in a GOPATH
 tree. That only works with modules switched off, so `go.mod` is never read
 and there is nothing to annotate from. Such a port cannot be gated on
 evidence — only on a guess.

 Converting one is mechanical: delete the `go.vendors` block and add
 `go.offline_build no`. `fq`, `duf` and `miller` were converted this way,
 removing 363 lines of vendor declarations between them, and the annotation
 follows from `go.mod` as usual.

 It is a real trade, though, and worth making deliberately: vendored builds
 are offline and every dependency is checksummed and mirrored by MacPorts,
 whereas module mode resolves and fetches at build time with integrity
 coming from the project's `go.sum`. The gain is that the vendor block no
 longer has to be regenerated on every update.

 == Builds now use the Go that is installed ==

 Module-mode builds ran with Go's default `GOTOOLCHAIN=auto`, which
 downloads and runs whatever release `go.mod` names when that is newer than
 the toolchain in hand. That silently defeats everything above — the build
 stops using the toolchain MacPorts installed — and on an older system it
 downloads a release that cannot start, which is this ticket arriving by
 another route. `restic` on 11 Big Sur showed it exactly:

 {{{
 go: downloading go1.25.10 (darwin/amd64)
 Error code: CHILDSTATUS 4003 134
 }}}

 That is a SIGABRT with neither the version nor the reason named. The
 PortGroup now sets `GOTOOLCHAIN=local`, so the same case reports:

 {{{
 go: go.mod requires go >= 1.26.9 (running go 1.26.5; GOTOOLCHAIN=local)
 }}}

 The cost is that MacPorts' packaged patch release becomes a hard floor. No
 port in the tree is affected today, and all seven packaged series are at
 upstream's newest patch — but keeping them current is now load-bearing,
 and `go.toolchain_min` will not warn about a shortfall because it compares
 only the series.

 == What has '''not''' been established ==

 These are builds. The toolchains compile, link and bootstrap on 10.13
 through 10.15, which is considerably more than was known before, but
 '''nobody has run Go's own test suite there'''. This does not establish
 that every standard library package behaves on High Sierra the way it does
 on Monterey — `crypto/x509` verifying a chain, the `os`/`syscall`
 fallbacks, and runtime timers on `clock_gettime` are the plausible places
 for a difference to hide.

 The ports builders never invoke `port test` — they run only `install-
 dependencies` and `install-port` — so that answer cannot come from CI as
 it stands.

 '''If anyone here runs 10.13, 10.14 or 10.15 and is willing to spend half
 an hour, that would settle it.''' `go tool dist test` in short mode is
 roughly 25–40 minutes on hardware of that vintage, and a platform-focused
 subset (`crypto/x509`, `crypto/tls`, `os`, `syscall`, `net`, `runtime`) is
 a couple of minutes. I am happy to add `test.run` to the toolchain ports
 so it is just `sudo port test go-1.24` — it costs nothing, since the
 builders will not run it.

 == Two other notes ==

 '''10.6 and i386 have no Go at all now.''' The old port offered 1.11.13
 for i386 and there is still a `go-1.11.13_0.darwin_10.i386.tbz2` on the
 archive server; nothing replaces it. Go dropped darwin/386 in 1.15, so no
 packaged toolchain is built for it, and 10.6 cannot build 1.17 from source
 either — its `dsymutil` aborts on the debug information Go's linker emits.
 `go` is therefore not offered below 10.7. If this matters to anyone,
 please open a separate ticket.

 '''Go 1.27's floor is still upstream's claim''' (macOS 13) rather than
 something read off the release, so `go-devel` is offered only on 13 and
 later. A `go-devel-1.27rc2` archive exists for darwin 21, which suggests
 the real floor is 12; it will be checked the same way the others were
 before a `go-1.27` is packaged.

-- 
Ticket URL: <https://trac.macports.org/ticket/73086#comment:8>
MacPorts <https://www.macports.org/>
Ports system for macOS


More information about the macports-tickets mailing list