Cleanup statusbar template code a bit
[geany-mirror.git] / wscript
blob50f5c1835f363636e6806b21d30086c273b8b788
1 # -*- coding: utf-8 -*-
3 # WAF build script - this file is part of Geany, a fast and lightweight IDE
5 # Copyright 2008-2012 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
6 # Copyright 2008-2012 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software
20 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 """
23 This is a WAF build script (http://code.google.com/p/waf/).
24 It can be used as an alternative build system to autotools
25 for Geany. It does not (yet) cover all of the autotools tests and
26 configure options but all important things are working.
27 "make dist" should be done with autotools, most other targets and
28 functions should work better (regarding performance and flexibility)
29 or at least equally.
31 Missing features: --enable-binreloc, make targets: dist, pdf (in doc/)
32 Known issues: Dependency handling is buggy, e.g. if src/document.h is
33               changed, depending source files are not rebuilt (maybe Waf bug).
35 The code of this file itself loosely follows PEP 8 with some exceptions
36 (line width 100 characters and some other minor things).
38 Requires WAF 1.6.1 and Python 2.5 (or later).
39 """
42 import sys
43 import os
44 import tempfile
45 from waflib import Logs, Options, Scripting, Utils
46 from waflib.Configure import ConfigurationContext
47 from waflib.Errors import WafError
48 from waflib.TaskGen import feature
51 APPNAME = 'geany'
52 VERSION = '1.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.tool_options('compiler_cc')
306     opt.tool_options('compiler_cxx')
307     opt.tool_options('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.new_task_gen(
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.new_task_gen(
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.new_task_gen(
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.new_task_gen(
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.new_task_gen(
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.new_task_gen(
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.new_task_gen(
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.new_task_gen(
439             features        = ['linguas', 'intltool_po'],
440             podir           = 'po',
441             install_path    = '${LOCALEDIR}',
442             appname         = 'geany')
444     # geany.pc
445     bld.new_task_gen(
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.new_task_gen(
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.new_task_gen(
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.new_task_gen(
480             features        = 'subst',
481             source          = 'geany.spec.in',
482             target          = 'geany.spec',
483             install_path    = None,
484             dct             = {'VERSION': VERSION})
486         # Doxyfile
487         bld.new_task_gen(
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 def write_linguas_file(self):
578     if os.path.exists(LINGUAS_FILE):
579         return
580     linguas = ''
581     if 'LINGUAS' in self.env:
582         files = self.env['LINGUAS']
583         for po_filename in files.split(' '):
584             if os.path.exists('po/%s.po' % po_filename):
585                 linguas += '%s ' % po_filename
586     else:
587         files = os.listdir('%s/po' % self.path.abspath())
588         files.sort()
589         for filename in files:
590             if filename.endswith('.po'):
591                 linguas += '%s ' % filename[:-3]
592     file_h = open(LINGUAS_FILE, 'w')
593     file_h.write('# This file is autogenerated. Do not edit.\n%s\n' % linguas)
594     file_h.close()
597 def _post_install(ctx):
598     is_win32 = _target_is_win32(ctx)
599     if is_win32:
600         return
601     for d in 'hicolor', 'Tango':
602         theme_dir = Utils.subst_vars('${DATADIR}/icons/' + d, ctx.env)
603         icon_cache_updated = False
604         if not ctx.options.destdir:
605             ctx.exec_command('gtk-update-icon-cache -q -f -t %s' % theme_dir)
606             Logs.pprint('GREEN', 'GTK icon cache updated.')
607             icon_cache_updated = True
608         if not icon_cache_updated:
609             Logs.pprint('YELLOW', 'Icon cache not updated. After install, run this:')
610             Logs.pprint('YELLOW', 'gtk-update-icon-cache -q -f -t %s' % theme_dir)
613 def updatepo(ctx):
614     """update the message catalogs for internationalization"""
615     potfile = '%s.pot' % APPNAME
616     os.chdir('%s/po' % top)
617     try:
618         try:
619             old_size = os.stat(potfile).st_size
620         except OSError:
621             old_size = 0
622         ctx.exec_command('intltool-update --pot -g %s' % APPNAME)
623         size_new = os.stat(potfile).st_size
624         if size_new != old_size:
625             Logs.pprint('CYAN', 'Updated POT file.')
626             Logs.pprint('CYAN', 'Updating translations')
627             ret = ctx.exec_command('intltool-update -r -g %s' % APPNAME)
628             if ret != 0:
629                 Logs.pprint('RED', 'Updating translations failed')
630         else:
631             Logs.pprint('CYAN', 'POT file is up to date.')
632     except OSError:
633         Logs.pprint('RED', 'Failed to generate pot file.')
636 def apidoc(ctx):
637     """generate API reference documentation"""
638     basedir = ctx.path.abspath()
639     doxygen = _find_program(ctx, 'doxygen')
640     doxyfile = '%s/%s/doc/Doxyfile' % (basedir, out)
641     os.chdir('doc')
642     Logs.pprint('CYAN', 'Generating API documentation')
643     ret = ctx.exec_command('%s %s' % (doxygen, doxyfile))
644     if ret != 0:
645         raise WafError('Generating API documentation failed')
646     # update hacking.html
647     cmd = _find_rst2html(ctx)
648     ctx.exec_command('%s  -stg --stylesheet=geany.css %s %s' % (cmd, '../HACKING', 'hacking.html'))
649     os.chdir('..')
652 def htmldoc(ctx):
653     """generate HTML documentation"""
654     # first try rst2html.py as it is the upstream default, fall back to rst2html
655     cmd = _find_rst2html(ctx)
656     os.chdir('doc')
657     Logs.pprint('CYAN', 'Generating HTML documentation')
658     ctx.exec_command('%s  -stg --stylesheet=geany.css %s %s' % (cmd, 'geany.txt', 'geany.html'))
659     os.chdir('..')
662 def _find_program(ctx, cmd, **kw):
663     def noop(*args):
664         pass
666     ctx = ConfigurationContext()
667     ctx.to_log = noop
668     ctx.msg = noop
669     return ctx.find_program(cmd, **kw)
672 def _find_rst2html(ctx):
673     cmds = ['rst2html.py', 'rst2html']
674     for command in cmds:
675         cmd = _find_program(ctx, command, mandatory=False)
676         if cmd:
677             break
678     if not cmd:
679         raise WafError(
680             'rst2html.py could not be found. Please install the Python docutils package.')
681     return cmd
684 def _add_define_to_env(conf, key):
685     value = conf.get_define(key)
686     # strip quotes
687     value = value.replace('"', '')
688     conf.env[key] = value
691 def _add_to_env_and_define(conf, key, value, quote=False):
692     conf.define(key, value, quote)
693     conf.env[key] = value
696 def _define_from_opt(conf, define_name, opt_value, default_value, quote=1):
697     value = default_value
698     if opt_value:
699         if isinstance(opt_value, bool):
700             opt_value = 1
701         value = opt_value
703     if value is not None:
704         _add_to_env_and_define(conf, define_name, value, quote)
705     else:
706         conf.undefine(define_name)
709 def _get_git_rev(conf):
710     if not os.path.isdir('.git'):
711         return
713     try:
714         cmd = 'git rev-parse --short --revs-only HEAD'
715         revision = conf.cmd_and_log(cmd).strip()
716     except WafError:
717         return None
718     else:
719         return revision
722 def _load_intltool_if_available(conf):
723     try:
724         conf.check_tool('intltool')
725         if 'LINGUAS' in os.environ:
726             conf.env['LINGUAS'] = os.environ['LINGUAS']
727     except WafError:
728         # on Windows, we don't hard depend on intltool, on all other platforms raise an error
729         if not _target_is_win32(conf):
730             raise
733 def _target_is_win32(ctx):
734     if 'is_win32' in ctx.env:
735         # cached
736         return ctx.env['is_win32']
737     is_win32 = None
738     if sys.platform == 'win32':
739         is_win32 = True
740     if is_win32 is None:
741         if ctx.env and 'CC' in ctx.env:
742             env_cc = ctx.env['CC']
743             if not isinstance(env_cc, str):
744                 env_cc = ''.join(env_cc)
745             is_win32 = (env_cc.find('mingw') != -1)
746     if is_win32 is None:
747         is_win32 = False
748     # cache for future checks
749     ctx.env['is_win32'] = is_win32
750     return is_win32
753 def _uc_first(string, ctx):
754     if _target_is_win32(ctx):
755         return string.title()
756     return string