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/haskell.c',
86 'tagmanager/ctags/haxe.c',
87 'tagmanager/ctags/html.c',
88 'tagmanager/ctags/js.c',
89 'tagmanager/ctags/keyword.c',
90 'tagmanager/ctags/latex.c',
91 'tagmanager/ctags/lregex.c',
92 'tagmanager/ctags/lua.c',
93 'tagmanager/ctags/make.c',
94 'tagmanager/ctags/markdown.c',
95 'tagmanager/ctags/matlab.c',
96 'tagmanager/ctags/nsis.c',
97 'tagmanager/ctags/nestlevel.c',
98 'tagmanager/ctags/objc.c',
99 'tagmanager/ctags/options.c',
100 'tagmanager/ctags/parse.c',
101 'tagmanager/ctags/pascal.c',
102 'tagmanager/ctags/r.c',
103 'tagmanager/ctags/perl.c',
104 'tagmanager/ctags/php.c',
105 'tagmanager/ctags/python.c',
106 'tagmanager/ctags/read.c',
107 'tagmanager/ctags/rest.c',
108 'tagmanager/ctags/ruby.c',
109 'tagmanager/ctags/rust.c',
110 'tagmanager/ctags/sh.c',
111 'tagmanager/ctags/sort.c',
112 'tagmanager/ctags/sql.c',
113 'tagmanager/ctags/strlist.c',
114 'tagmanager/ctags/txt2tags.c',
115 'tagmanager/ctags/tcl.c',
116 'tagmanager/ctags/vhdl.c',
117 'tagmanager/ctags/verilog.c',
118 'tagmanager/ctags/vstring.c'])
120 tagmanager_sources = set([
121 'tagmanager/src/tm_file_entry.c',
122 'tagmanager/src/tm_source_file.c',
123 'tagmanager/src/tm_tag.c',
124 'tagmanager/src/tm_work_object.c',
125 'tagmanager/src/tm_workspace.c'])
127 scintilla_sources = set(['scintilla/gtk/scintilla-marshal.c'])
129 geany_sources = set([
130 'src/about.c', 'src/build.c', 'src/callbacks.c', 'src/dialogs.c', 'src/document.c',
131 'src/editor.c', 'src/encodings.c', 'src/filetypes.c', 'src/geanyentryaction.c',
132 'src/geanymenubuttonaction.c', 'src/geanyobject.c', 'src/geanywraplabel.c',
133 'src/highlighting.c', 'src/keybindings.c',
134 'src/keyfile.c', 'src/log.c', 'src/main.c', 'src/msgwindow.c', 'src/navqueue.c', 'src/notebook.c',
135 'src/plugins.c', 'src/pluginutils.c', 'src/prefix.c', 'src/prefs.c', 'src/printing.c', 'src/project.c',
136 'src/sciwrappers.c', 'src/search.c', 'src/socket.c', 'src/stash.c',
138 'src/templates.c', 'src/toolbar.c', 'src/tools.c', 'src/sidebar.c',
139 'src/ui_utils.c', 'src/utils.c'])
142 'hicolor/16x16/apps': ['16x16/classviewer-class.png',
143 '16x16/classviewer-macro.png',
144 '16x16/classviewer-member.png',
145 '16x16/classviewer-method.png',
146 '16x16/classviewer-namespace.png',
147 '16x16/classviewer-other.png',
148 '16x16/classviewer-struct.png',
149 '16x16/classviewer-var.png',
151 'hicolor/16x16/actions': ['16x16/geany-build.png',
152 '16x16/geany-close-all.png',
153 '16x16/geany-save-all.png'],
154 'hicolor/24x24/actions': ['24x24/geany-build.png',
155 '24x24/geany-close-all.png',
156 '24x24/geany-save-all.png'],
157 'hicolor/32x32/actions': ['32x32/geany-build.png',
158 '32x32/geany-close-all.png',
159 '32x32/geany-save-all.png'],
160 'hicolor/48x48/actions': ['48x48/geany-build.png',
161 '48x48/geany-close-all.png',
162 '48x48/geany-save-all.png'],
163 'hicolor/48x48/apps': ['48x48/geany.png'],
164 'hicolor/scalable/apps': ['scalable/geany.svg'],
165 'hicolor/scalable/actions': ['scalable/geany-build.svg',
166 'scalable/geany-close-all.svg',
167 'scalable/geany-save-all.svg'],
168 'Tango/16x16/actions': ['tango/16x16/geany-save-all.png'],
169 'Tango/24x24/actions': ['tango/24x24/geany-save-all.png'],
170 'Tango/32x32/actions': ['tango/32x32/geany-save-all.png'],
171 'Tango/48x48/actions': ['tango/48x48/geany-save-all.png'],
172 'Tango/scalable/actions': ['tango/scalable/geany-save-all.svg']
174 geany_icons_indexes = {
175 'hicolor': ['index.theme'],
176 'Tango': ['tango/index.theme']
182 conf.check_waf_version(mini='1.6.1')
184 conf.load('compiler_c')
185 is_win32 = _target_is_win32(conf)
187 conf.check_cc(header_name='fcntl.h', mandatory=False)
188 conf.check_cc(header_name='fnmatch.h', mandatory=False)
189 conf.check_cc(header_name='glob.h', mandatory=False)
190 conf.check_cc(header_name='sys/time.h', mandatory=False)
191 conf.check_cc(header_name='sys/types.h', mandatory=False)
192 conf.check_cc(header_name='sys/stat.h', mandatory=False)
193 conf.define('HAVE_STDLIB_H', 1) # are there systems without stdlib.h?
194 conf.define('STDC_HEADERS', 1) # an optimistic guess ;-)
195 _add_to_env_and_define(conf, 'HAVE_REGCOMP', 1) # needed for CTags
197 conf.check_cc(function_name='fgetpos', header_name='stdio.h', mandatory=False)
198 conf.check_cc(function_name='ftruncate', header_name='unistd.h', mandatory=False)
199 conf.check_cc(function_name='mkstemp', header_name='stdlib.h', mandatory=False)
200 conf.check_cc(function_name='strstr', header_name='string.h')
202 conf.check_cc(function_name='pow', header_name='math.h', lib='m', uselib_store='M')
204 # check sunOS socket support
205 if Options.platform == 'sunos':
206 conf.check_cc(function_name='socket', lib='socket',
207 header_name='sys/socket.h', uselib_store='SUNOS_SOCKET', mandatory=True)
209 # check for cxx after the header and function checks have been done to ensure they are
210 # checked with cc not cxx
211 conf.load('compiler_cxx')
214 _load_intltool_if_available(conf)
216 # GTK / GIO version check
217 gtk_package_name = 'gtk+-3.0' if conf.options.use_gtk3 else 'gtk+-2.0'
218 minimum_gtk_version = MINIMUM_GTK3_VERSION if conf.options.use_gtk3 else MINIMUM_GTK_VERSION
219 conf.check_cfg(package=gtk_package_name, atleast_version=minimum_gtk_version, uselib_store='GTK',
220 mandatory=True, args='--cflags --libs')
221 conf.check_cfg(package='glib-2.0', atleast_version=MINIMUM_GLIB_VERSION, uselib_store='GLIB',
222 mandatory=True, args='--cflags --libs')
223 conf.check_cfg(package='gmodule-2.0', uselib_store='GMODULE',
224 mandatory=True, args='--cflags --libs')
225 conf.check_cfg(package='gio-2.0', uselib_store='GIO', args='--cflags --libs', mandatory=True)
226 gtk_version = conf.check_cfg(modversion=gtk_package_name, uselib_store='GTK') or 'Unknown'
227 conf.check_cfg(package='gthread-2.0', uselib_store='GTHREAD', args='--cflags --libs')
228 # remember GTK version for the build step
229 conf.env['gtk_package_name'] = gtk_package_name
230 conf.env['minimum_gtk_version'] = minimum_gtk_version
231 conf.env['use_gtk3'] = conf.options.use_gtk3
233 revision = _get_git_rev(conf)
235 # rst2html for the HTML manual
236 if not conf.options.no_html_doc and revision is not None:
238 conf.env['RST2HTML'] = _find_rst2html(conf)
240 error_msg = '''Documentation enabled but rst2html not found.
241 You can explicitly disable building of the HTML manual with --disable-html-docs,
242 but you then may not have a local copy of the HTML manual.'''
243 raise WafError(error_msg)
247 if conf.env['PREFIX'].lower() == tempfile.gettempdir().lower():
248 # overwrite default prefix on Windows (tempfile.gettempdir() is the Waf default)
249 new_prefix = os.path.join(str(conf.root), '%s-%s' % (APPNAME, VERSION))
250 _add_to_env_and_define(conf, 'PREFIX', new_prefix, quote=True)
251 _add_to_env_and_define(conf, 'BINDIR', os.path.join(new_prefix, 'bin'), quote=True)
252 _add_to_env_and_define(conf, 'DOCDIR', os.path.join(conf.env['PREFIX'], 'doc'), quote=True)
253 _add_to_env_and_define(conf, 'LIBDIR', '%s/lib' % conf.env['PREFIX'], quote=True)
254 conf.define('LOCALEDIR', os.path.join('share' 'locale'), quote=True)
255 # overwrite LOCALEDIR to install message catalogues properly
256 conf.env['LOCALEDIR'] = os.path.join(conf.env['PREFIX'], 'share', 'locale')
257 # DATADIR is defined in objidl.h, so we remove it from config.h but keep it in env
258 conf.undefine('DATADIR')
259 conf.env['DATADIR'] = os.path.join(conf.env['PREFIX'], 'data')
260 conf.env.append_value('LINKFLAGS_cprogram', [
263 '-static-libstdc++'])
264 conf.env.append_value('LIB_WIN32', ['wsock32', 'uuid', 'ole32', 'iberty'])
266 conf.env['cshlib_PATTERN'] = '%s.so'
267 # DATADIR and LOCALEDIR are defined by the intltool tool
268 # but they are not added to the environment, so we need to
269 _add_define_to_env(conf, 'DATADIR')
270 _add_define_to_env(conf, 'LOCALEDIR')
271 docdir = os.path.join(conf.env['DATADIR'], 'doc', 'geany')
272 libdir = os.path.join(conf.env['PREFIX'], 'lib')
273 mandir = os.path.join(conf.env['DATADIR'], 'man')
274 _define_from_opt(conf, 'DOCDIR', conf.options.docdir, docdir)
275 _define_from_opt(conf, 'LIBDIR', conf.options.libdir, libdir)
276 _define_from_opt(conf, 'MANDIR', conf.options.mandir, mandir)
278 conf.define('ENABLE_NLS', 1)
279 conf.define('GEANY_LOCALEDIR', '' if is_win32 else conf.env['LOCALEDIR'], quote=True)
280 conf.define('GEANY_DATADIR', 'data' if is_win32 else conf.env['DATADIR'], quote=True)
281 conf.define('GEANY_DOCDIR', conf.env['DOCDIR'], quote=True)
282 conf.define('GEANY_LIBDIR', '' if is_win32 else conf.env['LIBDIR'], quote=True)
283 conf.define('GEANY_PREFIX', '' if is_win32 else conf.env['PREFIX'], quote=True)
284 conf.define('PACKAGE', APPNAME, quote=True)
285 conf.define('VERSION', VERSION, quote=True)
286 conf.define('REVISION', revision or '-1', quote=True)
288 conf.define('GETTEXT_PACKAGE', APPNAME, quote=True)
292 conf.options.no_vte = True
294 _define_from_opt(conf, 'HAVE_PLUGINS', not conf.options.no_plugins, None)
295 _define_from_opt(conf, 'HAVE_SOCKET', not conf.options.no_socket, None)
296 _define_from_opt(conf, 'HAVE_VTE', not conf.options.no_vte, None)
298 conf.write_config_header('config.h', remove=False)
300 # some more compiler flags
301 conf.env.append_value('CFLAGS', ['-DHAVE_CONFIG_H'])
302 if revision is not None:
303 conf.env.append_value('CFLAGS', ['-g', '-DGEANY_DEBUG'])
305 conf.env.append_value('CFLAGS', ['-DGTK'])
306 conf.env.append_value('CXXFLAGS',
307 ['-DNDEBUG', '-DGTK', '-DSCI_LEXER', '-DG_THREADS_IMPL_NONE'])
310 Logs.pprint('BLUE', 'Summary:')
311 conf.msg('Install Geany ' + VERSION + ' in', conf.env['PREFIX'])
312 conf.msg('Using GTK version', gtk_version)
313 conf.msg('Build with plugin support', conf.options.no_plugins and 'no' or 'yes')
314 conf.msg('Use virtual terminal support', conf.options.no_vte and 'no' or 'yes')
315 if revision is not None:
316 conf.msg('Compiling Git revision', revision)
320 # Disable MSVC detection on win32: building Geany with MSVC is currently not supported
321 # If anyone wants to add support for building with MSVC, this hack should be removed.
322 c_compiler['win32'] = ['gcc']
323 cxx_compiler['win32'] = ['g++']
325 opt.load('compiler_cc')
326 opt.load('compiler_cxx')
330 opt.add_option('--no-scm', action='store_true', default=False,
331 help='Disable SCM detection [default: No]', dest='no_scm')
333 opt.add_option('--disable-plugins', action='store_true', default=False,
334 help='compile without plugin support [default: No]', dest='no_plugins')
335 opt.add_option('--disable-socket', action='store_true', default=False,
336 help='compile without support to detect a running instance [[default: No]',
338 opt.add_option('--disable-vte', action='store_true', default=False,
339 help='compile without support for an embedded virtual terminal [[default: No]',
341 opt.add_option('--enable-gtk3', action='store_true', default=False,
342 help='compile with GTK3 support (experimental) [[default: No]',
344 opt.add_option('--disable-html-docs', action='store_true', default=False,
345 help='do not generate HTML documentation using rst2html [[default: No]',
348 opt.add_option('--mandir', type='string', default='',
349 help='man documentation', dest='mandir')
350 opt.add_option('--docdir', type='string', default='',
351 help='documentation root', dest='docdir')
352 opt.add_option('--libdir', type='string', default='',
353 help='object code libraries', dest='libdir')
357 is_win32 = _target_is_win32(bld)
359 if bld.cmd == 'clean':
360 _remove_linguas_file()
361 if bld.cmd in ('install', 'uninstall'):
362 bld.add_post_fun(_post_install)
364 def build_plugin(plugin_name, install=True, uselib_add=[]):
366 instpath = '${PREFIX}/lib' if is_win32 else '${LIBDIR}/geany'
371 features = ['c', 'cshlib'],
372 source = 'plugins/%s.c' % plugin_name,
373 includes = ['.', 'src/', 'scintilla/include', 'tagmanager/src'],
374 defines = 'G_LOG_DOMAIN="%s"' % plugin_name,
375 target = plugin_name,
376 uselib = ['GTK', 'GLIB', 'GMODULE'] + uselib_add,
377 install_path = instpath)
381 features = ['c', 'cstlib'],
382 source = ctags_sources,
385 includes = ['.', 'tagmanager', 'tagmanager/ctags'],
386 defines = 'G_LOG_DOMAIN="CTags"',
388 install_path = None) # do not install this library
392 features = ['c', 'cstlib'],
393 source = tagmanager_sources,
395 target = 'tagmanager',
396 includes = ['.', 'tagmanager', 'tagmanager/ctags'],
397 defines = 'G_LOG_DOMAIN="Tagmanager"',
398 uselib = ['GTK', 'GLIB'],
399 install_path = None) # do not install this library
403 features = ['c', 'cstlib'],
404 source = mio_sources,
407 includes = ['.', 'tagmanager/mio/'],
408 defines = 'G_LOG_DOMAIN="MIO"',
409 uselib = ['GTK', 'GLIB'],
410 install_path = None) # do not install this library
413 files = bld.srcnode.ant_glob('scintilla/**/*.cxx', src=True, dir=False)
414 scintilla_sources.update(files)
416 features = ['c', 'cxx', 'cxxstlib'],
418 target = 'scintilla',
419 source = scintilla_sources,
420 includes = ['.', 'scintilla/include', 'scintilla/src', 'scintilla/lexlib'],
421 uselib = ['GTK', 'GLIB', 'GMODULE', 'M'],
422 install_path = None) # do not install this library
425 if bld.env['HAVE_VTE'] == 1:
426 geany_sources.add('src/vte.c')
428 geany_sources.add('src/win32.c')
429 geany_sources.add('geany_private.rc')
432 features = ['c', 'cxx', 'cprogram'],
435 source = geany_sources,
436 includes = ['.', 'scintilla/include', 'tagmanager/src'],
437 defines = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
438 uselib = ['GTK', 'GLIB', 'GMODULE', 'GIO', 'GTHREAD', 'WIN32', 'SUNOS_SOCKET', 'M'],
439 use = ['scintilla', 'ctags', 'tagmanager', 'mio'])
443 source = ['plugins/genapi.py', 'src/plugins.c'],
444 name = 'geanyfunctions.h',
445 before = ['c', 'cxx'],
446 cwd = '%s/plugins' % bld.path.abspath(),
447 rule = '%s genapi.py -q' % sys.executable)
450 if bld.env['HAVE_PLUGINS'] == 1:
451 build_plugin('classbuilder')
452 build_plugin('demoplugin', False)
453 build_plugin('export', uselib_add=['M'])
454 build_plugin('filebrowser')
455 build_plugin('htmlchars')
456 build_plugin('saveactions')
457 build_plugin('splitwindow')
460 if bld.env['INTLTOOL']:
462 features = ['linguas', 'intltool_po'],
464 install_path = '${LOCALEDIR}',
467 # HTML documentation (build if it is not part of the tree already, as it is required for install)
468 html_doc_filename = os.path.join(bld.out_dir, 'doc', 'geany.html')
469 if bld.env['RST2HTML']:
470 rst2html = bld.env['RST2HTML']
472 source = ['doc/geany.txt'],
473 deps = ['doc/geany.css'],
474 target = 'doc/geany.html',
476 cwd = os.path.join(bld.path.abspath(), 'doc'),
477 rule = '%s -stg --stylesheet=geany.css geany.txt %s' % (rst2html, html_doc_filename))
481 # replace backward slashes by forward slashes as they could be interepreted as escape
483 geany_pc_prefix = bld.env['PREFIX'].replace('\\', '/')
485 geany_pc_prefix = bld.env['PREFIX']
487 source = 'geany.pc.in',
488 dct = {'VERSION': VERSION,
489 'DEPENDENCIES': '%s >= %s glib-2.0 >= %s' % \
490 (bld.env['gtk_package_name'],
491 bld.env['minimum_gtk_version'],
492 MINIMUM_GLIB_VERSION),
493 'prefix': geany_pc_prefix,
494 'exec_prefix': '${prefix}',
495 'libdir': '${exec_prefix}/lib',
496 'includedir': '${prefix}/include',
497 'datarootdir': '${prefix}/share',
498 'datadir': '${datarootdir}',
499 'localedir': '${datarootdir}/locale'})
503 if bld.env['INTLTOOL']:
505 features = 'intltool_in',
506 source = 'geany.desktop.in',
507 flags = ['-d', '-q', '-u', '-c'],
508 install_path = '${DATADIR}/applications')
513 source = 'doc/geany.1.in',
515 dct = {'VERSION': VERSION,
516 'GEANY_DATA_DIR': bld.env['DATADIR'] + '/geany'},
517 install_path = '${MANDIR}/man1')
522 source = 'geany.spec.in',
523 target = 'geany.spec',
525 dct = {'VERSION': VERSION})
530 source = 'doc/Doxyfile.in',
531 target = 'doc/Doxyfile',
533 dct = {'VERSION': VERSION,
534 'top_builddir': bld.out_dir,
535 'top_srcdir': bld.top_dir,})
541 bld.install_files('${PREFIX}/include/geany', '''
542 src/app.h src/document.h src/editor.h src/encodings.h src/filetypes.h src/geany.h
543 src/highlighting.h src/keybindings.h src/msgwindow.h src/plugindata.h
544 src/prefs.h src/project.h src/search.h src/stash.h src/support.h
545 src/templates.h src/toolbar.h src/ui_utils.h src/utils.h src/build.h src/gtkcompat.h
546 plugins/geanyplugin.h plugins/geanyfunctions.h''')
547 bld.install_files('${PREFIX}/include/geany/scintilla', '''
548 scintilla/include/SciLexer.h scintilla/include/Scintilla.h
549 scintilla/include/Scintilla.iface scintilla/include/ScintillaWidget.h ''')
550 bld.install_files('${PREFIX}/include/geany/tagmanager', '''
551 tagmanager/src/tm_file_entry.h
552 tagmanager/src/tm_source_file.h tagmanager/src/tm_parser.h
553 tagmanager/src/tm_tag.h
554 tagmanager/src/tm_tagmanager.h tagmanager/src/tm_work_object.h
555 tagmanager/src/tm_workspace.h ''')
557 base_dir = '${PREFIX}' if is_win32 else '${DOCDIR}'
558 ext = '.txt' if is_win32 else ''
559 for filename in 'AUTHORS ChangeLog COPYING README NEWS THANKS TODO'.split():
560 basename = _uc_first(filename, bld)
561 destination_filename = '%s%s' % (basename, ext)
562 destination = os.path.join(base_dir, destination_filename)
563 bld.install_as(destination, filename)
565 # install HTML documentation only if it exists, i.e. it was built before
566 # local_html_doc_filename supports installing HTML doc from in-tree geany.html if it exists
567 local_html_doc_filename = os.path.join(bld.path.abspath(), 'doc', 'geany.html')
568 if os.path.exists(html_doc_filename) or os.path.exists(local_html_doc_filename):
569 html_dir = '' if is_win32 else 'html/'
570 html_name = 'Manual.html' if is_win32 else 'index.html'
571 start_dir = bld.path.find_dir('doc/images')
572 bld.install_files('${DOCDIR}/%simages' % html_dir, start_dir.ant_glob('*.png'), cwd=start_dir)
573 bld.install_as('${DOCDIR}/%s%s' % (html_dir, html_name), 'doc/geany.html')
575 bld.install_as('${DOCDIR}/%s' % _uc_first('manual.txt', bld), 'doc/geany.txt')
576 bld.install_as('${DOCDIR}/ScintillaLicense.txt', 'scintilla/License.txt')
578 bld.install_as('${DOCDIR}/ReadMe.I18n.txt', 'README.I18N')
579 bld.install_as('${DOCDIR}/Hacking.txt', 'HACKING')
581 data_dir = '' if is_win32 else 'geany'
582 start_dir = bld.path.find_dir('data')
583 bld.install_as('${DATADIR}/%s/GPL-2' % data_dir, 'COPYING')
584 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('filetype*'), cwd=start_dir)
585 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('*.tags'), cwd=start_dir)
586 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.glade')
587 bld.install_files('${DATADIR}/%s' % data_dir, 'data/snippets.conf')
588 bld.install_files('${DATADIR}/%s' % data_dir, 'data/ui_toolbar.xml')
589 if bld.env['use_gtk3']:
590 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.css')
592 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.gtkrc')
594 start_dir = bld.path.find_dir('data/colorschemes')
595 template_dest = '${DATADIR}/%s/colorschemes' % data_dir
596 bld.install_files(template_dest, start_dir.ant_glob('*'), cwd=start_dir)
597 start_dir = bld.path.find_dir('data/templates')
598 template_dest = '${DATADIR}/%s/templates' % data_dir
599 bld.install_files(template_dest, start_dir.ant_glob('**/*'), cwd=start_dir, relative_trick=True)
601 for dest, srcs in geany_icons.items():
602 dest_dir = os.path.join('${PREFIX}/share/icons' if is_win32 else '${DATADIR}/icons', dest)
603 bld.install_files(dest_dir, srcs, cwd=bld.path.find_dir('icons'))
604 # install theme indexes on Windows
606 for dest, srcs in geany_icons_indexes.items():
607 bld.install_files(os.path.join('${PREFIX}/share/icons', dest), srcs, cwd=bld.path.find_dir('icons'))
611 Scripting.distclean(ctx)
612 _remove_linguas_file()
615 def _remove_linguas_file():
616 # remove LINGUAS file as well
618 os.unlink(LINGUAS_FILE)
624 @before_method('apply_intltool_po')
625 def write_linguas_file(self):
626 if os.path.exists(LINGUAS_FILE):
629 if 'LINGUAS' in self.env:
630 files = self.env['LINGUAS']
631 for po_filename in files.split(' '):
632 if os.path.exists('po/%s.po' % po_filename):
633 linguas += '%s ' % po_filename
635 files = os.listdir('%s/po' % self.path.abspath())
637 for filename in files:
638 if filename.endswith('.po'):
639 linguas += '%s ' % filename[:-3]
640 file_h = open(LINGUAS_FILE, 'w')
641 file_h.write('# This file is autogenerated. Do not edit.\n%s\n' % linguas)
645 def _post_install(ctx):
646 is_win32 = _target_is_win32(ctx)
649 for d in 'hicolor', 'Tango':
650 theme_dir = Utils.subst_vars('${DATADIR}/icons/' + d, ctx.env)
651 icon_cache_updated = False
652 if not ctx.options.destdir:
653 ctx.exec_command('gtk-update-icon-cache -q -f -t %s' % theme_dir)
654 Logs.pprint('GREEN', 'GTK icon cache updated.')
655 icon_cache_updated = True
656 if not icon_cache_updated:
657 Logs.pprint('YELLOW', 'Icon cache not updated. After install, run this:')
658 Logs.pprint('YELLOW', 'gtk-update-icon-cache -q -f -t %s' % theme_dir)
662 """update the message catalogs for internationalization"""
663 potfile = '%s.pot' % APPNAME
664 os.chdir('%s/po' % top)
667 old_size = os.stat(potfile).st_size
670 ctx.exec_command('intltool-update --pot -g %s' % APPNAME)
671 size_new = os.stat(potfile).st_size
672 if size_new != old_size:
673 Logs.pprint('CYAN', 'Updated POT file.')
674 Logs.pprint('CYAN', 'Updating translations')
675 ret = ctx.exec_command('intltool-update -r -g %s' % APPNAME)
677 Logs.pprint('RED', 'Updating translations failed')
679 Logs.pprint('CYAN', 'POT file is up to date.')
681 Logs.pprint('RED', 'Failed to generate pot file.')
685 """generate API reference documentation"""
686 ctx = BuildContext() # create our own context to have ctx.top_dir
687 basedir = ctx.top_dir
688 doxygen = _find_program(ctx, 'doxygen')
689 doxyfile = '%s/doc/Doxyfile' % ctx.out_dir
690 Logs.pprint('CYAN', 'Generating API documentation')
691 ret = ctx.exec_command('%s %s' % (doxygen, doxyfile))
693 raise WafError('Generating API documentation failed')
697 """generate HACKING documentation"""
698 ctx = BuildContext() # create our own context to have ctx.top_dir
699 Logs.pprint('CYAN', 'Generating HACKING documentation')
700 cmd = _find_rst2html(ctx)
701 hacking_file = os.path.join(ctx.top_dir, 'HACKING')
702 hacking_html_file = os.path.join(ctx.top_dir, 'doc', 'hacking.html')
703 stylesheet = os.path.join(ctx.top_dir, 'doc', 'geany.css')
704 ret = ctx.exec_command('%s -stg --stylesheet=%s %s %s' % (
705 cmd, stylesheet, hacking_file, hacking_html_file))
707 raise WafError('Generating HACKING documentation failed')
710 def _find_program(ctx, cmd, **kw):
714 if ctx is None or not isinstance(ctx, ConfigurationContext):
715 ctx = ConfigurationContext()
718 return ctx.find_program(cmd, **kw)
721 def _find_rst2html(ctx):
722 cmds = ['rst2html', 'rst2html2']
724 cmd = _find_program(ctx, command, mandatory=False, exts=',.py')
729 'rst2html.py could not be found. Please install the Python docutils package.')
733 def _add_define_to_env(conf, key):
734 value = conf.get_define(key)
736 value = value.replace('"', '')
737 conf.env[key] = value
740 def _add_to_env_and_define(conf, key, value, quote=False):
741 conf.define(key, value, quote)
742 conf.env[key] = value
745 def _define_from_opt(conf, define_name, opt_value, default_value, quote=1):
746 value = default_value
748 if isinstance(opt_value, bool):
752 if value is not None:
753 _add_to_env_and_define(conf, define_name, value, quote)
755 conf.undefine(define_name)
758 def _get_git_rev(conf):
759 if conf.options.no_scm:
762 if not os.path.isdir('.git'):
766 cmd = 'git rev-parse --short --revs-only HEAD'
767 revision = conf.cmd_and_log(cmd).strip()
774 def _load_intltool_if_available(conf):
776 conf.load('intltool')
777 if 'LINGUAS' in os.environ:
778 conf.env['LINGUAS'] = os.environ['LINGUAS']
780 # on Windows, we don't hard depend on intltool, on all other platforms raise an error
781 if not _target_is_win32(conf):
785 def _target_is_win32(ctx):
786 if 'is_win32' in ctx.env:
788 return ctx.env['is_win32']
790 if sys.platform == 'win32':
793 if ctx.env and 'CC' in ctx.env:
794 env_cc = ctx.env['CC']
795 if not isinstance(env_cc, str):
796 env_cc = ''.join(env_cc)
797 is_win32 = (env_cc.find('mingw') != -1)
800 # cache for future checks
801 ctx.env['is_win32'] = is_win32
805 def _uc_first(string, ctx):
806 if _target_is_win32(ctx):
807 return string.title()