1
1
#!/usr/bin/env python3
2
2
#
3
- # Copyright 2015-2021 the openage authors. See copying.md for legal info.
3
+ # Copyright 2015-2025 the openage authors. See copying.md for legal info.
4
4
5
5
"""
6
6
Runs Cython on all modules that were listed via add_cython_module.
@@ -73,7 +73,7 @@ def remove_if_exists(filename):
73
73
filename .unlink ()
74
74
75
75
76
- def cythonize_wrapper (modules , ** kwargs ):
76
+ def cythonize_wrapper (modules , force_optimized_lib = False , ** kwargs ):
77
77
""" Calls cythonize, filtering useless warnings """
78
78
bin_dir , bin_modules = kwargs ['build_dir' ], []
79
79
src_dir , src_modules = Path .cwd (), []
@@ -88,13 +88,59 @@ def cythonize_wrapper(modules, **kwargs):
88
88
with redirect_stdout (cython_filter ):
89
89
if src_modules :
90
90
cythonize (src_modules , ** kwargs )
91
+ if sys .platform == 'win32' and force_optimized_lib :
92
+ win_use_optimized_lib_python (src_modules , bin_dir )
91
93
92
94
if bin_modules :
93
95
os .chdir (bin_dir )
94
96
cythonize (bin_modules , ** kwargs )
97
+ if sys .platform == 'win32' and force_optimized_lib :
98
+ win_use_optimized_lib_python (bin_modules , bin_dir )
95
99
os .chdir (src_dir )
96
100
97
101
102
+ def win_use_optimized_lib_python (modules , path ):
103
+ """
104
+ Add an #ifdef statement in cythonized .cpp files to temporarily undefine _DEBUG before
105
+ #include "Python.h"
106
+
107
+ This function modifies the generated C++ files from Cython to prevent linking to
108
+ the debug version of the Python library on Windows. The debug version of the
109
+ Python library cannot import Python libraries that contain extension modules.
110
+ see: https://github.com/python/cpython/issues/127619 (To unserstand the problem)
111
+ see: https://stackoverflow.com/a/59566420 (To understand the soloution)
112
+ """
113
+
114
+ for module in modules :
115
+ module = str (module )
116
+ if path :
117
+ module = path + "\\ " + module
118
+ module = module .removesuffix (".py" ).removesuffix (".pyx" )
119
+ module = module + ".cpp"
120
+ with open (module , "r" , encoding = 'utf8' ) as file :
121
+ text = file .read ()
122
+ if not text .count ("OPENAGE: UNDEF_DEBUG_INSERTED" ):
123
+ text = text .replace (
124
+ '#include "Python.h"' ,
125
+ (
126
+ "\n \n // OPENAGE: UNDEF_DEBUG_INSERTED\n "
127
+ "// Avoid linking to the debug version of the Python library on Windows\n \n "
128
+ "#ifdef _DEBUG\n "
129
+ "#define _DEBUG_WAS_DEFINED\n "
130
+ "#undef _DEBUG\n #endif\n "
131
+ "#include \" Python.h\" \n "
132
+ "#ifdef _DEBUG_WAS_DEFINED\n "
133
+ "#define _DEBUG\n "
134
+ "#undef _DEBUG_WAS_DEFINED\n "
135
+ "#endif\n \n "
136
+ "// OPENAGE: UNDEF_DEBUG_INSERTED\n \n "
137
+ ),
138
+ 1
139
+ )
140
+ with open (module , "w" , encoding = 'utf8' ) as file :
141
+ file .write (text )
142
+
143
+
98
144
def main ():
99
145
""" CLI entry point """
100
146
cli = argparse .ArgumentParser ()
@@ -125,6 +171,8 @@ def main():
125
171
))
126
172
cli .add_argument ("--threads" , type = int , default = cpu_count (),
127
173
help = "number of compilation threads to use" )
174
+ cli .add_argument ("--force_optimized_lib" , action = "store_true" ,
175
+ help = "edit compiled .cpp files to link to optimized version of python libary" )
128
176
args = cli .parse_args ()
129
177
130
178
# cython emits warnings on using absolute paths to modules
@@ -159,12 +207,12 @@ def main():
159
207
# writing funny lines at the head of each file.
160
208
cythonize_args ['language' ] = 'c++'
161
209
162
- cythonize_wrapper (modules , ** cythonize_args )
210
+ cythonize_wrapper (modules , args . force_optimized_lib , ** cythonize_args )
163
211
164
212
# build standalone executables that embed the py interpreter
165
213
Options .embed = "main"
166
214
167
- cythonize_wrapper (embedded_modules , ** cythonize_args )
215
+ cythonize_wrapper (embedded_modules , args . force_optimized_lib , ** cythonize_args )
168
216
169
217
# verify depends
170
218
from Cython .Build .Dependencies import _dep_tree
0 commit comments