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


python_qt_binding
Author(s): Dave Hershberger, Dorian Scholz, Dirk Thomas
autogenerated on Mon Feb 28 2022 23:17:55