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/'''
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':
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'
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.')
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
):
78 # Install pygtk.pth, pygtk.py[c] and templates
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
)
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):
109 dstfile
= os
.path
.join(self
.test_dir
, srcfile
)
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
):
132 self
.add_template_option('VERSION', VERSION
)
133 self
.add_template_option('FFI_LIBS', '')
134 self
.add_template_option('LIBFFI_PC', '')
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.
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
)
181 glib
= PkgConfigExtension(name
='glib._glib',
182 pkc_name
='glib-%s' % PYGTK_SUFFIX
,
183 pkc_version
=GLIB_REQUIRED
,
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',
198 gobject
= PkgConfigExtension(name
='gobject._gobject',
199 pkc_name
='gobject-%s' % PYGTK_SUFFIX
,
200 pkc_version
=GLIB_REQUIRED
,
202 include_dirs
=['glib','gi'],
203 libraries
=['pyglib'],
204 sources
=['gobject/gobjectmodule.c',
205 'gobject/pygboxed.c',
207 'gobject/pygflags.c',
208 'gobject/pyginterface.c',
209 'gobject/pygobject.c',
210 'gobject/pygparamspec.c',
211 'gobject/pygpointer.c',
216 gio
= TemplateExtension(name
='gio',
217 pkc_name
='gio-%s' % PYGTK_SUFFIX
,
218 pkc_version
=GLIB_REQUIRED
,
221 include_dirs
=['glib'],
222 libraries
=['pyglib'],
223 sources
=['gio/giomodule.c',
225 'gio/pygio-utils.c'],
226 register
=['gio/gio-types.defs'],
227 override
='gio/gio.override')
233 #Install dsextras and codegen so that the pygtk installer can find them
234 py_modules
= ['dsextras']
235 packages
= ['codegen']
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
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']
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']
265 raise SystemExit('ERROR: Nothing to do, gobject could not be found and is essential.')
268 ext_modules
.append(gio
)
269 py_modules
+= ['gio.__init__']
270 data_files
.append((DEFS_DIR
,('gio/gio.defs', 'gio/gio-types.defs',)))
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
)
293 if '--disable-threading' in sys
.argv
:
294 sys
.argv
.remove('--disable-threading')
295 enable_threading
= False
297 if '--enable-threading' in sys
.argv
:
298 sys
.argv
.remove('--enable-threading')
302 print ('* Could not import thread module, disabling threading')
303 enable_threading
= False
305 enable_threading
= True
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:])
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:])
321 module
.extra_compile_args
.append(arg
)
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/',
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
,
341 ext_modules
=ext_modules
,
343 data_files
=data_files
,
344 scripts
=['pygobject_postinstall.py'],
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
})