Skip to content

Commit 13ad6d6

Browse files
committed
Fix C compilation warnings, revert python-build-standalone to 20221106 (next version is broken)
1 parent 5a7c5bb commit 13ad6d6

File tree

12 files changed

+150
-34
lines changed

12 files changed

+150
-34
lines changed

meson.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ project(
1010
# always done with a --destdir given installing this project globally on
1111
# the system is meaningless
1212
'prefix=/',
13-
'c_std=c11',
13+
'c_std=c17',
1414
]
1515
)
1616

meson_options.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
option('cpython_distrib_version', type: 'string', value: '3.9.7', description: 'Version of CPython to ship')
1+
option('cpython_distrib_version', type: 'string', value: '3.10.8', description: 'Version of CPython to ship')
22
option('godot_headers', type: 'string', value: 'godot_headers', description: 'Path to Godot extension headers directory')
33
option('real_is_double', type: 'boolean', value: false, description: 'Built for Godot with 64bits floating point numbers (i.e. double) in builtins instead of 32bits (i.e. float)')

scripts/python_distrib.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,17 @@
66
import shutil
77
import tarfile
88
import json
9-
from zstandard import ZstdDecompressor
9+
import gzip
10+
import zstandard
1011

1112

1213
PREBUILDS_BASE_URL = "https://github.com/indygreg/python-build-standalone/releases/download"
1314
PLATFORM_TO_PREBUILDS = {
14-
"3.9.7": {
15-
"linux-x86_64": f"{PREBUILDS_BASE_URL}/20211017/cpython-3.9.7-x86_64-unknown-linux-gnu-pgo+lto-20211017T1616.tar.zst",
16-
"windows-x86": f"{PREBUILDS_BASE_URL}/20211017/cpython-3.9.7-i686-pc-windows-msvc-shared-pgo-20211017T1616.tar.zst",
17-
"windows-x86_64": f"{PREBUILDS_BASE_URL}/20211017/cpython-3.9.7-x86_64-pc-windows-msvc-shared-pgo-20211017T1616.tar.zst",
18-
"macos-x86_64": f"{PREBUILDS_BASE_URL}/20211017/cpython-3.9.7-x86_64-apple-darwin-pgo+lto-20211017T1616.tar.zst",
15+
"3.10.8": {
16+
"linux-x86_64": f"{PREBUILDS_BASE_URL}/20221106/cpython-3.10.8+20221106-x86_64-unknown-linux-gnu-pgo+lto-full.tar.zst",
17+
"windows-x86": f"{PREBUILDS_BASE_URL}/20221106/cpython-3.10.8+20221106-i686-pc-windows-msvc-shared-pgo-full.tar.zst",
18+
"windows-x86_64": f"{PREBUILDS_BASE_URL}/20221106/cpython-3.10.8+20221106-x86_64-pc-windows-msvc-shared-pgo-full.tar.zst",
19+
"macos-x86_64": f"{PREBUILDS_BASE_URL}/20221106/cpython-3.10.8+20221106-x86_64-apple-darwin-pgo+lto-full.tar.zst",
1920
}
2021
}
2122

@@ -39,21 +40,36 @@ def fetch_prebuild(
3940
if not archive_path.exists() or force:
4041
print(f"Downloading {archive_url}...")
4142
tmp_archive_path = archive_path.parent / f"{archive_path.name}.tmp"
42-
with urlopen(archive_url) as infd:
43+
with urlopen(archive_url) as rep:
4344
with open(tmp_archive_path, "bw") as outfd:
44-
outfd.write(infd.read())
45+
length = int(rep.headers.get("Content-Length"))
46+
# Poor's man progress bar
47+
while True:
48+
if outfd.write(rep.read(2**20)) == 0:
49+
break
50+
print(f"{outfd.tell()//2**20}Mo/{length//2**20}Mo", flush=True, end="\r")
51+
4552
shutil.move(tmp_archive_path, archive_path)
4653

4754
if force and prebuild_dir.exists():
4855
shutil.rmtree(prebuild_dir)
4956

5057
if not prebuild_dir.exists():
5158
print(f"Extracting {archive_path}...")
52-
with open(archive_path, "rb") as fh:
53-
dctx = ZstdDecompressor()
54-
with dctx.stream_reader(fh) as reader:
55-
with tarfile.open(mode="r|", fileobj=reader) as tf:
56-
tf.extractall(prebuild_dir)
59+
60+
def _tar_extract(reader):
61+
with tarfile.open(mode="r|", fileobj=reader) as tf:
62+
tf.extractall(prebuild_dir)
63+
64+
if archive_path.suffix == ".gz":
65+
with gzip.open(archive_path, mode="rb") as reader:
66+
_tar_extract(reader)
67+
else:
68+
assert archive_path.suffix == ".zst"
69+
with open(archive_path, mode="rb") as fh:
70+
dctx = zstandard.ZstdDecompressor()
71+
with dctx.stream_reader(fh) as reader:
72+
_tar_extract(reader)
5773

5874

5975
def load_config(prebuild_dir: Path) -> dict:

src/_pythonscript.pyx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ cdef api void _pythonscript_late_init() with gil:
123123
pythonscript_gdextension.object_method_bind_ptrcall(
124124
bind,
125125
singleton,
126-
args,
126+
# Cast on args is required given autopxd2 incorrectly removes the const
127+
# attributes when converting gdextension_interface.c to .pxd
128+
<const void * const*>args,
127129
NULL,
128130
)
129131

src/godot/classes.pyx.j2

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,9 @@ cdef object _object_call(GDExtensionObjectPtr obj, str meth, args):
189189
pythonscript_gdextension.object_method_bind_call(
190190
Object_call,
191191
classdb,
192-
<GDExtensionVariantPtr *>&variant_args_ptrs,
192+
# Cast is required given autopxd2 incorrectly removes the const attributes
193+
# when converting gdextension_interface.c to .pxd
194+
<const void * const*>&variant_args_ptrs,
193195
args_with_meth_len,
194196
&ret,
195197
&call_error,

src/godot/hazmat/gdapi.pxd.j2

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
cimport cython
3232
from libc.stdint cimport *
33+
from libc.string cimport memset
3334

3435
from .gdextension_interface cimport *
3536
from .gdnative_ptrs cimport *

src/godot/hazmat/gdapi_pxd/meth.pxd.j2

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,20 @@ cdef inline {{ render_utility_function_signature(builtin) }}:
4747
{% if not builtin.return_type.is_stack_only %}
4848
# ptrcall makes us jump right into C++ code (i.e. Godot internals) that expects constructor to be called on each parameter
4949
__ret = {{ builtin.return_type.c_name_prefix }}_new()
50+
{% else %}
51+
# C compiler doesn't like passing to a function a pointer on uninitialized
52+
# data (see `-Wmaybe-uninitialized`).
53+
# Should be optimized out in the end given the called function end up inlined.
54+
memset(&__ret, 0, sizeof(__ret))
5055
{% endif %}
5156
{% endif %}
5257
gd_utility_{{ builtin.original_name }}_ptr(
5358
{# GDExtensionTypePtr ret #}
5459
{{ "NULL" if builtin.return_type.is_nil else "&__ret" }},
5560
{# const GDExtensionTypePtr *p_arguments #}
56-
{{ "NULL" if (builtin.arguments | length) == 0 else "__args" }},
61+
# Cast on args is required given autopxd2 incorrectly removes the const
62+
# attributes when converting gdextension_interface.c to .pxd
63+
<const void *const*>{{ "NULL" if (builtin.arguments | length) == 0 else "__args" }},
5764
{# int p_argument_count #}
5865
{{ builtin.arguments | length }}
5966
)
@@ -70,12 +77,16 @@ cdef inline {{ render_utility_function_signature(builtin) }}:
7077
{# to pass a `gd_variant_t**` as parameter) whose size is passed in the number #}
7178
{# of parameters fields... Yes this is very confusing stuff, my brain hurts ! #}
7279
{% if builtin.return_type.is_nil %}
73-
gd_utility_{{ builtin.original_name }}_ptr(NULL, <GDExtensionTypePtr *>&args, args_count)
80+
# Cast on args is required given autopxd2 incorrectly removes the const
81+
# attributes when converting gdextension_interface.c to .pxd
82+
gd_utility_{{ builtin.original_name }}_ptr(NULL, <const void *const*>&args, args_count)
7483
{% else %}
7584
cdef gd_variant_t __ret # TODO: improve return type !
7685
# ptrcall makes us jump right into C++ code (i.e. Godot internals) that expects constructor to be called on each parameter
7786
__ret = gd_variant_new()
78-
gd_utility_{{ builtin.original_name }}_ptr(&__ret, <GDExtensionTypePtr *>&args, args_count)
87+
# Cast on args is required given autopxd2 incorrectly removes the const
88+
# attributes when converting gdextension_interface.c to .pxd
89+
gd_utility_{{ builtin.original_name }}_ptr(&__ret, <const void *const*>&args, args_count)
7990
return __ret
8091
{% endif %}
8192
{% endmacro %}
@@ -151,7 +162,9 @@ cdef inline {{ render_builtin_constructor_signature(builtin, constructor) }}:
151162
{% endif %}
152163
{{ builtin.c_name_prefix }}_constructor_{{ constructor.index }}_ptr(
153164
&obj,
154-
{{ "NULL" if (constructor.arguments | length) == 0 else "p_args" }}
165+
# Cast is required given autopxd2 incorrectly removes the const attributes
166+
# when converting gdextension_interface.c to .pxd
167+
<const void * const*>{{ "NULL" if (constructor.arguments | length) == 0 else "p_args" }}
155168
)
156169
return obj
157170
{% endmacro %}
@@ -195,13 +208,20 @@ cdef inline {{ render_builtin_method_signature(builtin, meth) }}:
195208
{% if not meth.return_type.is_stack_only %}
196209
# ptrcall makes us jump right into C++ code (i.e. Godot internals) that expects constructor to be called on each parameter
197210
__ret = {{ meth.return_type.c_name_prefix }}_new()
211+
{% else %}
212+
# C compiler doesn't like passing to a function a pointer on uninitialized
213+
# data (see `-Wmaybe-uninitialized`).
214+
# Should be optimized out in the end given the called function end up inlined.
215+
memset(&__ret, 0, sizeof(__ret))
198216
{% endif %}
199217
{% endif %}
200218
{{ builtin.c_name_prefix }}_meth_{{ meth.name }}_ptr(
201219
{# GDExtensionTypePtr p_base #}
202220
self,
203221
{# const GDExtensionTypePtr *__args #}
204-
__args,
222+
# Cast is required given autopxd2 incorrectly removes the const attributes
223+
# when converting gdextension_interface.c to .pxd
224+
<const void * const*>__args,
205225
{# GDExtensionTypePtr __ret #}
206226
{{ "NULL" if meth.return_type.is_nil else "&__ret" }},
207227
{# int p_argument_count #}
@@ -224,6 +244,11 @@ cdef inline {{ m.type.c_type }} {{ builtin.c_name_prefix }}_get_{{ m.name }}({{
224244
{% if not m.type.is_stack_only %}1
225245
# ptrcall makes us jump right into C++ code (i.e. Godot internals) that expects constructor to be called on each parameter
226246
__ret = {{ m.type.c_name_prefix }}_new()
247+
{% else %}
248+
# C compiler doesn't like passing to a function a pointer on uninitialized
249+
# data (see `-Wmaybe-uninitialized`).
250+
# Should be optimized out in the end given the called function end up inlined.
251+
memset(&__ret, 0, sizeof(__ret))
227252
{% endif %}
228253
{{ builtin.c_name_prefix }}_get_{{ m.name }}_ptr(self, &__ret)
229254
return __ret
@@ -250,6 +275,11 @@ cdef inline {{ builtin.indexing_return_type.c_type }} {{ builtin.c_name_prefix }
250275
{% if not builtin.indexing_return_type.is_stack_only %}
251276
# ptrcall makes us jump right into C++ code (i.e. Godot internals) that expects constructor to be called on each parameter
252277
__ret = {{ builtin.indexing_return_type.c_name_prefix }}_new()
278+
{% else %}
279+
# C compiler doesn't like passing to a function a pointer on uninitialized
280+
# data (see `-Wmaybe-uninitialized`).
281+
# Should be optimized out in the end given the called function end up inlined.
282+
memset(&__ret, 0, sizeof(__ret))
253283
{% endif %}
254284
{{ builtin.c_name_prefix }}_indexed_getter_ptr(self, index, &__ret)
255285
return __ret
@@ -277,6 +307,11 @@ cdef inline {{ builtin.indexing_return_type.c_type }} {{ builtin.c_name_prefix }
277307
{% if not builtin.indexing_return_type.is_stack_only %}
278308
# ptrcall makes us jump right into C++ code (i.e. Godot internals) that expects constructor to be called on each parameter
279309
__ret = {{ builtin.indexing_return_type.c_name_prefix }}_new()
310+
{% else %}
311+
# C compiler doesn't like passing to a function a pointer on uninitialized
312+
# data (see `-Wmaybe-uninitialized`).
313+
# Should be optimized out in the end given the called function end up inlined.
314+
memset(&__ret, 0, sizeof(__ret))
280315
{% endif %}
281316
{{ builtin.c_name_prefix }}_keyed_getter_ptr(self, key, &__ret)
282317
return __ret

src/pythonscript.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,12 @@ DLL_EXPORT void pythonscript_gdstringname_new(GDExtensionStringNamePtr ptr, cons
7777
// Method name must be passed as a StringName object... which itself has
7878
// to be built from a String object :(
7979
GDExtensionStringPtr as_gdstring;
80+
const GDExtensionConstTypePtr args[1] = {&as_gdstring};
8081
pythonscript_gdextension->string_new_with_utf8_chars(&as_gdstring, cstr);
81-
gdstringname_constructor(ptr, &as_gdstring);
82+
gdstringname_constructor(ptr, args);
8283
gdstring_destructor(&as_gdstring);
8384
}
85+
8486
DLL_EXPORT void pythonscript_gdstringname_delete(GDExtensionStringNamePtr ptr) {
8587
gdstringname_destructor(ptr);
8688
}

tests/1-cython-access-gdextension/build.py

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,64 @@
22
from pathlib import Path
33
import subprocess
44
import shutil
5-
5+
import zipfile
6+
import tempfile
67

78
PROJECT_DIR = Path(__file__).resolve().parent
89

10+
911
if platform.system() == "Windows":
1012
python_path = PROJECT_DIR / "addons/pythonscript/windows-x86_64/python.exe"
1113
lib_pattern = "my.*.pyd"
1214
elif platform.system() == "Darwin":
13-
python_path = PROJECT_DIR / "addons/pythonscript/macos-x86_64/bin/python"
15+
python_path = PROJECT_DIR / "addons/pythonscript/macos-x86_64/bin/python3"
1416
lib_pattern = "my.*.dylib"
1517
else:
1618
assert platform.system() == "Linux"
17-
python_path = PROJECT_DIR / "addons/pythonscript/linux-x86_64/bin/python"
19+
python_path = PROJECT_DIR / "addons/pythonscript/linux-x86_64/bin/python3"
1820
lib_pattern = "my.*.so"
1921

22+
2023
cmd = [str(python_path), "setup.py", "build_ext", "--build-lib", str(PROJECT_DIR)]
2124
print(" ".join(cmd))
2225
subprocess.check_call(cmd, cwd=PROJECT_DIR)
2326

2427
# Finally remove the platform info from the shared library, this is to avoid
25-
# annoying update everytime we change CPython embedded version
26-
28+
# annoying update everytime we change CPython embedded version.
2729
lib_candidates = list(PROJECT_DIR.glob(lib_pattern))
2830
assert len(lib_candidates) == 1, lib_candidates
2931
lib = lib_candidates[0]
3032
lib_new_name = f"my{lib.suffix}"
3133
print(f"rename {lib.name} -> {lib_new_name}")
3234
shutil.move(lib, lib.parent / lib_new_name)
35+
36+
37+
# with tempfile.TemporaryDirectory() as wheeldir:
38+
39+
# # 1) Build the project into a wheel
40+
# # This is needed to have a build that takes the `pyproject.toml` into account
41+
# # and install the correct build depedencies beforehand.
42+
# cmd = [str(python_path), "-m", "pip", "wheel", "--wheel-dir", wheeldir, "."]
43+
# print(" ".join(cmd))
44+
# subprocess.check_call(cmd, cwd=PROJECT_DIR)
45+
46+
# outputs = list(Path(wheeldir).iterdir())
47+
# if len(outputs) != 1:
48+
# raise RuntimeError(f"Target dir unexpectedly contains multiple or no files: {outputs}")
49+
# wheel_path = outputs[0]
50+
51+
# # 2) Extract the .so from the wheel (only thing we care about).
52+
# with zipfile.ZipFile(wheel_path) as wheel:
53+
# for info in wheel.infolist():
54+
# info.filename.rsplit("/", 1)[-1].startswith("my.")
55+
# wheel.extract(info.filename, path=PROJECT_DIR)
56+
# break
57+
58+
# # 3) Finally remove the platform info from the shared library, this is to avoid
59+
# # annoying update everytime we change CPython embedded version.
60+
# lib_candidates = list(PROJECT_DIR.glob(lib_pattern))
61+
# assert len(lib_candidates) == 1, lib_candidates
62+
# lib = lib_candidates[0]
63+
# lib_new_name = f"my{lib.suffix}"
64+
# print(f"rename {lib.name} -> {lib_new_name}")
65+
# shutil.move(lib, lib.parent / lib_new_name)

tests/1-cython-access-gdextension/my.pyx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ cdef extern GDExtensionBool _my_init(
1919
# print("==> _my_init")
2020
r_initialization.minimum_initialization_level = GDEXTENSION_INITIALIZATION_SERVERS
2121
r_initialization.userdata = NULL
22-
r_initialization.initialize = _my_initialize
23-
r_initialization.deinitialize = _my_deinitialize
22+
# r_initialization.initialize = _my_initialize
23+
# r_initialization.deinitialize = _my_deinitialize
2424
return True
2525

2626

0 commit comments

Comments
 (0)