Browse Source

Improve the logic to compile for Android by automatically detecting and setting up the Android NDK if needed.

(cherry picked from commit eee213e01a26054906fd07423f3620c98b786956)
Fredia Huya-Kouadio 4 years ago
parent
commit
5886d09521

+ 57 - 4
platform/android/detect.py

@@ -13,7 +13,7 @@ def get_name():
 
 
 def can_build():
-    return "ANDROID_NDK_ROOT" in os.environ
+    return ("ANDROID_NDK_ROOT" in os.environ) or ("ANDROID_SDK_ROOT" in os.environ) or ("ANDROID_HOME" in os.environ)
 
 
 def get_platform(platform):
@@ -24,13 +24,36 @@ def get_opts():
     from SCons.Variables import BoolVariable, EnumVariable
 
     return [
-        ("ANDROID_NDK_ROOT", "Path to the Android NDK", os.environ.get("ANDROID_NDK_ROOT", 0)),
+        ("ANDROID_NDK_ROOT", "Path to the Android NDK", get_android_ndk_root()),
+        ("ANDROID_SDK_ROOT", "Path to the Android SDK", get_android_sdk_root()),
         ("ndk_platform", 'Target platform (android-<api>, e.g. "android-18")', "android-18"),
         EnumVariable("android_arch", "Target architecture", "armv7", ("armv7", "arm64v8", "x86", "x86_64")),
         BoolVariable("android_neon", "Enable NEON support (armv7 only)", True),
     ]
 
 
+# Return the ANDROID_SDK_ROOT environment variable.
+# While ANDROID_HOME has been deprecated, it's used as a fallback for backward
+# compatibility purposes.
+def get_android_sdk_root():
+    if "ANDROID_SDK_ROOT" in os.environ:
+        return os.environ.get("ANDROID_SDK_ROOT", 0)
+    else:
+        return os.environ.get("ANDROID_HOME", 0)
+
+
+# Return the ANDROID_NDK_ROOT environment variable.
+# If the env variable is already defined, we use it with the expectation that
+# the user knows what they're doing (e.g: testing a new NDK version).
+# Otherwise, we generate one for this build using the ANDROID_SDK_ROOT env
+# variable and the project ndk version.
+def get_android_ndk_root():
+    if "ANDROID_NDK_ROOT" in os.environ:
+        return os.environ.get("ANDROID_NDK_ROOT", 0)
+    else:
+        return get_android_sdk_root() + "/ndk/" + get_project_ndk_version()
+
+
 def get_flags():
     return [
         ("tools", False),
@@ -47,7 +70,31 @@ def create(env):
     return env.Clone(tools=tools)
 
 
+# Check if ANDROID_NDK_ROOT is valid.
+# If not, install the ndk using ANDROID_SDK_ROOT and sdkmanager.
+def install_ndk_if_needed(env):
+    print("Checking for Android NDK...")
+    env_ndk_version = get_env_ndk_version(env["ANDROID_NDK_ROOT"])
+    if env_ndk_version is None:
+        # Reinstall the ndk and update ANDROID_NDK_ROOT.
+        print("Installing Android NDK...")
+        if env["ANDROID_SDK_ROOT"] is None:
+            raise Exception("Invalid ANDROID_SDK_ROOT environment variable.")
+
+        import subprocess
+
+        extension = ".bat" if os.name == "nt" else ""
+        sdkmanager_path = env["ANDROID_SDK_ROOT"] + "/cmdline-tools/latest/bin/sdkmanager" + extension
+        ndk_download_args = "ndk;" + get_project_ndk_version()
+        subprocess.check_call([sdkmanager_path, ndk_download_args])
+
+        env["ANDROID_NDK_ROOT"] = env["ANDROID_SDK_ROOT"] + "/ndk/" + get_project_ndk_version()
+        print("ANDROID_NDK_ROOT: " + env["ANDROID_NDK_ROOT"])
+
+
 def configure(env):
+    install_ndk_if_needed(env)
+
     # Workaround for MinGW. See:
     # http://www.scons.org/wiki/LongCmdLinesOnWin32
     if os.name == "nt":
@@ -265,7 +312,7 @@ def configure(env):
 
     # Link flags
 
-    ndk_version = get_ndk_version(env["ANDROID_NDK_ROOT"])
+    ndk_version = get_env_ndk_version(env["ANDROID_NDK_ROOT"])
     if ndk_version != None and LooseVersion(ndk_version) >= LooseVersion("17.1.4828580"):
         env.Append(LINKFLAGS=["-Wl,--exclude-libs,libgcc.a", "-Wl,--exclude-libs,libatomic.a", "-nostdlib++"])
     else:
@@ -318,8 +365,14 @@ def configure(env):
     env.Append(LIBS=["OpenSLES", "EGL", "GLESv3", "GLESv2", "android", "log", "z", "dl"])
 
 
+# Return the project NDK version.
+# This is kept in sync with the value in 'platform/android/java/app/config.gradle'.
+def get_project_ndk_version():
+    return "21.3.6528147"
+
+
 # Return NDK version string in source.properties (adapted from the Chromium project).
-def get_ndk_version(path):
+def get_env_ndk_version(path):
     if path is None:
         return None
     prop_file_path = os.path.join(path, "source.properties")

+ 2 - 0
platform/android/java/app/build.gradle

@@ -112,6 +112,8 @@ android {
         disable 'MissingTranslation', 'UnusedResources'
     }
 
+    ndkVersion versions.ndkVersion
+
     packagingOptions {
         exclude 'META-INF/LICENSE'
         exclude 'META-INF/NOTICE'

+ 2 - 1
platform/android/java/app/config.gradle

@@ -7,7 +7,8 @@ ext.versions = [
     supportCoreUtils   : '1.0.0',
     kotlinVersion      : '1.4.10',
     v4Support          : '1.0.0',
-    javaVersion        : 1.8
+    javaVersion        : 1.8,
+    ndkVersion         : '21.3.6528147' // Also update 'platform/android/detect.py#get_project_ndk_version()' when this is updated.
 
 ]
 

+ 2 - 0
platform/android/java/nativeSrcsConfigs/build.gradle

@@ -31,6 +31,8 @@ android {
         }
     }
 
+    ndkVersion versions.ndkVersion
+
     externalNativeBuild {
         cmake {
             path "CMakeLists.txt"