Force selection to change when Default or Alt colourscheme chosen
[geany-mirror.git] / wscript
blob84448c11d257d8e711ec3de1ef39eab998a2ff32
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 WafError
48 from waflib.TaskGen import feature
51 APPNAME = 'geany'
52 VERSION = '1.22'
53 LINGUAS_FILE = 'po/LINGUAS'
54 MINIMUM_GTK_VERSION = '2.16.0'
55 MINIMUM_GLIB_VERSION = '2.20.0'
57 top = '.'
58 out = '_build_'
61 mio_sources = set(['tagmanager/mio/mio.c'])
63 tagmanager_sources = set([
64     'tagmanager/args.c', 'tagmanager/abc.c', 'tagmanager/actionscript.c', 'tagmanager/asm.c',
65     'tagmanager/basic.c', 'tagmanager/c.c', 'tagmanager/cobol.c',
66     'tagmanager/conf.c', 'tagmanager/css.c', 'tagmanager/ctags.c', 'tagmanager/diff.c',
67     'tagmanager/docbook.c', 'tagmanager/entry.c', 'tagmanager/fortran.c', 'tagmanager/get.c',
68     'tagmanager/haskell.c', 'tagmanager/haxe.c', 'tagmanager/html.c', 'tagmanager/js.c',
69     'tagmanager/keyword.c', 'tagmanager/latex.c', 'tagmanager/lregex.c', 'tagmanager/lua.c',
70     'tagmanager/make.c', 'tagmanager/markdown.c', 'tagmanager/matlab.c', 'tagmanager/nsis.c',
71     'tagmanager/nestlevel.c', 'tagmanager/objc.c', 'tagmanager/options.c',
72     'tagmanager/parse.c', 'tagmanager/pascal.c', 'tagmanager/r.c',
73     'tagmanager/perl.c', 'tagmanager/php.c', 'tagmanager/python.c', 'tagmanager/read.c',
74     'tagmanager/rest.c', 'tagmanager/ruby.c', 'tagmanager/sh.c', 'tagmanager/sort.c',
75     'tagmanager/sql.c', 'tagmanager/strlist.c', 'tagmanager/txt2tags.c', 'tagmanager/tcl.c',
76     'tagmanager/tm_file_entry.c',
77     'tagmanager/tm_project.c', 'tagmanager/tm_source_file.c', 'tagmanager/tm_symbol.c',
78     'tagmanager/tm_tag.c', 'tagmanager/tm_tagmanager.c', 'tagmanager/tm_work_object.c',
79     'tagmanager/tm_workspace.c', 'tagmanager/vhdl.c', 'tagmanager/verilog.c', 'tagmanager/vstring.c'])
81 scintilla_sources = set(['scintilla/gtk/scintilla-marshal.c'])
83 geany_sources = set([
84     'src/about.c', 'src/build.c', 'src/callbacks.c', 'src/dialogs.c', 'src/document.c',
85     'src/editor.c', 'src/encodings.c', 'src/filetypes.c', 'src/geanyentryaction.c',
86     'src/geanymenubuttonaction.c', 'src/geanyobject.c', 'src/geanywraplabel.c',
87     'src/highlighting.c', 'src/keybindings.c',
88     'src/keyfile.c', 'src/log.c', 'src/main.c', 'src/msgwindow.c', 'src/navqueue.c', 'src/notebook.c',
89     'src/plugins.c', 'src/pluginutils.c', 'src/prefix.c', 'src/prefs.c', 'src/printing.c', 'src/project.c',
90     'src/sciwrappers.c', 'src/search.c', 'src/socket.c', 'src/stash.c',
91     'src/symbols.c',
92     'src/templates.c', 'src/toolbar.c', 'src/tools.c', 'src/sidebar.c',
93     'src/ui_utils.c', 'src/utils.c'])
96 def configure(conf):
98     conf.check_waf_version(mini='1.6.1')
100     conf.load('compiler_c')
101     is_win32 = _target_is_win32(conf)
103     conf.check_cc(header_name='fcntl.h', mandatory=False)
104     conf.check_cc(header_name='fnmatch.h', mandatory=False)
105     conf.check_cc(header_name='glob.h', mandatory=False)
106     conf.check_cc(header_name='sys/time.h', mandatory=False)
107     conf.check_cc(header_name='sys/types.h', mandatory=False)
108     conf.check_cc(header_name='sys/stat.h', mandatory=False)
109     conf.define('HAVE_STDLIB_H', 1)  # are there systems without stdlib.h?
110     conf.define('STDC_HEADERS', 1)  # an optimistic guess ;-)
111     _add_to_env_and_define(conf, 'HAVE_REGCOMP', 1)  # needed for CTags
113     conf.check_cc(function_name='fgetpos', header_name='stdio.h', mandatory=False)
114     conf.check_cc(function_name='ftruncate', header_name='unistd.h', mandatory=False)
115     conf.check_cc(function_name='gethostname', header_name='unistd.h', mandatory=False)
116     conf.check_cc(function_name='mkstemp', header_name='stdlib.h', mandatory=False)
117     conf.check_cc(function_name='strstr', header_name='string.h')
119     # check sunOS socket support
120     if Options.platform == 'sunos':
121         conf.check_cc(function_name='socket', lib='socket',
122                       header_name='sys/socket.h', uselib_store='SUNOS_SOCKET', mandatory=True)
124     # check for cxx after the header and function checks have been done to ensure they are
125     # checked with cc not cxx
126     conf.load('compiler_cxx')
127     if is_win32:
128         conf.load('winres')
129     _load_intltool_if_available(conf)
131     # GTK / GIO version check
132     conf.check_cfg(package='gtk+-2.0', atleast_version=MINIMUM_GTK_VERSION, uselib_store='GTK',
133         mandatory=True, args='--cflags --libs')
134     conf.check_cfg(package='glib-2.0', atleast_version=MINIMUM_GLIB_VERSION, uselib_store='GLIB',
135         mandatory=True, args='--cflags --libs')
136     conf.check_cfg(package='gmodule-2.0', uselib_store='GMODULE',
137         mandatory=True, args='--cflags --libs')
138     conf.check_cfg(package='gio-2.0', uselib_store='GIO', args='--cflags --libs', mandatory=True)
139     gtk_version = conf.check_cfg(modversion='gtk+-2.0', uselib_store='GTK') or 'Unknown'
140     conf.check_cfg(package='gthread-2.0', uselib_store='GTHREAD', args='--cflags --libs')
142     # Windows specials
143     if is_win32:
144         if conf.env['PREFIX'].lower() == tempfile.gettempdir().lower():
145             # overwrite default prefix on Windows (tempfile.gettempdir() is the Waf default)
146             new_prefix = os.path.join(str(conf.root), '%s-%s' % (APPNAME, VERSION))
147             _add_to_env_and_define(conf, 'PREFIX', new_prefix, quote=True)
148             _add_to_env_and_define(conf, 'BINDIR', os.path.join(new_prefix, 'bin'), quote=True)
149         _add_to_env_and_define(conf, 'DOCDIR', os.path.join(conf.env['PREFIX'], 'doc'), quote=True)
150         _add_to_env_and_define(conf, 'LIBDIR', conf.env['PREFIX'], quote=True)
151         conf.define('LOCALEDIR', os.path.join('share' 'locale'), quote=True)
152         # overwrite LOCALEDIR to install message catalogues properly
153         conf.env['LOCALEDIR'] = os.path.join(conf.env['PREFIX'], 'share/locale')
154         # DATADIR is defined in objidl.h, so we remove it from config.h but keep it in env
155         conf.undefine('DATADIR')
156         conf.env['DATADIR'] = os.path.join(conf.env['PREFIX'], 'data')
157         conf.env.append_value('LINKFLAGS_cprogram', ['-mwindows'])
158         conf.env.append_value('LIB_WIN32', ['wsock32', 'uuid', 'ole32', 'iberty'])
159     else:
160         conf.env['cshlib_PATTERN'] = '%s.so'
161         # DATADIR and LOCALEDIR are defined by the intltool tool
162         # but they are not added to the environment, so we need to
163         _add_define_to_env(conf, 'DATADIR')
164         _add_define_to_env(conf, 'LOCALEDIR')
165         docdir = os.path.join(conf.env['DATADIR'], 'doc', 'geany')
166         libdir = os.path.join(conf.env['PREFIX'], 'lib')
167         mandir = os.path.join(conf.env['DATADIR'], 'man')
168         _define_from_opt(conf, 'DOCDIR', conf.options.docdir, docdir)
169         _define_from_opt(conf, 'LIBDIR', conf.options.libdir, libdir)
170         _define_from_opt(conf, 'MANDIR', conf.options.mandir, mandir)
172     revision = _get_git_rev(conf)
174     conf.define('ENABLE_NLS', 1)
175     conf.define('GEANY_LOCALEDIR', '' if is_win32 else conf.env['LOCALEDIR'], quote=True)
176     conf.define('GEANY_DATADIR', 'data' if is_win32 else conf.env['DATADIR'], quote=True)
177     conf.define('GEANY_DOCDIR', conf.env['DOCDIR'], quote=True)
178     conf.define('GEANY_LIBDIR', '' if is_win32 else conf.env['LIBDIR'], quote=True)
179     conf.define('GEANY_PREFIX', '' if is_win32 else conf.env['PREFIX'], quote=True)
180     conf.define('PACKAGE', APPNAME, quote=True)
181     conf.define('VERSION', VERSION, quote=True)
182     conf.define('REVISION', revision or '-1', quote=True)
184     conf.define('GETTEXT_PACKAGE', APPNAME, quote=True)
186     # no VTE on Windows
187     if is_win32:
188         conf.options.no_vte = True
190     _define_from_opt(conf, 'HAVE_PLUGINS', not conf.options.no_plugins, None)
191     _define_from_opt(conf, 'HAVE_SOCKET', not conf.options.no_socket, None)
192     _define_from_opt(conf, 'HAVE_VTE', not conf.options.no_vte, None)
194     conf.write_config_header('config.h', remove=False)
196     # some more compiler flags
197     conf.env.append_value('CFLAGS', ['-DHAVE_CONFIG_H'])
198     if revision is not None:
199         conf.env.append_value('CFLAGS', ['-g', '-DGEANY_DEBUG'])
200     # Scintilla flags
201     conf.env.append_value('CFLAGS', ['-DGTK'])
202     conf.env.append_value('CXXFLAGS',
203         ['-DNDEBUG', '-DGTK', '-DSCI_LEXER', '-DG_THREADS_IMPL_NONE'])
205     # summary
206     Logs.pprint('BLUE', 'Summary:')
207     conf.msg('Install Geany ' + VERSION + ' in', conf.env['PREFIX'])
208     conf.msg('Using GTK version', gtk_version)
209     conf.msg('Build with plugin support', conf.options.no_plugins and 'no' or 'yes')
210     conf.msg('Use virtual terminal support', conf.options.no_vte and 'no' or 'yes')
211     if revision is not None:
212         conf.msg('Compiling Git revision', revision)
215 def options(opt):
216     opt.tool_options('compiler_cc')
217     opt.tool_options('compiler_cxx')
218     opt.tool_options('intltool')
220     # Features
221     opt.add_option('--disable-plugins', action='store_true', default=False,
222         help='compile without plugin support [default: No]', dest='no_plugins')
223     opt.add_option('--disable-socket', action='store_true', default=False,
224         help='compile without support to detect a running instance [[default: No]',
225         dest='no_socket')
226     opt.add_option('--disable-vte', action='store_true', default=False,
227         help='compile without support for an embedded virtual terminal [[default: No]',
228         dest='no_vte')
229     # Paths
230     opt.add_option('--mandir', type='string', default='',
231         help='man documentation', dest='mandir')
232     opt.add_option('--docdir', type='string', default='',
233         help='documentation root', dest='docdir')
234     opt.add_option('--libdir', type='string', default='',
235         help='object code libraries', dest='libdir')
236     # Actions
237     opt.add_option('--hackingdoc', action='store_true', default=False,
238         help='generate HTML documentation from HACKING file', dest='hackingdoc')
241 def build(bld):
242     is_win32 = _target_is_win32(bld)
244     if bld.cmd == 'clean':
245         _remove_linguas_file()
246     if bld.cmd in ('install', 'uninstall'):
247         bld.add_post_fun(_post_install)
249     def build_plugin(plugin_name, install=True):
250         if install:
251             instpath = '${PREFIX}/lib' if is_win32 else '${LIBDIR}/geany'
252         else:
253             instpath = None
255         bld.new_task_gen(
256             features                = ['c', 'cshlib'],
257             source                  = 'plugins/%s.c' % plugin_name,
258             includes                = ['.', 'src/', 'scintilla/include', 'tagmanager/include'],
259             defines                 = 'G_LOG_DOMAIN="%s"' % plugin_name,
260             target                  = plugin_name,
261             uselib                  = ['GTK', 'GLIB', 'GMODULE'],
262             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
275     # MIO
276     bld.new_task_gen(
277         features        = ['c', 'cstlib'],
278         source          = mio_sources,
279         name            = 'mio',
280         target          = 'mio',
281         includes        = ['.', 'tagmanager/mio/'],
282         defines         = 'G_LOG_DOMAIN="MIO"',
283         uselib          = ['GTK', 'GLIB'],
284         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', 'GLIB', 'GMODULE'],
296         install_path    = None)  # do not install this library
298     # Geany
299     if bld.env['HAVE_VTE'] == 1:
300         geany_sources.add('src/vte.c')
301     if is_win32:
302         geany_sources.add('src/win32.c')
303         geany_sources.add('geany_private.rc')
305     bld.new_task_gen(
306         features        = ['c', 'cxx', 'cprogram'],
307         name            = 'geany',
308         target          = 'geany',
309         source          = geany_sources,
310         includes        = ['.', 'scintilla/include/', 'tagmanager/include/'],
311         defines         = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
312         linkflags       = [] if is_win32 else ['-Wl,--export-dynamic'],
313         uselib          = ['GTK', 'GLIB', 'GMODULE', 'GIO', 'GTHREAD', 'WIN32', 'SUNOS_SOCKET'],
314         use             = ['scintilla', 'tagmanager', 'mio'])
316     # geanyfunctions.h
317     bld.new_task_gen(
318         source  = ['plugins/genapi.py', 'src/plugins.c'],
319         name    = 'geanyfunctions.h',
320         before  = ['c', 'cxx'],
321         cwd     = '%s/plugins' % bld.path.abspath(),
322         rule    = '%s genapi.py -q' % sys.executable)
324     # Plugins
325     if bld.env['HAVE_PLUGINS'] == 1:
326         build_plugin('classbuilder')
327         build_plugin('demoplugin', False)
328         build_plugin('export')
329         build_plugin('filebrowser')
330         build_plugin('htmlchars')
331         build_plugin('saveactions')
332         build_plugin('splitwindow')
334     # Translations
335     if bld.env['INTLTOOL']:
336         bld.new_task_gen(
337             features        = ['linguas', 'intltool_po'],
338             podir           = 'po',
339             install_path    = '${LOCALEDIR}',
340             appname         = 'geany')
342     # geany.pc
343     bld.new_task_gen(
344         source          = 'geany.pc.in',
345         dct             = {'VERSION': VERSION,
346                            'DEPENDENCIES': 'gtk+-2.0 >= %s glib-2.0 >= %s' % \
347                                 (MINIMUM_GTK_VERSION, MINIMUM_GLIB_VERSION),
348                            'prefix': bld.env['PREFIX'],
349                            'exec_prefix': '${prefix}',
350                            'libdir': '${exec_prefix}/lib',
351                            'includedir': '${prefix}/include',
352                            'datarootdir': '${prefix}/share',
353                            'datadir': '${datarootdir}',
354                            'localedir': '${datarootdir}/locale'})
356     if not is_win32:
357         # geany.desktop
358         if bld.env['INTLTOOL']:
359             bld.new_task_gen(
360                 features        = 'intltool_in',
361                 source          = 'geany.desktop.in',
362                 flags           = ['-d', '-q', '-u', '-c'],
363                 install_path    = '${DATADIR}/applications')
365         # geany.1
366         bld.new_task_gen(
367             features        = 'subst',
368             source          = 'doc/geany.1.in',
369             target          = 'geany.1',
370             dct             = {'VERSION': VERSION,
371                                 'GEANY_DATA_DIR': bld.env['DATADIR'] + '/geany'},
372             install_path    = '${MANDIR}/man1')
374         # geany.spec
375         bld.new_task_gen(
376             features        = 'subst',
377             source          = 'geany.spec.in',
378             target          = 'geany.spec',
379             install_path    = None,
380             dct             = {'VERSION': VERSION})
382         # Doxyfile
383         bld.new_task_gen(
384             features        = 'subst',
385             source          = 'doc/Doxyfile.in',
386             target          = 'doc/Doxyfile',
387             install_path    = None,
388             dct             = {'VERSION': VERSION})
390     ###
391     # Install files
392     ###
393     if not is_win32:
394         # Headers
395         bld.install_files('${PREFIX}/include/geany', '''
396             src/document.h src/editor.h src/encodings.h src/filetypes.h src/geany.h
397             src/highlighting.h src/keybindings.h src/msgwindow.h src/plugindata.h
398             src/prefs.h src/project.h src/search.h src/stash.h src/support.h
399             src/templates.h src/toolbar.h src/ui_utils.h src/utils.h src/build.h
400             plugins/geanyplugin.h plugins/geanyfunctions.h''')
401         bld.install_files('${PREFIX}/include/geany/scintilla', '''
402             scintilla/include/SciLexer.h scintilla/include/Scintilla.h
403             scintilla/include/Scintilla.iface scintilla/include/ScintillaWidget.h ''')
404         bld.install_files('${PREFIX}/include/geany/tagmanager', '''
405             tagmanager/include/tm_file_entry.h tagmanager/include/tm_project.h
406             tagmanager/include/tm_source_file.h
407             tagmanager/include/tm_symbol.h tagmanager/include/tm_tag.h
408             tagmanager/include/tm_tagmanager.h tagmanager/include/tm_work_object.h
409             tagmanager/include/tm_workspace.h ''')
410     # Docs
411     base_dir = '${PREFIX}' if is_win32 else '${DOCDIR}'
412     ext = '.txt' if is_win32 else ''
413     html_dir = '' if is_win32 else 'html/'
414     html_name = 'Manual.html' if is_win32 else 'index.html'
415     for filename in 'AUTHORS ChangeLog COPYING README NEWS THANKS TODO'.split():
416         basename = _uc_first(filename, bld)
417         destination_filename = '%s%s' % (basename, ext)
418         destination = os.path.join(base_dir, destination_filename)
419         bld.install_as(destination, filename)
421     start_dir = bld.path.find_dir('doc/images')
422     bld.install_files('${DOCDIR}/%simages' % html_dir, start_dir.ant_glob('*.png'), cwd=start_dir)
423     bld.install_as('${DOCDIR}/%s' % _uc_first('manual.txt', bld), 'doc/geany.txt')
424     bld.install_as('${DOCDIR}/%s%s' % (html_dir, html_name), 'doc/geany.html')
425     bld.install_as('${DOCDIR}/ScintillaLicense.txt', 'scintilla/License.txt')
426     if is_win32:
427         bld.install_as('${DOCDIR}/ReadMe.I18n.txt', 'README.I18N')
428         bld.install_as('${DOCDIR}/Hacking.txt', 'HACKING')
429     # Data
430     data_dir = '' if is_win32 else 'geany'
431     start_dir = bld.path.find_dir('data')
432     bld.install_as('${DATADIR}/%s/GPL-2' % data_dir, 'COPYING')
433     bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('filetype*'), cwd=start_dir)
434     bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('*.tags'), cwd=start_dir)
435     bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.glade')
436     bld.install_files('${DATADIR}/%s' % data_dir, 'data/snippets.conf')
437     bld.install_files('${DATADIR}/%s' % data_dir, 'data/ui_toolbar.xml')
438     start_dir = bld.path.find_dir('data/colorschemes')
439     template_dest = '${DATADIR}/%s/colorschemes' % data_dir
440     bld.install_files(template_dest, start_dir.ant_glob('*'), cwd=start_dir)
441     start_dir = bld.path.find_dir('data/templates')
442     template_dest = '${DATADIR}/%s/templates' % data_dir
443     bld.install_files(template_dest, start_dir.ant_glob('**/*'), cwd=start_dir, relative_trick=True)
444     # Icons
445     icon_dest = '${PREFIX}/share/icons' if is_win32 else '${DATADIR}/icons/hicolor/16x16/apps'
446     start_dir = bld.path.find_dir('icons/16x16')
447     bld.install_files(icon_dest, start_dir.ant_glob('*.png'), cwd=start_dir)
448     if not is_win32:
449         start_dir = bld.path.find_dir('icons/48x48')
450         icon_dest = '${DATADIR}/icons/hicolor/48x48/apps'
451         bld.install_files(icon_dest, start_dir.ant_glob('*.png'), cwd=start_dir)
452         start_dir = bld.path.find_dir('icons/scalable')
453         scalable_dest = '${DATADIR}/icons/hicolor/scalable/apps'
454         bld.install_files(scalable_dest, start_dir.ant_glob('*.svg'), cwd=start_dir)
457 def distclean(ctx):
458     Scripting.distclean(ctx)
459     _remove_linguas_file()
462 def _remove_linguas_file():
463     # remove LINGUAS file as well
464     try:
465         os.unlink(LINGUAS_FILE)
466     except OSError:
467         pass
470 @feature('linguas')
471 def write_linguas_file(self):
472     if os.path.exists(LINGUAS_FILE):
473         return
474     linguas = ''
475     if 'LINGUAS' in self.env:
476         files = self.env['LINGUAS']
477         for po_filename in files.split(' '):
478             if os.path.exists('po/%s.po' % po_filename):
479                 linguas += '%s ' % po_filename
480     else:
481         files = os.listdir('%s/po' % self.path.abspath())
482         files.sort()
483         for filename in files:
484             if filename.endswith('.po'):
485                 linguas += '%s ' % filename[:-3]
486     file_h = open(LINGUAS_FILE, 'w')
487     file_h.write('# This file is autogenerated. Do not edit.\n%s\n' % linguas)
488     file_h.close()
491 def _post_install(ctx):
492     is_win32 = _target_is_win32(ctx)
493     if is_win32:
494         return
495     theme_dir = Utils.subst_vars('${DATADIR}/icons/hicolor', ctx.env)
496     icon_cache_updated = False
497     if not ctx.options.destdir:
498         ctx.exec_command('gtk-update-icon-cache -q -f -t %s' % theme_dir)
499         Logs.pprint('GREEN', 'GTK icon cache updated.')
500         icon_cache_updated = True
501     if not icon_cache_updated:
502         Logs.pprint('YELLOW', 'Icon cache not updated. After install, run this:')
503         Logs.pprint('YELLOW', 'gtk-update-icon-cache -q -f -t %s' % theme_dir)
506 def updatepo(ctx):
507     """update the message catalogs for internationalization"""
508     potfile = '%s.pot' % APPNAME
509     os.chdir('%s/po' % top)
510     try:
511         try:
512             old_size = os.stat(potfile).st_size
513         except OSError:
514             old_size = 0
515         ctx.exec_command('intltool-update --pot -g %s' % APPNAME)
516         size_new = os.stat(potfile).st_size
517         if size_new != old_size:
518             Logs.pprint('CYAN', 'Updated POT file.')
519             Logs.pprint('CYAN', 'Updating translations')
520             ret = ctx.exec_command('intltool-update -r -g %s' % APPNAME)
521             if ret != 0:
522                 Logs.pprint('RED', 'Updating translations failed')
523         else:
524             Logs.pprint('CYAN', 'POT file is up to date.')
525     except OSError:
526         Logs.pprint('RED', 'Failed to generate pot file.')
529 def apidoc(ctx):
530     """generate API reference documentation"""
531     basedir = ctx.path.abspath()
532     doxygen = _find_program(ctx, 'doxygen')
533     doxyfile = '%s/%s/doc/Doxyfile' % (basedir, out)
534     os.chdir('doc')
535     Logs.pprint('CYAN', 'Generating API documentation')
536     ret = ctx.exec_command('%s %s' % (doxygen, doxyfile))
537     if ret != 0:
538         raise WafError('Generating API documentation failed')
539     # update hacking.html
540     cmd = _find_rst2html(ctx)
541     ctx.exec_command('%s  -stg --stylesheet=geany.css %s %s' % (cmd, '../HACKING', 'hacking.html'))
542     os.chdir('..')
545 def htmldoc(ctx):
546     """generate HTML documentation"""
547     # first try rst2html.py as it is the upstream default, fall back to rst2html
548     cmd = _find_rst2html(ctx)
549     os.chdir('doc')
550     Logs.pprint('CYAN', 'Generating HTML documentation')
551     ctx.exec_command('%s  -stg --stylesheet=geany.css %s %s' % (cmd, 'geany.txt', 'geany.html'))
552     os.chdir('..')
555 def _find_program(ctx, cmd, **kw):
556     def noop(*args):
557         pass
559     ctx = ConfigurationContext()
560     ctx.to_log = noop
561     ctx.msg = noop
562     return ctx.find_program(cmd, **kw)
565 def _find_rst2html(ctx):
566     cmds = ['rst2html.py', 'rst2html']
567     for command in cmds:
568         cmd = _find_program(ctx, command, mandatory=False)
569         if cmd:
570             break
571     if not cmd:
572         raise WafError(
573             'rst2html.py could not be found. Please install the Python docutils package.')
574     return cmd
577 def _add_define_to_env(conf, key):
578     value = conf.get_define(key)
579     # strip quotes
580     value = value.replace('"', '')
581     conf.env[key] = value
584 def _add_to_env_and_define(conf, key, value, quote=False):
585     conf.define(key, value, quote)
586     conf.env[key] = value
589 def _define_from_opt(conf, define_name, opt_value, default_value, quote=1):
590     value = default_value
591     if opt_value:
592         if isinstance(opt_value, bool):
593             opt_value = 1
594         value = opt_value
596     if value is not None:
597         _add_to_env_and_define(conf, define_name, value, quote)
598     else:
599         conf.undefine(define_name)
602 def _get_git_rev(conf):
603     if not os.path.isdir('.git'):
604         return
606     try:
607         cmd = 'git rev-parse --short --revs-only HEAD'
608         revision = conf.cmd_and_log(cmd).strip()
609     except WafError:
610         return None
611     else:
612         return revision
615 def _load_intltool_if_available(conf):
616     try:
617         conf.check_tool('intltool')
618         if 'LINGUAS' in os.environ:
619             conf.env['LINGUAS'] = os.environ['LINGUAS']
620     except WafError:
621         # on Windows, we don't hard depend on intltool, on all other platforms raise an error
622         if not _target_is_win32(conf):
623             raise
626 def _target_is_win32(ctx):
627     if 'is_win32' in ctx.env:
628         # cached
629         return ctx.env['is_win32']
630     is_win32 = None
631     if sys.platform == 'win32':
632         is_win32 = True
633     if is_win32 is None:
634         if ctx.env and 'CC' in ctx.env:
635             env_cc = ctx.env['CC']
636             if not isinstance(env_cc, str):
637                 env_cc = ''.join(env_cc)
638             is_win32 = (env_cc.find('mingw') != -1)
639     if is_win32 is None:
640         is_win32 = False
641     # cache for future checks
642     ctx.env['is_win32'] = is_win32
643     return is_win32
646 def _uc_first(string, ctx):
647     if _target_is_win32(ctx):
648         return string.title()
649     return string