Release 2.28.7
[pygobject.git] / setup.py
blob74b9141f95474c559c7fc39cb2d3419a7c9e31fd
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
4 # setup.py - distutils configuration for pygobject
7 '''Python Bindings for GObject.
9 PyGObject is a set of bindings for the glib, gobject and gio libraries.
10 It provides an object oriented interface that is slightly higher level than
11 the C one. It automatically does all the type casting and reference
12 counting that you would have to do normally with the C API. You can
13 find out more on the official homepage, http://www.pygtk.org/'''
16 import os
17 import sys
18 import glob
20 from distutils.command.build import build
21 from distutils.command.build_clib import build_clib
22 from distutils.command.build_scripts import build_scripts
23 from distutils.sysconfig import get_python_inc
24 from distutils.extension import Extension
25 from distutils.core import setup
27 from dsextras import GLOBAL_MACROS, GLOBAL_INC, get_m4_define, getoutput, \
28 have_pkgconfig, pkgc_get_libraries, \
29 pkgc_get_library_dirs, pkgc_get_include_dirs, \
30 PkgConfigExtension, TemplateExtension, \
31 BuildExt, InstallLib, InstallData
34 if sys.platform != 'win32':
35 msg = '*' * 68 + '\n'
36 msg += '* Building PyGObject using distutils is only supported on windows. *\n'
37 msg += '* To build PyGObject in a supported way, read the INSTALL file. *\n'
38 msg += '*' * 68
39 raise SystemExit(msg)
41 MIN_PYTHON_VERSION = (2, 6, 0)
43 if sys.version_info[:3] < MIN_PYTHON_VERSION:
44 raise SystemExit('ERROR: Python %s or higher is required, %s found.' % (
45 '.'.join(map(str, MIN_PYTHON_VERSION)),
46 '.'.join(map(str, sys.version_info[:3]))))
48 if not have_pkgconfig():
49 raise SystemExit('ERROR: Could not find pkg-config: '
50 'Please check your PATH environment variable.')
53 PYGTK_SUFFIX = '2.0'
54 PYGTK_SUFFIX_LONG = 'gtk-' + PYGTK_SUFFIX
56 GLIB_REQUIRED = get_m4_define('glib_required_version')
58 MAJOR_VERSION = int(get_m4_define('pygobject_major_version'))
59 MINOR_VERSION = int(get_m4_define('pygobject_minor_version'))
60 MICRO_VERSION = int(get_m4_define('pygobject_micro_version'))
61 VERSION = '%d.%d.%d' % (MAJOR_VERSION, MINOR_VERSION, MICRO_VERSION)
63 GLOBAL_INC += ['gobject']
64 GLOBAL_MACROS += [('PYGOBJECT_MAJOR_VERSION', MAJOR_VERSION),
65 ('PYGOBJECT_MINOR_VERSION', MINOR_VERSION),
66 ('PYGOBJECT_MICRO_VERSION', MICRO_VERSION),
67 ('VERSION', '\\"%s\\"' % VERSION)]
69 BIN_DIR = os.path.join('Scripts')
70 INCLUDE_DIR = os.path.join('include', 'pygtk-%s' % PYGTK_SUFFIX)
71 DEFS_DIR = os.path.join('share', 'pygobject', PYGTK_SUFFIX, 'defs')
72 XSL_DIR = os.path.join('share', 'pygobject','xsl')
73 HTML_DIR = os.path.join('share', 'gtk-doc', 'html', 'pygobject')
76 class PyGObjectInstallLib(InstallLib):
77 def run(self):
78 # Install pygtk.pth, pygtk.py[c] and templates
79 self.install_pth()
80 self.install_pygtk()
82 # Modify the base installation dir
83 install_dir = os.path.join(self.install_dir, PYGTK_SUFFIX_LONG)
84 self.set_install_dir(install_dir)
86 # Install tests
87 self.install_tests()
89 InstallLib.run(self)
91 def install_pth(self):
92 '''Create the pygtk.pth file'''
93 file = os.path.join(self.install_dir, 'pygtk.pth')
94 self.mkpath(self.install_dir)
95 open(file, 'w').write(PYGTK_SUFFIX_LONG)
96 self.local_outputs.append(file)
97 self.local_inputs.append('pygtk.pth')
99 def install_pygtk(self):
100 '''Install pygtk.py in the right place.'''
101 self.copy_file('pygtk.py', self.install_dir)
102 pygtk = os.path.join(self.install_dir, 'pygtk.py')
103 self.byte_compile([pygtk])
104 self.local_outputs.append(pygtk)
105 self.local_inputs.append('pygtk.py')
107 def copy_test(self, srcfile, dstfile=None):
108 if dstfile is None:
109 dstfile = os.path.join(self.test_dir, srcfile)
110 else:
111 dstfile = os.path.join(self.test_dir, dstfile)
113 srcfile = os.path.join('tests', srcfile)
115 self.copy_file(srcfile, os.path.abspath(dstfile))
116 self.local_outputs.append(dstfile)
117 self.local_inputs.append('srcfile')
119 def install_tests(self):
120 self.test_dir = os.path.join(self.install_dir, 'tests', 'pygobject')
121 self.mkpath(self.test_dir)
123 self.copy_test('runtests-windows.py', 'runtests.py')
124 self.copy_test('compathelper.py')
126 for testfile in glob.glob('tests/test*.py'):
127 self.copy_test(os.path.basename(testfile))
130 class PyGObjectInstallData(InstallData):
131 def run(self):
132 self.add_template_option('VERSION', VERSION)
133 self.add_template_option('FFI_LIBS', '')
134 self.add_template_option('LIBFFI_PC', '')
135 self.prepare()
137 # Install templates
138 self.install_templates()
140 InstallData.run(self)
142 def install_templates(self):
143 self.install_template('pygobject-%s.pc.in' % PYGTK_SUFFIX,
144 os.path.join(self.install_dir, 'lib', 'pkgconfig'))
146 self.install_template('docs/xsl/fixxref.py.in',
147 os.path.join(self.install_dir, XSL_DIR))
150 class PyGObjectBuild(build):
151 enable_threading = True
153 PyGObjectBuild.user_options.append(('enable-threading', None,
154 'enable threading support'))
157 class PyGObjectBuildScripts(build_scripts):
159 Overrides distutils' build_script command so we can generate
160 a valid pygobject-codegen script that works on windows.
163 def run(self):
164 self.mkpath(self.build_dir)
165 self.install_codegen_script()
166 build_scripts.run(self)
168 def install_codegen_script(self):
169 '''Create pygobject-codegen'''
170 script = ('#!/bin/sh\n\n'
171 'codegendir=`pkg-config pygobject-%s --variable=codegendir`\n\n'
172 'PYTHONPATH=$codegendir\n'
173 'export PYTHONPATH\n\n'
174 'exec pythonw.exe "$codegendir/codegen.py" "$@"\n' % PYGTK_SUFFIX)
176 outfile = os.path.join(self.build_dir, 'pygobject-codegen-%s' % PYGTK_SUFFIX)
177 open(outfile, 'w').write(script)
180 # glib
181 glib = PkgConfigExtension(name='glib._glib',
182 pkc_name='glib-%s' % PYGTK_SUFFIX,
183 pkc_version=GLIB_REQUIRED,
184 pygobject_pkc=None,
185 include_dirs=['glib'],
186 libraries=['pyglib'],
187 sources=['glib/glibmodule.c',
188 'glib/pygiochannel.c',
189 'glib/pygmaincontext.c',
190 'glib/pygmainloop.c',
191 'glib/pygoptioncontext.c',
192 'glib/pygoptiongroup.c',
193 'glib/pygsource.c',
194 'glib/pygspawn.c',
197 # GObject
198 gobject = PkgConfigExtension(name='gobject._gobject',
199 pkc_name='gobject-%s' % PYGTK_SUFFIX,
200 pkc_version=GLIB_REQUIRED,
201 pygobject_pkc=None,
202 include_dirs=['glib','gi'],
203 libraries=['pyglib'],
204 sources=['gobject/gobjectmodule.c',
205 'gobject/pygboxed.c',
206 'gobject/pygenum.c',
207 'gobject/pygflags.c',
208 'gobject/pyginterface.c',
209 'gobject/pygobject.c',
210 'gobject/pygparamspec.c',
211 'gobject/pygpointer.c',
212 'gobject/pygtype.c',
215 # gio
216 gio = TemplateExtension(name='gio',
217 pkc_name='gio-%s' % PYGTK_SUFFIX,
218 pkc_version=GLIB_REQUIRED,
219 output='gio._gio',
220 defs='gio/gio.defs',
221 include_dirs=['glib'],
222 libraries=['pyglib'],
223 sources=['gio/giomodule.c',
224 'gio/gio.c',
225 'gio/pygio-utils.c'],
226 register=['gio/gio-types.defs'],
227 override='gio/gio.override')
229 clibs = []
230 data_files = []
231 ext_modules = []
233 #Install dsextras and codegen so that the pygtk installer can find them
234 py_modules = ['dsextras']
235 packages = ['codegen']
237 if glib.can_build():
238 #It would have been nice to create another class, such as PkgConfigCLib to
239 #encapsulate this dictionary, but it is impossible. build_clib.py does
240 #a dumb check to see if its only arguments are a 2-tuple containing a
241 #string and a Dictionary type - which makes it impossible to hide behind a
242 #subclass
244 #So we are stuck with this ugly thing
245 clibs.append(('pyglib', {'sources': ['glib/pyglib.c'],
246 'macros': GLOBAL_MACROS,
247 'include_dirs': ['glib', get_python_inc()] +
248 pkgc_get_include_dirs('glib-%s' % PYGTK_SUFFIX)}))
249 #this library is not installed, so probably should not include its header
250 #data_files.append((INCLUDE_DIR, ('glib/pyglib.h',)))
252 ext_modules.append(glib)
253 py_modules += ['glib.__init__', 'glib.option']
254 else:
255 raise SystemExit('ERROR: Nothing to do, glib could not be found and is essential.')
257 if gobject.can_build():
258 ext_modules.append(gobject)
259 data_files.append((INCLUDE_DIR, ('gobject/pygobject.h',)))
260 data_files.append((HTML_DIR, glob.glob('docs/html/*.html')))
261 data_files.append((HTML_DIR, ['docs/style.css']))
262 data_files.append((XSL_DIR, glob.glob('docs/xsl/*.xsl')))
263 py_modules += ['gobject.__init__', 'gobject.propertyhelper', 'gobject.constants']
264 else:
265 raise SystemExit('ERROR: Nothing to do, gobject could not be found and is essential.')
267 if gio.can_build():
268 ext_modules.append(gio)
269 py_modules += ['gio.__init__']
270 data_files.append((DEFS_DIR,('gio/gio.defs', 'gio/gio-types.defs',)))
271 else:
272 raise SystemExit, 'ERROR: Nothing to do, gio could not be found and is essential.'
274 # Build testhelper library
275 testhelper = Extension(name='testhelper',
276 sources=['tests/testhelpermodule.c',
277 'tests/test-floating.c',
278 'tests/test-thread.c',
279 'tests/test-unknown.c'],
280 libraries=['pyglib'] +
281 pkgc_get_libraries('glib-%s' % PYGTK_SUFFIX) +
282 pkgc_get_libraries('gobject-%s' % PYGTK_SUFFIX),
283 include_dirs=['tests', 'glib',
284 'gobject', get_python_inc()] +
285 pkgc_get_include_dirs('glib-%s' % PYGTK_SUFFIX) +
286 pkgc_get_include_dirs('gobject-%s' % PYGTK_SUFFIX),
287 library_dirs=pkgc_get_library_dirs('glib%s' % PYGTK_SUFFIX) +
288 pkgc_get_library_dirs('gobject-%s' % PYGTK_SUFFIX))
290 ext_modules.append(testhelper)
292 # Threading support
293 if '--disable-threading' in sys.argv:
294 sys.argv.remove('--disable-threading')
295 enable_threading = False
296 else:
297 if '--enable-threading' in sys.argv:
298 sys.argv.remove('--enable-threading')
299 try:
300 import thread
301 except ImportError:
302 print ('* Could not import thread module, disabling threading')
303 enable_threading = False
304 else:
305 enable_threading = True
307 if enable_threading:
308 name = 'gthread-%s' % PYGTK_SUFFIX
309 for module in ext_modules:
310 raw = getoutput('pkg-config --libs-only-l %s' % name)
311 for arg in raw.split():
312 if arg.startswith('-l'):
313 module.libraries.append(arg[2:])
314 else:
315 module.extra_link_args.append(arg)
316 raw = getoutput('pkg-config --cflags-only-I %s' % name)
317 for arg in raw.split():
318 if arg.startswith('-I'):
319 module.include_dirs.append(arg[2:])
320 else:
321 module.extra_compile_args.append(arg)
322 else:
323 GLOBAL_MACROS.append(('DISABLE_THREADING', 1))
325 doclines = __doc__.split('\n')
326 options = {'bdist_wininst': {'install_script': 'pygobject_postinstall.py',
327 'user_access_control': 'auto'}}
329 setup(name='pygobject',
330 url='http://www.pygtk.org/',
331 version=VERSION,
332 license='LGPL',
333 platforms=['MS Windows'],
334 maintainer='Johan Dahlin',
335 maintainer_email='johan@gnome.org',
336 description=doclines[0],
337 long_description='\n'.join(doclines[2:]),
338 provides=['codegen', 'dsextras', 'gio', 'glib', 'gobject'],
339 py_modules=py_modules,
340 packages=packages,
341 ext_modules=ext_modules,
342 libraries=clibs,
343 data_files=data_files,
344 scripts=['pygobject_postinstall.py'],
345 options=options,
346 cmdclass={'install_lib': PyGObjectInstallLib,
347 'install_data': PyGObjectInstallData,
348 'build_scripts': PyGObjectBuildScripts,
349 'build_clib' : build_clib,
350 'build_ext': BuildExt,
351 'build': PyGObjectBuild})