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'
61 GEANY_LIB_VERSION = '0.0.0'
67 mio_sources = set(['tagmanager/mio/mio.c'])
70 'tagmanager/ctags/abaqus.c',
71 'tagmanager/ctags/args.c',
72 'tagmanager/ctags/abc.c',
73 'tagmanager/ctags/actionscript.c',
74 'tagmanager/ctags/asciidoc.c',
75 'tagmanager/ctags/asm.c',
76 'tagmanager/ctags/basic.c',
77 'tagmanager/ctags/c.c',
78 'tagmanager/ctags/cobol.c',
79 'tagmanager/ctags/conf.c',
80 'tagmanager/ctags/css.c',
81 'tagmanager/ctags/ctags.c',
82 'tagmanager/ctags/diff.c',
83 'tagmanager/ctags/docbook.c',
84 'tagmanager/ctags/entry.c',
85 'tagmanager/ctags/fortran.c',
86 'tagmanager/ctags/get.c',
87 'tagmanager/ctags/go.c',
88 'tagmanager/ctags/haskell.c',
89 'tagmanager/ctags/haxe.c',
90 'tagmanager/ctags/html.c',
91 'tagmanager/ctags/js.c',
92 'tagmanager/ctags/json.c',
93 'tagmanager/ctags/keyword.c',
94 'tagmanager/ctags/latex.c',
95 'tagmanager/ctags/lregex.c',
96 'tagmanager/ctags/lua.c',
97 'tagmanager/ctags/make.c',
98 'tagmanager/ctags/markdown.c',
99 'tagmanager/ctags/matlab.c',
100 'tagmanager/ctags/nsis.c',
101 'tagmanager/ctags/nestlevel.c',
102 'tagmanager/ctags/objc.c',
103 'tagmanager/ctags/options.c',
104 'tagmanager/ctags/parse.c',
105 'tagmanager/ctags/pascal.c',
106 'tagmanager/ctags/r.c',
107 'tagmanager/ctags/perl.c',
108 'tagmanager/ctags/php.c',
109 'tagmanager/ctags/python.c',
110 'tagmanager/ctags/read.c',
111 'tagmanager/ctags/rest.c',
112 'tagmanager/ctags/ruby.c',
113 'tagmanager/ctags/rust.c',
114 'tagmanager/ctags/sh.c',
115 'tagmanager/ctags/sort.c',
116 'tagmanager/ctags/sql.c',
117 'tagmanager/ctags/strlist.c',
118 'tagmanager/ctags/txt2tags.c',
119 'tagmanager/ctags/tcl.c',
120 'tagmanager/ctags/vhdl.c',
121 'tagmanager/ctags/verilog.c',
122 'tagmanager/ctags/vstring.c'])
124 tagmanager_sources = set([
125 'tagmanager/src/tm_source_file.c',
126 'tagmanager/src/tm_tag.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/libmain.c', 'src/msgwindow.c', 'src/navqueue.c', 'src/notebook.c', 'src/osx.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',
140 'src/templates.c', 'src/toolbar.c', 'src/tools.c', 'src/sidebar.c',
141 'src/ui_utils.c', 'src/utils.c'])
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',
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']
184 conf.check_waf_version(mini='1.6.1')
186 conf.load('compiler_c')
187 is_win32 = _target_is_win32(conf)
189 visibility_hidden_supported = conf.check_cc(cflags=['-Werror', '-fvisibility=hidden'], mandatory=False)
190 conf.check_cc(header_name='fcntl.h', mandatory=False)
191 conf.check_cc(header_name='fnmatch.h', mandatory=False)
192 conf.check_cc(header_name='glob.h', mandatory=False)
193 conf.check_cc(header_name='sys/time.h', mandatory=False)
194 conf.check_cc(header_name='sys/types.h', mandatory=False)
195 conf.check_cc(header_name='sys/stat.h', mandatory=False)
196 conf.define('HAVE_STDLIB_H', 1) # are there systems without stdlib.h?
197 conf.define('STDC_HEADERS', 1) # an optimistic guess ;-)
198 _add_to_env_and_define(conf, 'HAVE_REGCOMP', 1) # needed for CTags
200 conf.check_cc(function_name='fgetpos', header_name='stdio.h', mandatory=False)
201 conf.check_cc(function_name='fnmatch', header_name='fnmatch.h', mandatory=False)
202 conf.check_cc(function_name='ftruncate', header_name='unistd.h', mandatory=False)
203 conf.check_cc(function_name='mkstemp', header_name='stdlib.h', mandatory=False)
204 conf.check_cc(function_name='strstr', header_name='string.h')
206 conf.check_cc(function_name='pow', header_name='math.h', lib='m', uselib_store='M')
208 # check sunOS socket support
209 if Options.platform == 'sunos':
210 conf.check_cc(function_name='socket', lib='socket',
211 header_name='sys/socket.h', uselib_store='SUNOS_SOCKET', mandatory=True)
213 # check for cxx after the header and function checks have been done to ensure they are
214 # checked with cc not cxx
215 conf.load('compiler_cxx')
218 _load_intltool_if_available(conf)
220 # GTK / GIO version check
221 gtk_package_name = 'gtk+-3.0' if conf.options.use_gtk3 else 'gtk+-2.0'
222 minimum_gtk_version = MINIMUM_GTK3_VERSION if conf.options.use_gtk3 else MINIMUM_GTK_VERSION
223 conf.check_cfg(package=gtk_package_name, atleast_version=minimum_gtk_version, uselib_store='GTK',
224 mandatory=True, args='--cflags --libs')
225 conf.check_cfg(package='glib-2.0', atleast_version=MINIMUM_GLIB_VERSION, uselib_store='GLIB',
226 mandatory=True, args='--cflags --libs')
227 conf.check_cfg(package='gmodule-2.0', uselib_store='GMODULE',
228 mandatory=True, args='--cflags --libs')
229 conf.check_cfg(package='gio-2.0', uselib_store='GIO', args='--cflags --libs', mandatory=True)
230 gtk_version = conf.check_cfg(modversion=gtk_package_name, uselib_store='GTK') or 'Unknown'
231 conf.check_cfg(package='gthread-2.0', uselib_store='GTHREAD', args='--cflags --libs')
232 if conf.options.enable_mac_integration:
233 pkgname = 'gtk-mac-integration-gtk3' if conf.options.use_gtk3 else 'gtk-mac-integration-gtk2'
234 conf.check_cfg(package=pkgname, uselib_store='MAC_INTEGRATION',
235 mandatory=True, args='--cflags --libs')
236 # remember GTK version for the build step
237 conf.env['gtk_package_name'] = gtk_package_name
238 conf.env['minimum_gtk_version'] = minimum_gtk_version
239 conf.env['use_gtk3'] = conf.options.use_gtk3
241 revision = _get_git_rev(conf)
243 # rst2html for the HTML manual
244 if not conf.options.no_html_doc and revision is not None:
246 conf.env['RST2HTML'] = _find_rst2html(conf)
248 error_msg = '''Documentation enabled but rst2html not found.
249 You can explicitly disable building of the HTML manual with --disable-html-docs,
250 but you then may not have a local copy of the HTML manual.'''
251 raise WafError(error_msg)
255 if conf.env['PREFIX'].lower() == tempfile.gettempdir().lower():
256 # overwrite default prefix on Windows (tempfile.gettempdir() is the Waf default)
257 new_prefix = os.path.join(str(conf.root), '%s-%s' % (APPNAME, VERSION))
258 _add_to_env_and_define(conf, 'PREFIX', new_prefix, quote=True)
259 _add_to_env_and_define(conf, 'BINDIR', os.path.join(new_prefix, 'bin'), quote=True)
260 _add_to_env_and_define(conf, 'DOCDIR', os.path.join(conf.env['PREFIX'], 'doc'), quote=True)
261 _add_to_env_and_define(conf, 'LIBDIR', '%s/lib' % conf.env['PREFIX'], quote=True)
262 conf.define('LOCALEDIR', os.path.join('share' 'locale'), quote=True)
263 # overwrite LOCALEDIR to install message catalogues properly
264 conf.env['LOCALEDIR'] = os.path.join(conf.env['PREFIX'], 'share', 'locale')
265 # DATADIR is defined in objidl.h, so we remove it from config.h but keep it in env
266 conf.undefine('DATADIR')
267 conf.env['DATADIR'] = os.path.join(conf.env['PREFIX'], 'data')
268 conf.env.append_value('LINKFLAGS_cprogram', [
271 '-static-libstdc++'])
272 conf.env.append_value('LIB_WIN32', ['wsock32', 'uuid', 'ole32'])
273 # explicitly define Windows version for older Mingw environments
274 conf.define('WINVER', '0x0501', quote=False) # for SHGetFolderPathAndSubDirW
275 conf.define('_WIN32_IE', '0x0500', quote=False) # for SHGFP_TYPE
277 conf.env['cshlib_PATTERN'] = '%s.so'
278 # DATADIR and LOCALEDIR are defined by the intltool tool
279 # but they are not added to the environment, so we need to
280 _add_define_to_env(conf, 'DATADIR')
281 _add_define_to_env(conf, 'LOCALEDIR')
282 docdir = os.path.join(conf.env['DATADIR'], 'doc', 'geany')
283 libdir = os.path.join(conf.env['PREFIX'], 'lib')
284 mandir = os.path.join(conf.env['DATADIR'], 'man')
285 _define_from_opt(conf, 'DOCDIR', conf.options.docdir, docdir)
286 _define_from_opt(conf, 'LIBDIR', conf.options.libdir, libdir)
287 _define_from_opt(conf, 'MANDIR', conf.options.mandir, mandir)
289 conf.define('ENABLE_NLS', 1)
290 conf.define('GEANY_LOCALEDIR', '' if is_win32 else conf.env['LOCALEDIR'], quote=True)
291 conf.define('GEANY_DATADIR', 'data' if is_win32 else conf.env['DATADIR'], quote=True)
292 conf.define('GEANY_DOCDIR', conf.env['DOCDIR'], quote=True)
293 conf.define('GEANY_LIBDIR', '' if is_win32 else conf.env['LIBDIR'], quote=True)
294 conf.define('GEANY_PREFIX', '' if is_win32 else conf.env['PREFIX'], quote=True)
295 conf.define('PACKAGE', APPNAME, quote=True)
296 conf.define('VERSION', VERSION, quote=True)
297 conf.define('REVISION', revision or '-1', quote=True)
299 conf.define('GETTEXT_PACKAGE', APPNAME, quote=True)
303 conf.options.no_vte = True
305 _define_from_opt(conf, 'HAVE_PLUGINS', not conf.options.no_plugins, None)
306 _define_from_opt(conf, 'HAVE_SOCKET', not conf.options.no_socket, None)
307 _define_from_opt(conf, 'HAVE_VTE', not conf.options.no_vte, None)
309 conf.write_config_header('config.h', remove=False)
311 # GEANY_EXPORT_SYMBOL and GEANY_API_SYMBOL
313 geany_symbol_flags = ['-DGEANY_EXPORT_SYMBOL=__declspec(dllexport)']
314 elif visibility_hidden_supported:
315 geany_symbol_flags = ['-fvisibility=hidden',
316 '-DGEANY_EXPORT_SYMBOL=__attribute__((visibility("default")))']
317 else: # unknown, define to nothing
318 geany_symbol_flags = ['-DGEANY_EXPORT_SYMBOL=']
319 geany_symbol_flags.append('-DGEANY_API_SYMBOL=GEANY_EXPORT_SYMBOL')
320 conf.env.append_value('CFLAGS', geany_symbol_flags)
321 conf.env.append_value('CXXFLAGS', geany_symbol_flags)
323 # some more compiler flags
324 conf.env.append_value('CFLAGS', ['-DHAVE_CONFIG_H'])
325 if conf.env['CC_NAME'] == 'gcc' and '-O' not in ''.join(conf.env['CFLAGS']):
326 conf.env.append_value('CFLAGS', ['-O2'])
327 if revision is not None:
328 conf.env.append_value('CFLAGS', ['-g', '-DGEANY_DEBUG'])
330 conf.env.append_value('CFLAGS', ['-DGTK'])
331 conf.env.append_value('CXXFLAGS',
332 ['-DNDEBUG', '-DGTK', '-DSCI_LEXER', '-DG_THREADS_IMPL_NONE'])
335 Logs.pprint('BLUE', 'Summary:')
336 conf.msg('Install Geany ' + VERSION + ' in', conf.env['PREFIX'])
337 conf.msg('Using GTK version', gtk_version)
338 conf.msg('Build with plugin support', conf.options.no_plugins and 'no' or 'yes')
339 conf.msg('Use virtual terminal support', conf.options.no_vte and 'no' or 'yes')
340 if revision is not None:
341 conf.msg('Compiling Git revision', revision)
345 # Disable MSVC detection on win32: building Geany with MSVC is currently not supported
346 # If anyone wants to add support for building with MSVC, this hack should be removed.
347 c_compiler['win32'] = ['gcc']
348 cxx_compiler['win32'] = ['g++']
350 opt.load('compiler_cc')
351 opt.load('compiler_cxx')
355 opt.add_option('--no-scm', action='store_true', default=False,
356 help='Disable SCM detection [default: No]', dest='no_scm')
358 opt.add_option('--disable-plugins', action='store_true', default=False,
359 help='compile without plugin support [default: No]', dest='no_plugins')
360 opt.add_option('--disable-socket', action='store_true', default=False,
361 help='compile without support to detect a running instance [[default: No]',
363 opt.add_option('--disable-vte', action='store_true', default=False,
364 help='compile without support for an embedded virtual terminal [[default: No]',
366 opt.add_option('--enable-gtk3', action='store_true', default=False,
367 help='compile with GTK3 support (experimental) [[default: No]',
369 opt.add_option('--enable-mac-integration', action='store_true', default=False,
370 help='use gtk-mac-integration to enable improved OS X integration [[default: No]',
371 dest='enable_mac_integration')
372 opt.add_option('--disable-html-docs', action='store_true', default=False,
373 help='do not generate HTML documentation using rst2html [[default: No]',
376 opt.add_option('--mandir', type='string', default='',
377 help='man documentation', dest='mandir')
378 opt.add_option('--docdir', type='string', default='',
379 help='documentation root', dest='docdir')
380 opt.add_option('--libdir', type='string', default='',
381 help='object code libraries', dest='libdir')
385 is_win32 = _target_is_win32(bld)
387 if bld.cmd == 'clean':
388 _remove_linguas_file()
389 if bld.cmd in ('install', 'uninstall'):
390 bld.add_post_fun(_post_install)
392 def build_plugin(plugin_name, install=True, uselib_add=[]):
394 instpath = '${PREFIX}/lib' if is_win32 else '${LIBDIR}/geany'
399 features = ['c', 'cshlib'],
400 source = 'plugins/%s.c' % plugin_name,
401 includes = ['.', 'src/', 'scintilla/include', 'tagmanager/src'],
402 defines = 'G_LOG_DOMAIN="%s"' % plugin_name,
403 target = plugin_name,
404 uselib = ['GTK', 'GLIB', 'GMODULE'] + uselib_add,
406 install_path = instpath)
410 features = ['c', 'cstlib'],
411 source = ctags_sources,
414 includes = ['.', 'tagmanager', 'tagmanager/ctags'],
415 defines = 'G_LOG_DOMAIN="CTags"',
417 install_path = None) # do not install this library
421 features = ['c', 'cstlib'],
422 source = tagmanager_sources,
424 target = 'tagmanager',
425 includes = ['.', 'tagmanager', 'tagmanager/ctags'],
426 defines = ['GEANY_PRIVATE', 'G_LOG_DOMAIN="Tagmanager"'],
427 uselib = ['GTK', 'GLIB'],
428 install_path = None) # do not install this library
432 features = ['c', 'cstlib'],
433 source = mio_sources,
436 includes = ['.', 'tagmanager/mio/'],
437 defines = 'G_LOG_DOMAIN="MIO"',
438 uselib = ['GTK', 'GLIB'],
439 install_path = None) # do not install this library
442 files = bld.srcnode.ant_glob('scintilla/**/*.cxx', src=True, dir=False)
443 scintilla_sources.update([file.path_from(bld.srcnode) for file in files])
445 features = ['c', 'cxx', 'cxxstlib'],
447 target = 'scintilla',
448 source = scintilla_sources,
449 includes = ['.', 'scintilla/include', 'scintilla/src', 'scintilla/lexlib'],
450 uselib = ['GTK', 'GLIB', 'GMODULE', 'M'],
451 install_path = None) # do not install this library
454 if bld.env['HAVE_VTE'] == 1:
455 geany_sources.add('src/vte.c')
457 geany_sources.add('src/win32.c')
458 geany_sources.add('geany_private.rc')
460 base_uselibs = ['GTK', 'GLIB', 'GMODULE', 'GIO', 'GTHREAD', 'WIN32', 'MAC_INTEGRATION', 'SUNOS_SOCKET', 'M']
463 features = ['c', 'cxx', 'cshlib'],
466 source = geany_sources,
467 includes = ['.', 'scintilla/include', 'tagmanager/src'],
468 defines = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
469 uselib = base_uselibs,
470 use = ['scintilla', 'ctags', 'tagmanager', 'mio'],
471 vnum = GEANY_LIB_VERSION)
475 features = ['c', 'cxx', 'cprogram'],
478 source = ['src/main.c'],
479 includes = ['.', 'scintilla/include', 'tagmanager/src'],
480 defines = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
481 uselib = base_uselibs,
485 if bld.env['HAVE_PLUGINS'] == 1:
486 build_plugin('classbuilder')
487 build_plugin('demoplugin', False)
488 build_plugin('export', uselib_add=['M'])
489 build_plugin('filebrowser')
490 build_plugin('htmlchars')
491 build_plugin('saveactions')
492 build_plugin('splitwindow')
495 if bld.env['INTLTOOL']:
497 features = ['linguas', 'intltool_po'],
499 install_path = '${LOCALEDIR}',
502 # HTML documentation (build if it is not part of the tree already, as it is required for install)
503 html_doc_filename = os.path.join(bld.out_dir, 'doc', 'geany.html')
504 if bld.env['RST2HTML']:
505 rst2html = bld.env['RST2HTML']
507 source = ['doc/geany.txt'],
508 deps = ['doc/geany.css'],
509 target = 'doc/geany.html',
511 cwd = os.path.join(bld.path.abspath(), 'doc'),
512 rule = '%s -stg --stylesheet=geany.css geany.txt %s' % (rst2html, html_doc_filename))
516 # replace backward slashes by forward slashes as they could be interepreted as escape
518 geany_pc_prefix = bld.env['PREFIX'].replace('\\', '/')
520 geany_pc_prefix = bld.env['PREFIX']
522 source = 'geany.pc.in',
523 dct = {'VERSION': VERSION,
524 'DEPENDENCIES': '%s >= %s glib-2.0 >= %s' % \
525 (bld.env['gtk_package_name'],
526 bld.env['minimum_gtk_version'],
527 MINIMUM_GLIB_VERSION),
528 'prefix': geany_pc_prefix,
529 'exec_prefix': '${prefix}',
530 'libdir': '${exec_prefix}/lib',
531 'includedir': '${prefix}/include',
532 'datarootdir': '${prefix}/share',
533 'datadir': '${datarootdir}',
534 'localedir': '${datarootdir}/locale'})
538 if bld.env['INTLTOOL']:
540 features = 'intltool_in',
541 source = 'geany.desktop.in',
542 flags = ['-d', '-q', '-u', '-c'],
543 install_path = '${DATADIR}/applications')
548 source = 'doc/geany.1.in',
550 dct = {'VERSION': VERSION,
551 'GEANY_DATA_DIR': bld.env['DATADIR'] + '/geany'},
552 install_path = '${MANDIR}/man1')
557 source = 'geany.spec.in',
558 target = 'geany.spec',
560 dct = {'VERSION': VERSION})
565 source = 'doc/Doxyfile.in',
566 target = 'doc/Doxyfile',
568 dct = {'VERSION': VERSION,
569 'top_builddir': bld.out_dir,
570 'top_srcdir': bld.top_dir,})
576 bld.install_files('${PREFIX}/include/geany', '''
577 src/app.h src/document.h src/editor.h src/encodings.h src/filetypes.h src/geany.h
578 src/highlighting.h src/keybindings.h src/msgwindow.h src/plugindata.h
579 src/prefs.h src/project.h src/search.h src/stash.h src/support.h
580 src/templates.h src/toolbar.h src/ui_utils.h src/utils.h src/build.h src/gtkcompat.h
581 plugins/geanyplugin.h plugins/geanyfunctions.h''')
582 bld.install_files('${PREFIX}/include/geany/scintilla', '''
583 scintilla/include/SciLexer.h scintilla/include/Scintilla.h
584 scintilla/include/Scintilla.iface scintilla/include/ScintillaWidget.h ''')
585 bld.install_files('${PREFIX}/include/geany/tagmanager', '''
586 tagmanager/src/tm_source_file.h
587 tagmanager/src/tm_tag.h
588 tagmanager/src/tm_tagmanager.h
589 tagmanager/src/tm_workspace.h ''')
591 base_dir = '${PREFIX}' if is_win32 else '${DOCDIR}'
592 ext = '.txt' if is_win32 else ''
593 for filename in 'AUTHORS ChangeLog COPYING README NEWS THANKS TODO'.split():
594 basename = _uc_first(filename, bld)
595 destination_filename = '%s%s' % (basename, ext)
596 destination = os.path.join(base_dir, destination_filename)
597 bld.install_as(destination, filename)
599 # install HTML documentation only if it exists, i.e. it was built before
600 # local_html_doc_filename supports installing HTML doc from in-tree geany.html if it exists
601 local_html_doc_filename = os.path.join(bld.path.abspath(), 'doc', 'geany.html')
602 if os.path.exists(html_doc_filename) or os.path.exists(local_html_doc_filename):
603 html_dir = '' if is_win32 else 'html/'
604 html_name = 'Manual.html' if is_win32 else 'index.html'
605 start_dir = bld.path.find_dir('doc/images')
606 bld.install_files('${DOCDIR}/%simages' % html_dir, start_dir.ant_glob('*.png'), cwd=start_dir)
607 bld.install_as('${DOCDIR}/%s%s' % (html_dir, html_name), 'doc/geany.html')
609 bld.install_as('${DOCDIR}/%s' % _uc_first('manual.txt', bld), 'doc/geany.txt')
610 bld.install_as('${DOCDIR}/ScintillaLicense.txt', 'scintilla/License.txt')
612 bld.install_as('${DOCDIR}/ReadMe.I18n.txt', 'README.I18N')
613 bld.install_as('${DOCDIR}/Hacking.txt', 'HACKING')
615 data_dir = '' if is_win32 else 'geany'
616 start_dir = bld.path.find_dir('data')
617 bld.install_as('${DATADIR}/%s/GPL-2' % data_dir, 'COPYING')
618 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('filetype*'), cwd=start_dir)
619 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('*.tags'), cwd=start_dir)
620 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.glade')
621 bld.install_files('${DATADIR}/%s' % data_dir, 'data/snippets.conf')
622 bld.install_files('${DATADIR}/%s' % data_dir, 'data/ui_toolbar.xml')
623 if bld.env['use_gtk3']:
624 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.css')
626 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.gtkrc')
628 start_dir = bld.path.find_dir('data/colorschemes')
629 template_dest = '${DATADIR}/%s/colorschemes' % data_dir
630 bld.install_files(template_dest, start_dir.ant_glob('*'), cwd=start_dir)
631 start_dir = bld.path.find_dir('data/templates')
632 template_dest = '${DATADIR}/%s/templates' % data_dir
633 bld.install_files(template_dest, start_dir.ant_glob('**/*'), cwd=start_dir, relative_trick=True)
635 for dest, srcs in geany_icons.items():
636 dest_dir = os.path.join('${PREFIX}/share/icons' if is_win32 else '${DATADIR}/icons', dest)
637 bld.install_files(dest_dir, srcs, cwd=bld.path.find_dir('icons'))
638 # install theme indexes on Windows
640 for dest, srcs in geany_icons_indexes.items():
641 bld.install_files(os.path.join('${PREFIX}/share/icons', dest), srcs, cwd=bld.path.find_dir('icons'))
645 Scripting.distclean(ctx)
646 _remove_linguas_file()
649 def _remove_linguas_file():
650 # remove LINGUAS file as well
652 os.unlink(LINGUAS_FILE)
658 @before_method('apply_intltool_po')
659 def write_linguas_file(self):
660 if os.path.exists(LINGUAS_FILE):
663 if 'LINGUAS' in self.env:
664 files = self.env['LINGUAS']
665 for po_filename in files.split(' '):
666 if os.path.exists('po/%s.po' % po_filename):
667 linguas += '%s ' % po_filename
669 files = os.listdir('%s/po' % self.path.abspath())
671 for filename in files:
672 if filename.endswith('.po'):
673 linguas += '%s ' % filename[:-3]
674 file_h = open(LINGUAS_FILE, 'w')
675 file_h.write('# This file is autogenerated. Do not edit.\n%s\n' % linguas)
679 def _post_install(ctx):
680 is_win32 = _target_is_win32(ctx)
683 for d in 'hicolor', 'Tango':
684 theme_dir = Utils.subst_vars('${DATADIR}/icons/' + d, ctx.env)
685 icon_cache_updated = False
686 if not ctx.options.destdir:
687 ctx.exec_command('gtk-update-icon-cache -q -f -t %s' % theme_dir)
688 Logs.pprint('GREEN', 'GTK icon cache updated.')
689 icon_cache_updated = True
690 if not icon_cache_updated:
691 Logs.pprint('YELLOW', 'Icon cache not updated. After install, run this:')
692 Logs.pprint('YELLOW', 'gtk-update-icon-cache -q -f -t %s' % theme_dir)
696 """update the message catalogs for internationalization"""
697 potfile = '%s.pot' % APPNAME
698 os.chdir('%s/po' % top)
701 old_size = os.stat(potfile).st_size
704 ctx.exec_command('intltool-update --pot -g %s' % APPNAME)
705 size_new = os.stat(potfile).st_size
706 if size_new != old_size:
707 Logs.pprint('CYAN', 'Updated POT file.')
708 Logs.pprint('CYAN', 'Updating translations')
709 ret = ctx.exec_command('intltool-update -r -g %s' % APPNAME)
711 Logs.pprint('RED', 'Updating translations failed')
713 Logs.pprint('CYAN', 'POT file is up to date.')
715 Logs.pprint('RED', 'Failed to generate pot file.')
719 """generate API reference documentation"""
720 ctx = BuildContext() # create our own context to have ctx.top_dir
721 basedir = ctx.top_dir
722 doxygen = _find_program(ctx, 'doxygen')
723 doxyfile = '%s/doc/Doxyfile' % ctx.out_dir
724 Logs.pprint('CYAN', 'Generating API documentation')
725 ret = ctx.exec_command('%s %s' % (doxygen, doxyfile))
727 raise WafError('Generating API documentation failed')
731 """generate HACKING documentation"""
732 ctx = BuildContext() # create our own context to have ctx.top_dir
733 Logs.pprint('CYAN', 'Generating HACKING documentation')
734 cmd = _find_rst2html(ctx)
735 hacking_file = os.path.join(ctx.top_dir, 'HACKING')
736 hacking_html_file = os.path.join(ctx.top_dir, 'doc', 'hacking.html')
737 stylesheet = os.path.join(ctx.top_dir, 'doc', 'geany.css')
738 ret = ctx.exec_command('%s -stg --stylesheet=%s %s %s' % (
739 cmd, stylesheet, hacking_file, hacking_html_file))
741 raise WafError('Generating HACKING documentation failed')
744 def _find_program(ctx, cmd, **kw):
748 if ctx is None or not isinstance(ctx, ConfigurationContext):
749 ctx = ConfigurationContext()
752 return ctx.find_program(cmd, **kw)
755 def _find_rst2html(ctx):
756 cmds = ['rst2html', 'rst2html2']
758 cmd = _find_program(ctx, command, mandatory=False, exts=',.py')
763 'rst2html.py could not be found. Please install the Python docutils package.')
767 def _add_define_to_env(conf, key):
768 value = conf.get_define(key)
770 value = value.replace('"', '')
771 conf.env[key] = value
774 def _add_to_env_and_define(conf, key, value, quote=False):
775 conf.define(key, value, quote)
776 conf.env[key] = value
779 def _define_from_opt(conf, define_name, opt_value, default_value, quote=1):
780 value = default_value
782 if isinstance(opt_value, bool):
786 if value is not None:
787 _add_to_env_and_define(conf, define_name, value, quote)
789 conf.undefine(define_name)
792 def _get_git_rev(conf):
793 if conf.options.no_scm:
796 if not os.path.isdir('.git'):
800 cmd = 'git rev-parse --short --revs-only HEAD'
801 revision = conf.cmd_and_log(cmd).strip()
808 def _load_intltool_if_available(conf):
810 conf.load('intltool')
811 if 'LINGUAS' in os.environ:
812 conf.env['LINGUAS'] = os.environ['LINGUAS']
814 # on Windows, we don't hard depend on intltool, on all other platforms raise an error
815 if not _target_is_win32(conf):
819 def _target_is_win32(ctx):
820 if 'is_win32' in ctx.env:
822 return ctx.env['is_win32']
824 if sys.platform == 'win32':
827 if ctx.env and 'CC' in ctx.env:
828 env_cc = ctx.env['CC']
829 if not isinstance(env_cc, str):
830 env_cc = ''.join(env_cc)
831 is_win32 = (env_cc.find('mingw') != -1)
834 # cache for future checks
835 ctx.env['is_win32'] = is_win32
839 def _uc_first(string, ctx):
840 if _target_is_win32(ctx):
841 return string.title()