Branch and push for 2.0
[profile/ivi/pygobject2.git] / setup.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 #
4 # setup.py - distutils configuration for pygobject
5
6
7 '''Python Bindings for GObject.
8
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/'''
14
15
16 import os
17 import sys
18 import glob
19
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
26
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
32
33
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)
40
41 MIN_PYTHON_VERSION = (2, 6, 0)
42
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]))))
47
48 if not have_pkgconfig():
49     raise SystemExit('ERROR: Could not find pkg-config: '
50                      'Please check your PATH environment variable.')
51
52
53 PYGTK_SUFFIX = '2.0'
54 PYGTK_SUFFIX_LONG = 'gtk-' + PYGTK_SUFFIX
55
56 GLIB_REQUIRED = get_m4_define('glib_required_version')
57
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)
62
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)]
68
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')
74
75
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()
81
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)
85
86         # Install tests
87         self.install_tests()
88
89         InstallLib.run(self)
90
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')
98
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')
106
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)
112
113         srcfile = os.path.join('tests', srcfile)
114
115         self.copy_file(srcfile, os.path.abspath(dstfile))
116         self.local_outputs.append(dstfile)
117         self.local_inputs.append('srcfile')
118
119     def install_tests(self):
120         self.test_dir = os.path.join(self.install_dir, 'tests', 'pygobject')
121         self.mkpath(self.test_dir)
122
123         self.copy_test('runtests-windows.py', 'runtests.py')
124         self.copy_test('compathelper.py')
125
126         for testfile in glob.glob('tests/test*.py'):
127             self.copy_test(os.path.basename(testfile))
128
129
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()
136
137         # Install templates
138         self.install_templates()
139
140         InstallData.run(self)
141
142     def install_templates(self):
143         self.install_template('pygobject-%s.pc.in' % PYGTK_SUFFIX,
144                               os.path.join(self.install_dir, 'lib', 'pkgconfig'))
145
146         self.install_template('docs/xsl/fixxref.py.in',
147                               os.path.join(self.install_dir, XSL_DIR))
148
149
150 class PyGObjectBuild(build):
151     enable_threading = True
152
153 PyGObjectBuild.user_options.append(('enable-threading', None,
154                                     'enable threading support'))
155
156
157 class PyGObjectBuildScripts(build_scripts):
158     '''
159     Overrides distutils' build_script command so we can generate
160     a valid pygobject-codegen script that works on windows.
161     '''
162
163     def run(self):
164         self.mkpath(self.build_dir)
165         self.install_codegen_script()
166         build_scripts.run(self)
167
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)
175
176         outfile = os.path.join(self.build_dir, 'pygobject-codegen-%s' % PYGTK_SUFFIX)
177         open(outfile, 'w').write(script)
178
179
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',
195                                    ])
196
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',
213                                       ])
214
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')
228
229 clibs = []
230 data_files = []
231 ext_modules = []
232
233 #Install dsextras and codegen so that the pygtk installer can find them
234 py_modules = ['dsextras']
235 packages = ['codegen']
236
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
243     #
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',)))
251
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.')
256
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.')
266
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.'
273
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))
289
290 ext_modules.append(testhelper)
291
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
306
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))
324
325 doclines = __doc__.split('\n')
326 options = {'bdist_wininst': {'install_script': 'pygobject_postinstall.py',
327                              'user_access_control': 'auto'}}
328
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})