-
Notifications
You must be signed in to change notification settings - Fork 53
/
sip_configure.py
178 lines (143 loc) · 5.86 KB
/
sip_configure.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
from copy import copy
from distutils.spawn import find_executable
import os
import re
import subprocess
import sys
import sipconfig
from PyQt5 import QtCore
class Configuration(sipconfig.Configuration):
def __init__(self):
env = copy(os.environ)
env['QT_SELECT'] = '5'
qmake_exe = 'qmake-qt5' if find_executable('qmake-qt5') else 'qmake'
qtconfig = subprocess.check_output(
[qmake_exe, '-query'], env=env, universal_newlines=True)
qtconfig = dict(line.split(':', 1) for line in qtconfig.splitlines())
pyqtconfig = {
'qt_archdata_dir': qtconfig['QT_INSTALL_DATA'],
'qt_data_dir': qtconfig['QT_INSTALL_DATA'],
'qt_dir': qtconfig['QT_INSTALL_PREFIX'],
'qt_inc_dir': qtconfig['QT_INSTALL_HEADERS'],
'qt_lib_dir': qtconfig['QT_INSTALL_LIBS'],
'qt_threaded': 1,
'qt_version': QtCore.QT_VERSION,
'qt_winconfig': 'shared exceptions',
}
if sys.platform == 'darwin':
pyqtconfig['qt_framework'] = 1
sipconfig.Configuration.__init__(self, [pyqtconfig])
macros = sipconfig._default_macros.copy()
macros['INCDIR_QT'] = qtconfig['QT_INSTALL_HEADERS']
macros['LIBDIR_QT'] = qtconfig['QT_INSTALL_LIBS']
macros['MOC'] = 'moc-qt5'
self.set_build_macros(macros)
def get_sip_dir_flags(config):
"""
Get the extra SIP flags needed by the imported qt module, and locate PyQt5 sip install files.
Note that this normally only includes those flags (-x and -t) that relate to SIP's versioning
system.
"""
try:
sip_dir = config.pyqt_sip_dir
sip_flags = config.pyqt_sip_flags
return sip_dir, sip_flags
except AttributeError:
# sipconfig.Configuration does not have a pyqt_sip_dir or pyqt_sip_flags AttributeError
sip_flags = QtCore.PYQT_CONFIGURATION['sip_flags']
default_sip_dir = os.path.join(sipconfig._pkg_config['default_sip_dir'], 'PyQt5')
if os.path.exists(default_sip_dir):
return default_sip_dir, sip_flags
# Homebrew installs sip files here by default
default_sip_dir = os.path.join(sipconfig._pkg_config['default_sip_dir'], 'Qt5')
if os.path.exists(default_sip_dir):
return default_sip_dir, sip_flags
raise FileNotFoundError('The sip directory for PyQt5 could not be located. Please ensure' +
' that PyQt5 is installed')
if len(sys.argv) != 8:
print('usage: %s build-dir sip-file output_dir include_dirs libs lib_dirs ldflags' %
sys.argv[0])
sys.exit(1)
# The SIP build folder, the SIP file, the output directory, the include
# directories, the libraries, the library directories and the linker
# flags.
build_dir, sip_file, output_dir, include_dirs, libs, lib_dirs, ldflags = sys.argv[1:]
# The name of the SIP build file generated by SIP and used by the build system.
build_file = 'pyqtscripting.sbf'
# Get the PyQt configuration information.
config = Configuration()
sip_dir, sip_flags = get_sip_dir_flags(config)
try:
os.makedirs(build_dir)
except OSError:
pass
# Run SIP to generate the code. Note that we tell SIP where to find the qt
# module's specification files using the -I flag.
sip_bin = config.sip_bin
# Without the .exe, this might actually be a directory in Windows
if sys.platform == 'win32' and os.path.isdir(sip_bin):
sip_bin += '.exe'
cmd = [
sip_bin,
'-c', build_dir,
'-b', os.path.join(build_dir, build_file),
'-I', sip_dir,
'-w'
]
cmd += sip_flags.split(' ')
cmd.append(sip_file)
subprocess.check_call(cmd)
# Create the Makefile. The QtModuleMakefile class provided by the
# pyqtconfig module takes care of all the extra preprocessor, compiler and
# linker flags needed by the Qt library.
makefile = sipconfig.SIPModuleMakefile(
dir=build_dir,
configuration=config,
build_file=build_file,
qt=['QtCore', 'QtGui']
)
# hack to override makefile behavior which always prepend -l to libraries
# which is wrong for absolute paths
default_platform_lib_function = sipconfig.SIPModuleMakefile.platform_lib
def custom_platform_lib_function(self, clib, framework=0):
if not clib or clib.isspace():
return None
# Only add '-l' if a library doesn't already start with '-l' and is not an absolute path
if os.path.isabs(clib) or clib.startswith('-l'):
return clib
return default_platform_lib_function(self, clib, framework)
sipconfig.SIPModuleMakefile.platform_lib = custom_platform_lib_function
# split paths on whitespace
# while dealing with whitespaces within the paths if they are escaped with backslashes
def split_paths(paths):
paths = re.split('(?<=[^\\\\]) ', paths)
return paths
for include_dir in split_paths(include_dirs):
include_dir = include_dir.replace('\\', '')
makefile.extra_include_dirs.append(include_dir)
for lib in split_paths(libs):
makefile.extra_libs.append(lib)
for lib_dir in split_paths(lib_dirs):
lib_dir = lib_dir.replace('\\', '')
makefile.extra_lib_dirs.append(lib_dir)
for ldflag in ldflags.split('\\ '):
makefile.LFLAGS.append(ldflag)
# redirect location of generated library
makefile._target = '"%s"' % os.path.join(output_dir, makefile._target)
# Force c++14
if sys.platform == 'win32':
makefile.extra_cxxflags.append('/std:c++14')
# The __cplusplus flag is not properly set on Windows for backwards
# compatibilty. This flag sets it correctly
makefile.CXXFLAGS.append('/Zc:__cplusplus')
else:
makefile.extra_cxxflags.append('-std=c++14')
# Finalise the Makefile, preparing it to be saved to disk
makefile.finalise()
# Replace Qt variables from libraries
libs = makefile.LIBS.as_list()
for i in range(len(libs)):
libs[i] = libs[i].replace('$$[QT_INSTALL_LIBS]', config.build_macros()['LIBDIR_QT'])
makefile.LIBS.set(libs)
# Generate the Makefile itself
makefile.generate()