GodotPythonJSONRPC/addons/kiripythonrpcwrapper/PythonBuildWrangler.gd

191 lines
5.4 KiB
GDScript3
Raw Normal View History

2024-07-14 08:54:08 -07:00
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)
#
#