Merge pull request #22 from RetroX/patch-1
[geany-mirror.git] / wscript
blob605795058ec435b310769a1e8b5810be583fcd0a
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.
22 """
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)
29 or at least equally.
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).
39 """
42 import sys
43 import os
44 import tempfile
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
51 APPNAME = 'geany'
52 VERSION = '1.22'
53 LINGUAS_FILE = 'po/LINGUAS'
55 top = '.'
56 out = '_build_'
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'])
81 geany_sources = set([
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',
89     'src/symbols.c',
90     'src/templates.c', 'src/toolbar.c', 'src/tools.c', 'src/sidebar.c',
91     'src/ui_utils.c', 'src/utils.c'])
95 def configure(conf):
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')
126     if is_win32:
127         conf.load('winres')
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='gio-2.0', uselib_store='GIO', args='--cflags --libs', mandatory=True)
136     gtk_version = conf.check_cfg(modversion='gtk+-2.0', uselib_store='GTK') or 'Unknown'
137     conf.check_cfg(package='gthread-2.0', uselib_store='GTHREAD', args='--cflags --libs')
139     # Windows specials
140     if is_win32:
141         if conf.env['PREFIX'].lower() == tempfile.gettempdir().lower():
142             # overwrite default prefix on Windows (tempfile.gettempdir() is the Waf default)
143             new_prefix = os.path.join(str(conf.root), '%s-%s' % (APPNAME, VERSION))
144             _add_to_env_and_define(conf, 'PREFIX', new_prefix, quote=True)
145             _add_to_env_and_define(conf, 'BINDIR', os.path.join(new_prefix, 'bin'), quote=True)
146         _add_to_env_and_define(conf, 'DOCDIR', os.path.join(conf.env['PREFIX'], 'doc'), quote=True)
147         _add_to_env_and_define(conf, 'LIBDIR', conf.env['PREFIX'], quote=True)
148         conf.define('LOCALEDIR', os.path.join('share' 'locale'), quote=True)
149         # overwrite LOCALEDIR to install message catalogues properly
150         conf.env['LOCALEDIR'] = os.path.join(conf.env['PREFIX'], 'share/locale')
151         # DATADIR is defined in objidl.h, so we remove it from config.h but keep it in env
152         conf.undefine('DATADIR')
153         conf.env['DATADIR'] = os.path.join(conf.env['PREFIX'], 'data')
154         conf.env.append_value('LINKFLAGS_cprogram', ['-mwindows'])
155         conf.env.append_value('LIB_WIN32', ['wsock32', 'uuid', 'ole32', 'iberty'])
156     else:
157         conf.env['cshlib_PATTERN'] = '%s.so'
158         # DATADIR and LOCALEDIR are defined by the intltool tool
159         # but they are not added to the environment, so we need to
160         _add_define_to_env(conf, 'DATADIR')
161         _add_define_to_env(conf, 'LOCALEDIR')
162         docdir = os.path.join(conf.env['DATADIR'], 'doc', 'geany')
163         libdir = os.path.join(conf.env['PREFIX'], 'lib')
164         mandir = os.path.join(conf.env['DATADIR'], 'man')
165         _define_from_opt(conf, 'DOCDIR', conf.options.docdir, docdir)
166         _define_from_opt(conf, 'LIBDIR', conf.options.libdir, libdir)
167         _define_from_opt(conf, 'MANDIR', conf.options.mandir, mandir)
169     revision = _get_git_rev(conf)
171     conf.define('ENABLE_NLS', 1)
172     conf.define('GEANY_LOCALEDIR', '' if is_win32 else conf.env['LOCALEDIR'], quote=True)
173     conf.define('GEANY_DATADIR', 'data' if is_win32 else conf.env['DATADIR'], quote=True)
174     conf.define('GEANY_DOCDIR', conf.env['DOCDIR'], quote=True)
175     conf.define('GEANY_LIBDIR', '' if is_win32 else conf.env['LIBDIR'], quote=True)
176     conf.define('GEANY_PREFIX', '' if is_win32 else conf.env['PREFIX'], quote=True)
177     conf.define('PACKAGE', APPNAME, quote=True)
178     conf.define('VERSION', VERSION, quote=True)
179     conf.define('REVISION', revision or '-1', quote=True)
181     conf.define('GETTEXT_PACKAGE', APPNAME, quote=True)
183     # no VTE on Windows
184     if is_win32:
185         conf.options.no_vte = True
187     _define_from_opt(conf, 'HAVE_PLUGINS', not conf.options.no_plugins, None)
188     _define_from_opt(conf, 'HAVE_SOCKET', not conf.options.no_socket, None)
189     _define_from_opt(conf, 'HAVE_VTE', not conf.options.no_vte, None)
191     conf.write_config_header('config.h', remove=False)
193     # some more compiler flags
194     conf.env.append_value('CFLAGS', ['-DHAVE_CONFIG_H'])
195     if revision is not None:
196         conf.env.append_value('CFLAGS', ['-g', '-DGEANY_DEBUG'])
197     # Scintilla flags
198     conf.env.append_value('CFLAGS', ['-DGTK'])
199     conf.env.append_value('CXXFLAGS',
200         ['-DNDEBUG', '-DGTK', '-DSCI_LEXER', '-DG_THREADS_IMPL_NONE'])
202     # summary
203     Logs.pprint('BLUE', 'Summary:')
204     conf.msg('Install Geany ' + VERSION + ' in', conf.env['PREFIX'])
205     conf.msg('Using GTK version', gtk_version)
206     conf.msg('Build with plugin support', conf.options.no_plugins and 'no' or 'yes')
207     conf.msg('Use virtual terminal support', conf.options.no_vte and 'no' or 'yes')
208     if revision is not None:
209         conf.msg('Compiling Git revision', revision)
212 def options(opt):
213     opt.tool_options('compiler_cc')
214     opt.tool_options('compiler_cxx')
215     opt.tool_options('intltool')
217     # Features
218     opt.add_option('--disable-plugins', action='store_true', default=False,
219         help='compile without plugin support [default: No]', dest='no_plugins')
220     opt.add_option('--disable-socket', action='store_true', default=False,
221         help='compile without support to detect a running instance [[default: No]',
222         dest='no_socket')
223     opt.add_option('--disable-vte', action='store_true', default=False,
224         help='compile without support for an embedded virtual terminal [[default: No]',
225         dest='no_vte')
226     # Paths
227     opt.add_option('--mandir', type='string', default='',
228         help='man documentation', dest='mandir')
229     opt.add_option('--docdir', type='string', default='',
230         help='documentation root', dest='docdir')
231     opt.add_option('--libdir', type='string', default='',
232         help='object code libraries', dest='libdir')
233     # Actions
234     opt.add_option('--hackingdoc', action='store_true', default=False,
235         help='generate HTML documentation from HACKING file', dest='hackingdoc')
238 def build(bld):
239     is_win32 = _target_is_win32(bld)
241     if bld.cmd == 'clean':
242         _remove_linguas_file()
243     if bld.cmd in ('install', 'uninstall'):
244         bld.add_post_fun(_post_install)
246     def build_plugin(plugin_name, install=True):
247         if install:
248             instpath = '${PREFIX}/lib' if is_win32 else '${LIBDIR}/geany'
249         else:
250             instpath = None
252         bld.new_task_gen(
253             features                = ['c', 'cshlib'],
254             source                  = 'plugins/%s.c' % plugin_name,
255             includes                = ['.', 'src/', 'scintilla/include', 'tagmanager/include'],
256             defines                 = 'G_LOG_DOMAIN="%s"' % plugin_name,
257             target                  = plugin_name,
258             uselib                  = ['GTK', 'GLIB'],
259             install_path            = instpath)
262     # Tagmanager
263     bld.new_task_gen(
264         features        = ['c', 'cstlib'],
265         source          = tagmanager_sources,
266         name            = 'tagmanager',
267         target          = 'tagmanager',
268         includes        = ['.', 'tagmanager', 'tagmanager/include'],
269         defines         = 'G_LOG_DOMAIN="Tagmanager"',
270         uselib          = ['GTK', 'GLIB'],
271         install_path    = None) # do not install this library
274     # MIO
275     bld.new_task_gen(
276         features        = ['c', 'cstlib'],
277         source          = mio_sources,
278         name            = 'mio',
279         target          = 'mio',
280         includes        = ['.', 'tagmanager/mio/'],
281         defines         = 'G_LOG_DOMAIN="MIO"',
282         uselib          = ['GTK', 'GLIB'],
283         install_path    = None) # do not install this library
286     # Scintilla
287     files = bld.srcnode.ant_glob('scintilla/**/*.cxx', src=True, dir=False)
288     scintilla_sources.update(files)
289     bld.new_task_gen(
290         features        = ['c', 'cxx', 'cxxstlib'],
291         name            = 'scintilla',
292         target          = 'scintilla',
293         source          = scintilla_sources,
294         includes        = ['.', 'scintilla/include', 'scintilla/src', 'scintilla/lexlib'],
295         uselib          = 'GTK',
296         install_path    = None) # do not install this library
299     # Geany
300     if bld.env['HAVE_VTE'] == 1:
301         geany_sources.add('src/vte.c')
302     if is_win32:
303         geany_sources.add('src/win32.c')
304         geany_sources.add('geany_private.rc')
306     bld.new_task_gen(
307         features        = ['c', 'cxx', 'cprogram'],
308         name            = 'geany',
309         target          = 'geany',
310         source          = geany_sources,
311         includes        = ['.', 'scintilla/include/', 'tagmanager/include/'],
312         defines         = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
313         linkflags       = [] if is_win32 else ['-Wl,--export-dynamic'],
314         uselib          = ['GTK', 'GLIB', 'GIO', 'GTHREAD', 'WIN32', 'SUNOS_SOCKET'],
315         use             = ['scintilla', 'tagmanager', 'mio'])
317     # geanyfunctions.h
318     bld.new_task_gen(
319         source  = ['plugins/genapi.py', 'src/plugins.c'],
320         name    = 'geanyfunctions.h',
321         before  = ['c', 'cxx'],
322         cwd     = '%s/plugins' % bld.path.abspath(),
323         rule    = 'python genapi.py -q')
325     # Plugins
326     if bld.env['HAVE_PLUGINS'] == 1:
327         build_plugin('classbuilder')
328         build_plugin('demoplugin', False)
329         build_plugin('export')
330         build_plugin('filebrowser')
331         build_plugin('htmlchars')
332         build_plugin('saveactions')
333         build_plugin('splitwindow')
335     # Translations
336     if bld.env['INTLTOOL']:
337         bld.new_task_gen(
338             features        = ['linguas', 'intltool_po'],
339             podir           = 'po',
340             install_path    = '${LOCALEDIR}',
341             appname         = 'geany')
343     # geany.pc
344     bld.new_task_gen(
345         source          = 'geany.pc.in',
346         dct             = {'VERSION' : VERSION,
347                            'prefix': bld.env['PREFIX'],
348                            'exec_prefix': '${prefix}',
349                            'libdir': '${exec_prefix}/lib',
350                            'includedir': '${prefix}/include',
351                            'datarootdir': '${prefix}/share',
352                            'datadir': '${datarootdir}',
353                            'localedir': '${datarootdir}/locale'})
355     if not is_win32:
356         # geany.desktop
357         if bld.env['INTLTOOL']:
358             bld.new_task_gen(
359                 features        = 'intltool_in',
360                 source          = 'geany.desktop.in',
361                 flags           = [ '-d', '-q', '-u', '-c' ],
362                 install_path    = '${DATADIR}/applications')
364         # geany.1
365         bld.new_task_gen(
366             features        = 'subst',
367             source          = 'doc/geany.1.in',
368             target          = 'geany.1',
369             dct             = {'VERSION' : VERSION,
370                                 'GEANY_DATA_DIR': bld.env['DATADIR'] + '/geany'},
371             install_path    = '${MANDIR}/man1')
373         # geany.spec
374         bld.new_task_gen(
375             features        = 'subst',
376             source          = 'geany.spec.in',
377             target          = 'geany.spec',
378             install_path    = None,
379             dct             = {'VERSION' : VERSION})
381         # Doxyfile
382         bld.new_task_gen(
383             features        = 'subst',
384             source          = 'doc/Doxyfile.in',
385             target          = 'doc/Doxyfile',
386             install_path    = None,
387             dct             = {'VERSION' : VERSION})
389     ###
390     # Install files
391     ###
392     if not is_win32:
393         # Headers
394         bld.install_files('${PREFIX}/include/geany', '''
395             src/document.h src/editor.h src/encodings.h src/filetypes.h src/geany.h
396             src/highlighting.h src/keybindings.h src/msgwindow.h src/plugindata.h
397             src/prefs.h src/project.h src/search.h src/stash.h src/support.h
398             src/templates.h src/toolbar.h src/ui_utils.h src/utils.h
399             plugins/geanyplugin.h plugins/geanyfunctions.h''')
400         bld.install_files('${PREFIX}/include/geany/scintilla', '''
401             scintilla/include/SciLexer.h scintilla/include/Scintilla.h
402             scintilla/include/Scintilla.iface scintilla/include/ScintillaWidget.h ''')
403         bld.install_files('${PREFIX}/include/geany/tagmanager', '''
404             tagmanager/include/tm_file_entry.h tagmanager/include/tm_project.h
405             tagmanager/include/tm_source_file.h
406             tagmanager/include/tm_symbol.h tagmanager/include/tm_tag.h
407             tagmanager/include/tm_tagmanager.h tagmanager/include/tm_work_object.h
408             tagmanager/include/tm_workspace.h ''')
409     # Docs
410     base_dir = '${PREFIX}' if is_win32 else '${DOCDIR}'
411     ext = '.txt' if is_win32 else ''
412     html_dir = '' if is_win32 else 'html/'
413     html_name = 'Manual.html' if is_win32 else 'index.html'
414     for filename in 'AUTHORS ChangeLog COPYING README NEWS THANKS TODO'.split():
415         basename = _uc_first(filename, bld)
416         destination_filename = '%s%s' % (basename, ext)
417         destination = os.path.join(base_dir, destination_filename)
418         bld.install_as(destination, filename)
420     start_dir = bld.path.find_dir('doc/images')
421     bld.install_files('${DOCDIR}/%simages' % html_dir, start_dir.ant_glob('*.png'), cwd=start_dir)
422     bld.install_as('${DOCDIR}/%s' % _uc_first('manual.txt', bld), 'doc/geany.txt')
423     bld.install_as('${DOCDIR}/%s%s' % (html_dir, html_name), 'doc/geany.html')
424     bld.install_as('${DOCDIR}/ScintillaLicense.txt', 'scintilla/License.txt')
425     if is_win32:
426         bld.install_as('${DOCDIR}/ReadMe.I18n.txt', 'README.I18N')
427         bld.install_as('${DOCDIR}/Hacking.txt', 'HACKING')
428     # Data
429     data_dir = '' if is_win32 else 'geany'
430     start_dir = bld.path.find_dir('data')
431     bld.install_as('${DATADIR}/%s/GPL-2' % data_dir, 'COPYING')
432     bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('filetype*'), cwd=start_dir)
433     bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('*.tags'), cwd=start_dir)
434     bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.glade')
435     bld.install_files('${DATADIR}/%s' % data_dir, 'data/snippets.conf')
436     bld.install_files('${DATADIR}/%s' % data_dir, 'data/ui_toolbar.xml')
437     start_dir = bld.path.find_dir('data/colorschemes')
438     template_dest = '${DATADIR}/%s/colorschemes' % data_dir
439     bld.install_files(template_dest, start_dir.ant_glob('*'), cwd=start_dir)
440     start_dir = bld.path.find_dir('data/templates')
441     template_dest = '${DATADIR}/%s/templates' % data_dir
442     bld.install_files(template_dest, start_dir.ant_glob('**/*'), cwd=start_dir, relative_trick=True)
443     # Icons
444     icon_dest = '${PREFIX}/share/icons' if is_win32 else '${DATADIR}/icons/hicolor/16x16/apps'
445     start_dir = bld.path.find_dir('icons/16x16')
446     bld.install_files(icon_dest, start_dir.ant_glob('*.png'), cwd=start_dir)
447     if not is_win32:
448         start_dir = bld.path.find_dir('icons/48x48')
449         icon_dest = '${DATADIR}/icons/hicolor/48x48/apps'
450         bld.install_files(icon_dest, start_dir.ant_glob('*.png'), cwd=start_dir)
451         start_dir = bld.path.find_dir('icons/scalable')
452         scalable_dest = '${DATADIR}/icons/hicolor/scalable/apps'
453         bld.install_files(scalable_dest, start_dir.ant_glob('*.svg'), cwd=start_dir)
456 def distclean(ctx):
457     Scripting.distclean(ctx)
458     _remove_linguas_file()
461 def _remove_linguas_file():
462     # remove LINGUAS file as well
463     try:
464         os.unlink(LINGUAS_FILE)
465     except OSError:
466         pass
469 @feature('linguas')
470 def write_linguas_file(self):
471     if os.path.exists(LINGUAS_FILE):
472         return
473     linguas = ''
474     if 'LINGUAS' in self.env:
475         files = self.env['LINGUAS']
476         for po_filename in files.split(' '):
477             if os.path.exists ('po/%s.po' % po_filename):
478                 linguas += '%s ' % po_filename
479     else:
480         files = os.listdir('%s/po' % self.path.abspath())
481         files.sort()
482         for filename in files:
483             if filename.endswith('.po'):
484                 linguas += '%s ' % filename[:-3]
485     file_h = open(LINGUAS_FILE, 'w')
486     file_h.write('# This file is autogenerated. Do not edit.\n%s\n' % linguas)
487     file_h.close()
490 def _post_install(ctx):
491     is_win32 = _target_is_win32(ctx)
492     if is_win32:
493         return
494     theme_dir = Utils.subst_vars('${DATADIR}/icons/hicolor', ctx.env)
495     icon_cache_updated = False
496     if not ctx.options.destdir:
497         ctx.exec_command('gtk-update-icon-cache -q -f -t %s' % theme_dir)
498         Logs.pprint('GREEN', 'GTK icon cache updated.')
499         icon_cache_updated = True
500     if not icon_cache_updated:
501         Logs.pprint('YELLOW', 'Icon cache not updated. After install, run this:')
502         Logs.pprint('YELLOW', 'gtk-update-icon-cache -q -f -t %s' % theme_dir)
505 def updatepo(ctx):
506     """update the message catalogs for internationalization"""
507     potfile = '%s.pot' % APPNAME
508     os.chdir('%s/po' % top)
509     try:
510         try:
511             old_size = os.stat(potfile).st_size
512         except OSError:
513             old_size = 0
514         ctx.exec_command('intltool-update --pot -g %s' % APPNAME)
515         size_new = os.stat(potfile).st_size
516         if size_new != old_size:
517             Logs.pprint('CYAN', 'Updated POT file.')
518             Logs.pprint('CYAN', 'Updating translations')
519             ret = ctx.exec_command('intltool-update -r -g %s' % APPNAME)
520             if ret != 0:
521                 Logs.pprint('RED', 'Updating translations failed')
522         else:
523             Logs.pprint('CYAN', 'POT file is up to date.')
524     except OSError:
525         Logs.pprint('RED', 'Failed to generate pot file.')
528 def apidoc(ctx):
529     """generate API reference documentation"""
530     basedir = ctx.path.abspath()
531     doxygen = _find_program(ctx, 'doxygen')
532     doxyfile = '%s/%s/doc/Doxyfile' % (basedir, out)
533     os.chdir('doc')
534     Logs.pprint('CYAN', 'Generating API documentation')
535     ret = ctx.exec_command('%s %s' % (doxygen, doxyfile))
536     if ret != 0:
537         raise WafError('Generating API documentation failed')
538     # update hacking.html
539     cmd = _find_rst2html(ctx)
540     ctx.exec_command('%s  -stg --stylesheet=geany.css %s %s' % (cmd, '../HACKING', 'hacking.html'))
541     os.chdir('..')
544 def htmldoc(ctx):
545     """generate HTML documentation"""
546     # first try rst2html.py as it is the upstream default, fall back to rst2html
547     cmd = _find_rst2html(ctx)
548     os.chdir('doc')
549     Logs.pprint('CYAN', 'Generating HTML documentation')
550     ctx.exec_command('%s  -stg --stylesheet=geany.css %s %s' % (cmd, 'geany.txt', 'geany.html'))
551     os.chdir('..')
554 def _find_program(ctx, cmd, **kw):
555     def noop(*args):
556         pass
558     ctx = ConfigurationContext()
559     ctx.to_log = noop
560     ctx.msg = noop
561     return ctx.find_program(cmd, **kw)
564 def _find_rst2html(ctx):
565     cmds = ['rst2html.py', 'rst2html']
566     for command in cmds:
567         cmd = _find_program(ctx, command, mandatory=False)
568         if cmd:
569             break
570     if not cmd:
571         raise WafError(
572             'rst2html.py could not be found. Please install the Python docutils package.')
573     return cmd
576 def _add_define_to_env(conf, key):
577     value = conf.get_define(key)
578     # strip quotes
579     value = value.replace('"', '')
580     conf.env[key] = value
583 def _add_to_env_and_define(conf, key, value, quote=False):
584     conf.define(key, value, quote)
585     conf.env[key] = value
588 def _define_from_opt(conf, define_name, opt_value, default_value, quote=1):
589     value = default_value
590     if opt_value:
591         if isinstance(opt_value, bool):
592             opt_value = 1
593         value = opt_value
595     if value is not None:
596         _add_to_env_and_define(conf, define_name, value, quote)
597     else:
598         conf.undefine(define_name)
601 def _get_git_rev(conf):
602     if not os.path.isdir('.git'):
603         return
605     try:
606         cmd = 'git rev-parse --short --revs-only HEAD'
607         revision = conf.cmd_and_log(cmd).strip()
608     except WafError:
609         return None
610     else:
611         return revision
614 def _load_intltool_if_available(conf):
615     try:
616         conf.check_tool('intltool')
617         if 'LINGUAS' in os.environ:
618             conf.env['LINGUAS'] = os.environ['LINGUAS']
619     except WafError:
620         # on Windows, we don't hard depend on intltool, on all other platforms raise an error
621         if not _target_is_win32(conf):
622             raise
625 def _target_is_win32(ctx):
626     if 'is_win32' in ctx.env:
627         # cached
628         return ctx.env['is_win32']
629     is_win32 = None
630     if sys.platform == 'win32':
631         is_win32 = True
632     if is_win32 is None:
633         if ctx.env and 'CC' in ctx.env:
634             env_cc = ctx.env['CC']
635             if not isinstance(env_cc, str):
636                 env_cc = ''.join(env_cc)
637             is_win32 = (env_cc.find('mingw') != -1)
638     if is_win32 is None:
639         is_win32 = False
640     # cache for future checks
641     ctx.env['is_win32'] = is_win32
642     return is_win32
645 def _uc_first(string, ctx):
646     if _target_is_win32(ctx):
647         return string.title()
648     return string