app,cmd/gomobile,exp/gl/glutil: support target architectures for iOS build and bind

While we're here, add 386 to the list of supported architectures
on iOS.

To support gomobile build for amd64 and 386, use the "ios" tag to
distinguish between iOS and macOS builds.

Change-Id: Ie09a432794bd8d9853950115349f8d3b57cf43f5
Reviewed-on: https://go-review.googlesource.com/102915
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This commit is contained in:
Elias Naur 2018-03-28 13:37:41 +02:00
parent 4e3d9b7944
commit 54bca60619
13 changed files with 73 additions and 100 deletions

View File

@ -133,8 +133,7 @@ func runBind(cmd *command) error {
if !xcodeAvailable() {
return fmt.Errorf("-target=ios requires XCode")
}
// TODO: use targetArchs?
return goIOSBind(gobind, pkgs)
return goIOSBind(gobind, pkgs, targetArchs)
default:
return fmt.Errorf(`invalid -target=%q`, buildTarget)
}

View File

@ -15,7 +15,7 @@ import (
"text/template"
)
func goIOSBind(gobind string, pkgs []*build.Package) error {
func goIOSBind(gobind string, pkgs []*build.Package, archs []string) error {
// Run gobind to generate the bindings
cmd := exec.Command(
gobind,
@ -56,14 +56,14 @@ func goIOSBind(gobind string, pkgs []*build.Package) error {
cmd = exec.Command("xcrun", "lipo", "-create")
for _, env := range [][]string{darwinArmEnv, darwinArm64Env, darwinAmd64Env} {
for _, arch := range archs {
env := darwinEnv[arch]
env = append(env, gopath)
arch := archClang(getenv(env, "GOARCH"))
path, err := goIOSBindArchive(name, env)
if err != nil {
return fmt.Errorf("darwin-%s: %v", arch, err)
}
cmd.Args = append(cmd.Args, "-arch", arch, path)
cmd.Args = append(cmd.Args, "-arch", archClang(arch), path)
}
// Build static framework output directory.

View File

@ -111,17 +111,19 @@ func runBuild(cmd *command) (err error) {
return err
}
case "darwin":
// TODO: use targetArchs?
if !xcodeAvailable() {
return fmt.Errorf("-target=ios requires XCode")
}
if pkg.Name != "main" {
if err := goBuild(pkg.ImportPath, darwinArmEnv); err != nil {
return err
for _, arch := range targetArchs {
env := darwinEnv[arch]
if err := goBuild(pkg.ImportPath, env); err != nil {
return err
}
}
return goBuild(pkg.ImportPath, darwinArm64Env)
return nil
}
nmpkgs, err = goIOSBuild(pkg, buildBundleID)
nmpkgs, err = goIOSBuild(pkg, buildBundleID, targetArchs)
if err != nil {
return err
}
@ -329,16 +331,8 @@ func parseBuildTarget(buildTarget string) (os string, archs []string, _ error) {
}
// verify all archs are supported one while deduping.
var supported []string
switch os {
case "ios":
supported = []string{"arm", "arm64", "amd64"}
case "android":
supported = []string{"arm", "arm64", "386", "amd64"}
}
isSupported := func(arch string) bool {
for _, a := range supported {
for _, a := range allArchs {
if a == arch {
return true
}
@ -364,7 +358,7 @@ func parseBuildTarget(buildTarget string) (os string, archs []string, _ error) {
targetOS = "darwin"
}
if all {
return targetOS, supported, nil
return targetOS, allArchs, nil
}
return targetOS, archs, nil
}

View File

@ -76,7 +76,7 @@ mkdir -p $WORK/main
echo "{{template "infoplist" .Xinfo}}" > $WORK/main/Info.plist
mkdir -p $WORK/main/Images.xcassets/AppIcon.appiconset
echo "{{.Xcontents}}" > $WORK/main/Images.xcassets/AppIcon.appiconset/Contents.json
GOOS=darwin GOARCH=arm GOARM=7 CC=clang-iphoneos CXX=clang-iphoneos CGO_CFLAGS=-isysroot=iphoneos -miphoneos-version-min=6.1 -arch armv7 CGO_LDFLAGS=-isysroot=iphoneos -miphoneos-version-min=6.1 -arch armv7 CGO_ENABLED=1 go build -tags tag1 ios -x -o=$WORK/arm golang.org/x/mobile/example/basic
GOARM=7 GOOS=darwin GOARCH=arm CC=clang-iphoneos CXX=clang-iphoneos CGO_CFLAGS=-isysroot=iphoneos -miphoneos-version-min=6.1 -arch armv7 CGO_LDFLAGS=-isysroot=iphoneos -miphoneos-version-min=6.1 -arch armv7 CGO_ENABLED=1 go build -tags tag1 ios -x -o=$WORK/arm golang.org/x/mobile/example/basic
GOOS=darwin GOARCH=arm64 CC=clang-iphoneos CXX=clang-iphoneos CGO_CFLAGS=-isysroot=iphoneos -miphoneos-version-min=6.1 -arch arm64 CGO_LDFLAGS=-isysroot=iphoneos -miphoneos-version-min=6.1 -arch arm64 CGO_ENABLED=1 go build -tags tag1 ios -x -o=$WORK/arm64 golang.org/x/mobile/example/basic
xcrun lipo -create $WORK/arm $WORK/arm64 -o $WORK/main/main
mkdir -p $WORK/main/assets

View File

@ -19,7 +19,7 @@ import (
"text/template"
)
func goIOSBuild(pkg *build.Package, bundleID string) (map[string]bool, error) {
func goIOSBuild(pkg *build.Package, bundleID string, archs []string) (map[string]bool, error) {
src := pkg.ImportPath
if buildO != "" && !strings.HasSuffix(buildO, ".app") {
return nil, fmt.Errorf("-o must have an .app for -target=ios")
@ -64,29 +64,28 @@ func goIOSBuild(pkg *build.Package, bundleID string) (map[string]bool, error) {
ctx.BuildTags = append(ctx.BuildTags, "ios")
armPath := filepath.Join(tmpdir, "arm")
if err := goBuild(src, darwinArmEnv, "-o="+armPath); err != nil {
return nil, err
}
nmpkgs, err := extractPkgs(darwinArmNM, armPath)
if err != nil {
return nil, err
}
arm64Path := filepath.Join(tmpdir, "arm64")
if err := goBuild(src, darwinArm64Env, "-o="+arm64Path); err != nil {
return nil, err
}
// Apple requires builds to target both darwin/arm and darwin/arm64.
// We are using lipo tool to build multiarchitecture binaries.
// TODO(jbd): Investigate the new announcements about iO9's fat binary
// size limitations are breaking this feature.
cmd := exec.Command(
"xcrun", "lipo",
"-create", armPath, arm64Path,
"-o", filepath.Join(tmpdir, "main/main"),
"-create",
)
var nmpkgs map[string]bool
for _, arch := range archs {
path := filepath.Join(tmpdir, arch)
if err := goBuild(src, darwinEnv[arch], "-o="+path); err != nil {
return nil, err
}
if nmpkgs == nil {
var err error
nmpkgs, err = extractPkgs(darwinArmNM, path)
if err != nil {
return nil, err
}
}
cmd.Args = append(cmd.Args, path)
}
if err := runCmd(cmd); err != nil {
return nil, err
}

View File

@ -109,8 +109,7 @@ GOOS=android GOARCH=arm CC=$GOMOBILE/ndk-toolchains/arm/bin/arm-linux-androideab
`))
func TestParseBuildTargetFlag(t *testing.T) {
androidArchs := "arm,arm64,386,amd64"
iosArchs := "arm,arm64,amd64"
archs := strings.Join(allArchs, ",")
tests := []struct {
in string
@ -118,12 +117,12 @@ func TestParseBuildTargetFlag(t *testing.T) {
wantOS string
wantArchs string
}{
{"android", false, "android", androidArchs},
{"android,android/arm", false, "android", androidArchs},
{"android", false, "android", archs},
{"android,android/arm", false, "android", archs},
{"android/arm", false, "android", "arm"},
{"ios", false, "darwin", iosArchs},
{"ios,ios/arm", false, "darwin", iosArchs},
{"ios", false, "darwin", archs},
{"ios,ios/arm", false, "darwin", archs},
{"ios/arm", false, "darwin", "arm"},
{"ios/amd64", false, "darwin", "amd64"},

View File

@ -18,15 +18,12 @@ var (
androidEnv map[string][]string // android arch -> []string
darwinArmEnv []string
darwinArm64Env []string
darwin386Env []string
darwinAmd64Env []string
darwinEnv map[string][]string
androidArmNM string
darwinArmNM string
archs = []string{"arm", "arm64", "386", "amd64"}
allArchs = []string{"arm", "arm64", "386", "amd64"}
)
func buildEnvInit() (cleanup func(), err error) {
@ -104,52 +101,38 @@ func envInit() (err error) {
return nil
}
clang, cflags, err := envClang("iphoneos")
if err != nil {
return err
}
darwinArmEnv = []string{
"GOOS=darwin",
"GOARCH=arm",
"GOARM=7",
"CC=" + clang,
"CXX=" + clang,
"CGO_CFLAGS=" + cflags + " -miphoneos-version-min=6.1 -arch " + archClang("arm"),
"CGO_LDFLAGS=" + cflags + " -miphoneos-version-min=6.1 -arch " + archClang("arm"),
"CGO_ENABLED=1",
}
darwinArmNM = "nm"
darwinArm64Env = []string{
"GOOS=darwin",
"GOARCH=arm64",
"CC=" + clang,
"CXX=" + clang,
"CGO_CFLAGS=" + cflags + " -miphoneos-version-min=6.1 -arch " + archClang("arm64"),
"CGO_LDFLAGS=" + cflags + " -miphoneos-version-min=6.1 -arch " + archClang("arm64"),
"CGO_ENABLED=1",
}
clang, cflags, err = envClang("iphonesimulator")
if err != nil {
return err
}
darwin386Env = []string{
"GOOS=darwin",
"GOARCH=386",
"CC=" + clang,
"CXX=" + clang,
"CGO_CFLAGS=" + cflags + " -mios-simulator-version-min=6.1 -arch " + archClang("386"),
"CGO_LDFLAGS=" + cflags + " -mios-simulator-version-min=6.1 -arch " + archClang("386"),
"CGO_ENABLED=1",
}
darwinAmd64Env = []string{
"GOOS=darwin",
"GOARCH=amd64",
"CC=" + clang,
"CXX=" + clang,
"CGO_CFLAGS=" + cflags + " -mios-simulator-version-min=6.1 -arch x86_64",
"CGO_LDFLAGS=" + cflags + " -mios-simulator-version-min=6.1 -arch x86_64",
"CGO_ENABLED=1",
darwinEnv = make(map[string][]string)
for _, arch := range allArchs {
var env []string
var err error
var clang, cflags string
switch arch {
case "arm":
env = append(env, "GOARM=7")
fallthrough
case "arm64":
clang, cflags, err = envClang("iphoneos")
cflags += " -miphoneos-version-min=6.1"
case "386", "amd64":
clang, cflags, err = envClang("iphonesimulator")
cflags += " -mios-simulator-version-min=6.1"
default:
panic(fmt.Errorf("unknown GOARCH: %q", arch))
}
if err != nil {
return err
}
env = append(env,
"GOOS=darwin",
"GOARCH="+arch,
"CC="+clang,
"CXX="+clang,
"CGO_CFLAGS="+cflags+" -arch "+archClang(arch),
"CGO_LDFLAGS="+cflags+" -arch "+archClang(arch),
"CGO_ENABLED=1",
)
darwinEnv[arch] = env
}
return nil
@ -181,7 +164,6 @@ func envClang(sdkName string) (clang, cflags string, err error) {
return "", "", fmt.Errorf("xcrun --show-sdk-path: %v\n%s", err, out)
}
sdk := strings.TrimSpace(string(out))
return clang, "-isysroot " + sdk, nil
}

View File

@ -151,7 +151,7 @@ func installNDKToolchains(gomobilepath string) error {
}
toolsDir := filepath.Join(initNDK, "prebuilt", archNDK(), "bin")
py27 := filepath.Join(toolsDir, "python2.7")
for _, arch := range archs {
for _, arch := range allArchs {
t := ndk[arch]
// Split android-XX to get the api version.
platform := strings.SplitN(t.platform, "-", 2)
@ -226,7 +226,7 @@ func installOpenAL(gomobilepath string) error {
}
}
for _, arch := range archs {
for _, arch := range allArchs {
t := ndk[arch]
abi := t.arch
if abi == "arm" {