golang / go

The Go programming language

Home Page:https://go.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

bradfitz opened this issue · comments

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.

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

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

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 #38485 (comment) 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 #38485 (comment), 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 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 #38485 (comment) 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.

commented

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

commented

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 (96e8366) 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 #38485 (comment).

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.

commented

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/263639 mentions this issue: cmd/link: fix TestDWARFiOS

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

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.