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_source_file.c',
123 'tagmanager/src/tm_tag.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',
137 'src/templates.c', 'src/toolbar.c', 'src/tools.c', 'src/sidebar.c',
138 'src/ui_utils.c', 'src/utils.c'])
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',
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']
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='fnmatch', header_name='fnmatch.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'])
265 # explicitly define Windows version for older Mingw environments
266 conf.define('WINVER', '0x0501', quote=False) # for SHGetFolderPathAndSubDirW
267 conf.define('_WIN32_IE', '0x0500', quote=False) # for SHGFP_TYPE
269 conf.env['cshlib_PATTERN'] = '%s.so'
270 # DATADIR and LOCALEDIR are defined by the intltool tool
271 # but they are not added to the environment, so we need to
272 _add_define_to_env(conf, 'DATADIR')
273 _add_define_to_env(conf, 'LOCALEDIR')
274 docdir = os.path.join(conf.env['DATADIR'], 'doc', 'geany')
275 libdir = os.path.join(conf.env['PREFIX'], 'lib')
276 mandir = os.path.join(conf.env['DATADIR'], 'man')
277 _define_from_opt(conf, 'DOCDIR', conf.options.docdir, docdir)
278 _define_from_opt(conf, 'LIBDIR', conf.options.libdir, libdir)
279 _define_from_opt(conf, 'MANDIR', conf.options.mandir, mandir)
281 conf.define('ENABLE_NLS', 1)
282 conf.define('GEANY_LOCALEDIR', '' if is_win32 else conf.env['LOCALEDIR'], quote=True)
283 conf.define('GEANY_DATADIR', 'data' if is_win32 else conf.env['DATADIR'], quote=True)
284 conf.define('GEANY_DOCDIR', conf.env['DOCDIR'], quote=True)
285 conf.define('GEANY_LIBDIR', '' if is_win32 else conf.env['LIBDIR'], quote=True)
286 conf.define('GEANY_PREFIX', '' if is_win32 else conf.env['PREFIX'], quote=True)
287 conf.define('PACKAGE', APPNAME, quote=True)
288 conf.define('VERSION', VERSION, quote=True)
289 conf.define('REVISION', revision or '-1', quote=True)
291 conf.define('GETTEXT_PACKAGE', APPNAME, quote=True)
295 conf.options.no_vte = True
297 _define_from_opt(conf, 'HAVE_PLUGINS', not conf.options.no_plugins, None)
298 _define_from_opt(conf, 'HAVE_SOCKET', not conf.options.no_socket, None)
299 _define_from_opt(conf, 'HAVE_VTE', not conf.options.no_vte, None)
301 conf.write_config_header('config.h', remove=False)
303 # some more compiler flags
304 conf.env.append_value('CFLAGS', ['-DHAVE_CONFIG_H'])
305 if conf.env['CC_NAME'] == 'gcc' and '-O' not in ''.join(conf.env['CFLAGS']):
306 conf.env.append_value('CFLAGS', ['-O2'])
307 if revision is not None:
308 conf.env.append_value('CFLAGS', ['-g', '-DGEANY_DEBUG'])
310 conf.env.append_value('CFLAGS', ['-DGTK'])
311 conf.env.append_value('CXXFLAGS',
312 ['-DNDEBUG', '-DGTK', '-DSCI_LEXER', '-DG_THREADS_IMPL_NONE'])
315 Logs.pprint('BLUE', 'Summary:')
316 conf.msg('Install Geany ' + VERSION + ' in', conf.env['PREFIX'])
317 conf.msg('Using GTK version', gtk_version)
318 conf.msg('Build with plugin support', conf.options.no_plugins and 'no' or 'yes')
319 conf.msg('Use virtual terminal support', conf.options.no_vte and 'no' or 'yes')
320 if revision is not None:
321 conf.msg('Compiling Git revision', revision)
325 # Disable MSVC detection on win32: building Geany with MSVC is currently not supported
326 # If anyone wants to add support for building with MSVC, this hack should be removed.
327 c_compiler['win32'] = ['gcc']
328 cxx_compiler['win32'] = ['g++']
330 opt.load('compiler_cc')
331 opt.load('compiler_cxx')
335 opt.add_option('--no-scm', action='store_true', default=False,
336 help='Disable SCM detection [default: No]', dest='no_scm')
338 opt.add_option('--disable-plugins', action='store_true', default=False,
339 help='compile without plugin support [default: No]', dest='no_plugins')
340 opt.add_option('--disable-socket', action='store_true', default=False,
341 help='compile without support to detect a running instance [[default: No]',
343 opt.add_option('--disable-vte', action='store_true', default=False,
344 help='compile without support for an embedded virtual terminal [[default: No]',
346 opt.add_option('--enable-gtk3', action='store_true', default=False,
347 help='compile with GTK3 support (experimental) [[default: No]',
349 opt.add_option('--disable-html-docs', action='store_true', default=False,
350 help='do not generate HTML documentation using rst2html [[default: No]',
353 opt.add_option('--mandir', type='string', default='',
354 help='man documentation', dest='mandir')
355 opt.add_option('--docdir', type='string', default='',
356 help='documentation root', dest='docdir')
357 opt.add_option('--libdir', type='string', default='',
358 help='object code libraries', dest='libdir')
362 is_win32 = _target_is_win32(bld)
364 if bld.cmd == 'clean':
365 _remove_linguas_file()
366 if bld.cmd in ('install', 'uninstall'):
367 bld.add_post_fun(_post_install)
369 def build_plugin(plugin_name, install=True, uselib_add=[]):
371 instpath = '${PREFIX}/lib' if is_win32 else '${LIBDIR}/geany'
376 features = ['c', 'cshlib'],
377 source = 'plugins/%s.c' % plugin_name,
378 includes = ['.', 'src/', 'scintilla/include', 'tagmanager/src'],
379 defines = 'G_LOG_DOMAIN="%s"' % plugin_name,
380 target = plugin_name,
381 uselib = ['GTK', 'GLIB', 'GMODULE'] + uselib_add,
382 install_path = instpath)
386 features = ['c', 'cstlib'],
387 source = ctags_sources,
390 includes = ['.', 'tagmanager', 'tagmanager/ctags'],
391 defines = 'G_LOG_DOMAIN="CTags"',
393 install_path = None) # do not install this library
397 features = ['c', 'cstlib'],
398 source = tagmanager_sources,
400 target = 'tagmanager',
401 includes = ['.', 'tagmanager', 'tagmanager/ctags'],
402 defines = ['GEANY_PRIVATE', 'G_LOG_DOMAIN="Tagmanager"'],
403 uselib = ['GTK', 'GLIB'],
404 install_path = None) # do not install this library
408 features = ['c', 'cstlib'],
409 source = mio_sources,
412 includes = ['.', 'tagmanager/mio/'],
413 defines = 'G_LOG_DOMAIN="MIO"',
414 uselib = ['GTK', 'GLIB'],
415 install_path = None) # do not install this library
418 files = bld.srcnode.ant_glob('scintilla/**/*.cxx', src=True, dir=False)
419 scintilla_sources.update([file.path_from(bld.srcnode) for file in files])
421 features = ['c', 'cxx', 'cxxstlib'],
423 target = 'scintilla',
424 source = scintilla_sources,
425 includes = ['.', 'scintilla/include', 'scintilla/src', 'scintilla/lexlib'],
426 uselib = ['GTK', 'GLIB', 'GMODULE', 'M'],
427 install_path = None) # do not install this library
430 if bld.env['HAVE_VTE'] == 1:
431 geany_sources.add('src/vte.c')
433 geany_sources.add('src/win32.c')
434 geany_sources.add('geany_private.rc')
437 features = ['c', 'cxx', 'cprogram'],
440 source = geany_sources,
441 includes = ['.', 'scintilla/include', 'tagmanager/src'],
442 defines = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
443 uselib = ['GTK', 'GLIB', 'GMODULE', 'GIO', 'GTHREAD', 'WIN32', 'SUNOS_SOCKET', 'M'],
444 use = ['scintilla', 'ctags', 'tagmanager', 'mio'])
448 source = ['plugins/genapi.py', 'src/plugins.c'],
449 name = 'geanyfunctions.h',
450 before = ['c', 'cxx'],
451 cwd = '%s/plugins' % bld.path.abspath(),
452 rule = '%s genapi.py -q' % sys.executable)
455 if bld.env['HAVE_PLUGINS'] == 1:
456 build_plugin('classbuilder')
457 build_plugin('demoplugin', False)
458 build_plugin('export', uselib_add=['M'])
459 build_plugin('filebrowser')
460 build_plugin('htmlchars')
461 build_plugin('saveactions')
462 build_plugin('splitwindow')
465 if bld.env['INTLTOOL']:
467 features = ['linguas', 'intltool_po'],
469 install_path = '${LOCALEDIR}',
472 # HTML documentation (build if it is not part of the tree already, as it is required for install)
473 html_doc_filename = os.path.join(bld.out_dir, 'doc', 'geany.html')
474 if bld.env['RST2HTML']:
475 rst2html = bld.env['RST2HTML']
477 source = ['doc/geany.txt'],
478 deps = ['doc/geany.css'],
479 target = 'doc/geany.html',
481 cwd = os.path.join(bld.path.abspath(), 'doc'),
482 rule = '%s -stg --stylesheet=geany.css geany.txt %s' % (rst2html, html_doc_filename))
486 # replace backward slashes by forward slashes as they could be interepreted as escape
488 geany_pc_prefix = bld.env['PREFIX'].replace('\\', '/')
490 geany_pc_prefix = bld.env['PREFIX']
492 source = 'geany.pc.in',
493 dct = {'VERSION': VERSION,
494 'DEPENDENCIES': '%s >= %s glib-2.0 >= %s' % \
495 (bld.env['gtk_package_name'],
496 bld.env['minimum_gtk_version'],
497 MINIMUM_GLIB_VERSION),
498 'prefix': geany_pc_prefix,
499 'exec_prefix': '${prefix}',
500 'libdir': '${exec_prefix}/lib',
501 'includedir': '${prefix}/include',
502 'datarootdir': '${prefix}/share',
503 'datadir': '${datarootdir}',
504 'localedir': '${datarootdir}/locale'})
508 if bld.env['INTLTOOL']:
510 features = 'intltool_in',
511 source = 'geany.desktop.in',
512 flags = ['-d', '-q', '-u', '-c'],
513 install_path = '${DATADIR}/applications')
518 source = 'doc/geany.1.in',
520 dct = {'VERSION': VERSION,
521 'GEANY_DATA_DIR': bld.env['DATADIR'] + '/geany'},
522 install_path = '${MANDIR}/man1')
527 source = 'geany.spec.in',
528 target = 'geany.spec',
530 dct = {'VERSION': VERSION})
535 source = 'doc/Doxyfile.in',
536 target = 'doc/Doxyfile',
538 dct = {'VERSION': VERSION,
539 'top_builddir': bld.out_dir,
540 'top_srcdir': bld.top_dir,})
546 bld.install_files('${PREFIX}/include/geany', '''
547 src/app.h src/document.h src/editor.h src/encodings.h src/filetypes.h src/geany.h
548 src/highlighting.h src/keybindings.h src/msgwindow.h src/plugindata.h
549 src/prefs.h src/project.h src/search.h src/stash.h src/support.h
550 src/templates.h src/toolbar.h src/ui_utils.h src/utils.h src/build.h src/gtkcompat.h
551 plugins/geanyplugin.h plugins/geanyfunctions.h''')
552 bld.install_files('${PREFIX}/include/geany/scintilla', '''
553 scintilla/include/SciLexer.h scintilla/include/Scintilla.h
554 scintilla/include/Scintilla.iface scintilla/include/ScintillaWidget.h ''')
555 bld.install_files('${PREFIX}/include/geany/tagmanager', '''
556 tagmanager/src/tm_source_file.h
557 tagmanager/src/tm_tag.h
558 tagmanager/src/tm_tagmanager.h
559 tagmanager/src/tm_workspace.h ''')
561 base_dir = '${PREFIX}' if is_win32 else '${DOCDIR}'
562 ext = '.txt' if is_win32 else ''
563 for filename in 'AUTHORS ChangeLog COPYING README NEWS THANKS TODO'.split():
564 basename = _uc_first(filename, bld)
565 destination_filename = '%s%s' % (basename, ext)
566 destination = os.path.join(base_dir, destination_filename)
567 bld.install_as(destination, filename)
569 # install HTML documentation only if it exists, i.e. it was built before
570 # local_html_doc_filename supports installing HTML doc from in-tree geany.html if it exists
571 local_html_doc_filename = os.path.join(bld.path.abspath(), 'doc', 'geany.html')
572 if os.path.exists(html_doc_filename) or os.path.exists(local_html_doc_filename):
573 html_dir = '' if is_win32 else 'html/'
574 html_name = 'Manual.html' if is_win32 else 'index.html'
575 start_dir = bld.path.find_dir('doc/images')
576 bld.install_files('${DOCDIR}/%simages' % html_dir, start_dir.ant_glob('*.png'), cwd=start_dir)
577 bld.install_as('${DOCDIR}/%s%s' % (html_dir, html_name), 'doc/geany.html')
579 bld.install_as('${DOCDIR}/%s' % _uc_first('manual.txt', bld), 'doc/geany.txt')
580 bld.install_as('${DOCDIR}/ScintillaLicense.txt', 'scintilla/License.txt')
582 bld.install_as('${DOCDIR}/ReadMe.I18n.txt', 'README.I18N')
583 bld.install_as('${DOCDIR}/Hacking.txt', 'HACKING')
585 data_dir = '' if is_win32 else 'geany'
586 start_dir = bld.path.find_dir('data')
587 bld.install_as('${DATADIR}/%s/GPL-2' % data_dir, 'COPYING')
588 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('filetype*'), cwd=start_dir)
589 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('*.tags'), cwd=start_dir)
590 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.glade')
591 bld.install_files('${DATADIR}/%s' % data_dir, 'data/snippets.conf')
592 bld.install_files('${DATADIR}/%s' % data_dir, 'data/ui_toolbar.xml')
593 if bld.env['use_gtk3']:
594 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.css')
596 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.gtkrc')
598 start_dir = bld.path.find_dir('data/colorschemes')
599 template_dest = '${DATADIR}/%s/colorschemes' % data_dir
600 bld.install_files(template_dest, start_dir.ant_glob('*'), cwd=start_dir)
601 start_dir = bld.path.find_dir('data/templates')
602 template_dest = '${DATADIR}/%s/templates' % data_dir
603 bld.install_files(template_dest, start_dir.ant_glob('**/*'), cwd=start_dir, relative_trick=True)
605 for dest, srcs in geany_icons.items():
606 dest_dir = os.path.join('${PREFIX}/share/icons' if is_win32 else '${DATADIR}/icons', dest)
607 bld.install_files(dest_dir, srcs, cwd=bld.path.find_dir('icons'))
608 # install theme indexes on Windows
610 for dest, srcs in geany_icons_indexes.items():
611 bld.install_files(os.path.join('${PREFIX}/share/icons', dest), srcs, cwd=bld.path.find_dir('icons'))
615 Scripting.distclean(ctx)
616 _remove_linguas_file()
619 def _remove_linguas_file():
620 # remove LINGUAS file as well
622 os.unlink(LINGUAS_FILE)
628 @before_method('apply_intltool_po')
629 def write_linguas_file(self):
630 if os.path.exists(LINGUAS_FILE):
633 if 'LINGUAS' in self.env:
634 files = self.env['LINGUAS']
635 for po_filename in files.split(' '):
636 if os.path.exists('po/%s.po' % po_filename):
637 linguas += '%s ' % po_filename
639 files = os.listdir('%s/po' % self.path.abspath())
641 for filename in files:
642 if filename.endswith('.po'):
643 linguas += '%s ' % filename[:-3]
644 file_h = open(LINGUAS_FILE, 'w')
645 file_h.write('# This file is autogenerated. Do not edit.\n%s\n' % linguas)
649 def _post_install(ctx):
650 is_win32 = _target_is_win32(ctx)
653 for d in 'hicolor', 'Tango':
654 theme_dir = Utils.subst_vars('${DATADIR}/icons/' + d, ctx.env)
655 icon_cache_updated = False
656 if not ctx.options.destdir:
657 ctx.exec_command('gtk-update-icon-cache -q -f -t %s' % theme_dir)
658 Logs.pprint('GREEN', 'GTK icon cache updated.')
659 icon_cache_updated = True
660 if not icon_cache_updated:
661 Logs.pprint('YELLOW', 'Icon cache not updated. After install, run this:')
662 Logs.pprint('YELLOW', 'gtk-update-icon-cache -q -f -t %s' % theme_dir)
666 """update the message catalogs for internationalization"""
667 potfile = '%s.pot' % APPNAME
668 os.chdir('%s/po' % top)
671 old_size = os.stat(potfile).st_size
674 ctx.exec_command('intltool-update --pot -g %s' % APPNAME)
675 size_new = os.stat(potfile).st_size
676 if size_new != old_size:
677 Logs.pprint('CYAN', 'Updated POT file.')
678 Logs.pprint('CYAN', 'Updating translations')
679 ret = ctx.exec_command('intltool-update -r -g %s' % APPNAME)
681 Logs.pprint('RED', 'Updating translations failed')
683 Logs.pprint('CYAN', 'POT file is up to date.')
685 Logs.pprint('RED', 'Failed to generate pot file.')
689 """generate API reference documentation"""
690 ctx = BuildContext() # create our own context to have ctx.top_dir
691 basedir = ctx.top_dir
692 doxygen = _find_program(ctx, 'doxygen')
693 doxyfile = '%s/doc/Doxyfile' % ctx.out_dir
694 Logs.pprint('CYAN', 'Generating API documentation')
695 ret = ctx.exec_command('%s %s' % (doxygen, doxyfile))
697 raise WafError('Generating API documentation failed')
701 """generate HACKING documentation"""
702 ctx = BuildContext() # create our own context to have ctx.top_dir
703 Logs.pprint('CYAN', 'Generating HACKING documentation')
704 cmd = _find_rst2html(ctx)
705 hacking_file = os.path.join(ctx.top_dir, 'HACKING')
706 hacking_html_file = os.path.join(ctx.top_dir, 'doc', 'hacking.html')
707 stylesheet = os.path.join(ctx.top_dir, 'doc', 'geany.css')
708 ret = ctx.exec_command('%s -stg --stylesheet=%s %s %s' % (
709 cmd, stylesheet, hacking_file, hacking_html_file))
711 raise WafError('Generating HACKING documentation failed')
714 def _find_program(ctx, cmd, **kw):
718 if ctx is None or not isinstance(ctx, ConfigurationContext):
719 ctx = ConfigurationContext()
722 return ctx.find_program(cmd, **kw)
725 def _find_rst2html(ctx):
726 cmds = ['rst2html', 'rst2html2']
728 cmd = _find_program(ctx, command, mandatory=False, exts=',.py')
733 'rst2html.py could not be found. Please install the Python docutils package.')
737 def _add_define_to_env(conf, key):
738 value = conf.get_define(key)
740 value = value.replace('"', '')
741 conf.env[key] = value
744 def _add_to_env_and_define(conf, key, value, quote=False):
745 conf.define(key, value, quote)
746 conf.env[key] = value
749 def _define_from_opt(conf, define_name, opt_value, default_value, quote=1):
750 value = default_value
752 if isinstance(opt_value, bool):
756 if value is not None:
757 _add_to_env_and_define(conf, define_name, value, quote)
759 conf.undefine(define_name)
762 def _get_git_rev(conf):
763 if conf.options.no_scm:
766 if not os.path.isdir('.git'):
770 cmd = 'git rev-parse --short --revs-only HEAD'
771 revision = conf.cmd_and_log(cmd).strip()
778 def _load_intltool_if_available(conf):
780 conf.load('intltool')
781 if 'LINGUAS' in os.environ:
782 conf.env['LINGUAS'] = os.environ['LINGUAS']
784 # on Windows, we don't hard depend on intltool, on all other platforms raise an error
785 if not _target_is_win32(conf):
789 def _target_is_win32(ctx):
790 if 'is_win32' in ctx.env:
792 return ctx.env['is_win32']
794 if sys.platform == 'win32':
797 if ctx.env and 'CC' in ctx.env:
798 env_cc = ctx.env['CC']
799 if not isinstance(env_cc, str):
800 env_cc = ''.join(env_cc)
801 is_win32 = (env_cc.find('mingw') != -1)
804 # cache for future checks
805 ctx.env['is_win32'] = is_win32
809 def _uc_first(string, ctx):
810 if _target_is_win32(ctx):
811 return string.title()