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.
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)
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).
45 from waflib import Logs, Options, Scripting, Utils
46 from waflib.Build import BuildContext
47 from waflib.Configure import ConfigurationContext
48 from waflib.Errors import WafError
49 from waflib.TaskGen import feature, before_method
50 from waflib.Tools.compiler_c import c_compiler
51 from waflib.Tools.compiler_cxx import cxx_compiler
56 LINGUAS_FILE = os.path.join('po', 'LINGUAS')
57 MINIMUM_GTK_VERSION = '2.16.0'
58 MINIMUM_GTK3_VERSION = '3.0.0'
59 MINIMUM_GLIB_VERSION = '2.20.0'
65 mio_sources = set(['tagmanager/mio/mio.c'])
68 'tagmanager/ctags/abaqus.c',
69 'tagmanager/ctags/args.c',
70 'tagmanager/ctags/abc.c',
71 'tagmanager/ctags/actionscript.c',
72 'tagmanager/ctags/asciidoc.c',
73 'tagmanager/ctags/asm.c',
74 'tagmanager/ctags/basic.c',
75 'tagmanager/ctags/c.c',
76 'tagmanager/ctags/cobol.c',
77 'tagmanager/ctags/conf.c',
78 'tagmanager/ctags/css.c',
79 'tagmanager/ctags/ctags.c',
80 'tagmanager/ctags/diff.c',
81 'tagmanager/ctags/docbook.c',
82 'tagmanager/ctags/entry.c',
83 'tagmanager/ctags/fortran.c',
84 'tagmanager/ctags/get.c',
85 'tagmanager/ctags/go.c',
86 'tagmanager/ctags/haskell.c',
87 'tagmanager/ctags/haxe.c',
88 'tagmanager/ctags/html.c',
89 'tagmanager/ctags/js.c',
90 'tagmanager/ctags/keyword.c',
91 'tagmanager/ctags/latex.c',
92 'tagmanager/ctags/lregex.c',
93 'tagmanager/ctags/lua.c',
94 'tagmanager/ctags/make.c',
95 'tagmanager/ctags/markdown.c',
96 'tagmanager/ctags/matlab.c',
97 'tagmanager/ctags/nsis.c',
98 'tagmanager/ctags/nestlevel.c',
99 'tagmanager/ctags/objc.c',
100 'tagmanager/ctags/options.c',
101 'tagmanager/ctags/parse.c',
102 'tagmanager/ctags/pascal.c',
103 'tagmanager/ctags/r.c',
104 'tagmanager/ctags/perl.c',
105 'tagmanager/ctags/php.c',
106 'tagmanager/ctags/python.c',
107 'tagmanager/ctags/read.c',
108 'tagmanager/ctags/rest.c',
109 'tagmanager/ctags/ruby.c',
110 'tagmanager/ctags/rust.c',
111 'tagmanager/ctags/sh.c',
112 'tagmanager/ctags/sort.c',
113 'tagmanager/ctags/sql.c',
114 'tagmanager/ctags/strlist.c',
115 'tagmanager/ctags/txt2tags.c',
116 'tagmanager/ctags/tcl.c',
117 'tagmanager/ctags/vhdl.c',
118 'tagmanager/ctags/verilog.c',
119 'tagmanager/ctags/vstring.c'])
121 tagmanager_sources = set([
122 'tagmanager/src/tm_file_entry.c',
123 'tagmanager/src/tm_source_file.c',
124 'tagmanager/src/tm_tag.c',
125 'tagmanager/src/tm_work_object.c',
126 'tagmanager/src/tm_workspace.c'])
128 scintilla_sources = set(['scintilla/gtk/scintilla-marshal.c'])
130 geany_sources = set([
131 'src/about.c', 'src/build.c', 'src/callbacks.c', 'src/dialogs.c', 'src/document.c',
132 'src/editor.c', 'src/encodings.c', 'src/filetypes.c', 'src/geanyentryaction.c',
133 'src/geanymenubuttonaction.c', 'src/geanyobject.c', 'src/geanywraplabel.c',
134 'src/highlighting.c', 'src/keybindings.c',
135 'src/keyfile.c', 'src/log.c', 'src/main.c', 'src/msgwindow.c', 'src/navqueue.c', 'src/notebook.c',
136 'src/plugins.c', 'src/pluginutils.c', 'src/prefix.c', 'src/prefs.c', 'src/printing.c', 'src/project.c',
137 'src/sciwrappers.c', 'src/search.c', 'src/socket.c', 'src/stash.c',
139 'src/templates.c', 'src/toolbar.c', 'src/tools.c', 'src/sidebar.c',
140 'src/ui_utils.c', 'src/utils.c'])
143 'hicolor/16x16/apps': ['16x16/classviewer-class.png',
144 '16x16/classviewer-macro.png',
145 '16x16/classviewer-member.png',
146 '16x16/classviewer-method.png',
147 '16x16/classviewer-namespace.png',
148 '16x16/classviewer-other.png',
149 '16x16/classviewer-struct.png',
150 '16x16/classviewer-var.png',
152 'hicolor/16x16/actions': ['16x16/geany-build.png',
153 '16x16/geany-close-all.png',
154 '16x16/geany-save-all.png'],
155 'hicolor/24x24/actions': ['24x24/geany-build.png',
156 '24x24/geany-close-all.png',
157 '24x24/geany-save-all.png'],
158 'hicolor/32x32/actions': ['32x32/geany-build.png',
159 '32x32/geany-close-all.png',
160 '32x32/geany-save-all.png'],
161 'hicolor/48x48/actions': ['48x48/geany-build.png',
162 '48x48/geany-close-all.png',
163 '48x48/geany-save-all.png'],
164 'hicolor/48x48/apps': ['48x48/geany.png'],
165 'hicolor/scalable/apps': ['scalable/geany.svg'],
166 'hicolor/scalable/actions': ['scalable/geany-build.svg',
167 'scalable/geany-close-all.svg',
168 'scalable/geany-save-all.svg'],
169 'Tango/16x16/actions': ['tango/16x16/geany-save-all.png'],
170 'Tango/24x24/actions': ['tango/24x24/geany-save-all.png'],
171 'Tango/32x32/actions': ['tango/32x32/geany-save-all.png'],
172 'Tango/48x48/actions': ['tango/48x48/geany-save-all.png'],
173 'Tango/scalable/actions': ['tango/scalable/geany-save-all.svg']
175 geany_icons_indexes = {
176 'hicolor': ['index.theme'],
177 'Tango': ['tango/index.theme']
183 conf.check_waf_version(mini='1.6.1')
185 conf.load('compiler_c')
186 is_win32 = _target_is_win32(conf)
188 conf.check_cc(header_name='fcntl.h', mandatory=False)
189 conf.check_cc(header_name='fnmatch.h', mandatory=False)
190 conf.check_cc(header_name='glob.h', mandatory=False)
191 conf.check_cc(header_name='sys/time.h', mandatory=False)
192 conf.check_cc(header_name='sys/types.h', mandatory=False)
193 conf.check_cc(header_name='sys/stat.h', mandatory=False)
194 conf.define('HAVE_STDLIB_H', 1) # are there systems without stdlib.h?
195 conf.define('STDC_HEADERS', 1) # an optimistic guess ;-)
196 _add_to_env_and_define(conf, 'HAVE_REGCOMP', 1) # needed for CTags
198 conf.check_cc(function_name='fgetpos', header_name='stdio.h', mandatory=False)
199 conf.check_cc(function_name='ftruncate', header_name='unistd.h', mandatory=False)
200 conf.check_cc(function_name='mkstemp', header_name='stdlib.h', mandatory=False)
201 conf.check_cc(function_name='strstr', header_name='string.h')
203 conf.check_cc(function_name='pow', header_name='math.h', lib='m', uselib_store='M')
205 # check sunOS socket support
206 if Options.platform == 'sunos':
207 conf.check_cc(function_name='socket', lib='socket',
208 header_name='sys/socket.h', uselib_store='SUNOS_SOCKET', mandatory=True)
210 # check for cxx after the header and function checks have been done to ensure they are
211 # checked with cc not cxx
212 conf.load('compiler_cxx')
215 _load_intltool_if_available(conf)
217 # GTK / GIO version check
218 gtk_package_name = 'gtk+-3.0' if conf.options.use_gtk3 else 'gtk+-2.0'
219 minimum_gtk_version = MINIMUM_GTK3_VERSION if conf.options.use_gtk3 else MINIMUM_GTK_VERSION
220 conf.check_cfg(package=gtk_package_name, atleast_version=minimum_gtk_version, uselib_store='GTK',
221 mandatory=True, args='--cflags --libs')
222 conf.check_cfg(package='glib-2.0', atleast_version=MINIMUM_GLIB_VERSION, uselib_store='GLIB',
223 mandatory=True, args='--cflags --libs')
224 conf.check_cfg(package='gmodule-2.0', uselib_store='GMODULE',
225 mandatory=True, args='--cflags --libs')
226 conf.check_cfg(package='gio-2.0', uselib_store='GIO', args='--cflags --libs', mandatory=True)
227 gtk_version = conf.check_cfg(modversion=gtk_package_name, uselib_store='GTK') or 'Unknown'
228 conf.check_cfg(package='gthread-2.0', uselib_store='GTHREAD', args='--cflags --libs')
229 # remember GTK version for the build step
230 conf.env['gtk_package_name'] = gtk_package_name
231 conf.env['minimum_gtk_version'] = minimum_gtk_version
232 conf.env['use_gtk3'] = conf.options.use_gtk3
234 revision = _get_git_rev(conf)
236 # rst2html for the HTML manual
237 if not conf.options.no_html_doc and revision is not None:
239 conf.env['RST2HTML'] = _find_rst2html(conf)
241 error_msg = '''Documentation enabled but rst2html not found.
242 You can explicitly disable building of the HTML manual with --disable-html-docs,
243 but you then may not have a local copy of the HTML manual.'''
244 raise WafError(error_msg)
248 if conf.env['PREFIX'].lower() == tempfile.gettempdir().lower():
249 # overwrite default prefix on Windows (tempfile.gettempdir() is the Waf default)
250 new_prefix = os.path.join(str(conf.root), '%s-%s' % (APPNAME, VERSION))
251 _add_to_env_and_define(conf, 'PREFIX', new_prefix, quote=True)
252 _add_to_env_and_define(conf, 'BINDIR', os.path.join(new_prefix, 'bin'), quote=True)
253 _add_to_env_and_define(conf, 'DOCDIR', os.path.join(conf.env['PREFIX'], 'doc'), quote=True)
254 _add_to_env_and_define(conf, 'LIBDIR', '%s/lib' % conf.env['PREFIX'], quote=True)
255 conf.define('LOCALEDIR', os.path.join('share' 'locale'), quote=True)
256 # overwrite LOCALEDIR to install message catalogues properly
257 conf.env['LOCALEDIR'] = os.path.join(conf.env['PREFIX'], 'share', 'locale')
258 # DATADIR is defined in objidl.h, so we remove it from config.h but keep it in env
259 conf.undefine('DATADIR')
260 conf.env['DATADIR'] = os.path.join(conf.env['PREFIX'], 'data')
261 conf.env.append_value('LINKFLAGS_cprogram', [
264 '-static-libstdc++'])
265 conf.env.append_value('LIB_WIN32', ['wsock32', 'uuid', 'ole32', 'iberty'])
266 # explicitly define Windows version for older Mingw environments
267 conf.define('WINVER', '0x0501', quote=False) # for SHGetFolderPathAndSubDirW
268 conf.define('_WIN32_IE', '0x0500', quote=False) # for SHGFP_TYPE
270 conf.env['cshlib_PATTERN'] = '%s.so'
271 # DATADIR and LOCALEDIR are defined by the intltool tool
272 # but they are not added to the environment, so we need to
273 _add_define_to_env(conf, 'DATADIR')
274 _add_define_to_env(conf, 'LOCALEDIR')
275 docdir = os.path.join(conf.env['DATADIR'], 'doc', 'geany')
276 libdir = os.path.join(conf.env['PREFIX'], 'lib')
277 mandir = os.path.join(conf.env['DATADIR'], 'man')
278 _define_from_opt(conf, 'DOCDIR', conf.options.docdir, docdir)
279 _define_from_opt(conf, 'LIBDIR', conf.options.libdir, libdir)
280 _define_from_opt(conf, 'MANDIR', conf.options.mandir, mandir)
282 conf.define('ENABLE_NLS', 1)
283 conf.define('GEANY_LOCALEDIR', '' if is_win32 else conf.env['LOCALEDIR'], quote=True)
284 conf.define('GEANY_DATADIR', 'data' if is_win32 else conf.env['DATADIR'], quote=True)
285 conf.define('GEANY_DOCDIR', conf.env['DOCDIR'], quote=True)
286 conf.define('GEANY_LIBDIR', '' if is_win32 else conf.env['LIBDIR'], quote=True)
287 conf.define('GEANY_PREFIX', '' if is_win32 else conf.env['PREFIX'], quote=True)
288 conf.define('PACKAGE', APPNAME, quote=True)
289 conf.define('VERSION', VERSION, quote=True)
290 conf.define('REVISION', revision or '-1', quote=True)
292 conf.define('GETTEXT_PACKAGE', APPNAME, quote=True)
296 conf.options.no_vte = True
298 _define_from_opt(conf, 'HAVE_PLUGINS', not conf.options.no_plugins, None)
299 _define_from_opt(conf, 'HAVE_SOCKET', not conf.options.no_socket, None)
300 _define_from_opt(conf, 'HAVE_VTE', not conf.options.no_vte, None)
302 conf.write_config_header('config.h', remove=False)
304 # some more compiler flags
305 conf.env.append_value('CFLAGS', ['-DHAVE_CONFIG_H'])
306 if conf.env['CC_NAME'] == 'gcc' and '-O' not in ''.join(conf.env['CFLAGS']):
307 conf.env.append_value('CFLAGS', ['-O2'])
308 if revision is not None:
309 conf.env.append_value('CFLAGS', ['-g', '-DGEANY_DEBUG'])
311 conf.env.append_value('CFLAGS', ['-DGTK'])
312 conf.env.append_value('CXXFLAGS',
313 ['-DNDEBUG', '-DGTK', '-DSCI_LEXER', '-DG_THREADS_IMPL_NONE'])
316 Logs.pprint('BLUE', 'Summary:')
317 conf.msg('Install Geany ' + VERSION + ' in', conf.env['PREFIX'])
318 conf.msg('Using GTK version', gtk_version)
319 conf.msg('Build with plugin support', conf.options.no_plugins and 'no' or 'yes')
320 conf.msg('Use virtual terminal support', conf.options.no_vte and 'no' or 'yes')
321 if revision is not None:
322 conf.msg('Compiling Git revision', revision)
326 # Disable MSVC detection on win32: building Geany with MSVC is currently not supported
327 # If anyone wants to add support for building with MSVC, this hack should be removed.
328 c_compiler['win32'] = ['gcc']
329 cxx_compiler['win32'] = ['g++']
331 opt.load('compiler_cc')
332 opt.load('compiler_cxx')
336 opt.add_option('--no-scm', action='store_true', default=False,
337 help='Disable SCM detection [default: No]', dest='no_scm')
339 opt.add_option('--disable-plugins', action='store_true', default=False,
340 help='compile without plugin support [default: No]', dest='no_plugins')
341 opt.add_option('--disable-socket', action='store_true', default=False,
342 help='compile without support to detect a running instance [[default: No]',
344 opt.add_option('--disable-vte', action='store_true', default=False,
345 help='compile without support for an embedded virtual terminal [[default: No]',
347 opt.add_option('--enable-gtk3', action='store_true', default=False,
348 help='compile with GTK3 support (experimental) [[default: No]',
350 opt.add_option('--disable-html-docs', action='store_true', default=False,
351 help='do not generate HTML documentation using rst2html [[default: No]',
354 opt.add_option('--mandir', type='string', default='',
355 help='man documentation', dest='mandir')
356 opt.add_option('--docdir', type='string', default='',
357 help='documentation root', dest='docdir')
358 opt.add_option('--libdir', type='string', default='',
359 help='object code libraries', dest='libdir')
363 is_win32 = _target_is_win32(bld)
365 if bld.cmd == 'clean':
366 _remove_linguas_file()
367 if bld.cmd in ('install', 'uninstall'):
368 bld.add_post_fun(_post_install)
370 def build_plugin(plugin_name, install=True, uselib_add=[]):
372 instpath = '${PREFIX}/lib' if is_win32 else '${LIBDIR}/geany'
377 features = ['c', 'cshlib'],
378 source = 'plugins/%s.c' % plugin_name,
379 includes = ['.', 'src/', 'scintilla/include', 'tagmanager/src'],
380 defines = 'G_LOG_DOMAIN="%s"' % plugin_name,
381 target = plugin_name,
382 uselib = ['GTK', 'GLIB', 'GMODULE'] + uselib_add,
383 install_path = instpath)
387 features = ['c', 'cstlib'],
388 source = ctags_sources,
391 includes = ['.', 'tagmanager', 'tagmanager/ctags'],
392 defines = 'G_LOG_DOMAIN="CTags"',
394 install_path = None) # do not install this library
398 features = ['c', 'cstlib'],
399 source = tagmanager_sources,
401 target = 'tagmanager',
402 includes = ['.', 'tagmanager', 'tagmanager/ctags'],
403 defines = ['GEANY_PRIVATE', 'G_LOG_DOMAIN="Tagmanager"'],
404 uselib = ['GTK', 'GLIB'],
405 install_path = None) # do not install this library
409 features = ['c', 'cstlib'],
410 source = mio_sources,
413 includes = ['.', 'tagmanager/mio/'],
414 defines = 'G_LOG_DOMAIN="MIO"',
415 uselib = ['GTK', 'GLIB'],
416 install_path = None) # do not install this library
419 files = bld.srcnode.ant_glob('scintilla/**/*.cxx', src=True, dir=False)
420 scintilla_sources.update(files)
422 features = ['c', 'cxx', 'cxxstlib'],
424 target = 'scintilla',
425 source = scintilla_sources,
426 includes = ['.', 'scintilla/include', 'scintilla/src', 'scintilla/lexlib'],
427 uselib = ['GTK', 'GLIB', 'GMODULE', 'M'],
428 install_path = None) # do not install this library
431 if bld.env['HAVE_VTE'] == 1:
432 geany_sources.add('src/vte.c')
434 geany_sources.add('src/win32.c')
435 geany_sources.add('geany_private.rc')
438 features = ['c', 'cxx', 'cprogram'],
441 source = geany_sources,
442 includes = ['.', 'scintilla/include', 'tagmanager/src'],
443 defines = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
444 uselib = ['GTK', 'GLIB', 'GMODULE', 'GIO', 'GTHREAD', 'WIN32', 'SUNOS_SOCKET', 'M'],
445 use = ['scintilla', 'ctags', 'tagmanager', 'mio'])
449 source = ['plugins/genapi.py', 'src/plugins.c'],
450 name = 'geanyfunctions.h',
451 before = ['c', 'cxx'],
452 cwd = '%s/plugins' % bld.path.abspath(),
453 rule = '%s genapi.py -q' % sys.executable)
456 if bld.env['HAVE_PLUGINS'] == 1:
457 build_plugin('classbuilder')
458 build_plugin('demoplugin', False)
459 build_plugin('export', uselib_add=['M'])
460 build_plugin('filebrowser')
461 build_plugin('htmlchars')
462 build_plugin('saveactions')
463 build_plugin('splitwindow')
466 if bld.env['INTLTOOL']:
468 features = ['linguas', 'intltool_po'],
470 install_path = '${LOCALEDIR}',
473 # HTML documentation (build if it is not part of the tree already, as it is required for install)
474 html_doc_filename = os.path.join(bld.out_dir, 'doc', 'geany.html')
475 if bld.env['RST2HTML']:
476 rst2html = bld.env['RST2HTML']
478 source = ['doc/geany.txt'],
479 deps = ['doc/geany.css'],
480 target = 'doc/geany.html',
482 cwd = os.path.join(bld.path.abspath(), 'doc'),
483 rule = '%s -stg --stylesheet=geany.css geany.txt %s' % (rst2html, html_doc_filename))
487 # replace backward slashes by forward slashes as they could be interepreted as escape
489 geany_pc_prefix = bld.env['PREFIX'].replace('\\', '/')
491 geany_pc_prefix = bld.env['PREFIX']
493 source = 'geany.pc.in',
494 dct = {'VERSION': VERSION,
495 'DEPENDENCIES': '%s >= %s glib-2.0 >= %s' % \
496 (bld.env['gtk_package_name'],
497 bld.env['minimum_gtk_version'],
498 MINIMUM_GLIB_VERSION),
499 'prefix': geany_pc_prefix,
500 'exec_prefix': '${prefix}',
501 'libdir': '${exec_prefix}/lib',
502 'includedir': '${prefix}/include',
503 'datarootdir': '${prefix}/share',
504 'datadir': '${datarootdir}',
505 'localedir': '${datarootdir}/locale'})
509 if bld.env['INTLTOOL']:
511 features = 'intltool_in',
512 source = 'geany.desktop.in',
513 flags = ['-d', '-q', '-u', '-c'],
514 install_path = '${DATADIR}/applications')
519 source = 'doc/geany.1.in',
521 dct = {'VERSION': VERSION,
522 'GEANY_DATA_DIR': bld.env['DATADIR'] + '/geany'},
523 install_path = '${MANDIR}/man1')
528 source = 'geany.spec.in',
529 target = 'geany.spec',
531 dct = {'VERSION': VERSION})
536 source = 'doc/Doxyfile.in',
537 target = 'doc/Doxyfile',
539 dct = {'VERSION': VERSION,
540 'top_builddir': bld.out_dir,
541 'top_srcdir': bld.top_dir,})
547 bld.install_files('${PREFIX}/include/geany', '''
548 src/app.h src/document.h src/editor.h src/encodings.h src/filetypes.h src/geany.h
549 src/highlighting.h src/keybindings.h src/msgwindow.h src/plugindata.h
550 src/prefs.h src/project.h src/search.h src/stash.h src/support.h
551 src/templates.h src/toolbar.h src/ui_utils.h src/utils.h src/build.h src/gtkcompat.h
552 plugins/geanyplugin.h plugins/geanyfunctions.h''')
553 bld.install_files('${PREFIX}/include/geany/scintilla', '''
554 scintilla/include/SciLexer.h scintilla/include/Scintilla.h
555 scintilla/include/Scintilla.iface scintilla/include/ScintillaWidget.h ''')
556 bld.install_files('${PREFIX}/include/geany/tagmanager', '''
557 tagmanager/src/tm_source_file.h
558 tagmanager/src/tm_tag.h
559 tagmanager/src/tm_tagmanager.h tagmanager/src/tm_work_object.h
560 tagmanager/src/tm_workspace.h ''')
562 base_dir = '${PREFIX}' if is_win32 else '${DOCDIR}'
563 ext = '.txt' if is_win32 else ''
564 for filename in 'AUTHORS ChangeLog COPYING README NEWS THANKS TODO'.split():
565 basename = _uc_first(filename, bld)
566 destination_filename = '%s%s' % (basename, ext)
567 destination = os.path.join(base_dir, destination_filename)
568 bld.install_as(destination, filename)
570 # install HTML documentation only if it exists, i.e. it was built before
571 # local_html_doc_filename supports installing HTML doc from in-tree geany.html if it exists
572 local_html_doc_filename = os.path.join(bld.path.abspath(), 'doc', 'geany.html')
573 if os.path.exists(html_doc_filename) or os.path.exists(local_html_doc_filename):
574 html_dir = '' if is_win32 else 'html/'
575 html_name = 'Manual.html' if is_win32 else 'index.html'
576 start_dir = bld.path.find_dir('doc/images')
577 bld.install_files('${DOCDIR}/%simages' % html_dir, start_dir.ant_glob('*.png'), cwd=start_dir)
578 bld.install_as('${DOCDIR}/%s%s' % (html_dir, html_name), 'doc/geany.html')
580 bld.install_as('${DOCDIR}/%s' % _uc_first('manual.txt', bld), 'doc/geany.txt')
581 bld.install_as('${DOCDIR}/ScintillaLicense.txt', 'scintilla/License.txt')
583 bld.install_as('${DOCDIR}/ReadMe.I18n.txt', 'README.I18N')
584 bld.install_as('${DOCDIR}/Hacking.txt', 'HACKING')
586 data_dir = '' if is_win32 else 'geany'
587 start_dir = bld.path.find_dir('data')
588 bld.install_as('${DATADIR}/%s/GPL-2' % data_dir, 'COPYING')
589 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('filetype*'), cwd=start_dir)
590 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('*.tags'), cwd=start_dir)
591 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.glade')
592 bld.install_files('${DATADIR}/%s' % data_dir, 'data/snippets.conf')
593 bld.install_files('${DATADIR}/%s' % data_dir, 'data/ui_toolbar.xml')
594 if bld.env['use_gtk3']:
595 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.css')
597 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.gtkrc')
599 start_dir = bld.path.find_dir('data/colorschemes')
600 template_dest = '${DATADIR}/%s/colorschemes' % data_dir
601 bld.install_files(template_dest, start_dir.ant_glob('*'), cwd=start_dir)
602 start_dir = bld.path.find_dir('data/templates')
603 template_dest = '${DATADIR}/%s/templates' % data_dir
604 bld.install_files(template_dest, start_dir.ant_glob('**/*'), cwd=start_dir, relative_trick=True)
606 for dest, srcs in geany_icons.items():
607 dest_dir = os.path.join('${PREFIX}/share/icons' if is_win32 else '${DATADIR}/icons', dest)
608 bld.install_files(dest_dir, srcs, cwd=bld.path.find_dir('icons'))
609 # install theme indexes on Windows
611 for dest, srcs in geany_icons_indexes.items():
612 bld.install_files(os.path.join('${PREFIX}/share/icons', dest), srcs, cwd=bld.path.find_dir('icons'))
616 Scripting.distclean(ctx)
617 _remove_linguas_file()
620 def _remove_linguas_file():
621 # remove LINGUAS file as well
623 os.unlink(LINGUAS_FILE)
629 @before_method('apply_intltool_po')
630 def write_linguas_file(self):
631 if os.path.exists(LINGUAS_FILE):
634 if 'LINGUAS' in self.env:
635 files = self.env['LINGUAS']
636 for po_filename in files.split(' '):
637 if os.path.exists('po/%s.po' % po_filename):
638 linguas += '%s ' % po_filename
640 files = os.listdir('%s/po' % self.path.abspath())
642 for filename in files:
643 if filename.endswith('.po'):
644 linguas += '%s ' % filename[:-3]
645 file_h = open(LINGUAS_FILE, 'w')
646 file_h.write('# This file is autogenerated. Do not edit.\n%s\n' % linguas)
650 def _post_install(ctx):
651 is_win32 = _target_is_win32(ctx)
654 for d in 'hicolor', 'Tango':
655 theme_dir = Utils.subst_vars('${DATADIR}/icons/' + d, ctx.env)
656 icon_cache_updated = False
657 if not ctx.options.destdir:
658 ctx.exec_command('gtk-update-icon-cache -q -f -t %s' % theme_dir)
659 Logs.pprint('GREEN', 'GTK icon cache updated.')
660 icon_cache_updated = True
661 if not icon_cache_updated:
662 Logs.pprint('YELLOW', 'Icon cache not updated. After install, run this:')
663 Logs.pprint('YELLOW', 'gtk-update-icon-cache -q -f -t %s' % theme_dir)
667 """update the message catalogs for internationalization"""
668 potfile = '%s.pot' % APPNAME
669 os.chdir('%s/po' % top)
672 old_size = os.stat(potfile).st_size
675 ctx.exec_command('intltool-update --pot -g %s' % APPNAME)
676 size_new = os.stat(potfile).st_size
677 if size_new != old_size:
678 Logs.pprint('CYAN', 'Updated POT file.')
679 Logs.pprint('CYAN', 'Updating translations')
680 ret = ctx.exec_command('intltool-update -r -g %s' % APPNAME)
682 Logs.pprint('RED', 'Updating translations failed')
684 Logs.pprint('CYAN', 'POT file is up to date.')
686 Logs.pprint('RED', 'Failed to generate pot file.')
690 """generate API reference documentation"""
691 ctx = BuildContext() # create our own context to have ctx.top_dir
692 basedir = ctx.top_dir
693 doxygen = _find_program(ctx, 'doxygen')
694 doxyfile = '%s/doc/Doxyfile' % ctx.out_dir
695 Logs.pprint('CYAN', 'Generating API documentation')
696 ret = ctx.exec_command('%s %s' % (doxygen, doxyfile))
698 raise WafError('Generating API documentation failed')
702 """generate HACKING documentation"""
703 ctx = BuildContext() # create our own context to have ctx.top_dir
704 Logs.pprint('CYAN', 'Generating HACKING documentation')
705 cmd = _find_rst2html(ctx)
706 hacking_file = os.path.join(ctx.top_dir, 'HACKING')
707 hacking_html_file = os.path.join(ctx.top_dir, 'doc', 'hacking.html')
708 stylesheet = os.path.join(ctx.top_dir, 'doc', 'geany.css')
709 ret = ctx.exec_command('%s -stg --stylesheet=%s %s %s' % (
710 cmd, stylesheet, hacking_file, hacking_html_file))
712 raise WafError('Generating HACKING documentation failed')
715 def _find_program(ctx, cmd, **kw):
719 if ctx is None or not isinstance(ctx, ConfigurationContext):
720 ctx = ConfigurationContext()
723 return ctx.find_program(cmd, **kw)
726 def _find_rst2html(ctx):
727 cmds = ['rst2html', 'rst2html2']
729 cmd = _find_program(ctx, command, mandatory=False, exts=',.py')
734 'rst2html.py could not be found. Please install the Python docutils package.')
738 def _add_define_to_env(conf, key):
739 value = conf.get_define(key)
741 value = value.replace('"', '')
742 conf.env[key] = value
745 def _add_to_env_and_define(conf, key, value, quote=False):
746 conf.define(key, value, quote)
747 conf.env[key] = value
750 def _define_from_opt(conf, define_name, opt_value, default_value, quote=1):
751 value = default_value
753 if isinstance(opt_value, bool):
757 if value is not None:
758 _add_to_env_and_define(conf, define_name, value, quote)
760 conf.undefine(define_name)
763 def _get_git_rev(conf):
764 if conf.options.no_scm:
767 if not os.path.isdir('.git'):
771 cmd = 'git rev-parse --short --revs-only HEAD'
772 revision = conf.cmd_and_log(cmd).strip()
779 def _load_intltool_if_available(conf):
781 conf.load('intltool')
782 if 'LINGUAS' in os.environ:
783 conf.env['LINGUAS'] = os.environ['LINGUAS']
785 # on Windows, we don't hard depend on intltool, on all other platforms raise an error
786 if not _target_is_win32(conf):
790 def _target_is_win32(ctx):
791 if 'is_win32' in ctx.env:
793 return ctx.env['is_win32']
795 if sys.platform == 'win32':
798 if ctx.env and 'CC' in ctx.env:
799 env_cc = ctx.env['CC']
800 if not isinstance(env_cc, str):
801 env_cc = ''.join(env_cc)
802 is_win32 = (env_cc.find('mingw') != -1)
805 # cache for future checks
806 ctx.env['is_win32'] = is_win32
810 def _uc_first(string, ctx):
811 if _target_is_win32(ctx):
812 return string.title()