|
2 | 2 | from distutils.spawn import find_executable
|
3 | 3 | import os
|
4 | 4 | import re
|
| 5 | +import shutil |
5 | 6 | import subprocess
|
6 | 7 | import sys
|
| 8 | +import tempfile |
7 | 9 |
|
8 | 10 | import PyQt5
|
9 | 11 | from PyQt5 import QtCore
|
@@ -111,16 +113,43 @@ def get_sip_dir_flags(config):
|
111 | 113 | if sys.platform == 'win32' and os.path.isdir(sip_bin):
|
112 | 114 | sip_bin += '.exe'
|
113 | 115 |
|
114 |
| -cmd = [ |
115 |
| - sip_bin, |
116 |
| - '-c', build_dir, |
117 |
| - '-b', os.path.join(build_dir, build_file), |
118 |
| - '-I', sip_dir, |
119 |
| - '-w' |
120 |
| -] |
121 |
| -cmd += sip_flags.split(' ') |
122 |
| -cmd.append(sip_file) |
123 |
| -subprocess.check_call(cmd) |
| 116 | +# SIP4 has an incompatibility with Qt 5.15.6. In particular, Qt 5.15.6 uses a new SIP directive |
| 117 | +# called py_ssize_t_clean in QtCoremod.sip that SIP4 does not understand. |
| 118 | +# |
| 119 | +# Unfortunately, the combination of SIP4 and Qt 5.15.6 is common. Archlinux, Ubuntu 22.04 |
| 120 | +# and RHEL-9 all have this combination. On Ubuntu 22.04, there is a custom patch to SIP4 |
| 121 | +# to make it understand the py_ssize_t_clean tag, so the combination works. But on most |
| 122 | +# other platforms, it fails. |
| 123 | +# |
| 124 | +# To workaround this, copy all of the SIP files into a temporary directory, remove the offending |
| 125 | +# line, and then use that temporary directory as the include path. This is unnecessary on |
| 126 | +# Ubuntu 22.04, but shouldn't hurt anything there. |
| 127 | +with tempfile.TemporaryDirectory() as tmpdirname: |
| 128 | + shutil.copytree(sip_dir, tmpdirname, dirs_exist_ok=True) |
| 129 | + |
| 130 | + output = '' |
| 131 | + with open(os.path.join(tmpdirname, 'QtCore', 'QtCoremod.sip'), 'r') as infp: |
| 132 | + for line in infp: |
| 133 | + if line.startswith('%Module(name='): |
| 134 | + result = re.sub(r', py_ssize_t_clean=True', '', line) |
| 135 | + output += result |
| 136 | + else: |
| 137 | + output += line |
| 138 | + |
| 139 | + with open(os.path.join(tmpdirname, 'QtCore', 'QtCoremod.sip'), 'w') as outfp: |
| 140 | + outfp.write(output) |
| 141 | + |
| 142 | + cmd = [ |
| 143 | + sip_bin, |
| 144 | + '-c', build_dir, |
| 145 | + '-b', os.path.join(build_dir, build_file), |
| 146 | + '-I', tmpdirname, |
| 147 | + '-w' |
| 148 | + ] |
| 149 | + cmd += sip_flags.split(' ') |
| 150 | + cmd.append(sip_file) |
| 151 | + |
| 152 | + subprocess.check_call(cmd) |
124 | 153 |
|
125 | 154 | # Create the Makefile. The QtModuleMakefile class provided by the
|
126 | 155 | # pyqtconfig module takes care of all the extra preprocessor, compiler and
|
|
0 commit comments