Skip to content

Commit

Permalink
use buildinfo to detect ARM version instead of taping the runtime.goa…
Browse files Browse the repository at this point in the history
…rm internal variable
  • Loading branch information
creativeprojects committed Jun 15, 2024
1 parent f77f4c8 commit 491f286
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 3 deletions.
25 changes: 22 additions & 3 deletions arm.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
package selfupdate

import (
// unsafe is used to get a private variable from the runtime package
_ "unsafe"
"debug/buildinfo"
"os"
)

//go:linkname goarm runtime.goarm
var goarm uint8

//nolint:gochecknoinits
func init() {
// avoid using runtime.goarm directly
goarm = getGOARM(os.Args[0])
}

func getGOARM(goBinary string) uint8 {
build, err := buildinfo.ReadFile(goBinary)
if err != nil {
return 0
}
for _, setting := range build.Settings {
if setting.Key == "GOARM" {
// the value is coming from the linker, so it should be safe to convert
return uint8(setting.Value[0] - '0')
}
}
return 0
}
45 changes: 45 additions & 0 deletions arm_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package selfupdate

import (
"fmt"
"os"
"os/exec"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestGetGOARM(t *testing.T) {
t.Parallel()

testCases := []struct {
goOS string
goArch string
goArm string
expectedGoArm uint8
}{
{"linux", "arm", "7", 7},
{"linux", "arm", "6", 6},
{"linux", "arm", "5", 5},
{"linux", "arm", "", 7}, // armv7 is the default
{"linux", "arm64", "", 0},
{"linux", "amd64", "", 0},
{"darwin", "arm64", "", 0},
}

for _, tc := range testCases {
t.Run(tc.goOS+" "+tc.goArch+" "+tc.goArm, func(t *testing.T) {
tempBinary := t.TempDir() + "/tempBinary-" + tc.goOS + tc.goArch + "v" + tc.goArm
buildCmd := fmt.Sprintf("GOOS=%s GOARCH=%s GOARM=%s go build -o %s ./testdata/hello", tc.goOS, tc.goArch, tc.goArm, tempBinary)
cmd := exec.Command("sh", "-c", buildCmd)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
require.NoError(t, err)

goArm := getGOARM(tempBinary)
assert.Equal(t, tc.expectedGoArm, goArm)
})
}
}
1 change: 1 addition & 0 deletions cmd/macho/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/macho_*
5 changes: 5 additions & 0 deletions cmd/macho/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.PHONY: build
build:
GOOS=darwin GOARCH=amd64 go build -o macho_amd64 .
GOOS=darwin GOARCH=arm64 go build -o macho_arm64 .
lipo -create -output macho_universal macho_amd64 macho_arm64
17 changes: 17 additions & 0 deletions cmd/macho/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package main

import (
"debug/macho"
"fmt"
"os"
)

func main() {
fatFile, err := macho.OpenFat(os.Args[0])
if err != nil {
fmt.Printf("not a universal binary: %s\n", err)
} else {
fmt.Printf("this is a universal binary\n")
fatFile.Close()
}
}
5 changes: 5 additions & 0 deletions testdata/hello/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package main

func main() {
// This is a dummy main function
}

0 comments on commit 491f286

Please sign in to comment.