diff --git a/src/extension/extension.cpp b/src/extension/extension.cpp index 3b0b24a..76b4e0b 100644 --- a/src/extension/extension.cpp +++ b/src/extension/extension.cpp @@ -93,11 +93,11 @@ static struct runtime_config_t { // `python_home_path` if(likely_running_from_editor) { - python_home_path = lib_dir_path; + python_home_path = lib_dir_path / "python"; } else { auto platform_arch = std::string(PYGODOT_PLATFORM) + "-" + std::string(PYGODOT_ARCH); - python_home_path = lib_dir_path / "lib" / platform_arch; + python_home_path = lib_dir_path / "lib" / platform_arch / "python"; } } } runtime_config; @@ -171,12 +171,13 @@ static bool init_python_isolated() { auto py_version = py_major + "." + py_minor; auto py_version_no_dot = py_major + py_minor; auto python_zip_name = "python" + py_version_no_dot + ".zip"; + auto python_lib_path = runtime_config.python_home_path / "lib"; auto python_lib_name = "python" + py_version; add_module_search_path((runtime_config.python_home_path / python_zip_name).string()); - add_module_search_path((runtime_config.python_home_path / python_lib_name).string()); - add_module_search_path((runtime_config.python_home_path / python_lib_name / "lib-dynload").string()); - add_module_search_path((runtime_config.python_home_path / python_lib_name / "site-packages").string()); + add_module_search_path((python_lib_path / python_lib_name).string()); + add_module_search_path((python_lib_path / python_lib_name / "lib-dynload").string()); + add_module_search_path((python_lib_path / python_lib_name / "site-packages").string()); config.module_search_paths_set = 1; diff --git a/tools/build/prepare_python.py b/tools/build/prepare_python.py index 651f36f..618fa7c 100644 --- a/tools/build/prepare_python.py +++ b/tools/build/prepare_python.py @@ -17,6 +17,7 @@ class PlatformConfig: ext_suffixes: list[str] so_path: str python_lib_dir: str + python_bin_paths: list[str] python_ext_dir: str executable: str @@ -42,6 +43,7 @@ def add_platform_config(*args, **kwargs): ext_suffixes = ['.so'], so_path = 'lib/libpython3.12.so.1.0', python_lib_dir = 'lib/python3.12', + python_bin_paths = ['bin'], python_ext_dir = 'lib/python3.12/lib-dynload', executable = 'bin/python3.12', ) @@ -55,6 +57,7 @@ def add_platform_config(*args, **kwargs): ext_suffixes = ['.dll', '.pyd'], so_path = 'python312.dll', python_lib_dir = 'Lib', + python_bin_paths = ['python.exe', 'pythonw.exe'], python_ext_dir = 'DLLs', executable = 'python.exe', ) @@ -68,6 +71,7 @@ def add_platform_config(*args, **kwargs): ext_suffixes = ['.so'], so_path = 'lib/libpython3.12.dylib', python_lib_dir = 'lib/python3.12', + python_bin_paths = ['bin'], python_ext_dir = 'lib/python3.12/lib-dynload', executable = 'bin/python3.12', ) @@ -81,6 +85,7 @@ def add_platform_config(*args, **kwargs): ext_suffixes = ['.so'], so_path = 'lib/libpython3.12.dylib', python_lib_dir = 'lib/python3.12', + python_bin_paths = ['bin'], python_ext_dir = 'lib/python3.12/lib-dynload', executable = 'bin/python3.12', ) @@ -105,32 +110,41 @@ def prepare_for_platform(platform: str, arch: str, shutil.unpack_archive(src_dir / pathlib.Path(config.source_url).name, extract_dir = src_dir) - src = src_dir / 'python' - src_lib_path = src / config.so_path + src_python = src_dir / 'python' + src_lib_path = src_python / config.so_path lib_filename = pathlib.Path(config.so_path).name if platform == 'macos': # Rename the library id (which we depend on) to be in @rpath. # (it defaults to /install/lib/) - subprocess.run(['install_name_tool', '-id', f'@rpath/{lib_filename}', src_lib_path], check=True) + subprocess.run(['install_name_tool', '-id', f'@rpath/python/lib/{lib_filename}', src_lib_path], check=True) + - dest_dir.mkdir(parents=True, exist_ok=True) - shutil.copy2(src_lib_path, dest_dir) + dest_dir_python = dest_dir / 'python' + dest_dir_python_lib = dest_dir_python / 'lib' + dest_dir_python_lib.mkdir(parents=True, exist_ok=True) + shutil.copy2(src_lib_path, dest_dir_python_lib) if platform == 'macos': - subprocess.run(['strip', '-x', dest_dir / lib_filename], check=True) + subprocess.run(['strip', '-x', dest_dir_python_lib / lib_filename], check=True) else: - subprocess.run(['strip', '-s', dest_dir / lib_filename], check=True) + subprocess.run(['strip', '-s', dest_dir_python_lib / lib_filename], check=True) + + for bin_path in config.python_bin_paths: + shutil.copytree(src_python / bin_path, dest_dir_python / bin_path, dirs_exist_ok=True) + if bin_path == 'bin': + # Ignore the bin path in Godot. + open(dest_dir_python / bin_path / '.gdignore', 'a').close() - if (src / config.python_ext_dir).exists(): - dest_ext_dir = dest_dir / 'python3.12' / 'lib-dynload' + if (src_python / config.python_ext_dir).exists(): + dest_ext_dir = dest_dir_python_lib / 'python3.12' / 'lib-dynload' dest_ext_dir.mkdir(parents=True, exist_ok=True) - for path in (src / config.python_ext_dir).iterdir(): + for path in (src_python / config.python_ext_dir).iterdir(): if any(suffix in path.suffixes for suffix in config.ext_suffixes): shutil.copy2(path, dest_ext_dir) - shutil.make_archive(dest_dir / 'python312', 'zip', root_dir=src / config.python_lib_dir, base_dir='') + shutil.make_archive(dest_dir / 'python312', 'zip', root_dir=src_python / config.python_lib_dir, base_dir='') def get_python_for_platform(platform: str, arch: str, src_dir: pathlib.Path) -> pathlib.Path: