Skip to content

Commit 8578da9

Browse files
Ben Schwartzhyangah
Ben Schwartz
authored andcommitted
all: modernize handling of Android SDK and NDK paths
This change removes Gomobile's dependency on ANDROID_HOME and ANDROID_NDK_HOME. Setting ANDROID_HOME is generally optional, and ANDROID_NDK_HOME is deprecated. This change also increases the minimum API version to 16, as all SDKs that supported API 15 are now deprecated. Fixes golang/go#52470 Change-Id: I546365774a089e5d7ae1be0a538efd72741d92ac Reviewed-on: https://go-review.googlesource.com/c/mobile/+/401574 TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Daniel Skinner <[email protected]> Reviewed-by: Suzy Mueller <[email protected]> Reviewed-by: Hajime Hoshi <[email protected]> Reviewed-by: Hyang-Ah Hana Kim <[email protected]> Run-TryBot: Hyang-Ah Hana Kim <[email protected]>
1 parent eae5320 commit 8578da9

22 files changed

+527
-176
lines changed

bind/java/seq_test.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"testing"
1818

1919
"golang.org/x/mobile/internal/importers/java"
20+
"golang.org/x/mobile/internal/sdkpath"
2021
)
2122

2223
var gomobileBin string
@@ -98,8 +99,8 @@ func TestJavaSeqBench(t *testing.T) {
9899
// runTest runs the Android java test class specified with javaCls. If javaPkg is
99100
// set, it is passed with the -javapkg flag to gomobile. The pkgNames lists the Go
100101
// packages to bind for the test.
101-
// This requires the gradle command in PATH and
102-
// the Android SDK whose path is available through ANDROID_HOME environment variable.
102+
// This requires the gradle command to be in PATH and the Android SDK to be
103+
// installed.
103104
func runTest(t *testing.T, pkgNames []string, javaPkg, javaCls string) {
104105
if gomobileBin == "" {
105106
t.Skipf("no gomobile on %s", runtime.GOOS)
@@ -108,8 +109,8 @@ func runTest(t *testing.T, pkgNames []string, javaPkg, javaCls string) {
108109
if err != nil {
109110
t.Skip("command gradle not found, skipping")
110111
}
111-
if sdk := os.Getenv("ANDROID_HOME"); sdk == "" {
112-
t.Skip("ANDROID_HOME environment var not set, skipping")
112+
if _, err := sdkpath.AndroidHome(); err != nil {
113+
t.Skip("Android SDK not found, skipping")
113114
}
114115

115116
cwd, err := os.Getwd()

cmd/gomobile/bind.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"path/filepath"
1717
"strings"
1818

19+
"golang.org/x/mobile/internal/sdkpath"
1920
"golang.org/x/mod/modfile"
2021
"golang.org/x/tools/go/packages"
2122
)
@@ -42,9 +43,10 @@ example, in Android Studio (1.2+), an AAR file can be imported using
4243
the module import wizard (File > New > New Module > Import .JAR or
4344
.AAR package), and setting it as a new dependency
4445
(File > Project Structure > Dependencies). This requires 'javac'
45-
(version 1.7+) and Android SDK (API level 15 or newer) to build the
46-
library for Android. The environment variable ANDROID_HOME must be set
47-
to the path to Android SDK. Use the -javapkg flag to specify the Java
46+
(version 1.7+) and Android SDK (API level 16 or newer) to build the
47+
library for Android. The ANDROID_HOME and ANDROID_NDK_HOME environment
48+
variables can be used to specify the Android SDK and NDK if they are
49+
not in the default locations. Use the -javapkg flag to specify the Java
4850
package prefix for the generated classes.
4951
5052
By default, -target=android builds shared libraries for all supported
@@ -85,7 +87,7 @@ func runBind(cmd *command) error {
8587
if bindPrefix != "" {
8688
return fmt.Errorf("-prefix is supported only for Apple targets")
8789
}
88-
if _, err := ndkRoot(); err != nil {
90+
if _, err := ndkRoot(targets[0]); err != nil {
8991
return err
9092
}
9193
} else {
@@ -156,7 +158,7 @@ func bootClasspath() (string, error) {
156158
if bindBootClasspath != "" {
157159
return bindBootClasspath, nil
158160
}
159-
apiPath, err := androidAPIPath()
161+
apiPath, err := sdkpath.AndroidAPIPath(buildAndroidAPI)
160162
if err != nil {
161163
return "", err
162164
}

cmd/gomobile/bind_androidapp.go

+4-47
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ import (
1212
"os"
1313
"os/exec"
1414
"path/filepath"
15-
"strconv"
1615
"strings"
1716

17+
"golang.org/x/mobile/internal/sdkpath"
1818
"golang.org/x/tools/go/packages"
1919
)
2020

2121
func goAndroidBind(gobind string, pkgs []*packages.Package, targets []targetInfo) error {
22-
if sdkDir := os.Getenv("ANDROID_HOME"); sdkDir == "" {
23-
return fmt.Errorf("this command requires ANDROID_HOME environment variable (path to the Android SDK)")
22+
if _, err := sdkpath.AndroidHome(); err != nil {
23+
return fmt.Errorf("this command requires the Android SDK to be installed: %w", err)
2424
}
2525

2626
// Run gobind to generate the bindings
@@ -270,7 +270,7 @@ func buildAAR(srcDir, androidDir string, pkgs []*packages.Package, targets []tar
270270

271271
const (
272272
javacTargetVer = "1.7"
273-
minAndroidAPI = 15
273+
minAndroidAPI = 16
274274
)
275275

276276
func buildJar(w io.Writer, srcDir string) error {
@@ -370,46 +370,3 @@ func writeJar(w io.Writer, dir string) error {
370370
}
371371
return jarw.Close()
372372
}
373-
374-
// androidAPIPath returns an android SDK platform directory under ANDROID_HOME.
375-
// If there are multiple platforms that satisfy the minimum version requirement
376-
// androidAPIPath returns the latest one among them.
377-
func androidAPIPath() (string, error) {
378-
sdk := os.Getenv("ANDROID_HOME")
379-
if sdk == "" {
380-
return "", fmt.Errorf("ANDROID_HOME environment var is not set")
381-
}
382-
sdkDir, err := os.Open(filepath.Join(sdk, "platforms"))
383-
if err != nil {
384-
return "", fmt.Errorf("failed to find android SDK platform: %v", err)
385-
}
386-
defer sdkDir.Close()
387-
fis, err := sdkDir.Readdir(-1)
388-
if err != nil {
389-
return "", fmt.Errorf("failed to find android SDK platform (API level: %d): %v", buildAndroidAPI, err)
390-
}
391-
392-
var apiPath string
393-
var apiVer int
394-
for _, fi := range fis {
395-
name := fi.Name()
396-
if !strings.HasPrefix(name, "android-") {
397-
continue
398-
}
399-
n, err := strconv.Atoi(name[len("android-"):])
400-
if err != nil || n < buildAndroidAPI {
401-
continue
402-
}
403-
p := filepath.Join(sdkDir.Name(), name)
404-
_, err = os.Stat(filepath.Join(p, "android.jar"))
405-
if err == nil && apiVer < n {
406-
apiPath = p
407-
apiVer = n
408-
}
409-
}
410-
if apiVer == 0 {
411-
return "", fmt.Errorf("failed to find android SDK platform (API level: %d) in %s",
412-
buildAndroidAPI, sdkDir.Name())
413-
}
414-
return apiPath, nil
415-
}

cmd/gomobile/bind_test.go

+14-14
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,22 @@ import (
1414
"strings"
1515
"testing"
1616
"text/template"
17+
18+
"golang.org/x/mobile/internal/sdkpath"
1719
)
1820

1921
func TestBindAndroid(t *testing.T) {
20-
androidHome := os.Getenv("ANDROID_HOME")
21-
if androidHome == "" {
22-
t.Skip("ANDROID_HOME not found, skipping bind")
23-
}
24-
platform, err := androidAPIPath()
22+
platform, err := sdkpath.AndroidAPIPath(minAndroidAPI)
2523
if err != nil {
26-
t.Skip("No android API platform found in $ANDROID_HOME, skipping bind")
24+
t.Skip("No compatible Android API platform found, skipping bind")
2725
}
28-
platform = strings.Replace(platform, androidHome, "$ANDROID_HOME", -1)
26+
// platform is a path like "/path/to/Android/sdk/platforms/android-32"
27+
components := strings.Split(platform, string(filepath.Separator))
28+
if len(components) < 2 {
29+
t.Fatalf("API path is too short: %s", platform)
30+
}
31+
components = components[len(components)-2:]
32+
platformRel := filepath.Join("$ANDROID_HOME", components[0], components[1])
2933

3034
defer func() {
3135
xout = os.Stderr
@@ -77,7 +81,7 @@ func TestBindAndroid(t *testing.T) {
7781
JavaPkg string
7882
}{
7983
outputData: output,
80-
AndroidPlatform: platform,
84+
AndroidPlatform: platformRel,
8185
JavaPkg: tc.javaPkg,
8286
}
8387

@@ -273,12 +277,8 @@ func TestBindWithGoModules(t *testing.T) {
273277
t.Run(target, func(t *testing.T) {
274278
switch target {
275279
case "android":
276-
androidHome := os.Getenv("ANDROID_HOME")
277-
if androidHome == "" {
278-
t.Skip("ANDROID_HOME not found, skipping bind")
279-
}
280-
if _, err := androidAPIPath(); err != nil {
281-
t.Skip("No android API platform found in $ANDROID_HOME, skipping bind")
280+
if _, err := sdkpath.AndroidAPIPath(minAndroidAPI); err != nil {
281+
t.Skip("No compatible Android API platform found, skipping bind")
282282
}
283283
case "ios":
284284
if !xcodeAvailable() {

cmd/gomobile/build.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"strconv"
1818
"strings"
1919

20+
"golang.org/x/mobile/internal/sdkpath"
2021
"golang.org/x/tools/go/packages"
2122
)
2223

@@ -60,7 +61,7 @@ Flag -iosversion sets the minimal version of the iOS SDK to compile against.
6061
The default version is 13.0.
6162
6263
Flag -androidapi sets the Android API version to compile against.
63-
The default and minimum is 15.
64+
The default and minimum is 16.
6465
6566
The -bundleid flag is required for -target ios and sets the bundle ID to use
6667
with the app.
@@ -215,7 +216,7 @@ func printcmd(format string, args ...interface{}) {
215216
if tmpdir != "" {
216217
cmd = strings.Replace(cmd, tmpdir, "$WORK", -1)
217218
}
218-
if androidHome := os.Getenv("ANDROID_HOME"); androidHome != "" {
219+
if androidHome, err := sdkpath.AndroidHome(); err == nil {
219220
cmd = strings.Replace(cmd, androidHome, "$ANDROID_HOME", -1)
220221
}
221222
if gomobilepath != "" {

cmd/gomobile/build_androidapp.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import (
2525
)
2626

2727
func goAndroidBuild(pkg *packages.Package, targets []targetInfo) (map[string]bool, error) {
28-
ndkRoot, err := ndkRoot()
28+
ndkRoot, err := ndkRoot(targets...)
2929
if err != nil {
3030
return nil, err
3131
}

cmd/gomobile/build_test.go

+4-6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import (
1414
"strings"
1515
"testing"
1616
"text/template"
17+
18+
"golang.org/x/mobile/internal/sdkpath"
1719
)
1820

1921
func TestRFC1034Label(t *testing.T) {
@@ -228,12 +230,8 @@ func TestBuildWithGoModules(t *testing.T) {
228230
t.Run(target, func(t *testing.T) {
229231
switch target {
230232
case "android":
231-
androidHome := os.Getenv("ANDROID_HOME")
232-
if androidHome == "" {
233-
t.Skip("ANDROID_HOME not found, skipping bind")
234-
}
235-
if _, err := androidAPIPath(); err != nil {
236-
t.Skip("No android API platform found in $ANDROID_HOME, skipping bind")
233+
if _, err := sdkpath.AndroidAPIPath(minAndroidAPI); err != nil {
234+
t.Skip("No compatible android API platform found, skipping bind")
237235
}
238236
case "ios":
239237
if !xcodeAvailable() {

0 commit comments

Comments
 (0)