-
-
Notifications
You must be signed in to change notification settings - Fork 751
Expand file tree
/
Copy pathandroid.py
More file actions
141 lines (116 loc) · 4.84 KB
/
android.py
File metadata and controls
141 lines (116 loc) · 4.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import os
import sys
import common_compiler_flags
def options(opts):
opts.Add(
"android_api_level",
"Target Android API level",
"24",
)
opts.Add(
"ndk_version",
"Fully qualified version of ndk to use for compilation.",
"28.1.13356709",
)
opts.Add(
"ANDROID_HOME",
"Path to your Android SDK installation. By default, uses ANDROID_HOME from your defined environment variables.",
os.environ.get("ANDROID_HOME", os.environ.get("ANDROID_SDK_ROOT")),
)
def exists(env):
return get_android_ndk_root(env) is not None
def get_android_ndk_root(env):
if env["ANDROID_HOME"]:
return env["ANDROID_HOME"] + "/ndk/" + env["ndk_version"]
else:
return os.environ.get("ANDROID_NDK_ROOT")
def generate(env):
if get_android_ndk_root(env) is None:
raise ValueError(
"To build for Android, the path to the NDK must be defined. Please set ANDROID_HOME to the root folder of your Android SDK installation."
)
if env["arch"] not in ("arm64", "x86_64", "arm32", "x86_32"):
print("Only arm64, x86_64, arm32, and x86_32 are supported on Android. Exiting.")
env.Exit(1)
# Validate API level
if int(env["android_api_level"]) < 24:
print("WARNING: minimum supported Android target api is 24. Forcing target api 24.")
env["android_api_level"] = "24"
# Setup toolchain
toolchain = get_android_ndk_root(env) + "/toolchains/llvm/prebuilt/"
if sys.platform == "win32" or sys.platform == "msys":
toolchain += "windows"
import platform as pltfm
if pltfm.machine().endswith("64"):
toolchain += "-x86_64"
elif sys.platform.startswith("linux"):
toolchain += "linux-x86_64"
elif sys.platform == "darwin":
toolchain += "darwin-x86_64"
env.Append(LINKFLAGS=["-shared"])
if not os.path.exists(toolchain):
print("ERROR: Could not find NDK toolchain at " + toolchain + ".")
print("Make sure NDK version " + env["ndk_version"] + " is installed.")
env.Exit(1)
env.PrependENVPath("PATH", toolchain + "/bin") # This does nothing half of the time, but we'll put it here anyways
# Get architecture info
arch_info_table = {
"arm32": {
"march": "armv7-a",
"target": "armv7a-linux-androideabi",
"compiler_path": "armv7a-linux-androideabi",
"ccflags": ["-mfpu=neon"],
},
"arm64": {
"march": "armv8-a",
"target": "aarch64-linux-android",
"compiler_path": "aarch64-linux-android",
"ccflags": [],
},
"x86_32": {
"march": "i686",
"target": "i686-linux-android",
"compiler_path": "i686-linux-android",
"ccflags": ["-mstackrealign"],
},
"x86_64": {
"march": "x86-64",
"target": "x86_64-linux-android",
"compiler_path": "x86_64-linux-android",
"ccflags": [],
},
}
arch_info = arch_info_table[env["arch"]]
if sys.platform == "win32" or sys.platform == "msys":
# Using short path which is guaranteed to have no whitespaces
import subprocess
def get_short_path(long_path):
cmd = f'cmd /c for %A in ("{long_path}") do @echo %~sA'
output = subprocess.check_output(cmd, shell=True)
return output.decode('utf-8').strip()
toolchain = get_short_path(toolchain)
# Setup tools
env["CC"] = toolchain + "/bin/clang"
env["CXX"] = toolchain + "/bin/clang++"
env["LINK"] = toolchain + "/bin/clang++"
env["AR"] = toolchain + "/bin/llvm-ar"
env["AS"] = toolchain + "/bin/llvm-as"
env["STRIP"] = toolchain + "/bin/llvm-strip"
env["RANLIB"] = toolchain + "/bin/llvm-ranlib"
env["SHLIBSUFFIX"] = ".so"
if sys.platform == "win32" or sys.platform == "msys":
# Use TempFileMunge since some AR invocations are too long for cmd.exe.
# Use POSIX-style paths, required with TempFileMunge.
env["ARCOM_POSIX"] = env["ARCOM"].replace("$TARGET", "$TARGET.posix").replace("$SOURCES", "$SOURCES.posix")
env["ARCOM"] = "${TEMPFILE(ARCOM_POSIX)}"
env.Append(
CCFLAGS=["--target=" + arch_info["target"] + env["android_api_level"], "-march=" + arch_info["march"], "-fPIC"]
)
env.Append(CCFLAGS=arch_info["ccflags"])
env.Append(LINKFLAGS=["--target=" + arch_info["target"] + env["android_api_level"], "-march=" + arch_info["march"]])
env.Append(CPPDEFINES=["ANDROID_ENABLED", "UNIX_ENABLED"])
# Refer to https://github.com/godotengine/godot/blob/master/platform/android/detect.py
# LTO benefits for Android (size, performance) haven't been clearly established yet.
if env["lto"] == "auto":
env["lto"] = "none"
common_compiler_flags.generate(env)