Update bold flag after editing shortcut
[geany-mirror.git] / wscript
blobf7154f01546c27d610a826041913e4250e52b1b9
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='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')
141     # Windows specials
142     if is_win32:
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'])
158     else:
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)
185     # no VTE on Windows
186     if is_win32:
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'])
199     # Scintilla flags
200     conf.env.append_value('CFLAGS', ['-DGTK'])
201     conf.env.append_value('CXXFLAGS',
202         ['-DNDEBUG', '-DGTK', '-DSCI_LEXER', '-DG_THREADS_IMPL_NONE'])
204     # summary
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)
214 def options(opt):
215     opt.tool_options('compiler_cc')
216     opt.tool_options('compiler_cxx')
217     opt.tool_options('intltool')
219     # Features
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]',
224         dest='no_socket')
225     opt.add_option('--disable-vte', action='store_true', default=False,
226         help='compile without support for an embedded virtual terminal [[default: No]',
227         dest='no_vte')
228     # Paths
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')
235     # Actions
236     opt.add_option('--hackingdoc', action='store_true', default=False,
237         help='generate HTML documentation from HACKING file', dest='hackingdoc')
240 def build(bld):
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):
249         if install:
250             instpath = '${PREFIX}/lib' if is_win32 else '${LIBDIR}/geany'
251         else:
252             instpath = None
254         bld.new_task_gen(
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)
264     # Tagmanager
265     bld.new_task_gen(
266         features        = ['c', 'cstlib'],
267         source          = tagmanager_sources,
268         name            = 'tagmanager',
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
276     # MIO
277     bld.new_task_gen(
278         features        = ['c', 'cstlib'],
279         source          = mio_sources,
280         name            = 'mio',
281         target          = 'mio',
282         includes        = ['.', 'tagmanager/mio/'],
283         defines         = 'G_LOG_DOMAIN="MIO"',
284         uselib          = ['GTK', 'GLIB'],
285         install_path    = None) # do not install this library
288     # Scintilla
289     files = bld.srcnode.ant_glob('scintilla/**/*.cxx', src=True, dir=False)
290     scintilla_sources.update(files)
291     bld.new_task_gen(
292         features        = ['c', 'cxx', 'cxxstlib'],
293         name            = 'scintilla',
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
301     # Geany
302     if bld.env['HAVE_VTE'] == 1:
303         geany_sources.add('src/vte.c')
304     if is_win32:
305         geany_sources.add('src/win32.c')
306         geany_sources.add('geany_private.rc')
308     bld.new_task_gen(
309         features        = ['c', 'cxx', 'cprogram'],
310         name            = 'geany',
311         target          = 'geany',
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'])
319     # geanyfunctions.h
320     bld.new_task_gen(
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')
327     # Plugins
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')
337     # Translations
338     if bld.env['INTLTOOL']:
339         bld.new_task_gen(
340             features        = ['linguas', 'intltool_po'],
341             podir           = 'po',
342             install_path    = '${LOCALEDIR}',
343             appname         = 'geany')
345     # geany.pc
346     bld.new_task_gen(
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'})
357     if not is_win32:
358         # geany.desktop
359         if bld.env['INTLTOOL']:
360             bld.new_task_gen(
361                 features        = 'intltool_in',
362                 source          = 'geany.desktop.in',
363                 flags           = [ '-d', '-q', '-u', '-c' ],
364                 install_path    = '${DATADIR}/applications')
366         # geany.1
367         bld.new_task_gen(
368             features        = 'subst',
369             source          = 'doc/geany.1.in',
370             target          = 'geany.1',
371             dct             = {'VERSION' : VERSION,
372                                 'GEANY_DATA_DIR': bld.env['DATADIR'] + '/geany'},
373             install_path    = '${MANDIR}/man1')
375         # geany.spec
376         bld.new_task_gen(
377             features        = 'subst',
378             source          = 'geany.spec.in',
379             target          = 'geany.spec',
380             install_path    = None,
381             dct             = {'VERSION' : VERSION})
383         # Doxyfile
384         bld.new_task_gen(
385             features        = 'subst',
386             source          = 'doc/Doxyfile.in',
387             target          = 'doc/Doxyfile',
388             install_path    = None,
389             dct             = {'VERSION' : VERSION})
391     ###
392     # Install files
393     ###
394     if not is_win32:
395         # Headers
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 ''')
411     # Docs
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')
427     if is_win32:
428         bld.install_as('${DOCDIR}/ReadMe.I18n.txt', 'README.I18N')
429         bld.install_as('${DOCDIR}/Hacking.txt', 'HACKING')
430     # Data
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)
445     # Icons
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)
449     if not is_win32:
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)
458 def distclean(ctx):
459     Scripting.distclean(ctx)
460     _remove_linguas_file()
463 def _remove_linguas_file():
464     # remove LINGUAS file as well
465     try:
466         os.unlink(LINGUAS_FILE)
467     except OSError:
468         pass
471 @feature('linguas')
472 def write_linguas_file(self):
473     if os.path.exists(LINGUAS_FILE):
474         return
475     linguas = ''
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
481     else:
482         files = os.listdir('%s/po' % self.path.abspath())
483         files.sort()
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)
489     file_h.close()
492 def _post_install(ctx):
493     is_win32 = _target_is_win32(ctx)
494     if is_win32:
495         return
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)
507 def updatepo(ctx):
508     """update the message catalogs for internationalization"""
509     potfile = '%s.pot' % APPNAME
510     os.chdir('%s/po' % top)
511     try:
512         try:
513             old_size = os.stat(potfile).st_size
514         except OSError:
515             old_size = 0
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)
522             if ret != 0:
523                 Logs.pprint('RED', 'Updating translations failed')
524         else:
525             Logs.pprint('CYAN', 'POT file is up to date.')
526     except OSError:
527         Logs.pprint('RED', 'Failed to generate pot file.')
530 def apidoc(ctx):
531     """generate API reference documentation"""
532     basedir = ctx.path.abspath()
533     doxygen = _find_program(ctx, 'doxygen')
534     doxyfile = '%s/%s/doc/Doxyfile' % (basedir, out)
535     os.chdir('doc')
536     Logs.pprint('CYAN', 'Generating API documentation')
537     ret = ctx.exec_command('%s %s' % (doxygen, doxyfile))
538     if ret != 0:
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'))
543     os.chdir('..')
546 def htmldoc(ctx):
547     """generate HTML documentation"""
548     # first try rst2html.py as it is the upstream default, fall back to rst2html
549     cmd = _find_rst2html(ctx)
550     os.chdir('doc')
551     Logs.pprint('CYAN', 'Generating HTML documentation')
552     ctx.exec_command('%s  -stg --stylesheet=geany.css %s %s' % (cmd, 'geany.txt', 'geany.html'))
553     os.chdir('..')
556 def _find_program(ctx, cmd, **kw):
557     def noop(*args):
558         pass
560     ctx = ConfigurationContext()
561     ctx.to_log = noop
562     ctx.msg = noop
563     return ctx.find_program(cmd, **kw)
566 def _find_rst2html(ctx):
567     cmds = ['rst2html.py', 'rst2html']
568     for command in cmds:
569         cmd = _find_program(ctx, command, mandatory=False)
570         if cmd:
571             break
572     if not cmd:
573         raise WafError(
574             'rst2html.py could not be found. Please install the Python docutils package.')
575     return cmd
578 def _add_define_to_env(conf, key):
579     value = conf.get_define(key)
580     # strip quotes
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
592     if opt_value:
593         if isinstance(opt_value, bool):
594             opt_value = 1
595         value = opt_value
597     if value is not None:
598         _add_to_env_and_define(conf, define_name, value, quote)
599     else:
600         conf.undefine(define_name)
603 def _get_git_rev(conf):
604     if not os.path.isdir('.git'):
605         return
607     try:
608         cmd = 'git rev-parse --short --revs-only HEAD'
609         revision = conf.cmd_and_log(cmd).strip()
610     except WafError:
611         return None
612     else:
613         return revision
616 def _load_intltool_if_available(conf):
617     try:
618         conf.check_tool('intltool')
619         if 'LINGUAS' in os.environ:
620             conf.env['LINGUAS'] = os.environ['LINGUAS']
621     except WafError:
622         # on Windows, we don't hard depend on intltool, on all other platforms raise an error
623         if not _target_is_win32(conf):
624             raise
627 def _target_is_win32(ctx):
628     if 'is_win32' in ctx.env:
629         # cached
630         return ctx.env['is_win32']
631     is_win32 = None
632     if sys.platform == 'win32':
633         is_win32 = True
634     if is_win32 is None:
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)
640     if is_win32 is None:
641         is_win32 = False
642     # cache for future checks
643     ctx.env['is_win32'] = is_win32
644     return is_win32
647 def _uc_first(string, ctx):
648     if _target_is_win32(ctx):
649         return string.title()
650     return string