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