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