191 lines
5.4 KiB
GDScript
191 lines
5.4 KiB
GDScript
extends RefCounted
|
|
class_name KiriPythonBuildWrangler
|
|
|
|
var _python_release_info : Dictionary = {}
|
|
|
|
func _get_python_release_info():
|
|
if _python_release_info == {}:
|
|
var this_script_path = get_script().resource_path
|
|
var this_script_dir = this_script_path.get_base_dir()
|
|
var release_info_path = this_script_dir.path_join("StandalonePythonBuilds/python_release_info.json")
|
|
_python_release_info = load(release_info_path).data
|
|
return _python_release_info
|
|
|
|
func _get_python_version():
|
|
|
|
var info = _get_python_release_info()
|
|
var versions : Array = info["versions"]
|
|
|
|
# Sort version numbers so that the highest version is the first element.
|
|
versions.sort_custom(func(a : String, b : String):
|
|
var version_parts_a : PackedStringArray = a.split(".")
|
|
var version_parts_b : PackedStringArray = b.split(".")
|
|
for i in range(0, 3):
|
|
if int(version_parts_a[i]) > int(version_parts_b[i]):
|
|
return true
|
|
if int(version_parts_a[i]) < int(version_parts_b[i]):
|
|
return false
|
|
return false)
|
|
|
|
return versions[0]
|
|
|
|
func _get_python_release():
|
|
var info = _get_python_release_info()
|
|
return info["release"]
|
|
|
|
func _generate_python_archive_string(
|
|
python_version : String,
|
|
python_release : String,
|
|
arch : String,
|
|
os : String,
|
|
opt : String):
|
|
|
|
return "cpython-{python_version}+{python_release}-{python_arch}-{python_os}-{python_opt}-full.tar.zip".format(
|
|
{
|
|
"python_version" : python_version,
|
|
"python_release" : python_release,
|
|
"python_arch" : arch,
|
|
"python_os" : os,
|
|
"python_opt" : opt
|
|
})
|
|
|
|
func _get_python_opt_for_os(os_name : String) -> String:
|
|
if os_name == "pc-windows-msvc-shared":
|
|
return "pgo"
|
|
return "pgo+lto"
|
|
|
|
func _detect_archive_for_runtime( \
|
|
python_version : String,
|
|
python_release : String):
|
|
|
|
var arch : String = _get_python_architecture(Engine.get_architecture_name())
|
|
var os_name : String = _get_python_platform(OS.get_name(), arch)
|
|
var opt = _get_python_opt_for_os(os_name)
|
|
|
|
var archive_str : String = _generate_python_archive_string(
|
|
python_version, python_release,
|
|
arch, os_name, opt)
|
|
|
|
return archive_str
|
|
|
|
func _detect_archive_for_build(
|
|
python_version : String,
|
|
python_release : String,
|
|
arch : String,
|
|
os_name : String):
|
|
|
|
var opt = _get_python_opt_for_os(os_name)
|
|
|
|
var archive_str : String = _generate_python_archive_string(
|
|
python_version, python_release,
|
|
arch, os_name, opt)
|
|
|
|
return archive_str
|
|
|
|
# Note: arch variable is output of _get_python_architecture, not whatever Godot
|
|
# returns.
|
|
func _get_python_platform(os_name : String, arch : String) -> String:
|
|
var os_name_mappings : Dictionary = {
|
|
"Linux" : "unknown-linux-gnu",
|
|
"macOS" : "apple-darwin",
|
|
"Windows" : "pc-windows-msvc-shared"
|
|
}
|
|
|
|
# Special case for armv7 Linux:
|
|
if arch == "armv7" and os_name == "Linux":
|
|
return "linux-gnueabi"
|
|
|
|
assert(os_name_mappings.has(os_name))
|
|
return os_name_mappings[os_name]
|
|
|
|
func _get_python_architecture(engine_arch : String) -> String:
|
|
var arch_name_mappings : Dictionary = {
|
|
"x86_64" : "x86_64",
|
|
"x86_32" : "i686",
|
|
"arm64" : "aarch64", # FIXME: I dunno if this is correct.
|
|
"arm32" : "armv7", # FIXME: I dunno if this is correct.
|
|
}
|
|
assert(arch_name_mappings.has(engine_arch))
|
|
return arch_name_mappings[engine_arch]
|
|
|
|
func _get_cache_path_relative():
|
|
return "_python_dist".path_join(_get_python_release()).path_join(_get_python_version())
|
|
|
|
func _get_cache_path_system():
|
|
return OS.get_user_data_dir().path_join(_get_cache_path_relative())
|
|
|
|
func _get_cache_path_godot():
|
|
return "user://".path_join(_get_cache_path_relative())
|
|
|
|
func _get_runtime_python_archive_godot_path() -> String:
|
|
var this_script_path = get_script().resource_path
|
|
var this_script_dir = this_script_path.get_base_dir()
|
|
var python_archive_path = this_script_dir.path_join(
|
|
"StandalonePythonBuilds").path_join(
|
|
_detect_archive_for_runtime(
|
|
_get_python_version(),
|
|
_get_python_release()))
|
|
|
|
return python_archive_path
|
|
|
|
func get_export_python_archive_godot_path(platform : String, arch : String) -> String:
|
|
var this_script_path = get_script().resource_path
|
|
var this_script_dir = this_script_path.get_base_dir()
|
|
var python_archive_path = this_script_dir.path_join(
|
|
"StandalonePythonBuilds").path_join(
|
|
_detect_archive_for_build(
|
|
_get_python_version(),
|
|
_get_python_release(), arch, platform))
|
|
|
|
return python_archive_path
|
|
|
|
func _unpack_python():
|
|
|
|
var python_archive_path = _get_runtime_python_archive_godot_path()
|
|
var reader : TARReader = TARReader.new()
|
|
reader.open(python_archive_path)
|
|
|
|
#print(reader.get_files())
|
|
|
|
var file_list : PackedStringArray = reader.get_files()
|
|
|
|
for relative_filename : String in file_list:
|
|
reader.unpack_file(_get_cache_path_godot(), relative_filename)
|
|
|
|
pass
|
|
|
|
func _get_runtime_python_executable_godot_path():
|
|
var base_dir = _get_cache_path_godot().path_join("python/install")
|
|
if OS.get_name() == "Windows":
|
|
return base_dir.path_join("python.exe")
|
|
else:
|
|
return base_dir.path_join("bin/python3")
|
|
|
|
# TODO: Other platforms.
|
|
|
|
|
|
|
|
# Testing code follows...
|
|
|
|
#func _ready():
|
|
#
|
|
#print(_detect_archive_for_runtime(
|
|
#_get_python_version(), _get_python_release()))
|
|
#
|
|
#print(_get_cache_path_godot())
|
|
#print(_get_cache_path_system())
|
|
#print(_get_runtime_python_archive_godot_path())
|
|
#
|
|
##_unpack_python()
|
|
#print(_get_runtime_python_executable_godot_path())
|
|
#print(ProjectSettings.globalize_path(_get_runtime_python_executable_godot_path()))
|
|
#
|
|
#var out = []
|
|
#OS.execute(
|
|
#ProjectSettings.globalize_path(_get_runtime_python_executable_godot_path()),
|
|
#["asdfjknsdcjknsdcjknsdjkc"], out, true)
|
|
#print(out)
|
|
#
|
|
#
|
|
|