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