Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/platform_methods.py
9819 views
1
import os
2
import platform
3
import shutil
4
import subprocess
5
import sys
6
7
import methods
8
9
# NOTE: The multiprocessing module is not compatible with SCons due to conflict on cPickle
10
11
12
compatibility_platform_aliases = {
13
"osx": "macos",
14
"iphone": "ios",
15
"x11": "linuxbsd",
16
"javascript": "web",
17
}
18
19
# CPU architecture options.
20
architectures = ["x86_32", "x86_64", "arm32", "arm64", "rv64", "ppc64", "wasm32", "loongarch64"]
21
architecture_aliases = {
22
"x86": "x86_32",
23
"x64": "x86_64",
24
"amd64": "x86_64",
25
"armv7": "arm32",
26
"armv8": "arm64",
27
"arm64v8": "arm64",
28
"aarch64": "arm64",
29
"rv": "rv64",
30
"riscv": "rv64",
31
"riscv64": "rv64",
32
"ppc64le": "ppc64",
33
"loong64": "loongarch64",
34
}
35
36
37
def detect_arch():
38
host_machine = platform.machine().lower()
39
if host_machine in architectures:
40
return host_machine
41
elif host_machine in architecture_aliases.keys():
42
return architecture_aliases[host_machine]
43
elif "86" in host_machine:
44
# Catches x86, i386, i486, i586, i686, etc.
45
return "x86_32"
46
else:
47
methods.print_warning(f'Unsupported CPU architecture: "{host_machine}". Falling back to x86_64.')
48
return "x86_64"
49
50
51
def validate_arch(arch, platform_name, supported_arches):
52
if arch not in supported_arches:
53
methods.print_error(
54
'Unsupported CPU architecture "%s" for %s. Supported architectures are: %s.'
55
% (arch, platform_name, ", ".join(supported_arches))
56
)
57
sys.exit(255)
58
59
60
def get_build_version(short):
61
import version
62
63
name = "custom_build"
64
if os.getenv("BUILD_NAME") is not None:
65
name = os.getenv("BUILD_NAME")
66
v = "%d.%d" % (version.major, version.minor)
67
if version.patch > 0:
68
v += ".%d" % version.patch
69
status = version.status
70
if not short:
71
if os.getenv("GODOT_VERSION_STATUS") is not None:
72
status = str(os.getenv("GODOT_VERSION_STATUS"))
73
v += ".%s.%s" % (status, name)
74
return v
75
76
77
def lipo(prefix, suffix):
78
from pathlib import Path
79
80
target_bin = ""
81
lipo_command = ["lipo", "-create"]
82
arch_found = 0
83
84
for arch in architectures:
85
bin_name = prefix + "." + arch + suffix
86
if Path(bin_name).is_file():
87
target_bin = bin_name
88
lipo_command += [bin_name]
89
arch_found += 1
90
91
if arch_found > 1:
92
target_bin = prefix + ".fat" + suffix
93
lipo_command += ["-output", target_bin]
94
subprocess.run(lipo_command)
95
96
return target_bin
97
98
99
def get_mvk_sdk_path(osname):
100
def int_or_zero(i):
101
try:
102
return int(i)
103
except (TypeError, ValueError):
104
return 0
105
106
def ver_parse(a):
107
return [int_or_zero(i) for i in a.split(".")]
108
109
dirname = os.path.expanduser("~/VulkanSDK")
110
if not os.path.exists(dirname):
111
return ""
112
113
ver_min = ver_parse("1.3.231.0")
114
ver_num = ver_parse("0.0.0.0")
115
files = os.listdir(dirname)
116
lib_name_out = dirname
117
for file in files:
118
if os.path.isdir(os.path.join(dirname, file)):
119
ver_comp = ver_parse(file)
120
if ver_comp > ver_num and ver_comp >= ver_min:
121
# Try new SDK location.
122
lib_name = os.path.join(os.path.join(dirname, file), "macOS/lib/MoltenVK.xcframework/" + osname + "/")
123
if os.path.isfile(os.path.join(lib_name, "libMoltenVK.a")):
124
ver_num = ver_comp
125
lib_name_out = os.path.join(os.path.join(dirname, file), "macOS/lib/MoltenVK.xcframework")
126
else:
127
# Try old SDK location.
128
lib_name = os.path.join(
129
os.path.join(dirname, file), "MoltenVK/MoltenVK.xcframework/" + osname + "/"
130
)
131
if os.path.isfile(os.path.join(lib_name, "libMoltenVK.a")):
132
ver_num = ver_comp
133
lib_name_out = os.path.join(os.path.join(dirname, file), "MoltenVK/MoltenVK.xcframework")
134
135
return lib_name_out
136
137
138
def detect_mvk(env, osname):
139
mvk_list = [
140
get_mvk_sdk_path(osname),
141
"/opt/homebrew/Frameworks/MoltenVK.xcframework",
142
"/usr/local/homebrew/Frameworks/MoltenVK.xcframework",
143
"/opt/local/Frameworks/MoltenVK.xcframework",
144
]
145
if env["vulkan_sdk_path"] != "":
146
mvk_list.insert(0, os.path.expanduser(env["vulkan_sdk_path"]))
147
mvk_list.insert(
148
0,
149
os.path.join(os.path.expanduser(env["vulkan_sdk_path"]), "macOS/lib/MoltenVK.xcframework"),
150
)
151
mvk_list.insert(
152
0,
153
os.path.join(os.path.expanduser(env["vulkan_sdk_path"]), "MoltenVK/MoltenVK.xcframework"),
154
)
155
156
for mvk_path in mvk_list:
157
if mvk_path and os.path.isfile(os.path.join(mvk_path, f"{osname}/libMoltenVK.a")):
158
print(f"MoltenVK found at: {mvk_path}")
159
return mvk_path
160
161
return ""
162
163
164
def combine_libs_apple_embedded(target, source, env):
165
lib_path = target[0].srcnode().abspath
166
if "osxcross" in env:
167
libtool = "$APPLE_TOOLCHAIN_PATH/usr/bin/${apple_target_triple}libtool"
168
else:
169
libtool = "$APPLE_TOOLCHAIN_PATH/usr/bin/libtool"
170
env.Execute(
171
libtool + ' -static -o "' + lib_path + '" ' + " ".join([('"' + lib.srcnode().abspath + '"') for lib in source])
172
)
173
174
175
def generate_bundle_apple_embedded(platform, framework_dir, framework_dir_sim, use_mkv, target, source, env):
176
bin_dir = env.Dir("#bin").abspath
177
178
# Template bundle.
179
app_prefix = "godot." + platform
180
rel_prefix = "libgodot." + platform + "." + "template_release"
181
dbg_prefix = "libgodot." + platform + "." + "template_debug"
182
if env.dev_build:
183
app_prefix += ".dev"
184
rel_prefix += ".dev"
185
dbg_prefix += ".dev"
186
if env["precision"] == "double":
187
app_prefix += ".double"
188
rel_prefix += ".double"
189
dbg_prefix += ".double"
190
191
# Lipo template libraries.
192
#
193
# env.extra_suffix contains ".simulator" when building for simulator,
194
# but it's undesired when calling lipo()
195
extra_suffix = env.extra_suffix.replace(".simulator", "")
196
rel_target_bin = lipo(bin_dir + "/" + rel_prefix, extra_suffix + ".a")
197
dbg_target_bin = lipo(bin_dir + "/" + dbg_prefix, extra_suffix + ".a")
198
rel_target_bin_sim = lipo(bin_dir + "/" + rel_prefix, ".simulator" + extra_suffix + ".a")
199
dbg_target_bin_sim = lipo(bin_dir + "/" + dbg_prefix, ".simulator" + extra_suffix + ".a")
200
# Assemble Xcode project bundle.
201
app_dir = env.Dir("#bin/" + platform + "_xcode").abspath
202
templ = env.Dir("#misc/dist/" + platform + "_xcode").abspath
203
if os.path.exists(app_dir):
204
shutil.rmtree(app_dir)
205
shutil.copytree(templ, app_dir)
206
if rel_target_bin != "":
207
print(f' Copying "{platform}" release framework')
208
shutil.copy(
209
rel_target_bin, app_dir + "/libgodot." + platform + ".release.xcframework/" + framework_dir + "/libgodot.a"
210
)
211
if dbg_target_bin != "":
212
print(f' Copying "{platform}" debug framework')
213
shutil.copy(
214
dbg_target_bin, app_dir + "/libgodot." + platform + ".debug.xcframework/" + framework_dir + "/libgodot.a"
215
)
216
if rel_target_bin_sim != "":
217
print(f' Copying "{platform}" (simulator) release framework')
218
shutil.copy(
219
rel_target_bin_sim,
220
app_dir + "/libgodot." + platform + ".release.xcframework/" + framework_dir_sim + "/libgodot.a",
221
)
222
if dbg_target_bin_sim != "":
223
print(f' Copying "{platform}" (simulator) debug framework')
224
shutil.copy(
225
dbg_target_bin_sim,
226
app_dir + "/libgodot." + platform + ".debug.xcframework/" + framework_dir_sim + "/libgodot.a",
227
)
228
229
if use_mkv:
230
mvk_path = detect_mvk(env, "ios-arm64")
231
if mvk_path != "":
232
shutil.copytree(mvk_path, app_dir + "/MoltenVK.xcframework")
233
234
# ZIP Xcode project bundle.
235
zip_dir = env.Dir("#bin/" + (app_prefix + extra_suffix).replace(".", "_")).abspath
236
shutil.make_archive(zip_dir, "zip", root_dir=app_dir)
237
shutil.rmtree(app_dir)
238
239