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