We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
After reading the post from Peter Steinberger (a must-follow) about using Apple Silicon mac minis for their continuous integration, I was intrigued by the following code Ruby snippet:
action_class do
def download_url
#tricky way to load this Chef::Mixin::ShellOut utilities
Chef::Resource::RubyBlock.send(:include, Chef::Mixin::ShellOut)
command = 'sysctl -in sysctl.proc_translated'
command_out = shell_out(command)
architecture = command_out.stdout == "" ? 'amd64' : 'arm64'
platform = ['mac_os_x', 'macos'].include?(node['platform']) ? 'darwin' : 'linux'
"https://github.com/buildkite/agent/releases/download/v#{new_resource.version}/buildkite-agent-#{platform}-#{architecture}-#{new_resource.version}.tar.gz"
end
end
The code snippet shows a way to find out if you are running on an Intel mac, an Apple M1 mac natively or under Rosetta 2. In my previous post about Apple Silicon versus Go, I already showed how you can compile your Go code in such a way that they support both Intel and ARM (Apple Silicon) architectures in a single binary.
Let's take it a step further and see if we can figure out the actual version we're running without having to run an external program. Since Go supports syscall
, let's see how far we get with it.
We first start with getting the valid from sysctl.proc_translated
:
detectapplesilicon.go
package main
import (
"syscall"
)
func main() {
r, err := syscall.Sysctl("sysctl.proc_translated")
}
The syscall.Sysctl
call fetches that value and return a byte array and an error. On an Intel mac, sysctl.proc_translated
doesn't exist (as it doesn't support Rosetta 2), so in that case, an error will be returned. Since we want check if that's the actual error and not some other unrelated error, we can add the following error check:
detectapplesilicon.go
package main
import (
"fmt"
"runtime"
"syscall"
)
func main() {
r, err := syscall.Sysctl("sysctl.proc_translated")
if err != nil && err.Error() == "no such file or directory" {
fmt.Println("Running on intel mac, arch:", runtime.GOARCH)
}
}
We are checking if there is an error and that it's actually the error we except. In that case, we know we're running on an Intel mac. I added the value of runtime.GOARCH
as well so that we can check which slice of the binary we are running.
If there is no error, we check the resulting byte array. If it's a zero value, we are running natively on an ARM processor, if it's a non-zero value, we're running under Rosetta:
package main
import (
"fmt"
"runtime"
"syscall"
)
func main() {
r, err := syscall.Sysctl("sysctl.proc_translated")
if err != nil && err.Error() == "no such file or directory" {
fmt.Println("Running on intel mac, arch:", runtime.GOARCH)
}
if r == "\x00\x00\x00" {
fmt.Println("Running on apple silicon natively, arch:", runtime.GOARCH)
}
if r == "\x01\x00\x00" {
fmt.Println("Running on apple silicon under Rosetta 2, arch:", runtime.GOARCH)
}
}
So, the output you will get will depend on which platform you're running on:
On an Intel mac:
$ ./detectapplesilicon
Running on intel mac, arch: amd64
Natively on an Apple Silicon mac:
$ ./detectapplesilicon
Running on apple silicon natively, arch: arm64
Running via Rosetta 2
$ arch -arch x86_64 ./detectapplesilicon
Running on apple silicon under Rosetta 2, arch: amd64
There is actually a potential bug in the above code. If an unknown error is returned and the byte array is nil, the program might crash. A safer way to check the error is:
package main
import (
"fmt"
"runtime"
"syscall"
)
func main() {
r, err := syscall.Sysctl("sysctl.proc_translated")
if err != nil {
if err.Error() == "no such file or directory" {
fmt.Println("Running on intel mac, arch:", runtime.GOARCH)
} else {
fmt.Println("Unknown error:", err)
}
return
}
if r == "\x00\x00\x00" {
fmt.Println("Running on apple silicon natively, arch:", runtime.GOARCH)
}
if r == "\x01\x00\x00" {
fmt.Println("Running on apple silicon under Rosetta 2, arch:", runtime.GOARCH)
}
}
I created a sample repository on Github showing how this works⦠You can find it here.
If this post was enjoyable or useful for you, please share it! If you have comments, questions, or feedback, you can email my personal email. To get new posts, subscribe use the RSS feed.