|
|
@@ -564,11 +564,12 @@ def LocateBinary(binary):
|
|
|
p = os.environ["PATH"]
|
|
|
|
|
|
pathList = p.split(os.pathsep)
|
|
|
+ suffixes = ['']
|
|
|
|
|
|
if GetHost() == 'windows':
|
|
|
- if not binary.endswith('.exe'):
|
|
|
+ if not binary.lower().endswith('.exe') and not binary.lower().endswith('.bat'):
|
|
|
# Append .exe if necessary
|
|
|
- binary += '.exe'
|
|
|
+ suffixes = ['.exe', '.bat']
|
|
|
|
|
|
# On Windows the current directory is always implicitly
|
|
|
# searched before anything else on PATH.
|
|
|
@@ -576,8 +577,9 @@ def LocateBinary(binary):
|
|
|
|
|
|
for path in pathList:
|
|
|
binpath = os.path.join(os.path.expanduser(path), binary)
|
|
|
- if os.access(binpath, os.X_OK):
|
|
|
- return os.path.abspath(os.path.realpath(binpath))
|
|
|
+ for suffix in suffixes:
|
|
|
+ if os.access(binpath + suffix, os.X_OK):
|
|
|
+ return os.path.abspath(os.path.realpath(binpath + suffix))
|
|
|
return None
|
|
|
|
|
|
########################################################################
|
|
|
@@ -586,20 +588,31 @@ def LocateBinary(binary):
|
|
|
##
|
|
|
########################################################################
|
|
|
|
|
|
-def oscmd(cmd, ignoreError = False):
|
|
|
+def oscmd(cmd, ignoreError = False, cwd=None):
|
|
|
if VERBOSE:
|
|
|
print(GetColor("blue") + cmd.split(" ", 1)[0] + " " + GetColor("magenta") + cmd.split(" ", 1)[1] + GetColor())
|
|
|
sys.stdout.flush()
|
|
|
|
|
|
if sys.platform == "win32":
|
|
|
- exe = cmd.split()[0]
|
|
|
+ if cmd[0] == '"':
|
|
|
+ exe = cmd[1 : cmd.index('"', 1)]
|
|
|
+ else:
|
|
|
+ exe = cmd.split()[0]
|
|
|
exe_path = LocateBinary(exe)
|
|
|
if exe_path is None:
|
|
|
exit("Cannot find "+exe+" on search path")
|
|
|
+
|
|
|
+ if cwd is not None:
|
|
|
+ pwd = os.getcwd()
|
|
|
+ os.chdir(cwd)
|
|
|
+
|
|
|
res = os.spawnl(os.P_WAIT, exe_path, cmd)
|
|
|
+
|
|
|
+ if cwd is not None:
|
|
|
+ os.chdir(pwd)
|
|
|
else:
|
|
|
cmd = cmd.replace(';', '\\;')
|
|
|
- res = subprocess.call(cmd, shell=True)
|
|
|
+ res = subprocess.call(cmd, cwd=cwd, shell=True)
|
|
|
sig = res & 0x7F
|
|
|
if (GetVerbose() and res != 0):
|
|
|
print(ColorText("red", "Process exited with exit status %d and signal code %d" % ((res & 0xFF00) >> 8, sig)))
|
|
|
@@ -2463,22 +2476,46 @@ def SdkLocateAndroid():
|
|
|
SDK["ANDROID_TRIPLE"] = ANDROID_TRIPLE
|
|
|
|
|
|
if GetHost() == 'android':
|
|
|
+ # Assume we're compiling from termux.
|
|
|
+ prefix = os.environ.get("PREFIX", "/data/data/com.termux/files/usr")
|
|
|
+ SDK["ANDROID_JAR"] = prefix + "/share/aapt/android.jar"
|
|
|
return
|
|
|
|
|
|
+ # Find the location of the Android SDK.
|
|
|
+ sdk_root = os.environ.get('ANDROID_HOME')
|
|
|
+ if not sdk_root or not os.path.isdir(sdk_root):
|
|
|
+ sdk_root = os.environ.get('ANDROID_SDK_ROOT')
|
|
|
+
|
|
|
+ # Try the default installation location on Windows.
|
|
|
+ if not sdk_root and GetHost() == 'windows':
|
|
|
+ sdk_root = os.path.expanduser(os.path.join('~', 'AppData', 'Local', 'Android', 'Sdk'))
|
|
|
+
|
|
|
+ if not sdk_root:
|
|
|
+ exit('ANDROID_SDK_ROOT must be set when compiling for Android!')
|
|
|
+ elif not os.path.isdir(sdk_root):
|
|
|
+ exit('Cannot find %s. Please install Android SDK and set ANDROID_SDK_ROOT or ANDROID_HOME.' % (sdk_root))
|
|
|
+
|
|
|
# Determine the NDK installation directory.
|
|
|
- if 'NDK_ROOT' not in os.environ:
|
|
|
- exit('NDK_ROOT must be set when compiling for Android!')
|
|
|
+ if os.environ.get('NDK_ROOT') or os.environ.get('ANDROID_NDK_ROOT'):
|
|
|
+ # We have an explicit setting from an environment variable.
|
|
|
+ ndk_root = os.environ.get('ANDROID_NDK_ROOT')
|
|
|
+ if not ndk_root or not os.path.isdir(ndk_root):
|
|
|
+ ndk_root = os.environ.get('NDK_ROOT')
|
|
|
+ if not ndk_root or not os.path.isdir(ndk_root):
|
|
|
+ exit("Cannot find %s. Please install Android NDK and set ANDROID_NDK_ROOT." % (ndk_root))
|
|
|
+ else:
|
|
|
+ # Often, it's installed in the ndk-bundle subdirectory of the SDK.
|
|
|
+ ndk_root = os.path.join(sdk_root, 'ndk-bundle')
|
|
|
|
|
|
- ndk_root = os.environ["NDK_ROOT"]
|
|
|
- if not os.path.isdir(ndk_root):
|
|
|
- exit("Cannot find %s. Please install Android NDK and set NDK_ROOT." % (ndk_root))
|
|
|
+ if not os.path.isdir(os.path.join(ndk_root, 'toolchains')):
|
|
|
+ exit('Cannot find the Android NDK. Install it via the SDK manager or set the ANDROID_NDK_ROOT variable if you have installed it in a different location.')
|
|
|
|
|
|
SDK["ANDROID_NDK"] = ndk_root
|
|
|
|
|
|
# Determine the toolchain location.
|
|
|
prebuilt_dir = os.path.join(ndk_root, 'toolchains', 'llvm', 'prebuilt')
|
|
|
if not os.path.isdir(prebuilt_dir):
|
|
|
- exit('Not found: %s' % (prebuilt_dir))
|
|
|
+ exit('Not found: %s (is the Android NDK installed?)' % (prebuilt_dir))
|
|
|
|
|
|
host_tag = GetHost() + '-x86'
|
|
|
if host_64:
|
|
|
@@ -2527,7 +2564,44 @@ def SdkLocateAndroid():
|
|
|
# STL that ships with Android.
|
|
|
support = os.path.join(ndk_root, 'sources', 'android', 'support', 'include')
|
|
|
IncDirectory("ALWAYS", support.replace('\\', '/'))
|
|
|
- LibName("ALWAYS", "-landroid_support")
|
|
|
+ if api < 21:
|
|
|
+ LibName("ALWAYS", "-landroid_support")
|
|
|
+
|
|
|
+ # Determine the location of android.jar.
|
|
|
+ SDK["ANDROID_JAR"] = os.path.join(sdk_root, 'platforms', 'android-%s' % (api), 'android.jar')
|
|
|
+ if not os.path.isfile(SDK["ANDROID_JAR"]):
|
|
|
+ exit("Cannot find %s. Install platform API level %s via the SDK manager or change the targeted API level with --target=android-#" % (SDK["ANDROID_JAR"], api))
|
|
|
+
|
|
|
+ # Which build tools versions do we have? Pick the latest.
|
|
|
+ versions = []
|
|
|
+ for version in os.listdir(os.path.join(sdk_root, "build-tools")):
|
|
|
+ match = re.match('([0-9]+)\\.([0-9]+)\\.([0-9]+)', version)
|
|
|
+ if match:
|
|
|
+ version_tuple = int(match.group(1)), int(match.group(2)), int(match.group(3))
|
|
|
+ versions.append(version_tuple)
|
|
|
+
|
|
|
+ versions.sort()
|
|
|
+ if versions:
|
|
|
+ version = versions[-1]
|
|
|
+ SDK["ANDROID_BUILD_TOOLS"] = os.path.join(sdk_root, "build-tools", "{0}.{1}.{2}".format(*version))
|
|
|
+
|
|
|
+ # And find the location of the Java compiler.
|
|
|
+ if GetHost() == "windows":
|
|
|
+ jdk_home = os.environ.get("JDK_HOME") or os.environ.get("JAVA_HOME")
|
|
|
+ if not jdk_home:
|
|
|
+ # Try to use the Java shipped with Android Studio.
|
|
|
+ studio_path = GetRegistryKey("SOFTWARE\\Android Studio", "Path", override64=False)
|
|
|
+ if studio_path and os.path.isdir(studio_path):
|
|
|
+ jdk_home = os.path.join(studio_path, "jre")
|
|
|
+
|
|
|
+ if not jdk_home or not os.path.isdir(jdk_home):
|
|
|
+ exit("Cannot find JDK. Please set JDK_HOME or JAVA_HOME.")
|
|
|
+
|
|
|
+ javac = os.path.join(jdk_home, "bin", "javac.exe")
|
|
|
+ if not os.path.isfile(javac):
|
|
|
+ exit("Cannot find %s. Install the JDK and set JDK_HOME or JAVA_HOME." % (javac))
|
|
|
+
|
|
|
+ SDK["JDK"] = jdk_home
|
|
|
|
|
|
########################################################################
|
|
|
##
|
|
|
@@ -2793,6 +2867,13 @@ def SetupBuildEnvironment(compiler):
|
|
|
if GetTarget() == 'android' and GetHost() != 'android':
|
|
|
AddToPathEnv("PATH", os.path.join(SDK["ANDROID_TOOLCHAIN"], "bin"))
|
|
|
|
|
|
+ if "ANDROID_BUILD_TOOLS" in SDK:
|
|
|
+ AddToPathEnv("PATH", SDK["ANDROID_BUILD_TOOLS"])
|
|
|
+
|
|
|
+ if "JDK" in SDK:
|
|
|
+ AddToPathEnv("PATH", os.path.join(SDK["JDK"], "bin"))
|
|
|
+ os.environ["JAVA_HOME"] = SDK["JDK"]
|
|
|
+
|
|
|
if compiler == "MSVC":
|
|
|
# Add the visual studio tools to PATH et al.
|
|
|
SetupVisualStudioEnviron()
|
|
|
@@ -2844,8 +2925,22 @@ def SetupBuildEnvironment(compiler):
|
|
|
Warn("%s failed" % (cmd))
|
|
|
SYS_LIB_DIRS += [SDK.get("SYSROOT", "") + "/usr/lib"]
|
|
|
|
|
|
+ # The Android toolchain on Windows doesn't actually add this one.
|
|
|
+ if target == 'android' and GetHost() == 'windows':
|
|
|
+ libdir = SDK.get("SYSROOT", "") + "/usr/lib"
|
|
|
+ if GetTargetArch() == 'x86_64':
|
|
|
+ libdir += '64'
|
|
|
+ SYS_LIB_DIRS += [libdir]
|
|
|
+
|
|
|
# Now extract the preprocessor's include directories.
|
|
|
- cmd = GetCXX() + sysroot_flag + " -x c++ -v -E /dev/null"
|
|
|
+ cmd = GetCXX() + " -x c++ -v -E " + os.devnull
|
|
|
+ if "ANDROID_NDK" in SDK:
|
|
|
+ ndk_dir = SDK["ANDROID_NDK"].replace('\\', '/')
|
|
|
+ cmd += ' -isystem %s/sysroot/usr/include' % (ndk_dir)
|
|
|
+ cmd += ' -isystem %s/sysroot/usr/include/%s' % (ndk_dir, SDK["ANDROID_TRIPLE"])
|
|
|
+ else:
|
|
|
+ cmd += sysroot_flag
|
|
|
+
|
|
|
null = open(os.devnull, 'w')
|
|
|
handle = subprocess.Popen(cmd, stdout=null, stderr=subprocess.PIPE, shell=True)
|
|
|
scanning = False
|
|
|
@@ -2858,8 +2953,12 @@ def SetupBuildEnvironment(compiler):
|
|
|
scanning = True
|
|
|
continue
|
|
|
|
|
|
- if not line.startswith(' /'):
|
|
|
- continue
|
|
|
+ if sys.platform == "win32":
|
|
|
+ if not line.startswith(' '):
|
|
|
+ continue
|
|
|
+ else:
|
|
|
+ if not line.startswith(' /'):
|
|
|
+ continue
|
|
|
|
|
|
line = line.strip()
|
|
|
if line.endswith(" (framework directory)"):
|