1 # -*- coding: utf-8 -*-
3 # WAF build script - this file is part of Geany, a fast and lightweight IDE
5 # Copyright 2008-2011 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
6 # Copyright 2008-2011 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software
20 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 This is a WAF build script (http://code.google.com/p/waf/).
24 It can be used as an alternative build system to autotools
25 for Geany. It does not (yet) cover all of the autotools tests and
26 configure options but all important things are working.
27 "make dist" should be done with autotools, most other targets and
28 functions should work better (regarding performance and flexibility)
31 Missing features: --enable-binreloc, make targets: dist, pdf (in doc/)
32 Known issues: Dependency handling is buggy, e.g. if src/document.h is
33 changed, depending source files are not rebuilt (maybe Waf bug).
35 The code of this file itself loosely follows PEP 8 with some exceptions
36 (line width 100 characters and some other minor things).
38 Requires WAF 1.6.1 and Python 2.5 (or later).
45 from waflib import Logs, Options, Scripting, Utils
46 from waflib.Configure import ConfigurationContext
47 from waflib.Errors import ConfigurationError, WafError
48 from waflib.TaskGen import feature
53 LINGUAS_FILE = 'po/LINGUAS'
59 mio_sources = set(['tagmanager/mio/mio.c'])
61 tagmanager_sources = set([
62 'tagmanager/args.c', 'tagmanager/abc.c', 'tagmanager/actionscript.c', 'tagmanager/asm.c',
63 'tagmanager/basic.c', 'tagmanager/c.c', 'tagmanager/cobol.c',
64 'tagmanager/conf.c', 'tagmanager/css.c', 'tagmanager/ctags.c', 'tagmanager/diff.c',
65 'tagmanager/docbook.c', 'tagmanager/entry.c', 'tagmanager/fortran.c', 'tagmanager/get.c',
66 'tagmanager/haskell.c', 'tagmanager/haxe.c', 'tagmanager/html.c', 'tagmanager/js.c',
67 'tagmanager/keyword.c', 'tagmanager/latex.c', 'tagmanager/lregex.c', 'tagmanager/lua.c',
68 'tagmanager/make.c', 'tagmanager/markdown.c', 'tagmanager/matlab.c', 'tagmanager/nsis.c',
69 'tagmanager/nestlevel.c', 'tagmanager/objc.c', 'tagmanager/options.c',
70 'tagmanager/parse.c', 'tagmanager/pascal.c', 'tagmanager/r.c',
71 'tagmanager/perl.c', 'tagmanager/php.c', 'tagmanager/python.c', 'tagmanager/read.c',
72 'tagmanager/rest.c', 'tagmanager/ruby.c', 'tagmanager/sh.c', 'tagmanager/sort.c',
73 'tagmanager/sql.c', 'tagmanager/strlist.c', 'tagmanager/txt2tags.c', 'tagmanager/tcl.c',
74 'tagmanager/tm_file_entry.c',
75 'tagmanager/tm_project.c', 'tagmanager/tm_source_file.c', 'tagmanager/tm_symbol.c',
76 'tagmanager/tm_tag.c', 'tagmanager/tm_tagmanager.c', 'tagmanager/tm_work_object.c',
77 'tagmanager/tm_workspace.c', 'tagmanager/vhdl.c', 'tagmanager/verilog.c', 'tagmanager/vstring.c'])
79 scintilla_sources = set(['scintilla/gtk/scintilla-marshal.c'])
82 'src/about.c', 'src/build.c', 'src/callbacks.c', 'src/dialogs.c', 'src/document.c',
83 'src/editor.c', 'src/encodings.c', 'src/filetypes.c', 'src/geanyentryaction.c',
84 'src/geanymenubuttonaction.c', 'src/geanyobject.c', 'src/geanywraplabel.c',
85 'src/highlighting.c', 'src/keybindings.c',
86 'src/keyfile.c', 'src/log.c', 'src/main.c', 'src/msgwindow.c', 'src/navqueue.c', 'src/notebook.c',
87 'src/plugins.c', 'src/pluginutils.c', 'src/prefix.c', 'src/prefs.c', 'src/printing.c', 'src/project.c',
88 'src/sciwrappers.c', 'src/search.c', 'src/socket.c', 'src/stash.c',
90 'src/templates.c', 'src/toolbar.c', 'src/tools.c', 'src/sidebar.c',
91 'src/ui_utils.c', 'src/utils.c'])
97 conf.check_waf_version(mini='1.6.1')
99 conf.load('compiler_c')
100 is_win32 = _target_is_win32(conf)
102 conf.check_cc(header_name='fcntl.h', mandatory=False)
103 conf.check_cc(header_name='fnmatch.h', mandatory=False)
104 conf.check_cc(header_name='glob.h', mandatory=False)
105 conf.check_cc(header_name='sys/time.h', mandatory=False)
106 conf.check_cc(header_name='sys/types.h', mandatory=False)
107 conf.check_cc(header_name='sys/stat.h', mandatory=False)
108 conf.define('HAVE_STDLIB_H', 1) # are there systems without stdlib.h?
109 conf.define('STDC_HEADERS', 1) # an optimistic guess ;-)
110 _add_to_env_and_define(conf, 'HAVE_REGCOMP', 1) # needed for CTags
112 conf.check_cc(function_name='fgetpos', header_name='stdio.h', mandatory=False)
113 conf.check_cc(function_name='ftruncate', header_name='unistd.h', mandatory=False)
114 conf.check_cc(function_name='gethostname', header_name='unistd.h', mandatory=False)
115 conf.check_cc(function_name='mkstemp', header_name='stdlib.h', mandatory=False)
116 conf.check_cc(function_name='strstr', header_name='string.h')
118 # check sunOS socket support
119 if Options.platform == 'sunos':
120 conf.check_cc(function_name='socket', lib='socket',
121 header_name='sys/socket.h', uselib_store='SUNOS_SOCKET', mandatory=True)
123 # check for cxx after the header and function checks have been done to ensure they are
124 # checked with cc not cxx
125 conf.load('compiler_cxx')
128 _load_intltool_if_available(conf)
130 # GTK / GIO version check
131 conf.check_cfg(package='gtk+-2.0', atleast_version='2.16.0', uselib_store='GTK',
132 mandatory=True, args='--cflags --libs')
133 conf.check_cfg(package='glib-2.0', atleast_version='2.20.0', uselib_store='GLIB',
134 mandatory=True, args='--cflags --libs')
135 conf.check_cfg(package='gmodule-2.0', uselib_store='GMODULE',
136 mandatory=True, args='--cflags --libs')
137 conf.check_cfg(package='gio-2.0', uselib_store='GIO', args='--cflags --libs', mandatory=True)
138 gtk_version = conf.check_cfg(modversion='gtk+-2.0', uselib_store='GTK') or 'Unknown'
139 conf.check_cfg(package='gthread-2.0', uselib_store='GTHREAD', args='--cflags --libs')
143 if conf.env['PREFIX'].lower() == tempfile.gettempdir().lower():
144 # overwrite default prefix on Windows (tempfile.gettempdir() is the Waf default)
145 new_prefix = os.path.join(str(conf.root), '%s-%s' % (APPNAME, VERSION))
146 _add_to_env_and_define(conf, 'PREFIX', new_prefix, quote=True)
147 _add_to_env_and_define(conf, 'BINDIR', os.path.join(new_prefix, 'bin'), quote=True)
148 _add_to_env_and_define(conf, 'DOCDIR', os.path.join(conf.env['PREFIX'], 'doc'), quote=True)
149 _add_to_env_and_define(conf, 'LIBDIR', conf.env['PREFIX'], quote=True)
150 conf.define('LOCALEDIR', os.path.join('share' 'locale'), quote=True)
151 # overwrite LOCALEDIR to install message catalogues properly
152 conf.env['LOCALEDIR'] = os.path.join(conf.env['PREFIX'], 'share/locale')
153 # DATADIR is defined in objidl.h, so we remove it from config.h but keep it in env
154 conf.undefine('DATADIR')
155 conf.env['DATADIR'] = os.path.join(conf.env['PREFIX'], 'data')
156 conf.env.append_value('LINKFLAGS_cprogram', ['-mwindows'])
157 conf.env.append_value('LIB_WIN32', ['wsock32', 'uuid', 'ole32', 'iberty'])
159 conf.env['cshlib_PATTERN'] = '%s.so'
160 # DATADIR and LOCALEDIR are defined by the intltool tool
161 # but they are not added to the environment, so we need to
162 _add_define_to_env(conf, 'DATADIR')
163 _add_define_to_env(conf, 'LOCALEDIR')
164 docdir = os.path.join(conf.env['DATADIR'], 'doc', 'geany')
165 libdir = os.path.join(conf.env['PREFIX'], 'lib')
166 mandir = os.path.join(conf.env['DATADIR'], 'man')
167 _define_from_opt(conf, 'DOCDIR', conf.options.docdir, docdir)
168 _define_from_opt(conf, 'LIBDIR', conf.options.libdir, libdir)
169 _define_from_opt(conf, 'MANDIR', conf.options.mandir, mandir)
171 revision = _get_git_rev(conf)
173 conf.define('ENABLE_NLS', 1)
174 conf.define('GEANY_LOCALEDIR', '' if is_win32 else conf.env['LOCALEDIR'], quote=True)
175 conf.define('GEANY_DATADIR', 'data' if is_win32 else conf.env['DATADIR'], quote=True)
176 conf.define('GEANY_DOCDIR', conf.env['DOCDIR'], quote=True)
177 conf.define('GEANY_LIBDIR', '' if is_win32 else conf.env['LIBDIR'], quote=True)
178 conf.define('GEANY_PREFIX', '' if is_win32 else conf.env['PREFIX'], quote=True)
179 conf.define('PACKAGE', APPNAME, quote=True)
180 conf.define('VERSION', VERSION, quote=True)
181 conf.define('REVISION', revision or '-1', quote=True)
183 conf.define('GETTEXT_PACKAGE', APPNAME, quote=True)
187 conf.options.no_vte = True
189 _define_from_opt(conf, 'HAVE_PLUGINS', not conf.options.no_plugins, None)
190 _define_from_opt(conf, 'HAVE_SOCKET', not conf.options.no_socket, None)
191 _define_from_opt(conf, 'HAVE_VTE', not conf.options.no_vte, None)
193 conf.write_config_header('config.h', remove=False)
195 # some more compiler flags
196 conf.env.append_value('CFLAGS', ['-DHAVE_CONFIG_H'])
197 if revision is not None:
198 conf.env.append_value('CFLAGS', ['-g', '-DGEANY_DEBUG'])
200 conf.env.append_value('CFLAGS', ['-DGTK'])
201 conf.env.append_value('CXXFLAGS',
202 ['-DNDEBUG', '-DGTK', '-DSCI_LEXER', '-DG_THREADS_IMPL_NONE'])
205 Logs.pprint('BLUE', 'Summary:')
206 conf.msg('Install Geany ' + VERSION + ' in', conf.env['PREFIX'])
207 conf.msg('Using GTK version', gtk_version)
208 conf.msg('Build with plugin support', conf.options.no_plugins and 'no' or 'yes')
209 conf.msg('Use virtual terminal support', conf.options.no_vte and 'no' or 'yes')
210 if revision is not None:
211 conf.msg('Compiling Git revision', revision)
215 opt.tool_options('compiler_cc')
216 opt.tool_options('compiler_cxx')
217 opt.tool_options('intltool')
220 opt.add_option('--disable-plugins', action='store_true', default=False,
221 help='compile without plugin support [default: No]', dest='no_plugins')
222 opt.add_option('--disable-socket', action='store_true', default=False,
223 help='compile without support to detect a running instance [[default: No]',
225 opt.add_option('--disable-vte', action='store_true', default=False,
226 help='compile without support for an embedded virtual terminal [[default: No]',
229 opt.add_option('--mandir', type='string', default='',
230 help='man documentation', dest='mandir')
231 opt.add_option('--docdir', type='string', default='',
232 help='documentation root', dest='docdir')
233 opt.add_option('--libdir', type='string', default='',
234 help='object code libraries', dest='libdir')
236 opt.add_option('--hackingdoc', action='store_true', default=False,
237 help='generate HTML documentation from HACKING file', dest='hackingdoc')
241 is_win32 = _target_is_win32(bld)
243 if bld.cmd == 'clean':
244 _remove_linguas_file()
245 if bld.cmd in ('install', 'uninstall'):
246 bld.add_post_fun(_post_install)
248 def build_plugin(plugin_name, install=True):
250 instpath = '${PREFIX}/lib' if is_win32 else '${LIBDIR}/geany'
255 features = ['c', 'cshlib'],
256 source = 'plugins/%s.c' % plugin_name,
257 includes = ['.', 'src/', 'scintilla/include', 'tagmanager/include'],
258 defines = 'G_LOG_DOMAIN="%s"' % plugin_name,
259 target = plugin_name,
260 uselib = ['GTK', 'GLIB', 'GMODULE'],
261 install_path = instpath)
266 features = ['c', 'cstlib'],
267 source = tagmanager_sources,
269 target = 'tagmanager',
270 includes = ['.', 'tagmanager', 'tagmanager/include'],
271 defines = 'G_LOG_DOMAIN="Tagmanager"',
272 uselib = ['GTK', 'GLIB'],
273 install_path = None) # do not install this library
278 features = ['c', 'cstlib'],
279 source = mio_sources,
282 includes = ['.', 'tagmanager/mio/'],
283 defines = 'G_LOG_DOMAIN="MIO"',
284 uselib = ['GTK', 'GLIB'],
285 install_path = None) # do not install this library
289 files = bld.srcnode.ant_glob('scintilla/**/*.cxx', src=True, dir=False)
290 scintilla_sources.update(files)
292 features = ['c', 'cxx', 'cxxstlib'],
294 target = 'scintilla',
295 source = scintilla_sources,
296 includes = ['.', 'scintilla/include', 'scintilla/src', 'scintilla/lexlib'],
297 uselib = ['GTK', 'GLIB', 'GMODULE'],
298 install_path = None) # do not install this library
302 if bld.env['HAVE_VTE'] == 1:
303 geany_sources.add('src/vte.c')
305 geany_sources.add('src/win32.c')
306 geany_sources.add('geany_private.rc')
309 features = ['c', 'cxx', 'cprogram'],
312 source = geany_sources,
313 includes = ['.', 'scintilla/include/', 'tagmanager/include/'],
314 defines = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
315 linkflags = [] if is_win32 else ['-Wl,--export-dynamic'],
316 uselib = ['GTK', 'GLIB', 'GMODULE', 'GIO', 'GTHREAD', 'WIN32', 'SUNOS_SOCKET'],
317 use = ['scintilla', 'tagmanager', 'mio'])
321 source = ['plugins/genapi.py', 'src/plugins.c'],
322 name = 'geanyfunctions.h',
323 before = ['c', 'cxx'],
324 cwd = '%s/plugins' % bld.path.abspath(),
325 rule = 'python genapi.py -q')
328 if bld.env['HAVE_PLUGINS'] == 1:
329 build_plugin('classbuilder')
330 build_plugin('demoplugin', False)
331 build_plugin('export')
332 build_plugin('filebrowser')
333 build_plugin('htmlchars')
334 build_plugin('saveactions')
335 build_plugin('splitwindow')
338 if bld.env['INTLTOOL']:
340 features = ['linguas', 'intltool_po'],
342 install_path = '${LOCALEDIR}',
347 source = 'geany.pc.in',
348 dct = {'VERSION' : VERSION,
349 'prefix': bld.env['PREFIX'],
350 'exec_prefix': '${prefix}',
351 'libdir': '${exec_prefix}/lib',
352 'includedir': '${prefix}/include',
353 'datarootdir': '${prefix}/share',
354 'datadir': '${datarootdir}',
355 'localedir': '${datarootdir}/locale'})
359 if bld.env['INTLTOOL']:
361 features = 'intltool_in',
362 source = 'geany.desktop.in',
363 flags = [ '-d', '-q', '-u', '-c' ],
364 install_path = '${DATADIR}/applications')
369 source = 'doc/geany.1.in',
371 dct = {'VERSION' : VERSION,
372 'GEANY_DATA_DIR': bld.env['DATADIR'] + '/geany'},
373 install_path = '${MANDIR}/man1')
378 source = 'geany.spec.in',
379 target = 'geany.spec',
381 dct = {'VERSION' : VERSION})
386 source = 'doc/Doxyfile.in',
387 target = 'doc/Doxyfile',
389 dct = {'VERSION' : VERSION})
396 bld.install_files('${PREFIX}/include/geany', '''
397 src/document.h src/editor.h src/encodings.h src/filetypes.h src/geany.h
398 src/highlighting.h src/keybindings.h src/msgwindow.h src/plugindata.h
399 src/prefs.h src/project.h src/search.h src/stash.h src/support.h
400 src/templates.h src/toolbar.h src/ui_utils.h src/utils.h src/build.h
401 plugins/geanyplugin.h plugins/geanyfunctions.h''')
402 bld.install_files('${PREFIX}/include/geany/scintilla', '''
403 scintilla/include/SciLexer.h scintilla/include/Scintilla.h
404 scintilla/include/Scintilla.iface scintilla/include/ScintillaWidget.h ''')
405 bld.install_files('${PREFIX}/include/geany/tagmanager', '''
406 tagmanager/include/tm_file_entry.h tagmanager/include/tm_project.h
407 tagmanager/include/tm_source_file.h
408 tagmanager/include/tm_symbol.h tagmanager/include/tm_tag.h
409 tagmanager/include/tm_tagmanager.h tagmanager/include/tm_work_object.h
410 tagmanager/include/tm_workspace.h ''')
412 base_dir = '${PREFIX}' if is_win32 else '${DOCDIR}'
413 ext = '.txt' if is_win32 else ''
414 html_dir = '' if is_win32 else 'html/'
415 html_name = 'Manual.html' if is_win32 else 'index.html'
416 for filename in 'AUTHORS ChangeLog COPYING README NEWS THANKS TODO'.split():
417 basename = _uc_first(filename, bld)
418 destination_filename = '%s%s' % (basename, ext)
419 destination = os.path.join(base_dir, destination_filename)
420 bld.install_as(destination, filename)
422 start_dir = bld.path.find_dir('doc/images')
423 bld.install_files('${DOCDIR}/%simages' % html_dir, start_dir.ant_glob('*.png'), cwd=start_dir)
424 bld.install_as('${DOCDIR}/%s' % _uc_first('manual.txt', bld), 'doc/geany.txt')
425 bld.install_as('${DOCDIR}/%s%s' % (html_dir, html_name), 'doc/geany.html')
426 bld.install_as('${DOCDIR}/ScintillaLicense.txt', 'scintilla/License.txt')
428 bld.install_as('${DOCDIR}/ReadMe.I18n.txt', 'README.I18N')
429 bld.install_as('${DOCDIR}/Hacking.txt', 'HACKING')
431 data_dir = '' if is_win32 else 'geany'
432 start_dir = bld.path.find_dir('data')
433 bld.install_as('${DATADIR}/%s/GPL-2' % data_dir, 'COPYING')
434 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('filetype*'), cwd=start_dir)
435 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('*.tags'), cwd=start_dir)
436 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.glade')
437 bld.install_files('${DATADIR}/%s' % data_dir, 'data/snippets.conf')
438 bld.install_files('${DATADIR}/%s' % data_dir, 'data/ui_toolbar.xml')
439 start_dir = bld.path.find_dir('data/colorschemes')
440 template_dest = '${DATADIR}/%s/colorschemes' % data_dir
441 bld.install_files(template_dest, start_dir.ant_glob('*'), cwd=start_dir)
442 start_dir = bld.path.find_dir('data/templates')
443 template_dest = '${DATADIR}/%s/templates' % data_dir
444 bld.install_files(template_dest, start_dir.ant_glob('**/*'), cwd=start_dir, relative_trick=True)
446 icon_dest = '${PREFIX}/share/icons' if is_win32 else '${DATADIR}/icons/hicolor/16x16/apps'
447 start_dir = bld.path.find_dir('icons/16x16')
448 bld.install_files(icon_dest, start_dir.ant_glob('*.png'), cwd=start_dir)
450 start_dir = bld.path.find_dir('icons/48x48')
451 icon_dest = '${DATADIR}/icons/hicolor/48x48/apps'
452 bld.install_files(icon_dest, start_dir.ant_glob('*.png'), cwd=start_dir)
453 start_dir = bld.path.find_dir('icons/scalable')
454 scalable_dest = '${DATADIR}/icons/hicolor/scalable/apps'
455 bld.install_files(scalable_dest, start_dir.ant_glob('*.svg'), cwd=start_dir)
459 Scripting.distclean(ctx)
460 _remove_linguas_file()
463 def _remove_linguas_file():
464 # remove LINGUAS file as well
466 os.unlink(LINGUAS_FILE)
472 def write_linguas_file(self):
473 if os.path.exists(LINGUAS_FILE):
476 if 'LINGUAS' in self.env:
477 files = self.env['LINGUAS']
478 for po_filename in files.split(' '):
479 if os.path.exists ('po/%s.po' % po_filename):
480 linguas += '%s ' % po_filename
482 files = os.listdir('%s/po' % self.path.abspath())
484 for filename in files:
485 if filename.endswith('.po'):
486 linguas += '%s ' % filename[:-3]
487 file_h = open(LINGUAS_FILE, 'w')
488 file_h.write('# This file is autogenerated. Do not edit.\n%s\n' % linguas)
492 def _post_install(ctx):
493 is_win32 = _target_is_win32(ctx)
496 theme_dir = Utils.subst_vars('${DATADIR}/icons/hicolor', ctx.env)
497 icon_cache_updated = False
498 if not ctx.options.destdir:
499 ctx.exec_command('gtk-update-icon-cache -q -f -t %s' % theme_dir)
500 Logs.pprint('GREEN', 'GTK icon cache updated.')
501 icon_cache_updated = True
502 if not icon_cache_updated:
503 Logs.pprint('YELLOW', 'Icon cache not updated. After install, run this:')
504 Logs.pprint('YELLOW', 'gtk-update-icon-cache -q -f -t %s' % theme_dir)
508 """update the message catalogs for internationalization"""
509 potfile = '%s.pot' % APPNAME
510 os.chdir('%s/po' % top)
513 old_size = os.stat(potfile).st_size
516 ctx.exec_command('intltool-update --pot -g %s' % APPNAME)
517 size_new = os.stat(potfile).st_size
518 if size_new != old_size:
519 Logs.pprint('CYAN', 'Updated POT file.')
520 Logs.pprint('CYAN', 'Updating translations')
521 ret = ctx.exec_command('intltool-update -r -g %s' % APPNAME)
523 Logs.pprint('RED', 'Updating translations failed')
525 Logs.pprint('CYAN', 'POT file is up to date.')
527 Logs.pprint('RED', 'Failed to generate pot file.')
531 """generate API reference documentation"""
532 basedir = ctx.path.abspath()
533 doxygen = _find_program(ctx, 'doxygen')
534 doxyfile = '%s/%s/doc/Doxyfile' % (basedir, out)
536 Logs.pprint('CYAN', 'Generating API documentation')
537 ret = ctx.exec_command('%s %s' % (doxygen, doxyfile))
539 raise WafError('Generating API documentation failed')
540 # update hacking.html
541 cmd = _find_rst2html(ctx)
542 ctx.exec_command('%s -stg --stylesheet=geany.css %s %s' % (cmd, '../HACKING', 'hacking.html'))
547 """generate HTML documentation"""
548 # first try rst2html.py as it is the upstream default, fall back to rst2html
549 cmd = _find_rst2html(ctx)
551 Logs.pprint('CYAN', 'Generating HTML documentation')
552 ctx.exec_command('%s -stg --stylesheet=geany.css %s %s' % (cmd, 'geany.txt', 'geany.html'))
556 def _find_program(ctx, cmd, **kw):
560 ctx = ConfigurationContext()
563 return ctx.find_program(cmd, **kw)
566 def _find_rst2html(ctx):
567 cmds = ['rst2html.py', 'rst2html']
569 cmd = _find_program(ctx, command, mandatory=False)
574 'rst2html.py could not be found. Please install the Python docutils package.')
578 def _add_define_to_env(conf, key):
579 value = conf.get_define(key)
581 value = value.replace('"', '')
582 conf.env[key] = value
585 def _add_to_env_and_define(conf, key, value, quote=False):
586 conf.define(key, value, quote)
587 conf.env[key] = value
590 def _define_from_opt(conf, define_name, opt_value, default_value, quote=1):
591 value = default_value
593 if isinstance(opt_value, bool):
597 if value is not None:
598 _add_to_env_and_define(conf, define_name, value, quote)
600 conf.undefine(define_name)
603 def _get_git_rev(conf):
604 if not os.path.isdir('.git'):
608 cmd = 'git rev-parse --short --revs-only HEAD'
609 revision = conf.cmd_and_log(cmd).strip()
616 def _load_intltool_if_available(conf):
618 conf.check_tool('intltool')
619 if 'LINGUAS' in os.environ:
620 conf.env['LINGUAS'] = os.environ['LINGUAS']
622 # on Windows, we don't hard depend on intltool, on all other platforms raise an error
623 if not _target_is_win32(conf):
627 def _target_is_win32(ctx):
628 if 'is_win32' in ctx.env:
630 return ctx.env['is_win32']
632 if sys.platform == 'win32':
635 if ctx.env and 'CC' in ctx.env:
636 env_cc = ctx.env['CC']
637 if not isinstance(env_cc, str):
638 env_cc = ''.join(env_cc)
639 is_win32 = (env_cc.find('mingw') != -1)
642 # cache for future checks
643 ctx.env['is_win32'] = is_win32
647 def _uc_first(string, ctx):
648 if _target_is_win32(ctx):
649 return string.title()