cmd/gomobile: extend -target to accept {android,ios}/{arch} pairs
Not updated the doc yet.
Not useful for iOS yet.
For golang/go#10743
Change-Id: Iaffc41af2c876aa5889c44aae459241af9ec206e
Reviewed-on: https://go-review.googlesource.com/17580
Reviewed-by: David Crawshaw <crawshaw@golang.org>
diff --git a/cmd/gomobile/bind.go b/cmd/gomobile/bind.go
index 7641f63..340db72 100644
--- a/cmd/gomobile/bind.go
+++ b/cmd/gomobile/bind.go
@@ -70,16 +70,14 @@
args := cmd.flag.Args()
- ctx.GOARCH = "arm"
- switch buildTarget {
- case "android":
- ctx.GOOS = "android"
- case "ios":
- ctx.GOOS = "darwin"
- default:
- return fmt.Errorf(`unknown -target, %q.`, buildTarget)
+ targetOS, targetArchs, err := parseBuildTarget(buildTarget)
+ if err != nil {
+ return fmt.Errorf(`invalid -target=%q: %v`, buildTarget, err)
}
+ ctx.GOARCH = "arm"
+ ctx.GOOS = targetOS
+
if bindJavaPkg != "" && ctx.GOOS != "android" {
return fmt.Errorf("-javapkg is supported only for android target")
}
@@ -101,12 +99,12 @@
switch buildTarget {
case "android":
- androidArchs := []string{"arm"}
- return goAndroidBind(pkgs, androidArchs)
+ return goAndroidBind(pkgs, targetArchs)
case "ios":
+ // TODO: use targetArchs?
return goIOSBind(pkgs)
default:
- return fmt.Errorf(`unknown -target, %q.`, buildTarget)
+ return fmt.Errorf(`invalid -target=%q`, buildTarget)
}
}
diff --git a/cmd/gomobile/build.go b/cmd/gomobile/build.go
index 96f086a..87d0b8f 100644
--- a/cmd/gomobile/build.go
+++ b/cmd/gomobile/build.go
@@ -65,16 +65,14 @@
args := cmd.flag.Args()
- ctx.GOARCH = "arm"
- switch buildTarget {
- case "android":
- ctx.GOOS = "android"
- case "ios":
- ctx.GOOS = "darwin"
- default:
- return fmt.Errorf(`unknown -target, %q.`, buildTarget)
+ targetOS, targetArchs, err := parseBuildTarget(buildTarget)
+ if err != nil {
+ return fmt.Errorf(`invalid -target=%q: %v`, buildTarget, err)
}
+ ctx.GOARCH = targetArchs[0]
+ ctx.GOOS = targetOS
+
switch len(args) {
case 0:
pkg, err = ctx.ImportDir(cwd, build.ImportComment)
@@ -93,11 +91,10 @@
}
var nmpkgs map[string]bool
- switch buildTarget {
+ switch targetOS {
case "android":
- androidArchs := []string{"arm"}
if pkg.Name != "main" {
- for _, arch := range androidArchs {
+ for _, arch := range targetArchs {
env := androidEnv[arch]
if err := goBuild(pkg.ImportPath, env); err != nil {
return err
@@ -105,11 +102,12 @@
}
return nil
}
- nmpkgs, err = goAndroidBuild(pkg, androidArchs)
+ nmpkgs, err = goAndroidBuild(pkg, targetArchs)
if err != nil {
return err
}
case "ios":
+ // TODO: use targetArchs?
if runtime.GOOS != "darwin" {
return fmt.Errorf("-target=ios requires darwin host")
}
@@ -295,3 +293,72 @@
cmd.Env = append([]string{}, env...)
return runCmd(cmd)
}
+
+func parseBuildTarget(buildTarget string) (os string, archs []string, _ error) {
+ if buildTarget == "" {
+ return "", nil, fmt.Errorf(`invalid target ""`)
+ }
+
+ all := false
+ archNames := []string{}
+ for i, p := range strings.Split(buildTarget, ",") {
+ osarch := strings.SplitN(p, "/", 2) // len(osarch) > 0
+ if osarch[0] != "android" && osarch[0] != "ios" {
+ return "", nil, fmt.Errorf(`unsupported os`)
+ }
+
+ if i == 0 {
+ os = osarch[0]
+ }
+
+ if os != osarch[0] {
+ return "", nil, fmt.Errorf(`cannot target different OSes`)
+ }
+
+ if len(osarch) == 1 {
+ all = true
+ } else {
+ archNames = append(archNames, osarch[1])
+ }
+ }
+
+ // verify all archs are supported one while deduping.
+ var supported []string
+ switch os {
+ case "ios":
+ supported = []string{"arm", "arm64", "amd64"}
+ case "android":
+ for arch, tc := range ndk {
+ if tc.minGoVer <= goVersion {
+ supported = append(supported, arch)
+ }
+ }
+ }
+
+ isSupported := func(arch string) bool {
+ for _, a := range supported {
+ if a == arch {
+ return true
+ }
+ }
+ return false
+ }
+
+ seen := map[string]bool{}
+ for _, arch := range archNames {
+ if _, ok := seen[arch]; ok {
+ continue
+ }
+ if !isSupported(arch) {
+ return "", nil, fmt.Errorf(`unsupported arch: %q`, arch)
+ }
+
+ seen[arch] = true
+ archs = append(archs, arch)
+ }
+
+ if all {
+ return os, supported, nil
+ }
+ return os, archs, nil
+}
diff --git a/cmd/gomobile/build_androidapp.go b/cmd/gomobile/build_androidapp.go
index d22d6af..ae951a5 100644
--- a/cmd/gomobile/build_androidapp.go
+++ b/cmd/gomobile/build_androidapp.go
@@ -227,10 +227,7 @@
}
// TODO: return nmpkgs
- for _, v := range nmpkgs {
- return v, nil // first value
- }
- return nil, nil
+ return nmpkgs[androidArchs[0]], nil
}
// androidPkgName sanitizes the go package name to be acceptable as a android
diff --git a/cmd/gomobile/build_test.go b/cmd/gomobile/build_test.go
index 8ac96a8..5254f39 100644
--- a/cmd/gomobile/build_test.go
+++ b/cmd/gomobile/build_test.go
@@ -8,6 +8,7 @@
"bytes"
"os"
"path/filepath"
+ "strings"
"testing"
"text/template"
)
@@ -101,3 +102,46 @@
mkdir -p $WORK/lib/armeabi-v7a
GOOS=android GOARCH=arm CC=$GOMOBILE/android-{{.NDK}}/arm/bin/arm-linux-androideabi-gcc{{.EXE}} CXX=$GOMOBILE/android-{{.NDK}}/arm/bin/arm-linux-androideabi-g++{{.EXE}} CGO_ENABLED=1 GOARM=7 go build -p={{.NumCPU}} -pkgdir=$GOMOBILE/pkg_android_arm -tags="tag1" -x -buildmode=c-shared -o $WORK/lib/armeabi-v7a/libbasic.so golang.org/x/mobile/example/basic
`))
+
+func TestParseBuildTargetFlag(t *testing.T) {
+ androidArchs := "arm"
+ iosArchs := "arm,arm64,amd64"
+
+ tests := []struct {
+ in string
+ wantErr bool
+ wantOS string
+ wantArchs string
+ }{
+ {"android", false, "android", androidArchs},
+ {"android,android/arm", false, "android", androidArchs},
+ {"android/arm", false, "android", "arm"},
+
+ {"ios", false, "ios", iosArchs},
+ {"ios,ios/arm", false, "ios", iosArchs},
+ {"ios/arm", false, "ios", "arm"},
+ {"ios/amd64", false, "ios", "amd64"},
+
+ {"", true, "", ""},
+ {"linux", true, "", ""},
+ {"android/x86", true, "", ""},
+ {"android/arm5", true, "", ""},
+ {"ios/mips", true, "", ""},
+ {"android,ios", true, "", ""},
+ {"ios,android", true, "", ""},
+ }
+
+ for _, tc := range tests {
+ gotOS, gotArchs, err := parseBuildTarget(tc.in)
+ if tc.wantErr {
+ if err == nil {
+ t.Errorf("-target=%q; want error, got (%q, %q, nil)", tc.in, gotOS, gotArchs)
+ }
+ continue
+ }
+ if err != nil || gotOS != tc.wantOS || strings.Join(gotArchs, ",") != tc.wantArchs {
+ t.Errorf("-target=%q; want (%v, [%v], nil), got (%q, %q, %v)",
+ tc.in, tc.wantOS, tc.wantArchs, gotOS, gotArchs, err)
+ }
+ }
+}
diff --git a/cmd/gomobile/install.go b/cmd/gomobile/install.go
index d001018..522bd3d 100644
--- a/cmd/gomobile/install.go
+++ b/cmd/gomobile/install.go
@@ -30,7 +30,7 @@
}
func runInstall(cmd *command) error {
- if buildTarget != "android" {
+ if !strings.HasPrefix(buildTarget, "android") {
return fmt.Errorf("install is not supported for -target=%s", buildTarget)
}
if err := runBuild(cmd); err != nil {