diff --git a/cmd/gomobile/bind_androidapp.go b/cmd/gomobile/bind_androidapp.go index 0f733e0..c33c05f 100644 --- a/cmd/gomobile/bind_androidapp.go +++ b/cmd/gomobile/bind_androidapp.go @@ -28,7 +28,7 @@ func goAndroidBind(pkgs []*build.Package) error { // https://golang.org/issue/13234. androidArgs = []string{"-gcflags=-shared", "-ldflags=-shared"} } - typesPkgs, err := loadExportData(pkgs, androidArmEnv, androidArgs...) + typesPkgs, err := loadExportData(pkgs, androidEnv["arm"], androidArgs...) if err != nil { return err } @@ -56,7 +56,7 @@ func goAndroidBind(pkgs []*build.Package) error { err = goBuild( mainFile, - androidArmEnv, + androidEnv["arm"], "-buildmode=c-shared", "-o="+filepath.Join(androidDir, "src/main/jniLibs/armeabi-v7a/libgojni.so"), ) diff --git a/cmd/gomobile/bind_test.go b/cmd/gomobile/bind_test.go index 1088bb9..bfc06ea 100644 --- a/cmd/gomobile/bind_test.go +++ b/cmd/gomobile/bind_test.go @@ -101,7 +101,7 @@ func TestBindAndroid(t *testing.T) { var bindAndroidTmpl = template.Must(template.New("output").Parse(`GOMOBILE={{.GOPATH}}/pkg/gomobile WORK=$WORK -GOOS=android GOARCH=arm GOARM=7 CC=$GOMOBILE/android-ndk-r10e/arm/bin/arm-linux-androideabi-gcc CXX=$GOMOBILE/android-ndk-r10e/arm/bin/arm-linux-androideabi-g++ CGO_ENABLED=1 go install -p={{.NumCPU}} -pkgdir=$GOMOBILE/pkg_android_arm -tags="" -x golang.org/x/mobile/asset +GOOS=android GOARCH=arm CC=$GOMOBILE/android-ndk-r10e/arm/bin/arm-linux-androideabi-gcc CXX=$GOMOBILE/android-ndk-r10e/arm/bin/arm-linux-androideabi-g++ CGO_ENABLED=1 GOARM=7 go install -p={{.NumCPU}} -pkgdir=$GOMOBILE/pkg_android_arm -tags="" -x golang.org/x/mobile/asset rm -r -f "$WORK/fakegopath" mkdir -p $WORK/fakegopath/pkg cp $GOMOBILE/pkg_android_arm/golang.org/x/mobile/asset.a $WORK/fakegopath/pkg/android_arm/golang.org/x/mobile/asset.a @@ -109,7 +109,7 @@ mkdir -p $WORK/fakegopath/pkg/android_arm/golang.org/x/mobile mkdir -p $WORK/go_asset gobind -lang=go -outdir=$WORK/go_asset golang.org/x/mobile/asset mkdir -p $WORK/androidlib -GOOS=android GOARCH=arm GOARM=7 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 go build -p={{.NumCPU}} -pkgdir=$GOMOBILE/pkg_android_arm -tags="" -x -buildmode=c-shared -o=$WORK/android/src/main/jniLibs/armeabi-v7a/libgojni.so $WORK/androidlib/main.go +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="" -x -buildmode=c-shared -o=$WORK/android/src/main/jniLibs/armeabi-v7a/libgojni.so $WORK/androidlib/main.go mkdir -p $WORK/android/src/main/java/{{.JavaPkgDir}} {{.GobindJavaCmd}} -outdir=$WORK/android/src/main/java/{{.JavaPkgDir}} golang.org/x/mobile/asset mkdir -p $WORK/android/src/main/java/go diff --git a/cmd/gomobile/build.go b/cmd/gomobile/build.go index 08a5c69..0633ccf 100644 --- a/cmd/gomobile/build.go +++ b/cmd/gomobile/build.go @@ -96,7 +96,7 @@ func runBuild(cmd *command) (err error) { switch buildTarget { case "android": if pkg.Name != "main" { - return goBuild(pkg.ImportPath, androidArmEnv) + return goBuild(pkg.ImportPath, androidEnv["arm"]) } nmpkgs, err = goAndroidBuild(pkg) if err != nil { diff --git a/cmd/gomobile/build_androidapp.go b/cmd/gomobile/build_androidapp.go index d506099..ddd2e7b 100644 --- a/cmd/gomobile/build_androidapp.go +++ b/cmd/gomobile/build_androidapp.go @@ -52,11 +52,13 @@ func goAndroidBuild(pkg *build.Package) (map[string]bool, error) { return nil, fmt.Errorf("error parsing %s: %v", manifestPath, err) } } - libPath := filepath.Join(tmpdir, "lib"+libName+".so") + toolchain := ndk.Toolchain("arm") + + libPath := filepath.Join(tmpdir, "lib"+libName+".so") err = goBuild( pkg.ImportPath, - androidArmEnv, + androidEnv["arm"], "-buildmode=c-shared", "-o", libPath, ) @@ -64,7 +66,7 @@ func goAndroidBuild(pkg *build.Package) (map[string]bool, error) { return nil, err } - nmpkgs, err := extractPkgs(androidArmNM, libPath) + nmpkgs, err := extractPkgs(toolchain.Path("nm"), libPath) if err != nil { return nil, err } @@ -155,7 +157,7 @@ func goAndroidBuild(pkg *build.Package) (map[string]bool, error) { if nmpkgs["golang.org/x/mobile/exp/audio/al"] { dst := "lib/armeabi/libopenal.so" - src := filepath.Join(ndkccpath, "openal/"+dst) + src := filepath.Join(ndk.Root(), "openal/"+dst) if err := apkwWriteFile(dst, src); err != nil { return nil, err } diff --git a/cmd/gomobile/build_test.go b/cmd/gomobile/build_test.go index 3664a6e..83b27f9 100644 --- a/cmd/gomobile/build_test.go +++ b/cmd/gomobile/build_test.go @@ -98,5 +98,5 @@ func TestAndroidBuild(t *testing.T) { var androidBuildTmpl = template.Must(template.New("output").Parse(`GOMOBILE={{.GOPATH}}/pkg/gomobile WORK=$WORK -GOOS=android GOARCH=arm GOARM=7 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 go build -p={{.NumCPU}} -pkgdir=$GOMOBILE/pkg_android_arm -tags="tag1" -x -buildmode=c-shared -o $WORK/libbasic.so golang.org/x/mobile/example/basic +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/libbasic.so golang.org/x/mobile/example/basic `)) diff --git a/cmd/gomobile/env.go b/cmd/gomobile/env.go index f67b3a2..108d839 100644 --- a/cmd/gomobile/env.go +++ b/cmd/gomobile/env.go @@ -16,9 +16,9 @@ import ( var ( cwd string gomobilepath string // $GOPATH/pkg/gomobile - ndkccpath string // $GOPATH/pkg/gomobile/android-{{.NDK}} - androidArmEnv []string + androidEnv map[string][]string // android arch -> []string + darwinArmEnv []string darwinArm64Env []string darwin386Env []string @@ -92,23 +92,23 @@ func envInit() (err error) { // Setup the cross-compiler environments. - // TODO(crawshaw): Remove ndkccpath global. - ndkccpath = filepath.Join(gomobilepath, "android-"+ndkVersion) - ndkccbin := filepath.Join(ndkccpath, "arm", "bin") + androidEnv = make(map[string][]string) + for arch, toolchain := range ndk { + if goVersion < toolchain.minGoVer { + continue + } - exe := "" - if goos == "windows" { - exe = ".exe" + androidEnv[arch] = []string{ + "GOOS=android", + "GOARCH=" + arch, + "CC=" + toolchain.Path("gcc"), + "CXX=" + toolchain.Path("g++"), + "CGO_ENABLED=1", + } + if arch == "arm" { + androidEnv[arch] = append(androidEnv[arch], "GOARM=7") + } } - androidArmEnv = []string{ - "GOOS=android", - "GOARCH=arm", - "GOARM=7", - "CC=" + filepath.Join(ndkccbin, "arm-linux-androideabi-gcc"+exe), - "CXX=" + filepath.Join(ndkccbin, "arm-linux-androideabi-g++"+exe), - "CGO_ENABLED=1", - } - androidArmNM = filepath.Join(ndkccbin, "arm-linux-androideabi-nm"+exe) if runtime.GOOS != "darwin" { return nil @@ -250,3 +250,64 @@ func getenv(env []string, key string) string { func pkgdir(env []string) string { return gomobilepath + "/pkg_" + getenv(env, "GOOS") + "_" + getenv(env, "GOARCH") } + +type ndkToolchain struct { + arch string + abi string + platform string + gcc string + toolPrefix string + minGoVer goToolVersion +} + +func (tc *ndkToolchain) Path(toolName string) string { + if goos == "windows" { + toolName += ".exe" + } + return filepath.Join(ndk.Root(), tc.arch, "bin", tc.toolPrefix+"-"+toolName) +} + +type ndkConfig map[string]ndkToolchain // map: GOOS->androidConfig. + +func (nc ndkConfig) Root() string { + return filepath.Join(gomobilepath, "android-"+ndkVersion) +} + +func (nc ndkConfig) Toolchain(arch string) ndkToolchain { + tc, ok := nc[arch] + if !ok || tc.minGoVer > goVersion { + panic(`unsupported architecture: ` + arch) + } + return tc +} + +// TODO: share this with release.go +var ndk = ndkConfig{ + "arm": { + arch: "arm", + abi: "armeabi-v7a", + platform: "android-15", + gcc: "arm-linux-androideabi-4.8", + toolPrefix: "arm-linux-androideabi", + minGoVer: go1_5, + }, + /* + "386": { + arch: "x86", + abi: "x86", + platform: "android-15", + gcc: "x86-4.8", + toolPrefix: "i686-linux-android", + minGoVer: go1_6, + + }, + "amd64": { + arch: "x86_64", + abi: "x86_64", + platform: "android-21", + gcc: "x86_64-4.9", + toolPrefix: "x86_64-linux-android", + minGoVer: go1_6, + }, + */ +} diff --git a/cmd/gomobile/init.go b/cmd/gomobile/init.go index 0dc6dfb..9e3a5be 100644 --- a/cmd/gomobile/init.go +++ b/cmd/gomobile/init.go @@ -81,14 +81,14 @@ func runInit(cmd *command) error { return fmt.Errorf("GOPATH is not set") } gomobilepath = filepath.Join(gopaths[0], "pkg/gomobile") - ndkccpath = filepath.Join(gopaths[0], "pkg/gomobile/android-"+ndkVersion) - verpath := filepath.Join(gopaths[0], "pkg/gomobile/version") + + verpath := filepath.Join(gomobilepath, "version") if buildX || buildN { fmt.Fprintln(xout, "GOMOBILE="+gomobilepath) } removeGomobilepkg() - if err := mkdir(ndkccpath); err != nil { + if err := mkdir(ndk.Root()); err != nil { return err } @@ -146,7 +146,7 @@ func runInit(cmd *command) error { // https://golang.org/issue/13234. androidArgs = []string{"-gcflags=-shared", "-ldflags=-shared"} } - if err := installStd(androidArmEnv, androidArgs...); err != nil { + if err := installStd(androidEnv["arm"], androidArgs...); err != nil { return err } if err := installDarwin(); err != nil { @@ -309,12 +309,13 @@ func fetchOpenAL() error { if goos == "windows" { resetReadOnlyFlagAll(filepath.Join(tmpdir, "openal")) } - dst := filepath.Join(ndkccpath, "arm", "sysroot", "usr", "include") + ndkroot := ndk.Root() + dst := filepath.Join(ndkroot, "arm", "sysroot", "usr", "include") src := filepath.Join(tmpdir, "openal", "include") if err := move(dst, src, "AL"); err != nil { return err } - libDst := filepath.Join(ndkccpath, "openal") + libDst := filepath.Join(ndkroot, "openal") libSrc := filepath.Join(tmpdir, "openal") if err := mkdir(libDst); err != nil { return nil @@ -388,7 +389,7 @@ func fetchNDK() error { resetReadOnlyFlagAll(filepath.Join(tmpdir, "android-"+ndkVersion)) } - dst := filepath.Join(ndkccpath, "arm") + dst := filepath.Join(ndk.Root(), "arm") dstSysroot := filepath.Join(dst, "sysroot/usr") if err := mkdir(dstSysroot); err != nil { return err diff --git a/cmd/gomobile/init_test.go b/cmd/gomobile/init_test.go index 8d73a28..ba46993 100644 --- a/cmd/gomobile/init_test.go +++ b/cmd/gomobile/init_test.go @@ -132,7 +132,7 @@ mv $WORK/openal/lib $GOMOBILE/android-{{.NDK}}/openal/lib{{if eq .GOOS "darwin"} go install -p={{.NumCPU}} -x golang.org/x/mobile/gl go install -p={{.NumCPU}} -x golang.org/x/mobile/app go install -p={{.NumCPU}} -x golang.org/x/mobile/exp/app/debug{{end}} -GOOS=android GOARCH=arm GOARM=7 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 go install -p={{.NumCPU}} -pkgdir=$GOMOBILE/pkg_android_arm -x std +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 install -p={{.NumCPU}} -pkgdir=$GOMOBILE/pkg_android_arm -x std {{if eq .GOOS "darwin"}}GOOS=darwin GOARCH=arm GOARM=7 CC=clang-iphoneos CXX=clang-iphoneos CGO_CFLAGS=-isysroot=iphoneos -arch armv7 CGO_LDFLAGS=-isysroot=iphoneos -arch armv7 CGO_ENABLED=1 go install -p={{.NumCPU}} -pkgdir=$GOMOBILE/pkg_darwin_arm -x std GOOS=darwin GOARCH=arm64 CC=clang-iphoneos CXX=clang-iphoneos CGO_CFLAGS=-isysroot=iphoneos -arch arm64 CGO_LDFLAGS=-isysroot=iphoneos -arch arm64 CGO_ENABLED=1 go install -p={{.NumCPU}} -pkgdir=$GOMOBILE/pkg_darwin_arm64 -x std GOOS=darwin GOARCH=amd64 CC=clang-iphonesimulator CXX=clang-iphonesimulator CGO_CFLAGS=-isysroot=iphonesimulator -mios-simulator-version-min=6.1 -arch x86_64 CGO_LDFLAGS=-isysroot=iphonesimulator -mios-simulator-version-min=6.1 -arch x86_64 CGO_ENABLED=1 go install -p={{.NumCPU}} -tags=ios -pkgdir=$GOMOBILE/pkg_darwin_amd64 -x std