Skip to content

Commit 7dfeeb2

Browse files
committed
Add bin folder to python targets, and adapt the regular python layout (save for the zip). Use the zip upload archive method in the github runner for macOS, too, to preserve permissions.
1 parent 129b494 commit 7dfeeb2

File tree

3 files changed

+51
-27
lines changed

3 files changed

+51
-27
lines changed

.github/workflows/build.yml

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,21 @@ jobs:
6464
run: |
6565
scons platform=${{ matrix.platform }} arch=${{ matrix.arch }} single_source=true
6666
67-
- name: Upload artifacts (Linux)
68-
if: matrix.os == 'ubuntu-latest'
67+
# Creating an archive explicitly preserves permissions in the artifact,
68+
# which upload-artifact doesn't. See https://github.com/actions/upload-artifact/issues/38
69+
- name: Create archive (Linux, macOS)
70+
if: matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest'
71+
run: |
72+
cd bin/
73+
zip -q -r ../godot-python-${{ matrix.platform }}-${{ matrix.arch }}.zip *
74+
cd ../
75+
76+
- name: Upload artifacts (Linux, macOS)
77+
if: matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest'
6978
uses: actions/upload-artifact@v4
7079
with:
7180
name: godot-python-${{ matrix.platform }}-${{ matrix.arch }}
72-
path: bin/**/*
81+
path: godot-python-${{ matrix.platform }}-${{ matrix.arch }}.zip
7382
retention-days: 30
7483

7584
- name: Upload artifacts (Windows)
@@ -83,14 +92,6 @@ jobs:
8392
!bin/**/*.exp
8493
retention-days: 30
8594

86-
- name: Upload artifacts (macOS)
87-
if: matrix.os == 'macos-latest'
88-
uses: actions/upload-artifact@v4
89-
with:
90-
name: godot-python-${{ matrix.platform }}-${{ matrix.arch }}
91-
path: bin/**/*
92-
retention-days: 30
93-
9495
- name: Release artifact
9596
if: ${{ inputs.release }}
9697
run: |

src/extension/extension.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,11 @@ static struct runtime_config_t {
9393

9494
// `python_home_path`
9595
if(likely_running_from_editor) {
96-
python_home_path = lib_dir_path;
96+
python_home_path = lib_dir_path / "python";
9797
}
9898
else {
9999
auto platform_arch = std::string(PYGODOT_PLATFORM) + "-" + std::string(PYGODOT_ARCH);
100-
python_home_path = lib_dir_path / "lib" / platform_arch;
100+
python_home_path = lib_dir_path / "lib" / platform_arch / "python";
101101
}
102102
}
103103
} runtime_config;
@@ -171,12 +171,13 @@ static bool init_python_isolated() {
171171
auto py_version = py_major + "." + py_minor;
172172
auto py_version_no_dot = py_major + py_minor;
173173
auto python_zip_name = "python" + py_version_no_dot + ".zip";
174+
auto python_lib_path = runtime_config.python_home_path / "lib";
174175
auto python_lib_name = "python" + py_version;
175176

176177
add_module_search_path((runtime_config.python_home_path / python_zip_name).string());
177-
add_module_search_path((runtime_config.python_home_path / python_lib_name).string());
178-
add_module_search_path((runtime_config.python_home_path / python_lib_name / "lib-dynload").string());
179-
add_module_search_path((runtime_config.python_home_path / python_lib_name / "site-packages").string());
178+
add_module_search_path((python_lib_path / python_lib_name).string());
179+
add_module_search_path((python_lib_path / python_lib_name / "lib-dynload").string());
180+
add_module_search_path((python_lib_path / python_lib_name / "site-packages").string());
180181

181182
config.module_search_paths_set = 1;
182183

tools/build/prepare_python.py

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class PlatformConfig:
1717
ext_suffixes: list[str]
1818
so_path: str
1919
python_lib_dir: str
20+
python_bin_paths: list[str]
2021
python_ext_dir: str
2122
executable: str
2223

@@ -42,6 +43,7 @@ def add_platform_config(*args, **kwargs):
4243
ext_suffixes = ['.so'],
4344
so_path = 'lib/libpython3.12.so.1.0',
4445
python_lib_dir = 'lib/python3.12',
46+
python_bin_paths = ['bin'],
4547
python_ext_dir = 'lib/python3.12/lib-dynload',
4648
executable = 'bin/python3.12',
4749
)
@@ -55,6 +57,7 @@ def add_platform_config(*args, **kwargs):
5557
ext_suffixes = ['.dll', '.pyd'],
5658
so_path = 'python312.dll',
5759
python_lib_dir = 'Lib',
60+
python_bin_paths = ['python.exe', 'pythonw.exe'],
5861
python_ext_dir = 'DLLs',
5962
executable = 'python.exe',
6063
)
@@ -68,6 +71,7 @@ def add_platform_config(*args, **kwargs):
6871
ext_suffixes = ['.so'],
6972
so_path = 'lib/libpython3.12.dylib',
7073
python_lib_dir = 'lib/python3.12',
74+
python_bin_paths = ['bin'],
7175
python_ext_dir = 'lib/python3.12/lib-dynload',
7276
executable = 'bin/python3.12',
7377
)
@@ -81,6 +85,7 @@ def add_platform_config(*args, **kwargs):
8185
ext_suffixes = ['.so'],
8286
so_path = 'lib/libpython3.12.dylib',
8387
python_lib_dir = 'lib/python3.12',
88+
python_bin_paths = ['bin'],
8489
python_ext_dir = 'lib/python3.12/lib-dynload',
8590
executable = 'bin/python3.12',
8691
)
@@ -105,32 +110,49 @@ def prepare_for_platform(platform: str, arch: str,
105110

106111
shutil.unpack_archive(src_dir / pathlib.Path(config.source_url).name, extract_dir = src_dir)
107112

108-
src = src_dir / 'python'
109-
src_lib_path = src / config.so_path
113+
src_python = src_dir / 'python'
114+
src_lib_path = src_python / config.so_path
110115
lib_filename = pathlib.Path(config.so_path).name
111116

112117
if platform == 'macos':
113118
# Rename the library id (which we depend on) to be in @rpath.
114119
# (it defaults to /install/lib/)
115-
subprocess.run(['install_name_tool', '-id', f'@rpath/{lib_filename}', src_lib_path], check=True)
120+
subprocess.run(['install_name_tool', '-id', f'@rpath/python/lib/{lib_filename}', src_lib_path], check=True)
121+
116122

117-
dest_dir.mkdir(parents=True, exist_ok=True)
118-
shutil.copy2(src_lib_path, dest_dir)
123+
dest_dir_python = dest_dir / 'python'
124+
dest_dir_python_lib = dest_dir_python / 'lib'
125+
dest_dir_python_lib.mkdir(parents=True, exist_ok=True)
119126

127+
shutil.copy2(src_lib_path, dest_dir_python_lib)
120128
if platform == 'macos':
121-
subprocess.run(['strip', '-x', dest_dir / lib_filename], check=True)
129+
subprocess.run(['strip', '-x', dest_dir_python_lib / lib_filename], check=True)
122130
else:
123-
subprocess.run(['strip', '-s', dest_dir / lib_filename], check=True)
131+
subprocess.run(['strip', '-s', dest_dir_python_lib / lib_filename], check=True)
132+
133+
for bin_path in config.python_bin_paths:
134+
src_path: pathlib.Path = src_python / bin_path
135+
136+
if src_path.is_file():
137+
shutil.copy2(src_path, dest_dir_python / bin_path)
138+
elif src_path.is_dir():
139+
shutil.copytree(src_path, dest_dir_python / bin_path, dirs_exist_ok=True)
140+
else:
141+
raise RuntimeError(f"Cannot find file: {src_path}")
142+
143+
if bin_path == 'bin':
144+
# Ignore the bin path in Godot.
145+
(dest_dir_python / bin_path / '.gdignore').touch()
124146

125-
if (src / config.python_ext_dir).exists():
126-
dest_ext_dir = dest_dir / 'python3.12' / 'lib-dynload'
147+
if (src_python / config.python_ext_dir).exists():
148+
dest_ext_dir = dest_dir_python_lib / 'python3.12' / 'lib-dynload'
127149
dest_ext_dir.mkdir(parents=True, exist_ok=True)
128150

129-
for path in (src / config.python_ext_dir).iterdir():
151+
for path in (src_python / config.python_ext_dir).iterdir():
130152
if any(suffix in path.suffixes for suffix in config.ext_suffixes):
131153
shutil.copy2(path, dest_ext_dir)
132154

133-
shutil.make_archive(dest_dir / 'python312', 'zip', root_dir=src / config.python_lib_dir, base_dir='')
155+
shutil.make_archive(dest_dir / 'python312', 'zip', root_dir=src_python / config.python_lib_dir, base_dir='')
134156

135157

136158
def get_python_for_platform(platform: str, arch: str, src_dir: pathlib.Path) -> pathlib.Path:

0 commit comments

Comments
 (0)