Home > Net >  How to compile an amd64 binary that uses C on an M1 (arm64) Mac
How to compile an amd64 binary that uses C on an M1 (arm64) Mac

Time:12-26

My app compiles fine when GOARCH is set to arm64 (or is omitted). However, when I try to compile an amd64 binary (GOOS=darwin GOARCH=amd64 go build), I get the following error:

package [mainPackage]
        imports [internalPackageThatUsesC]: build constraints exclude all Go files in [pathToInternalPackageThatUsesC]

[internalPackageThatUsesC] consists of 3 files – an Objective C file with the implementation, a header for it and a Go file which provides an interface for the native code. Following is the Go file:

//  build darwin

package [internalPackageThatUsesC]

/*
#cgo CFLAGS: -x objective-c
#cgo LDFLAGS: -framework Cocoa

#include <Cocoa/Cocoa.h>
#include "[headerFile].h"
*/
import "C"
import (
    "encoding/json"
    "sync"
    "unsafe"
)

... public functions that use the C library to interact with the native code

Names annotated with [] mean they are a placeholder for the actual name.

I tried to run it with arch -x86_64 but the output is the same.

What's the problem here? Do I need to add another build tag?

P.S. I found questions on StackOverflow about this error but none of them were about compiling for amd64. This question was the closest but it was WebAssembly-specific.

Following is the result of go env:

GO111MODULE=""
GOARCH="arm64"
GOBIN=""
GOCACHE="/Users/fperson/Library/Caches/go-build"
GOENV="/Users/fperson/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/fperson/.asdf/installs/golang/1.16.4/packages/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/fperson/.asdf/installs/golang/1.16.4/packages"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/Users/fperson/.asdf/installs/golang/1.16.4/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/Users/fperson/.asdf/installs/golang/1.16.4/go/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="go1.16.4"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang  "
CGO_ENABLED="1"
GOMOD="/Users/fperson/workspace/personal_projects/timeow/timeow-mac/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/mh/02gmkb756x15018g919jcg980000gn/T/go-build4031963624=/tmp/go-build -gno-record-gcc-switches -fno-common"

CodePudding user response:

In my case, I also needed to set CGO_ENABLED to true. The app now compiles fine for amd64 with GOOS=darwin GOARCH=amd64 CGO_ENABLED=1 go build

(Thanks to this answer)

CodePudding user response:

The answer to the wasm question (as you posted) talks about cgo. cgo invokes platform compiler with platform specific headers/libs (on Mac, with framework too). When you cross-compile with CC, you also need cross-compile compiler headers/libs frameworks. It is not easy: you may need tools like xgo. But still cross-compile may fail.

Go is different, Go re-implements a HAL in go or plan9 ASM on each OS/arch. So when you cross-compile cgo go for am64 on arm64 together, go build will try to blend "cgo arm64" with "go amd64". Sadly, it is an empty set for the built-in go build tool.

Refer to the @fperson's own answer.

  • Related