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