Skip to content

Commit da67c3e

Browse files
committed
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 <[email protected]>
1 parent 6c7eb6c commit da67c3e

File tree

5 files changed

+134
-28
lines changed

5 files changed

+134
-28
lines changed

cmd/gomobile/bind.go

+9-11
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,14 @@ func runBind(cmd *command) error {
7070

7171
args := cmd.flag.Args()
7272

73-
ctx.GOARCH = "arm"
74-
switch buildTarget {
75-
case "android":
76-
ctx.GOOS = "android"
77-
case "ios":
78-
ctx.GOOS = "darwin"
79-
default:
80-
return fmt.Errorf(`unknown -target, %q.`, buildTarget)
73+
targetOS, targetArchs, err := parseBuildTarget(buildTarget)
74+
if err != nil {
75+
return fmt.Errorf(`invalid -target=%q: %v`, buildTarget, err)
8176
}
8277

78+
ctx.GOARCH = "arm"
79+
ctx.GOOS = targetOS
80+
8381
if bindJavaPkg != "" && ctx.GOOS != "android" {
8482
return fmt.Errorf("-javapkg is supported only for android target")
8583
}
@@ -101,12 +99,12 @@ func runBind(cmd *command) error {
10199

102100
switch buildTarget {
103101
case "android":
104-
androidArchs := []string{"arm"}
105-
return goAndroidBind(pkgs, androidArchs)
102+
return goAndroidBind(pkgs, targetArchs)
106103
case "ios":
104+
// TODO: use targetArchs?
107105
return goIOSBind(pkgs)
108106
default:
109-
return fmt.Errorf(`unknown -target, %q.`, buildTarget)
107+
return fmt.Errorf(`invalid -target=%q`, buildTarget)
110108
}
111109
}
112110

cmd/gomobile/build.go

+79-12
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,14 @@ func runBuild(cmd *command) (err error) {
6565

6666
args := cmd.flag.Args()
6767

68-
ctx.GOARCH = "arm"
69-
switch buildTarget {
70-
case "android":
71-
ctx.GOOS = "android"
72-
case "ios":
73-
ctx.GOOS = "darwin"
74-
default:
75-
return fmt.Errorf(`unknown -target, %q.`, buildTarget)
68+
targetOS, targetArchs, err := parseBuildTarget(buildTarget)
69+
if err != nil {
70+
return fmt.Errorf(`invalid -target=%q: %v`, buildTarget, err)
7671
}
7772

73+
ctx.GOARCH = targetArchs[0]
74+
ctx.GOOS = targetOS
75+
7876
switch len(args) {
7977
case 0:
8078
pkg, err = ctx.ImportDir(cwd, build.ImportComment)
@@ -93,23 +91,23 @@ func runBuild(cmd *command) (err error) {
9391
}
9492

9593
var nmpkgs map[string]bool
96-
switch buildTarget {
94+
switch targetOS {
9795
case "android":
98-
androidArchs := []string{"arm"}
9996
if pkg.Name != "main" {
100-
for _, arch := range androidArchs {
97+
for _, arch := range targetArchs {
10198
env := androidEnv[arch]
10299
if err := goBuild(pkg.ImportPath, env); err != nil {
103100
return err
104101
}
105102
}
106103
return nil
107104
}
108-
nmpkgs, err = goAndroidBuild(pkg, androidArchs)
105+
nmpkgs, err = goAndroidBuild(pkg, targetArchs)
109106
if err != nil {
110107
return err
111108
}
112109
case "ios":
110+
// TODO: use targetArchs?
113111
if runtime.GOOS != "darwin" {
114112
return fmt.Errorf("-target=ios requires darwin host")
115113
}
@@ -295,3 +293,72 @@ func goCmd(subcmd string, srcs []string, env []string, args ...string) error {
295293
cmd.Env = append([]string{}, env...)
296294
return runCmd(cmd)
297295
}
296+
297+
func parseBuildTarget(buildTarget string) (os string, archs []string, _ error) {
298+
if buildTarget == "" {
299+
return "", nil, fmt.Errorf(`invalid target ""`)
300+
}
301+
302+
all := false
303+
archNames := []string{}
304+
for i, p := range strings.Split(buildTarget, ",") {
305+
osarch := strings.SplitN(p, "/", 2) // len(osarch) > 0
306+
if osarch[0] != "android" && osarch[0] != "ios" {
307+
return "", nil, fmt.Errorf(`unsupported os`)
308+
}
309+
310+
if i == 0 {
311+
os = osarch[0]
312+
}
313+
314+
if os != osarch[0] {
315+
return "", nil, fmt.Errorf(`cannot target different OSes`)
316+
}
317+
318+
if len(osarch) == 1 {
319+
all = true
320+
} else {
321+
archNames = append(archNames, osarch[1])
322+
}
323+
}
324+
325+
// verify all archs are supported one while deduping.
326+
var supported []string
327+
switch os {
328+
case "ios":
329+
supported = []string{"arm", "arm64", "amd64"}
330+
case "android":
331+
for arch, tc := range ndk {
332+
if tc.minGoVer <= goVersion {
333+
supported = append(supported, arch)
334+
}
335+
}
336+
}
337+
338+
isSupported := func(arch string) bool {
339+
for _, a := range supported {
340+
if a == arch {
341+
return true
342+
}
343+
}
344+
return false
345+
}
346+
347+
seen := map[string]bool{}
348+
for _, arch := range archNames {
349+
if _, ok := seen[arch]; ok {
350+
continue
351+
}
352+
if !isSupported(arch) {
353+
return "", nil, fmt.Errorf(`unsupported arch: %q`, arch)
354+
}
355+
356+
seen[arch] = true
357+
archs = append(archs, arch)
358+
}
359+
360+
if all {
361+
return os, supported, nil
362+
}
363+
return os, archs, nil
364+
}

cmd/gomobile/build_androidapp.go

+1-4
Original file line numberDiff line numberDiff line change
@@ -227,10 +227,7 @@ func goAndroidBuild(pkg *build.Package, androidArchs []string) (map[string]bool,
227227
}
228228

229229
// TODO: return nmpkgs
230-
for _, v := range nmpkgs {
231-
return v, nil // first value
232-
}
233-
return nil, nil
230+
return nmpkgs[androidArchs[0]], nil
234231
}
235232

236233
// androidPkgName sanitizes the go package name to be acceptable as a android

cmd/gomobile/build_test.go

+44
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"bytes"
99
"os"
1010
"path/filepath"
11+
"strings"
1112
"testing"
1213
"text/template"
1314
)
@@ -101,3 +102,46 @@ WORK=$WORK
101102
mkdir -p $WORK/lib/armeabi-v7a
102103
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
103104
`))
105+
106+
func TestParseBuildTargetFlag(t *testing.T) {
107+
androidArchs := "arm"
108+
iosArchs := "arm,arm64,amd64"
109+
110+
tests := []struct {
111+
in string
112+
wantErr bool
113+
wantOS string
114+
wantArchs string
115+
}{
116+
{"android", false, "android", androidArchs},
117+
{"android,android/arm", false, "android", androidArchs},
118+
{"android/arm", false, "android", "arm"},
119+
120+
{"ios", false, "ios", iosArchs},
121+
{"ios,ios/arm", false, "ios", iosArchs},
122+
{"ios/arm", false, "ios", "arm"},
123+
{"ios/amd64", false, "ios", "amd64"},
124+
125+
{"", true, "", ""},
126+
{"linux", true, "", ""},
127+
{"android/x86", true, "", ""},
128+
{"android/arm5", true, "", ""},
129+
{"ios/mips", true, "", ""},
130+
{"android,ios", true, "", ""},
131+
{"ios,android", true, "", ""},
132+
}
133+
134+
for _, tc := range tests {
135+
gotOS, gotArchs, err := parseBuildTarget(tc.in)
136+
if tc.wantErr {
137+
if err == nil {
138+
t.Errorf("-target=%q; want error, got (%q, %q, nil)", tc.in, gotOS, gotArchs)
139+
}
140+
continue
141+
}
142+
if err != nil || gotOS != tc.wantOS || strings.Join(gotArchs, ",") != tc.wantArchs {
143+
t.Errorf("-target=%q; want (%v, [%v], nil), got (%q, %q, %v)",
144+
tc.in, tc.wantOS, tc.wantArchs, gotOS, gotArchs, err)
145+
}
146+
}
147+
}

cmd/gomobile/install.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ For documentation, see 'go help build'.
3030
}
3131

3232
func runInstall(cmd *command) error {
33-
if buildTarget != "android" {
33+
if !strings.HasPrefix(buildTarget, "android") {
3434
return fmt.Errorf("install is not supported for -target=%s", buildTarget)
3535
}
3636
if err := runBuild(cmd); err != nil {

0 commit comments

Comments
 (0)