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