Go: runtime: tracking bug for ARM-based macOS and GOOS/GOARCH values

Created on 16 Apr 2020  ·  151Comments  ·  Source: golang/go

The ARM-based Mac rumors of the past couple years continue to heat up (e.g. https://www.theverge.com/2020/3/27/21196611/arm-macbook-desktop-apple-2021-release-date)

Has anybody given any thought to what we're going to do with runtime.GOOS and runtime.GOARCH if/when that happens, so we don't add ambiguity between darwin/arm64 (which currently means iOS only) and darwin/arm64 (which might also mean macOS in the future)?

Changing GOARCH seems out.

Adding GOOS=macos would break any code that switches on those values.

Perhaps some magic behavior like we did for GOOS=android (implies linux build tags) and GOOS=illumos (implies solaris build tags)? But what would still break code that checks runtime.GOOS.

Perhaps keep darwin/arm64 on both iOS and macOS but add some some runtime exported const DarwinOS = {"macos", "ios", ""} that people could switch on when it matters?

If there's new API, might be nice to get that in earlier. But OTOH, don't want to jump the gun if rumors don't pan out.

NeedsInvestigation OS-Darwin mobile

Most helpful comment

For those like me seeking some information on how to get go working on an Apple Silicon Mac now, here is the way I had this working for myself for the master branch.

  1. You should have access to a different architecture, preferably Apple's Intel Mac.
  2. On that Mac you should have already a go installed, I had version 1.15.5 installed via homebrew.
  3. Download the source of golang and cd into the src folder. You should be in the master branch.
  4. Run this to build the binaries for ARM Darwin arch: GOARCH=arm64 GOOS=darwin ./bootstrap.bash.
  5. Copy the go-darwin-arm64-bootstrap.tbz to your Apple Silicon Mac, and unwrap it into /opt/go/ folder, so that the bin fodler can be in /opt/go/bin path.
  6. Add /opt/go/ to your PATH variable.
  7. Sign every binary in paths /opt/go/bin/ and /opt/go/pkg/tools/ with codesign -s - <binary_path>.

This should work now.

All 151 comments

If darwin/arm64 doesn't work for macos,
then I think we should reclaim it for macos
and move ios over to ios/arm64, much as we have
android as an almost-synonym for Linux on mobile.
(Many fewer GOOS=darwin users on mobile than desktop.)

I've thought about whether we should have GOOS=macos
independently of this issue, but it seems like too much churn
for too little benefit.

Interesting to note that way back when, we could have done
GOOS=osx and we'd be in the same boat of having the wrong
name. Moving to GOOS=macos will only match Apple terminology
until the next OS rename.

I think the suggestion here is:

  1. add ios as a valid GOOS value
  2. let ios imply darwin much as android implies linux

This will potentially break any existing mobile programs that test runtime.GOOS and expect to see darwin. After this change they will see ios.

This suggests that for 1.15 we should

  1. add ios as a valid build tag that implies darwin
  2. announce in the release notes that we plan to change to GOOS=ios in a future release

CC @hyangah

I think (but not sure) gomobile sets ios tag, to distinguish iOS emulator on x86 vs. macOS.

gomobile uses ios tag and also we use the ios tag in crypto/x509 package.
gomobile sets GOOS/GOARCH for crosscompile so it needs to use the right
value depending on the go version. I don't think that's too difficult.

In addition to gomobile, cc/ @eliasnaur elias.naur@gmail.com for gio,
@hajimehoshi for ebiten users

On Fri, May 1, 2020 at 2:38 PM cherrymui notifications@github.com wrote:

I think (but not sure) gomobile sets ios tag, to distinguish iOS emulator
on x86 vs. macOS.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/golang/go/issues/38485#issuecomment-622509793, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/ABGESL63JC4FILQFUNGUQH3RPMJJPANCNFSM4MJZNOPQ
.

--
__

cc @eliasnaur @hajimehoshi

Interesting to note that way back when, we could have done
GOOS=osx and we'd be in the same boat of having the wrong
name. Moving to GOOS=macos will only match Apple terminology
until the next OS rename.

Also interesting is that Apple currently has macOS, iOS, iPadOS, tvOS, and watchOS.

As far as I know about mobile application developing, there should be no problem to add ios to GOOS :-)

Change https://golang.org/cl/239278 mentions this issue: all: experiment with adding ios as a recognized GOOS value and build constraint that implies darwin

I expect we will learn relevant official information from Apple's WWDC 20 Keynote later today, and be able to use that information to make any definitive 1.15-specific decision.

However, given we are well into the code freeze for 1.15 with not much time left, and a change to build tags now would require getting a freeze exception (per bullet point 3 from the planning thread), I started investigating the plan for 1.15 @ianlancetaylor described in https://github.com/golang/go/issues/38485#issuecomment-622504803 in advance to learn more and be able to move quickly today if needed.

Based on what I've learned from the investigation (also see a draft DNS CL 239278), I suspect we will not need or want to make any code changes for 1.15, only add a note to the release notes. The rationale follows.

The motivation behind doing "add ios as a valid build tag that implies darwin" for 1.15, as I understand, is to enable people to start moving their iOS-specific code away from darwin,arm64 to something else as early as 1.15, rather than later. However, as @hyangah mentioned in https://github.com/golang/go/issues/38485#issuecomment-622526879, the gomobile tool already sets an "ios" build constraint whenever targeting iOS (see code here, here and here). That means we don't need to make changes in Go 1.15 for people to be able to start moving iOS-specific code behind a potentially more future-proof ios build constraint. They can already do that now, even with Go 1.14, 1.13, etc. (Runtime code that attempts to check runtime.GOOS to tell whether iOS is the target is a separate matter, and I'll address that in a later comment.)

Work to add a new port must be started before the code freeze, so by now we know for sure that Go 1.15 will not be able to support macOS on any new architectures beyond amd64. We can also defer any changes to the main tree until we know for certain we need to reclaim darwin,arm64 (as @rsc emphasized in his original comment).

This suggests for 1.15 it's likely sufficient to update release notes without any code changes.

I'll revisit and update this after the WWDC keynote, based on new official information that may be made available.

It's official.

(One source: https://www.wired.com/story/wwdc-2020-everything-apple-announced/)

It is! Apple has announced it during the WWDC20 keynote. Here are more sources:

The timeline they've announced is that it'll be a 2 year transition, with the first Apple Silicon Macs shipping by the end of the year and development kits this week. There will be more Intel-powered macOS devices coming out too.

I believe with this information, the plan to update release notes for Go 1.15 mentioned in https://github.com/golang/go/issues/38485#issuecomment-647584660 is still valid. All other changes can wait until the tree re-opens for 1.16 development. Feedback is welcome. I plan to send a CL for the release note entry for review this week.

It's possible the new "Apple Silicon" will be a superset of 64-bit ARM, or even a departure. Perhaps a new GOARCH symbol should be considered if that's the case, e.g. apl64?

We'll cross that bridge when we come to it.

(It seems fairly unlikely that Apple would stop running existing programs. If they introduce new instructions that we care about, we can address that through a GOARM64 environment variable if necessary.)

Apple just announced in their State of the Union talk at WWDC that they've developed patches for Go, that they hope to submit in the coming days. So exciting! Hope we can onboard support for macOS/arm64 (even on a branch) very soon. :)

@jpap Thanks for the heads up. A recording of that talk is available at https://developer.apple.com/videos/play/wwdc2020/102/. The phrase I heard around the 20:34 mark is a less definitive "we've already done the initial work for some of the more widely used open-source projects", so we may need to wait to learn details.

@jpap Thanks for the heads up. A recording of that talk is available at https://developer.apple.com/videos/play/wwdc2020/102/. The phrase I heard around the 20:34 mark is a less definitive "we've already done the initial work for some of the more widely used open-source projects", so we may need to wait to learn details.

That's right, with the statement that followed: "...and we will be publishing patches to them in the next days". You can see a reference to the Go project on the slide behind the speaker. Now I've only just noticed the bold type on some projects on the second slide below -- perhaps Apple will focus on those first, for which Go may have to wait.

image

image

I don't believe we have to do anything in the Go 1.15 release notes.
Nothing is changing for Go 1.15.

the gomobile tool already sets an "ios" build constraint whenever targeting iOS (see code here, here and here). That means we don't need to make changes in Go 1.15 for people to be able to start moving iOS-specific code behind a potentially more future-proof ios build constraint.

I just want to mention that gomobile is not the only way to build Go programs on iOS. There are probably other tools (not sure if they have ios tag set). Also it could be done by hand (only using Go tools).

(I'm not suggesting we should or should not do anything for it in Go 1.15.)

Can we please build universal binaries (Universal 2: x86-64/arm64 bundles) from go build?

Example:

GOOS=darwin GOARCH=universal2

Use case:

I build a go binary in my new ARM Mac and distribute it to a partner with a 2018 Mac and another one with Apple silicon

Indeed, most outfits shipping Mac apps would want universal binaries. You'd only want single-arch ones for development.

https://developer.apple.com/documentation/xcode/building_a_universal_macos_binary

Example:
GOOS=darwin GOARCH=universal2

Perhaps a comma separated list for the architecture could avoid having to define new GOARCH values? The "universal" (fat-binary) executable is just a set of slices, one for each architecture, which maps nicely to a comma separated list (array).

GOOS=darwin
GOARCH=amd64,arm64

It would not be hard to use 2 go build commands and lipo to make your own fat binaries.

It would not be hard for the Go tool to build fat binaries for pure Go programs. cgo programs might be quite a bit trickier as we'd need to specify multiple C toolchains, one for each arch.

FYI, it seems that the latest HEAD (96e8366437) is not able to create a bootstrap toolchain for GOOS=darwin GOARCH=arm64. If there's some way to do that, or if I should be reporting this somewhere else, please let me know.




Building packages and commands for target, darwin/arm64.

cmd/addr2line

/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-062812285/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64

❯ GOOS=darwin GOARCH=arm64 ./bootstrap.bash
#### Copying to ../../go-darwin-arm64-bootstrap

#### Cleaning ../../go-darwin-arm64-bootstrap
Removing VERSION.cache
Removing bin/
Removing pkg/
Removing src/cmd/cgo/zdefaultcc.go
Removing src/cmd/go/internal/cfg/zdefaultcc.go
Removing src/cmd/go/internal/cfg/zosarch.go
Removing src/cmd/internal/objabi/zbootstrap.go
Removing src/go/build/zcgo.go
Removing src/runtime/internal/sys/zversion.go

#### Building ../../go-darwin-arm64-bootstrap

Building Go cmd/dist using /Users/andre/src/golang/go. (devel +96e8366437 Tue Jun 30 20:14:48 2020 +0000 darwin/amd64)
Building Go toolchain1 using /Users/andre/src/golang/go.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.
Building Go toolchain2 using go_bootstrap and Go toolchain1.
Building Go toolchain3 using go_bootstrap and Go toolchain2.
Building packages and commands for host, darwin/amd64.
Building packages and commands for target, darwin/arm64.
# cmd/addr2line
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-062812285/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/buildid
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-326003277/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/cgo
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-952782147/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/dist
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-217315698/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/doc
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-739401087/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/cover
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-852101920/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/api
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-014825587/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/fix
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-060310708/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/gofmt
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-312610998/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/objdump
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-597275755/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/nm
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-365096583/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/asm
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-252140843/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/pack
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-617375788/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/test2json
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-244034780/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/vet
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-825391755/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/oldlink
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-990075442/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/trace
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-435026565/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/link
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-811680617/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/pprof
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-594500135/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/go
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-014547338/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/compile
/Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: warning: ignoring file /var/folders/qc/x0j95x2d6tgb4686by93p4b00000gn/T/go-link-285118437/go.o, building for macOS-x86_64 but attempting to link with file built for unknown-arm64
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

go tool dist: FAILED: /Users/andre/src/golang/go-darwin-arm64-bootstrap/pkg/tool/darwin_amd64/go_bootstrap install -gcflags=all= -ldflags=all= std cmd: exit status 2

@indirect This is the tracking bug for making that work.

@indirect for GOOS=darwin GOARCH=arm64, are you building for macOS or iOS? For macOS, the port doesn't exist yet (what this bug is for, as @ianlancetaylor said). For iOS, see https://tip.golang.org/misc/ios/README

Has Apple made contact yet to patch in support?

I don't believe so. We do have hardware coming, though.

If anyone wants to try this before we get the actual patches, I have some instructions in https://gist.github.com/tonistiigi/290d2e7118fe6f581e336bf3553b4501 .

Mostly everything seemed to work. I also built go itself, and that worked fine (and built go seemed to work fine), but when I tried to build on the native arch with GOROOT_BOOTSTRAP it errors somewhere in the middle of the build. Didn't have time to debug what was going on there yet.

Using the link @tonistiigi posted I was able to also build the darwin-arm64 toolchain on my MacBook Pro. however, when attempting to bootstrap on the native arch it seems to have failed while translating(?) which I don't think is part of the Go toolchain.

The most fun at this point was having to click the "Allow" button in Security & Privacy system panel for every tool that is used.

Steps on native arch:

$ mkdir buildgo
$ cd buildgo
$ git clone https://go.googlesource.com/go
$ cd go/src
$ git checkout release-branch.go1.14
$ git apply 0001-go1.14-temp-fix-for-darwin-arm64.patch
$ env CC=$HOME/Downloads/clang_arm64_wrapper.sh GOROOT_BOOTSTRAP=$HOME/buildgo/go-darwin-arm64-bootstrap GOOS=darwin GOARCH=arm64 ./all.bash

Happy to share the exact error, just unsure if allowed given that Google cannot find a single reference to the file or types mentioned meaning it is probably internal to Apple.

Following up on https://github.com/golang/go/issues/38485#issuecomment-647584660.

Since then, I found that Gio (/cc @eliasnaur) also sets the ios build tag unconditionally (see here) when building Go packages for the iOS target, like gomobile and gobind from x/mobile do. The ios build tag has been around since Go 1.5 and will be taken into account if any changes need to be made in the future.

I've talked with @hyangah and @cherrymui in case I was missing anything that's worth considering for the Go 1.15 release. In the past releases, we've sometimes added release note entries about likely upcoming changes that users should be aware of, so I wanted to see if there was something useful we could say that would meet the bar for inclusion. There turned out not to be anything at this time. As Russ said, nothing is changing for 1.15. Much of this issue remains as future work. So, I'll abandon CL 239278 and move this tracking issue to the 1.16 milestone as there's nothing left for the Go 1.15 release.

Re fat binaries, see #40698.

Change https://golang.org/cl/254740 mentions this issue: all: add GOOS=ios

CL 254740 brought up the iOS emulator. The CL leaves emulator builds to use GOOS=darwin, GOARCH=amd64, tags=ios, as detailed in @cherrymui's comment.

I hope the implementation of this issue includes support for ios/amd64 (and ignoring the ios tag) to target the iOS emulator. Cherry mentions the issue of verifying the target works. We don't have iOS emulator builders, which is unfortunate, but I don't think lack of a builder should block a clean separation of GOOS=darwin and GOOS=ios in Go 1.16.

@eliasnaur , could you share more information about GOOS=ios on AMD64? Specifically, how does it differ from GOOS=darwin? (Is it just all places that are currently tagged with "ios"? Is that all?) Also, asides from the builder, how do we know if it "works" (even on our local machine)? Is it that GOOS=ios GOARCH=amd64 all.bash passes on an AMD64 macOS machine, or something else? Thanks!

Change https://golang.org/cl/255257 mentions this issue: misc/ios: add support for running programs on the iOS simulator

@eliasnaur , could you share more information about GOOS=ios on AMD64? Specifically, how does it differ from GOOS=darwin? (Is it just all places that are currently tagged with "ios"? Is that all?)

I believe so, yes. FWIW, the gogio use the same go tool invocation for both ios/arm64 and ios/amd64, except for GOARCH.

Also, asides from the builder, how do we know if it "works" (even on our local machine)? Is it that GOOS=ios GOARCH=amd64 all.bash passes on an AMD64 macOS machine, or something else? Thanks!

Good question. There isn't support for running standard tests on the simulator, so I did that in https://go-review.googlesource.com/c/go/+/255257. Change useDevice to false to target the simulator.

Test binaries fail very early with a linker error. I'm running:

$ cd $GOROOT/src
$ go build -o ../bin/go_darwin_amd64_exec ../misc/ios/go_darwin_arm_exec.go && CC=~/go-tip/misc/ios/clangwrap.sh go test -exec ~/go-tip/bin/go_darwin_amd64_exec -tags ios -v ./image/
exit status 123
FAIL    image   2.660s
FAIL

The 123 exit status is caused by the program being killed by SIGABRT. Search for "exitStatus = 123" in my CL.

There's a bit more information if you launch the binary manually:

$ xcrun simctl launch --console booted golang.gotest     # golang.gotest is the bundle id if GOIOS_APP_ID is not set.
com.eliasnaur.mailtest: 42255
dyld: malformed mach-o image: __LINKEDIT segment does not have read-only permissions

I suppose the reason this basic error hasn't been discovered before is that tools like gogio and gomobile only build in c-archive mode.

Does it work with -buildmode=pie? On darwin/arm64 we always build PIE. It may not like the non-PIE binary we generated by default on AMD64.

Does it work with -buildmode=pie? On darwin/arm64 we always build PIE. It may not like the non-PIE binary we generated by default on AMD64.

Good idea, thank you. After fixing clangwrap.sh in my CL, linking fails:

$ go build -o ../bin/go_darwin_amd64_exec ../misc/ios/go_ios_exec.go && CC=~/go-tip/misc/ios/clangwrap.sh CGO_ENABLED=1 go test -exec ~/go-tip/bin/go_darwin_amd64_exec -tags ios -v -buildmode=pie ./image/
# image.test
/Users/elias/go-tip/pkg/tool/darwin_amd64/link: running /Users/elias/go-tip/misc/ios/clangwrap.sh failed: exit status 1
Undefined symbols for architecture x86_64:
  "_fdopendir$INODE64", referenced from:
      _syscall.libc_fdopendir_trampoline in go.o
  "_readdir_r$INODE64", referenced from:
      _syscall.libc_readdir_r_trampoline in go.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

FAIL    image [build failed]
FAIL

which sounds right: the $INODE64 versions of fdopendir and readdir do not exist on iOS.

The $INODE64 is added in the linker at https://tip.golang.org/src/cmd/link/internal/ld/macho.go#L812 . Maybe skip them if building for iOS. (Apparently machoPlatform == PLATFORM_MACOS predicate doesn't seem to do its job...)

Indeed, I needed

$ git diff
diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go
index 9765ce18d3..55b2f12d64 100644
--- a/src/cmd/link/internal/ld/macho.go
+++ b/src/cmd/link/internal/ld/macho.go
@@ -423,7 +423,7 @@ func (ctxt *Link) domacho() {
                                ml.data[0] = 10<<16 | 9<<8 | 0<<0 // OS X version 10.9.0
                                ml.data[1] = 10<<16 | 9<<8 | 0<<0 // SDK 10.9.0
                        }
-               case sys.ARM, sys.ARM64:
+               case sys.ARM, sys.ARM64, sys.AMD64:
                        machoPlatform = PLATFORM_IOS
                }
        }

With that, the binaries seem to run:

$ go build -o ../bin/go_darwin_amd64_exec ../misc/ios/go_darwin_arm_exec.go && CC=~/go-tip/misc/ios/clangwrap.sh CGO_ENABLED=1 GOIOS_APP_ID= go test -exec ~/go-tip/bin/go_darwin_amd64_exec -tags ios -v -buildmode=pie ./image/
exit status 1
FAIL    image   3.774s
FAIL

I'm not sure where the output is, but a manual run exposes it:

$ xcrun simctl launch --console booted golang.gotest
golang.gotest: 44504
--- FAIL: TestDecode (0.00s)
    decode_test.go:95: testdata/video-001.png: open testdata/video-001.png: no such file or directory
    decode_test.go:95: testdata/video-001.png: open testdata/video-001.png: no such file or directory
    decode_test.go:95: testdata/video-001.png: open testdata/video-001.png: no such file or directory
    decode_test.go:95: testdata/video-001.png: open testdata/video-001.png: no such file or directory
    decode_test.go:95: testdata/video-001.png: open testdata/video-001.png: no such file or directory
    decode_test.go:95: testdata/video-001.png: open testdata/video-001.png: no such file or directory
    decode_test.go:95: testdata/video-001.221212.png: open testdata/video-001.221212.png: no such file or directory
    decode_test.go:95: testdata/video-001.cmyk.png: open testdata/video-001.cmyk.png: no such file or directory
    decode_test.go:95: testdata/video-001.rgb.png: open testdata/video-001.rgb.png: no such file or directory
    decode_test.go:95: testdata/video-001.progressive.truncated.png: open testdata/video-001.progressive.truncated.png: no such file or directory
    decode_test.go:95: testdata/video-005.gray.png: open testdata/video-005.gray.png: no such file or directory
    decode_test.go:95: testdata/video-005.gray.png: open testdata/video-005.gray.png: no such file or directory
FAIL

Change https://golang.org/cl/255537 mentions this issue: all: add GOOS=ios

Change https://golang.org/cl/255557 mentions this issue: all: add GOOS=ios

Change https://golang.org/cl/257618 mentions this issue: vendor, cmd/vendor: update vendored x/sys and x/net

Change https://golang.org/cl/259337 mentions this issue: cmd/dist: detect gohostarch on ios/arm64

Change https://golang.org/cl/259439 mentions this issue: cmd/dist: test c-archive mode on ios/arm64

Change https://golang.org/cl/256918 mentions this issue: runtime: enable more address bits on macOS/ARM64

Change https://golang.org/cl/256920 mentions this issue: all: enable more tests on macOS/ARM64

Change https://golang.org/cl/259440 mentions this issue: runtime/cgo: only build xx_cgo_panicmem on iOS

Change https://golang.org/cl/259441 mentions this issue: cmd/link: support plugin on macOS/ARM64

Change https://golang.org/cl/259442 mentions this issue: cmd/link: support PIE on macOS/ARM64

Change https://golang.org/cl/259443 mentions this issue: cmd/link: support C-shared buildmode on macOS/ARM64

Change https://golang.org/cl/256919 mentions this issue: cmd/dist: enable more tests on macOS/ARM64

Change https://golang.org/cl/260339 mentions this issue: time: enable system zoneinfo on macOS/ARM64

Change https://golang.org/cl/260340 mentions this issue: crypto/x509: use macOS/AMD64 implementation on macOS/ARM64

@cherrymui, don't forget to update the predicates in internal/testenv: it looks like we're still skipping tests that use os/exec on darwin/arm64, under the erroneous assumption that darwin/arm64 implies iOS.

@bcmills actually I'm about to mail a CL for that, good timing :) I tried it a while ago and there were some tests failing. I have been fixing them along the way, and understanding the ones that actually need to be skipped. As of last night I think I got them all.

Change https://golang.org/cl/260718 mentions this issue: syscall: support ptrace on macOS/ARM64

Change https://golang.org/cl/260719 mentions this issue: all: enable more tests on macOS/ARM64

Change https://golang.org/cl/261643 mentions this issue: cmd/link: support internal linking on darwin/arm64

Change https://golang.org/cl/261642 mentions this issue: cmd/link: support PIE internal linking on darwin/amd64

Change https://golang.org/cl/262559 mentions this issue: runtime/cgo: build iOS-specific code only on iOS

Change https://golang.org/cl/262558 mentions this issue: cmd/dist: only build ios_exec wrapper for ios

Change https://golang.org/cl/262957 mentions this issue: unix: add support for ptrace on macOS/ARM64

Change https://golang.org/cl/262958 mentions this issue: unix: enable more tests on darwin/arm64

Change https://golang.org/cl/263265 mentions this issue: cmd/link: use GOOS=ios for TestBuildForTvOS

Change https://golang.org/cl/263637 mentions this issue: cmd/link: support cgo internal/linking on darwin/arm64

Change https://golang.org/cl/263638 mentions this issue: runtime: define ios/arm64 entry points

Change https://golang.org/cl/263639 mentions this issue: cmd/link: fix TestDWARFiOS

Is ios/amd64 for the iOS emulator going to part of Go 1.16? The freeze is near, and I don't think darwin/amd64,tags=ios is the right configuration for the emulator.

@eliasnaur mind sending a CL? I probably don't have enough knowledge (and time) to do it. Thanks.

Is there a way to set up a builder, or something, that we can test it? @dmitshur probably knows more about what needs to be done besides the CL.

Hi, I noticed in this Port your Mac app to Apple Silicon video at about 20m45s to 22m00s that they recommend replacing calls to mach_absolute_time with clock_gettime_nsec_np(CLOCK_UPTIME_RAW). Not sure if this is a real issue with go though, or if it's already handled correctly.

Change https://golang.org/cl/263798 mentions this issue: all: add GOOS=ios GOARCH=amd64 target for the ios simulator

@cherrymui CL 263798 contains the necessary changes for GOOS=ios GOARCH=amd64 to work with

$ go build -o ../bin/go_ios_amd64_exec ../misc/ios/go_ios_exec.go && CC=~/go-tip/misc/ios/clangwrap.sh CGO_ENABLED=1 GOOS=ios go test -exec ~/go-tip/bin/go_ios_amd64_exec -ldflags='-linkmode external' ./math
ok      math    2.648s

to work.

Note that without -linkmode external, the test hangs with the warning

$ go build -o ../bin/go_ios_amd64_exec ../misc/ios/go_ios_exec.go && CC=~/go-tip/misc/ios/clangwrap.sh CGO_ENABLED=1 GOOS=ios go test -exec ~/go-tip/bin/go_ios_amd64_exec ./math
# math.test
loadinternal: cannot find runtime/cgo

Patching MustLinkExternal didn't help:

diff --git a/src/cmd/internal/sys/supported.go b/src/cmd/internal/sys/supported.go
index ccc5b2245b..a9e061ab8d 100644
--- a/src/cmd/internal/sys/supported.go
+++ b/src/cmd/internal/sys/supported.go
@@ -39,7 +39,9 @@ func MustLinkExternal(goos, goarch string) bool {
                if goarch != "arm64" {
                        return true
                }
-       case "darwin", "ios":
+       case "ios":
+               return true
+       case "darwin":
                if goarch == "arm64" {
                        return true
                }

@eliasnaur thanks! Do you know where it hangs? Does the emulator require cgo binaries for some reason? What about changing externalLinkingForced in cmd/go/internal/load/pkg.go?

@cherrymui externalLinkingForced did it, thank you!

@eliasnaur In the context of running the iOS Simulator on an AMD64-powered macOS device, do you know if it is still a requirement that the .app bundle contains a binary compiled to amd64 architecture in order to run on the simulator, or is the modern iOS Simulator capable of running arm64-only binaries too, just at a performance cost?

This question occurred to me because the last time I tried to use cmd/gomobile to build an app and run on the simulator, it seemed not to make a difference when I selected a subset of instruction sets (i.e., -target=ios/arm64 vs -target=ios/arm64,ios/amd64). As far as I remember (which could be mistaken; I'd have to double check now to be sure), the .app bundle seemed to run even without an amd64 binary.

So far, I wasn't able to find documentation that specifies the capabilities of the modern iOS Simulator. So I wanted to ask in case you already know the answer. I'm asking this question to understand the situation better, especially in the context of a potential builder that tests the ios/amd64 port. Thanks.

I didn't know, but I suspected that the simulator couldn't run arm64 binaries, because it's not an emulator. The internet seems to agree: https://stackoverflow.com/questions/23895492/can-ios-arm-code-ever-be-run-in-a-simulator.

To make sure, I built an arm64 .app and pushed it to the simulator. It failed to start.

That said, it's likely that an arm-based macOS machine needs arm iOS binaries for the simulator.

The internet seems to agree: https://stackoverflow.com/questions/23895492/can-ios-arm-code-ever-be-run-in-a-simulator.

I had seen similar questions, but given they're multiple years old, I wasn't sure how relevant the answer was.

To make sure, I built an arm64 .app and pushed it to the simulator. It failed to start.

Great, thanks for trying and confirming that it fails today.

That said, it's likely that an arm-based macOS machine needs arm iOS binaries for the simulator.

That makes sense.

Yeah, I don't think it does instruction simulation, only system simulation, so it cannot run ARM64 code.

Why is everyone talking about iOS? Wasn't this about Darwin on ARM instead of x86-64? Wasn't the point of this issue to adapt Golang to ARM and Darwin? Shoudn't we say GOOS=darwin and GOARCH=arm64?

@eacp this issue is about arm64 macOS becoming GOOS=darwin and GOARCH=arm64. However, darwin/arm64 used to mean arm64 iOS, so part of fixing this issue was to separate iOS out into its own GOOS (ios). The same applies to the iOS simulator: used to be darwin/amd64 with an "ios" tag; it's moving to ios/amd64.

@ottob thanks for bringing this up.

The example in the video assumes mach_absolute_time returns nanoseconds, which is the problem. We don't assume that and query the scaling factor and do the scaling ourselves. So it is not a problem.

Using clock_gettime_nsec_np would be simpler, as we don't need to do the scaling ourselves. But when I tried it, it is actually slower (because it seems to call mach_absolute_time internally but also does more dispatching and doesn't seem to memoize the scaling factor). I think we'll keep the current code for now.

Change https://golang.org/cl/265120 mentions this issue: runtime: always enable async preemption on darwin/arm64

Change https://golang.org/cl/265121 mentions this issue: cmd/link: enable internal linking by default on darwin/arm64

Change https://golang.org/cl/265119 mentions this issue: runtime: save/restore g unconditionally on darwin/arm64

Change https://golang.org/cl/265118 mentions this issue: runtime: set up TLS without cgo on darwin/arm64

Change https://golang.org/cl/266373 mentions this issue: runtime, cmd: support race detector on darwin/arm64

I think the suggestion here is:

1. add `ios` as a valid `GOOS` value
2. let `ios` imply `darwin` much as `android` implies `linux`

This will potentially break any existing mobile programs that test runtime.GOOS and expect to see darwin. After this change they will see ios.

This suggests that for 1.15 we should

1. add `ios` as a valid build tag that implies `darwin`
2. announce in the release notes that we plan to change to `GOOS=ios` in a future release

Unfortunately this breaks the use of system object files (syso): an object named lib_darwin_arm64.syso will be picked up for both macOS and iOS builds (on arm64), when it may have been built only for macOS.

As I just discovered, the recent Xcode 12 has made the situation worse: the linker has become more selective and errors-out when the platform in the object file's LC_BUILD_VERSION load command doesn't match the build target [1]. (Prior to Xcode 12, you could link an object built for macOS/amd64 into an iOS simulator executable; it looks like they've tightened it up in preparation for the new arm64 Macs.)

Ideally, each platform would use a different GOOS; but there are many (to use the Apple SDK naming):

  • macosx
  • iphoneos
  • iphonesimulator
  • watchos
  • watchsimulator
  • appletvos
  • appletvsimulator

If we keep them all under GOOS=darwin and differentiate using a build tag instead, we need the ability to include tags into the filename build constraint. One approach is to use the + symbol: for example, the filename lib_arm64+iphonesimulator.syso would match tag iphonesimulator and GOARCH=arm64 only. Since syso files are always architecture dependent, a GOARCH must always be specified when a tag is specified.

At present tags are ignored when selecting syso files for a build: files are matched on GOOS and/or GOARCH only. For example, lib_ios_arm64.syso is matched for any GOOS and GOARCH=arm64, regardless of whether build tag ios is present.

I am working with projects that target some of the above platforms and I am happy to supply a build tag directly. But without the ability to select syso files by tag and GOARCH, I would need to write a custom build tool to extract and filter syso files from package dependencies before performing the build in a temporary folder with the right syso files. This approach is undesirable because the project is no-longer "go gettable" and a proprietary build tool is required.

[1] The new linker error with Xcode 12: ld: building for iOS Simulator, but linking in object file built for macOS, file '/var/folders/h7/r_43shxn71v0pq_gx72f57ph0000gn/T/go-link-172505736/000035.o' for architecture x86_64

Good point about syso matching. Unlike other files, there is no place to put an extra build tag to exclude ios. A possible workaround would be using sub-packages, something like

  • somepath/macos: lib.syso specific for macOS.
  • somepath/ios: lib.syso specific for iOS.
  • import somepath/macos or somepath/ios depending on build tag.
    I agree that this is not pretty.

Another possibility would be adding some mechanism to match negative tags in file names, maybe something like lib_darwin_noios_arm64.syso, which is not matched under ios.

Change https://golang.org/cl/267098 mentions this issue: race.bash: add darwin/arm64

Change https://golang.org/cl/267097 mentions this issue: cmd/link: use internal linking for -race mode on darwin/arm64

Change https://golang.org/cl/267718 mentions this issue: doc/go1.16: add release notes for darwin ports

Change https://golang.org/cl/268497 mentions this issue: doc/articles/race_detector.html: add darwin/arm64

Good point about syso matching. Unlike other files, there is no place to put an extra build tag to exclude ios.

A possible workaround would be using sub-packages, something like
[snipped]

Great suggestion -- that can work, though agreed it is messy.

Another possibility would be adding some mechanism to match negative tags in file names, maybe something like lib_darwin_noios_arm64.syso, which is not matched under ios.

Unfortunately we need more than negative tag-matching in filenames. For example, a syso in a Go package might be needed for each of the following distinct platforms.

  1. macOS (arm64; on an Apple Silicon Mac) #macosx
  2. iOS simulator (arm64; on an Apple Silicon Mac) #iphonesimulator
  3. iOS device (arm64) #iphoneos
  4. Apple TV simulator (arm64; on an Apple Silicon Mac) #appletvos
  5. Apple TV device (arm64) #appletvsimulator

The string _noios_ in a syso filename does not help to distinguish between the iOS simulator and iOS device, nor between iOS and Apple TV. If we employ user-defined build tags corresponding to the hashtags above, and included those in the syso filename suffix, we could correctly target each platform.

I've created a proposal #42477 to track this.

Simulators and tvOS have not been really "supported" platforms. They mostly "work" in practice, but we haven't really thought about them. If we want to actually "support" them, I think we need to think them more holistically (in #42477 or a separate issue). @eliasnaur can probably chime in. Thanks.

As far as I can tell, the darwin/arm64 port is now pretty much on parity with the darwin/amd64 port, and I don't expect much to be done on this issue. I think we can close this.

Feel free to reopen, or open a new issue, if I missed anything.

Are there any plans to address the numa issues introduced by the performance vs efficiency cores? Similarly, I think they're heading in the direction of numa for ram with on-die and off-die (in the next generation, assuming that the current 16GB limit is due to the ram being on-die)?

Honestly that sounds like a discussion to have on golang-dev. Making the goroutine scheduler NUMA aware would be a useful project, but quite a large one.

Any ETA on when this compatibility will be released? Clicking the Go 1.16 milestone says Jan 1st.

1.16 is scheduled for Feb 1.
I fixed the milestone due date.

Hi, Homebrew maintainer here. For testing and distribution purposes of a native compiler, we're looking at whether the Go project is hosting somewhere (or would consider hosting somewhere) a binary build for arm64-apple-darwin, in whatever 1.16-pre-pre release state (basically the current state). We typically do our builds by bootstrapping, so having such a version as bootstrap compiler would be appreciated. Is that something planned?

Hi @fxcoudert - It's easy to get the latest golang tip with gotip - That's your best path right now. I did a quick test and found it would compile... now when I get apple silicon I can test the results. AND thank you for your work maintaining Homebrew! Looking forward to it supporting arm64. Do you have a link to an issue I can follow about arm64 support?

@rfay I don't think that's what I need. It's a go program, so I would need a go compiler before it. My question is: where can I find a native Apple Silicon go compiler to serve as basis for the bootstrap process.

@fxcoudert golang is fantastic as a cross-compiler, so if you build gotip on any current architecture, you can build anything else you need with that (including nearly anything targeted at linux/arm64 or darwin/arm64). You can even just build golang itself with gotip on an existing architecture if that's critical. But golang is so very good at cross-compiling fat binaries that you might not even need to do that.

@rfay I love cross-compilers but my goal (well, Homebrew's goal) here is not a cross-compiler, rather a native bootstrapped Apple Silicon compiler

Again, it shouldn't be hard to build a native apple silicon golang compiler. It doesn't do me any good to speculate on the results since mine won't arrive until Nov 27, so if I cross-compiled golang right now... I wouldn't know what to do with it. But with golang it should be a matter of GOOS=darwin/arm64 <build gotip>.

FYI, Go does not build fat binaries. Here's an unofficial utility by @randall77 for that, which might land in x/ someday:

https://github.com/randall77/makefat

@fxcoudert I understand you need something to bootstrap the installation on arm64 machines, but it's unlikely we'll host binaries until the beta. The options are hosting a bootstrap toolchain you cross-compiled yourself, or bootstrapping from Go 1.4 which I believe should still build from clang and build tip. (I noticed before the Homebrew Formula uses Go 1.7 instead, any idea why?)

FWIW, I am getting an Apple Silicon machine on the 17th, and I'd be happy to help. Feel free to mention me in an issue in homebrew-core.

I don't think bootstrapping from Go 1.4 would work, because Go 1.4 doesn't support darwin/arm64.

So cross-bootstrapping is the easiest option. It can be done by running GOARCH=arm64 GOOS=darwin ./bootstrap.bash in GOROOT/src with Go tip on ~any platform.

Ah right, that makes sense of course.

Then I guess the problem becomes who hosts the bootstrapped compiler. If Homebrew has a solution to host binaries (presumably Go is not the only software in this position?) it'd be best for Homebrew to maintain it. Otherwise I can look into whether we can host an unofficial build.

Anyway, this is more on topic for a homebrew/homebrew-core issue, so ping me over there if I can help.

@FiloSottile I think if the Go project is not ready to host a bootstrap binary, we'd rather not ship our own. We defer to upstream for these sort of things, so if it's not deemed even alpha quality to be made available, we'll abstain and users will wait for the beta.

FYI, Go does not build fat binaries. Here's an unofficial utility by @randall77 for that, which might land in x/ someday:

https://github.com/randall77/makefat

In chromium project, there is a python script called universalize, that could also be of use, it does something similar.

Curious, is there any talk of an Apple Silicon darwin/arm64 backport from 1.16 to 1.15.x to get it out there before 1.16 scheduled for Feb 1st 2021...? Or an early 1.16 release?

New Apple Silicon/M1 hardware is starting to arrive in peoples hands already :) I can imagine a lot of projects will be waiting on a release before they push out new releases of their projects.

Anyone had success cross compiling from gotip. When I do this on an intel mac with

GOARCH=arm64 GOOS=darwin ./bootstrap.bash

everything builds fine but running go on the arm mac just gets killed:

./go
zsh: killed ./go

Some thing happens trying to cross compile a go project and running on the arm mac as well.

@gigq what version of Go are you using?

At tip, I did GOARCH=arm64 GOOS=darwin go build cmd/go and copy the binary to ARM64 Mac and it runs fine.

@cherrymui I had the same issue at current tip, with bootstrap.sh, which AFAICT does approximately that. I'll open a separate issue if I can find more clues as to why.

I just tried bootstrap.bash and it worked as well. Maybe the DTK and the machines on the market behave differently? That would be weird...

It's codsigning, the compiler started to work once I ran codesign -s - on bin/ and pkg/tool/ binaries.

I imagine the DTK might have it disabled, which sort of makes sense but sets developers up for this.

I'll open an issue about it, since it stops "go test" and "go run" from working, and "go build" generates binaries that are not runnable.

Thanks @FiloSottile !

If you don't mind, could you try to build a simple C program using the C compiler on the machine (if it has one?) and see if it runs? Does the C compiler do code signing itself? (That would be ... a bit weird.)

So maybe try installing the latest amd64 toolchain on your M1 and use that to run bootstrap.bash?

Not sure why this helps. The binaries produced by the amd64 toolchain are still not signed and won't run.

Code signing does indeed fix it so go now runs on the M1. As a test I also cloned redis and compiled and that ran without having to codesign. Maybe it's because go was cross compiled on an intel mac and copied over vs redis being built on the M1 machine itself.

I just got my M1 this afternoon -- loving it so far. Thanks for all your efforts porting Go to it.

Before unloading all of the dev tools on the machine, and before trying out Go tip, I installed just Xcode and the command line tools. I then compiled a simple "hello world" in C, built it with clang -o test test.c, and it ran just fine. The machine is still very much in a vanilla state: no changes to SIP or any system security settings.

It looks like the Apple linker has automatically added an ad-hoc signature to the binary -- it's particularly interesting to see what looks like a new linker-signed CodeDirectory flag 0x20000 (flag 0x2 is adhoc) indicating this:

% codesign -vvvvv -d test
Executable=/Users/jpap/test
Identifier=test
Format=Mach-O thin (arm64)
CodeDirectory v=20400 size=509 flags=0x20002(adhoc,linker-signed) hashes=13+0 location=embedded
VersionPlatform=1
VersionMin=720896
VersionSDK=720896
Hash type=sha256 size=32
CandidateCDHash sha256=f54d00ba0c20977c1a2a14e129ca6038500aff97
CandidateCDHashFull sha256=f54d00ba0c20977c1a2a14e129ca6038500aff971a0ef98f1ab927e2fa3fe272
Hash choices=sha256
CMSDigest=f54d00ba0c20977c1a2a14e129ca6038500aff971a0ef98f1ab927e2fa3fe272
CMSDigestType=2
Executable Segment base=0
Executable Segment limit=16384
Executable Segment flags=0x1
Page size=4096
CDHash=f54d00ba0c20977c1a2a14e129ca6038500aff97
Signature=adhoc
Info.plist=not bound
TeamIdentifier=not set
Sealed Resources=none
Internal requirements=none

You could try performing a Go build on the M1 forcing the external (Apple) linker with -ldflags "-linkmode=external": it will probably add an ad-hoc CodeDirectory to the final binary, making your M1 Go builds "just work".

Code signing does indeed fix it so go now runs on the M1. As a test I also cloned redis and compiled and that ran without having to codesign. Maybe it's because go was cross compiled on an intel mac and copied over vs redis being built on the M1 machine itself.

It's likely because of the linker ad-hoc signature. Can you verify by dumping the code signature from the executable you built on the M1 as shown in my post above?

Oops, looks like #42684 covers the codesigning issue now.

For those like me seeking some information on how to get go working on an Apple Silicon Mac now, here is the way I had this working for myself for the master branch.

  1. You should have access to a different architecture, preferably Apple's Intel Mac.
  2. On that Mac you should have already a go installed, I had version 1.15.5 installed via homebrew.
  3. Download the source of golang and cd into the src folder. You should be in the master branch.
  4. Run this to build the binaries for ARM Darwin arch: GOARCH=arm64 GOOS=darwin ./bootstrap.bash.
  5. Copy the go-darwin-arm64-bootstrap.tbz to your Apple Silicon Mac, and unwrap it into /opt/go/ folder, so that the bin fodler can be in /opt/go/bin path.
  6. Add /opt/go/ to your PATH variable.
  7. Sign every binary in paths /opt/go/bin/ and /opt/go/pkg/tools/ with codesign -s - <binary_path>.

This should work now.

Change https://golang.org/cl/272257 mentions this issue: cmd/internal/buildid: update Mach-O code signature when rewriting buildid

Change https://golang.org/cl/272255 mentions this issue: cmd/internal/buildid: exclude Mach-O code signature in hash calculation

Change https://golang.org/cl/272256 mentions this issue: cmd/link: code-sign on darwin/arm64

Change https://golang.org/cl/272254 mentions this issue: cmd/internal/codesign: new package

Change https://golang.org/cl/272258 mentions this issue: cmd/link: invalidate kernel cache on darwin

For those like me seeking some information on how to get go working on an Apple Silicon Mac now, here is the way I had this working for myself for the master branch.

  1. You should have access to a different architecture, preferably Apple's Intel Mac.
  2. On that Mac you should have already a go installed, I had version 1.15.5 installed via homebrew.
  3. Download the source of golang and cd into the src folder. You should be in the master branch.
  4. Run this to build the binaries for ARM Darwin arch: GOARCH=arm64 GOOS=darwin ./bootstrap.bash.
  5. Copy the go-darwin-arm64-bootstrap.tbz to your Apple Silicon Mac, and unwrap it into /opt/go/ folder, so that the bin fodler can be in /opt/go/bin path.
  6. Add /opt/go/ to your PATH variable.
  7. Sign every binary in paths /opt/go/bin/ and /opt/go/pkg/tools/ with codesign -s - <binary_path>.

This should work now.

@MarkusBansky Did this actually work for you? I was under the impression that this just bootstraps the toolchain for darwin-arm64, but would still require using this toolchain to actually build Go, judging by the official documentation?

Either way, I can run go version, but attempting to install packages to run .go files results in errors such as this:

# runtime/cgo
gcc_arm64.S:28:16: error: brackets expression not supported on this target
 stp x29, x30, [sp, #-96]!

EDIT: While I can't seem to build Go for darwin-arm64, I _can_ use the previously built bootstrap Go binary, so long as I specify CGO_ENABLED=0, however running my projects seems to always end with signal: killed, and while I initially thought this just meant it needed to be signed, this doesn't seem to be the case.

EDIT 2: Got it working! While I still can't run go run without it being killed, I can run go build and then execute the binary, which seems to work so far.

EDIT 3: go test similarly gets killed, by when compiled with go test -c ... it works just fine.

@Dids Have you signed the binaries? All binaries are required to be signed.
I had the same problem, and signing them fixed it for me.

would anyone mind sharing the signed binaries for others like me that don't currently have an Intel mac available?

@MarkusBansky I have indeed signed them, but also found a much better/"official" fix here: https://github.com/golang/go/issues/42684#issuecomment-731821237

This patch/commit fixes the actual issue and means we no longer need to sign anything ourselves, as apparently the LLVM linker automatically signs binaries/libraries when linking. Much more on this topic in the issue I linked.

But do note that I've yet to get the runtime to compile, as it seems to just stall endlessly when compiling (bootstrap toolchain compiled fine on both Intel and M1). Left it compiling for a few hours on the M1, but it still wasn't done, so gave up for the day.

would anyone mind sharing the signed binaries for others like me that don't currently have an Intel mac available?

@felipecsl Unfortunately the signing only works locally/per machine, unless you sign with a valid Developer ID etc.

Unfortunately the signing only works locally/per machine, unless you sign with a valid Developer ID etc

Not true. Ad-hoc signing and linker signing remains valid if you transfer binaries to other machines.

https://github.com/golang/go/issues/38485#issuecomment-730247329
Would it be possible to run these steps (cross compile?) from Linux amd64 instead of Apple Intel?
I'm getting the following errors:

$ GOARCH=arm64 GOOS=darwin ./bootstrap.bash
#### Copying to ../../go-darwin-arm64-bootstrap

#### Cleaning ../../go-darwin-arm64-bootstrap

#### Building ../../go-darwin-arm64-bootstrap

Building Go cmd/dist using /home/ec2-user/go. (go1.15.5 linux/amd64)
Building Go toolchain1 using /home/ec2-user/go.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.
Building Go toolchain2 using go_bootstrap and Go toolchain1.
Building Go toolchain3 using go_bootstrap and Go toolchain2.
Building packages and commands for host, linux/amd64.
Building packages and commands for target, darwin/arm64.
# cmd/addr2line
/home/ec2-user/go-darwin-arm64-bootstrap/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/tmp/go-link-434896474/go.o: file not recognized: File format not recognized
collect2: error: ld returned 1 exit status

# cmd/api
/home/ec2-user/go-darwin-arm64-bootstrap/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/tmp/go-link-513009092/go.o: file not recognized: File format not recognized
collect2: error: ld returned 1 exit status

Sorry for my direct jump in.

  • What's the current status of installing Go on darwin/arm64? The issue was closed, but it seems still a few problems out there.
  • Will Go 1.4 adding bootstrap support for darwin/arm64?
    How will we compile/install Go without having another well-supported machine before Go 1.16 release?

Please see the open issues for the status of the darwin/arm64 port (especially #42684 and #42700).

You can use a Go 1.15 binary release under Rosetta 2 and bootstrap.sh (or even GOARCH=arm64 ./make.bash) to generate a darwin/arm64 toolchain directly on an M1 machine. Please ask on the golang-nuts mailing list if you need help with it.

@felipecsl bootstrap.bash should work on Linux, if you use a Go version that is recent enough (nearly tip). What Go version do you use?

@cherrymui I tried with latest 1.15.5 release from the website. I can try again with latest master then!

Go 1.15.x does not support macOS/ARM64 port, only tip (Go1.16-to-be) does. For the moment, you may want to use the version mentioned at https://github.com/golang/go/issues/42684#issuecomment-731821237, to incorporate some ongoing work.

Also, in case it helps anyone, I've written a fairly rough walkthrough on compiling Go for the M1 entirely on the M1 itself: https://gist.github.com/Dids/dbe6356377e2a0b0dc8eacb0101dc3a7

The process is fairly straightforward, but after spending a few days scratching my head due to various issues (3rd party terminals running in x86 mode for example), this is the best I could come up with.

CLs for #42684 are in. Now it should work at tip (without checking out https://go.googlesource.com/go/refs/changes/58/272258/1 ).

all.bash failed though:

arch --arm64e env GOROOT_BOOTSTRAP=$GO_TMP/go-darwin-arm64-bootstrap ./all.bash
Building Go cmd/dist using /var/folders/73/8zyvcpds2612pj0nmtwt68_c0000gn/T/go-arm-bootstrap.PB58nt4i/go-darwin-arm64-bootstrap. (devel +cf7aa585ac Tue Dec 1 23:39:15 2020 +0000 darwin/arm64)
Building Go toolchain1 using /var/folders/73/8zyvcpds2612pj0nmtwt68_c0000gn/T/go-arm-bootstrap.PB58nt4i/go-darwin-arm64-bootstrap.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.
Building Go toolchain2 using go_bootstrap and Go toolchain1.
Building Go toolchain3 using go_bootstrap and Go toolchain2.
Building packages and commands for darwin/arm64.

##### Testing packages.
ok      archive/tar 0.464s
ok      archive/zip 0.572s
ok      bufio   0.425s
ok      bytes   0.533s
ok      compress/bzip2  0.208s
ok      compress/flate  0.970s
ok      compress/gzip   0.543s
ok      compress/lzw    0.658s
ok      compress/zlib   0.863s
ok      container/heap  0.285s
ok      container/list  0.807s
ok      container/ring  0.855s
ok      context 0.678s
ok      crypto  0.805s
ok      crypto/aes  0.747s
ok      crypto/cipher   0.656s
ok      crypto/des  0.547s
ok      crypto/dsa  0.723s
ok      crypto/ecdsa    0.765s
ok      crypto/ed25519  0.471s
ok      crypto/elliptic 0.704s
ok      crypto/hmac 0.492s
ok      crypto/internal/subtle  0.579s
ok      crypto/md5  0.678s
ok      crypto/rand 0.686s
ok      crypto/rc4  0.722s
ok      crypto/rsa  0.905s
ok      crypto/sha1 0.522s
ok      crypto/sha256   0.604s
ok      crypto/sha512   0.551s
ok      crypto/subtle   0.591s
ok      crypto/tls  1.305s
ok      crypto/x509 1.077s
ok      database/sql    0.874s
ok      database/sql/driver 0.156s
ok      debug/dwarf 0.203s
ok      debug/elf   0.167s
ok      debug/gosym 0.294s
ok      debug/macho 0.240s
ok      debug/pe    0.426s
ok      debug/plan9obj  0.276s
ok      embed/internal/embedtest    0.405s
ok      encoding/ascii85    0.438s
ok      encoding/asn1   0.159s
ok      encoding/base32 0.186s
ok      encoding/base64 0.242s
ok      encoding/binary 0.200s
ok      encoding/csv    0.171s
ok      encoding/gob    0.263s
ok      encoding/hex    0.160s
ok      encoding/json   0.397s
ok      encoding/pem    0.200s
ok      encoding/xml    0.161s
ok      errors  0.162s
ok      expvar  0.194s
ok      flag    0.235s
ok      fmt 0.400s
ok      go/ast  0.298s
ok      go/build    1.393s
ok      go/constant 0.284s
ok      go/doc  0.389s
ok      go/format   0.382s
ok      go/importer 0.296s
ok      go/internal/gccgoimporter   0.382s
ok      go/internal/gcimporter  0.291s
ok      go/internal/srcimporter 4.194s
ok      go/parser   0.361s
ok      go/printer  0.537s
ok      go/scanner  0.275s
ok      go/token    0.275s
ok      go/types    1.547s
ok      hash    0.183s
ok      hash/adler32    0.179s
ok      hash/crc32  0.339s
ok      hash/crc64  0.209s
ok      hash/fnv    0.212s
ok      hash/maphash    0.717s
ok      html    0.641s
ok      html/template   0.283s
ok      image   0.322s
ok      image/color 0.218s
ok      image/draw  0.216s
ok      image/gif   0.555s
ok      image/jpeg  0.471s
ok      image/png   0.494s
ok      index/suffixarray   0.594s
ok      internal/cpu    0.240s
ok      internal/fmtsort    0.156s
ok      internal/poll   0.182s
ok      internal/profile    0.159s
ok      internal/reflectlite    0.173s
ok      internal/singleflight   0.185s
ok      internal/trace  0.192s
ok      internal/unsafeheader   0.253s
ok      internal/xcoff  0.168s
ok      io  0.294s
ok      io/fs   0.154s
ok      io/ioutil   0.401s
ok      log 0.333s
ok      log/syslog  1.558s
ok      math    0.272s
ok      math/big    0.666s
ok      math/bits   0.379s
ok      math/cmplx  0.165s
ok      math/rand   0.237s
ok      mime    0.239s
ok      mime/multipart  0.434s
ok      mime/quotedprintable    0.445s
ok      net 1.907s
ok      net/http    5.836s
ok      net/http/cgi    1.129s
ok      net/http/cookiejar  0.182s
ok      net/http/fcgi   0.189s
ok      net/http/httptest   0.325s
ok      net/http/httptrace  0.162s
ok      net/http/httputil   0.232s
ok      net/http/internal   0.148s
ok      net/http/pprof  5.399s
ok      net/internal/socktest   0.363s
ok      net/mail    0.194s
ok      net/rpc 0.220s
ok      net/rpc/jsonrpc 0.182s
ok      net/smtp    0.179s
ok      net/textproto   0.176s
ok      net/url 0.153s
ok      os  0.936s
ok      os/exec 1.325s
ok      os/signal   2.320s
ok      os/user 0.301s
ok      path    0.140s
ok      path/filepath   0.153s
ok      plugin  0.167s
ok      reflect 0.524s
ok      regexp  0.231s
ok      regexp/syntax   0.768s
--- FAIL: ExampleFrames (0.00s)
got:
- more:true | runtime.Callers
- more:true | runtime_test.ExampleFrames.func1
- more:true | runtime_test.ExampleFrames.func2
- more:true | runtime_test.ExampleFrames.func3
- more:true | runtime_test.ExampleFrames
- more:true | testing.runExample
- more:true | testing.runExamples
- more:true | testing.(*M).Run
- more:true | runtime_test.TestMain
want:
- more:true | runtime.Callers
- more:true | runtime_test.ExampleFrames.func1
- more:true | runtime_test.ExampleFrames.func2
- more:true | runtime_test.ExampleFrames.func3
- more:true | runtime_test.ExampleFrames
FAIL
FAIL    runtime 68.642s
ok      runtime/debug   0.186s
ok      runtime/internal/atomic 0.314s
ok      runtime/internal/math   0.150s
ok      runtime/internal/sys    0.174s
ok      runtime/metrics 0.289s
ok      runtime/pprof   6.390s
ok      runtime/race    0.478s
ok      runtime/trace   0.655s
ok      sort    0.189s
ok      strconv 0.403s
ok      strings 0.250s
ok      sync    0.568s
ok      sync/atomic 0.216s
ok      syscall 0.335s
ok      testing 0.633s
ok      testing/fstest  0.218s
ok      testing/iotest  0.168s
ok      testing/quick   0.200s
ok      text/scanner    0.392s
ok      text/tabwriter  0.316s
ok      text/template   0.189s
ok      text/template/parse 0.156s
ok      time    2.770s
ok      unicode 0.156s
ok      unicode/utf16   0.160s
ok      unicode/utf8    0.182s
ok      cmd/addr2line   4.773s
ok      cmd/api 5.862s
ok      cmd/asm/internal/asm    1.224s
ok      cmd/asm/internal/lex    0.170s
ok      cmd/compile 0.202s
ok      cmd/compile/internal/gc 10.480s
ok      cmd/compile/internal/logopt 0.210s
ok      cmd/compile/internal/ssa    0.668s
ok      cmd/compile/internal/syntax 0.166s
ok      cmd/compile/internal/test   0.207s
ok      cmd/compile/internal/types  0.170s
ok      cmd/cover   3.462s
ok      cmd/doc 0.358s
ok      cmd/fix 1.869s
ok      cmd/go  63.549s
ok      cmd/go/internal/auth    0.162s
ok      cmd/go/internal/cache   0.383s
ok      cmd/go/internal/fsys    0.194s
ok      cmd/go/internal/generate    0.293s
ok      cmd/go/internal/get 0.312s
ok      cmd/go/internal/imports 0.218s
ok      cmd/go/internal/load    0.183s
ok      cmd/go/internal/lockedfile  0.228s
ok      cmd/go/internal/lockedfile/internal/filelock    0.176s
ok      cmd/go/internal/modconv 0.195s
ok      cmd/go/internal/modfetch    0.256s
ok      cmd/go/internal/modfetch/codehost   0.217s
ok      cmd/go/internal/modfetch/zip_sum_test   0.192s
ok      cmd/go/internal/modload 0.512s
ok      cmd/go/internal/mvs 0.189s
ok      cmd/go/internal/par 0.244s
ok      cmd/go/internal/renameio    2.166s
ok      cmd/go/internal/search  0.662s
ok      cmd/go/internal/str 0.595s
ok      cmd/go/internal/test    0.364s
ok      cmd/go/internal/txtar   0.168s
ok      cmd/go/internal/vcs 0.219s
ok      cmd/go/internal/web 0.184s
ok      cmd/go/internal/work    0.481s
ok      cmd/gofmt   0.202s
ok      cmd/internal/archive    3.054s
ok      cmd/internal/buildid    0.374s
ok      cmd/internal/dwarf  0.336s
ok      cmd/internal/edit   0.418s
ok      cmd/internal/goobj  1.053s
ok      cmd/internal/moddeps    7.314s
ok      cmd/internal/obj    0.603s
ok      cmd/internal/obj/arm64  0.433s
ok      cmd/internal/obj/ppc64  0.453s
ok      cmd/internal/obj/riscv  0.318s
ok      cmd/internal/obj/s390x  0.149s
ok      cmd/internal/obj/x86    7.075s
ok      cmd/internal/objabi 0.196s
ok      cmd/internal/pkgpath    0.273s
ok      cmd/internal/src    0.142s
ok      cmd/internal/sys    0.206s
ok      cmd/internal/test2json  0.339s
ok      cmd/link    8.938s
ok      cmd/link/internal/benchmark 0.498s
ok      cmd/link/internal/ld    13.037s
ok      cmd/link/internal/loader    0.310s
ok      cmd/nm  5.512s
ok      cmd/objdump 8.401s
ok      cmd/pack    4.955s
ok      cmd/trace   0.613s
ok      cmd/vet 21.658s
FAIL
go tool dist: Failed: exit status 1

Hmmm, I cannot reproduce the ExampleFrames failure. Maybe try again?

https://github.com/golang/go/issues/38485#issuecomment-735270352

Can confirm I'm also getting these errors when building for darwin/arm64 on 64-bit Linux, with Go version 1.15.5

/usr/lib/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/tmp/go-link-303716583/go.o: file not recognized: file format not recognized
collect2: error: ld returned 1 exit status

@makeworld-the-better-one Go 1.15.x does not support macOS/ARM64 port (see https://github.com/golang/go/issues/38485#issuecomment-735940523). Use tip of the master branch.

As Go 1.16 beta is released, now macOS ARM64 binary release can be downloaded at https://golang.org/dl/#go1.16beta1 .

Was this page helpful?
0 / 5 - 0 ratings