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 conf.check_cc(header_name='fcntl.h', mandatory=False)
190 conf.check_cc(header_name='fnmatch.h', mandatory=False)
191 conf.check_cc(header_name='glob.h', mandatory=False)
192 conf.check_cc(header_name='sys/time.h', mandatory=False)
193 conf.check_cc(header_name='sys/types.h', mandatory=False)
194 conf.check_cc(header_name='sys/stat.h', mandatory=False)
195 conf.define('HAVE_STDLIB_H', 1) # are there systems without stdlib.h?
196 conf.define('STDC_HEADERS', 1) # an optimistic guess ;-)
197 _add_to_env_and_define(conf, 'HAVE_REGCOMP', 1) # needed for CTags
199 conf.check_cc(function_name='fgetpos', header_name='stdio.h', mandatory=False)
200 conf.check_cc(function_name='fnmatch', header_name='fnmatch.h', mandatory=False)
201 conf.check_cc(function_name='ftruncate', header_name='unistd.h', mandatory=False)
202 conf.check_cc(function_name='mkstemp', header_name='stdlib.h', mandatory=False)
203 conf.check_cc(function_name='strstr', header_name='string.h')
205 conf.check_cc(function_name='pow', header_name='math.h', lib='m', uselib_store='M')
207 # check sunOS socket support
208 if Options.platform == 'sunos':
209 conf.check_cc(function_name='socket', lib='socket',
210 header_name='sys/socket.h', uselib_store='SUNOS_SOCKET', mandatory=True)
212 # check for cxx after the header and function checks have been done to ensure they are
213 # checked with cc not cxx
214 conf.load('compiler_cxx')
217 _load_intltool_if_available(conf)
219 # GTK / GIO version check
220 gtk_package_name = 'gtk+-3.0' if conf.options.use_gtk3 else 'gtk+-2.0'
221 minimum_gtk_version = MINIMUM_GTK3_VERSION if conf.options.use_gtk3 else MINIMUM_GTK_VERSION
222 conf.check_cfg(package=gtk_package_name, atleast_version=minimum_gtk_version, uselib_store='GTK',
223 mandatory=True, args='--cflags --libs')
224 conf.check_cfg(package='glib-2.0', atleast_version=MINIMUM_GLIB_VERSION, uselib_store='GLIB',
225 mandatory=True, args='--cflags --libs')
226 conf.check_cfg(package='gmodule-2.0', uselib_store='GMODULE',
227 mandatory=True, args='--cflags --libs')
228 conf.check_cfg(package='gio-2.0', uselib_store='GIO', args='--cflags --libs', mandatory=True)
229 gtk_version = conf.check_cfg(modversion=gtk_package_name, uselib_store='GTK') or 'Unknown'
230 conf.check_cfg(package='gthread-2.0', uselib_store='GTHREAD', args='--cflags --libs')
231 if conf.options.enable_mac_integration:
232 pkgname = 'gtk-mac-integration-gtk3' if conf.options.use_gtk3 else 'gtk-mac-integration-gtk2'
233 conf.check_cfg(package=pkgname, uselib_store='MAC_INTEGRATION',
234 mandatory=True, args='--cflags --libs')
235 # remember GTK version for the build step
236 conf.env['gtk_package_name'] = gtk_package_name
237 conf.env['minimum_gtk_version'] = minimum_gtk_version
238 conf.env['use_gtk3'] = conf.options.use_gtk3
240 revision = _get_git_rev(conf)
242 # rst2html for the HTML manual
243 if not conf.options.no_html_doc and revision is not None:
245 conf.env['RST2HTML'] = _find_rst2html(conf)
247 error_msg = '''Documentation enabled but rst2html not found.
248 You can explicitly disable building of the HTML manual with --disable-html-docs,
249 but you then may not have a local copy of the HTML manual.'''
250 raise WafError(error_msg)
254 if conf.env['PREFIX'].lower() == tempfile.gettempdir().lower():
255 # overwrite default prefix on Windows (tempfile.gettempdir() is the Waf default)
256 new_prefix = os.path.join(str(conf.root), '%s-%s' % (APPNAME, VERSION))
257 _add_to_env_and_define(conf, 'PREFIX', new_prefix, quote=True)
258 _add_to_env_and_define(conf, 'BINDIR', os.path.join(new_prefix, 'bin'), quote=True)
259 _add_to_env_and_define(conf, 'DOCDIR', os.path.join(conf.env['PREFIX'], 'doc'), quote=True)
260 _add_to_env_and_define(conf, 'LIBDIR', '%s/lib' % conf.env['PREFIX'], quote=True)
261 conf.define('LOCALEDIR', os.path.join('share' 'locale'), quote=True)
262 # overwrite LOCALEDIR to install message catalogues properly
263 conf.env['LOCALEDIR'] = os.path.join(conf.env['PREFIX'], 'share', 'locale')
264 # DATADIR is defined in objidl.h, so we remove it from config.h but keep it in env
265 conf.undefine('DATADIR')
266 conf.env['DATADIR'] = os.path.join(conf.env['PREFIX'], 'data')
267 conf.env.append_value('LINKFLAGS_cprogram', [
270 '-static-libstdc++'])
271 conf.env.append_value('LIB_WIN32', ['wsock32', 'uuid', 'ole32'])
272 # explicitly define Windows version for older Mingw environments
273 conf.define('WINVER', '0x0501', quote=False) # for SHGetFolderPathAndSubDirW
274 conf.define('_WIN32_IE', '0x0500', quote=False) # for SHGFP_TYPE
276 conf.env['cshlib_PATTERN'] = '%s.so'
277 # DATADIR and LOCALEDIR are defined by the intltool tool
278 # but they are not added to the environment, so we need to
279 _add_define_to_env(conf, 'DATADIR')
280 _add_define_to_env(conf, 'LOCALEDIR')
281 docdir = os.path.join(conf.env['DATADIR'], 'doc', 'geany')
282 libdir = os.path.join(conf.env['PREFIX'], 'lib')
283 mandir = os.path.join(conf.env['DATADIR'], 'man')
284 _define_from_opt(conf, 'DOCDIR', conf.options.docdir, docdir)
285 _define_from_opt(conf, 'LIBDIR', conf.options.libdir, libdir)
286 _define_from_opt(conf, 'MANDIR', conf.options.mandir, mandir)
288 conf.define('ENABLE_NLS', 1)
289 conf.define('GEANY_LOCALEDIR', '' if is_win32 else conf.env['LOCALEDIR'], quote=True)
290 conf.define('GEANY_DATADIR', 'data' if is_win32 else conf.env['DATADIR'], quote=True)
291 conf.define('GEANY_DOCDIR', conf.env['DOCDIR'], quote=True)
292 conf.define('GEANY_LIBDIR', '' if is_win32 else conf.env['LIBDIR'], quote=True)
293 conf.define('GEANY_PREFIX', '' if is_win32 else conf.env['PREFIX'], quote=True)
294 conf.define('PACKAGE', APPNAME, quote=True)
295 conf.define('VERSION', VERSION, quote=True)
296 conf.define('REVISION', revision or '-1', quote=True)
298 conf.define('GETTEXT_PACKAGE', APPNAME, quote=True)
302 conf.options.no_vte = True
304 _define_from_opt(conf, 'HAVE_PLUGINS', not conf.options.no_plugins, None)
305 _define_from_opt(conf, 'HAVE_SOCKET', not conf.options.no_socket, None)
306 _define_from_opt(conf, 'HAVE_VTE', not conf.options.no_vte, None)
308 conf.write_config_header('config.h', remove=False)
310 # GEANY_EXPORT_SYMBOL and GEANY_API_SYMBOL
312 geany_symbol_flags = ['-DGEANY_EXPORT_SYMBOL=__declspec(dllexport)']
313 # FIXME: check for -fvisibility and the __attribute__((visibility)), or
314 # at least for GCC >= 4
315 elif conf.env['CC_NAME'] == 'gcc':
316 geany_symbol_flags = ['-fvisibility=hidden',
317 '-DGEANY_EXPORT_SYMBOL=__attribute__((visibility("default")))']
318 else: # unknown, define to nothing
319 geany_symbol_flags = ['-DGEANY_EXPORT_SYMBOL=']
320 geany_symbol_flags.append('-DGEANY_API_SYMBOL=GEANY_EXPORT_SYMBOL')
321 conf.env.append_value('CFLAGS', geany_symbol_flags)
322 conf.env.append_value('CXXFLAGS', geany_symbol_flags)
324 # some more compiler flags
325 conf.env.append_value('CFLAGS', ['-DHAVE_CONFIG_H'])
326 if conf.env['CC_NAME'] == 'gcc' and '-O' not in ''.join(conf.env['CFLAGS']):
327 conf.env.append_value('CFLAGS', ['-O2'])
328 if revision is not None:
329 conf.env.append_value('CFLAGS', ['-g', '-DGEANY_DEBUG'])
331 conf.env.append_value('CFLAGS', ['-DGTK'])
332 conf.env.append_value('CXXFLAGS',
333 ['-DNDEBUG', '-DGTK', '-DSCI_LEXER', '-DG_THREADS_IMPL_NONE'])
336 Logs.pprint('BLUE', 'Summary:')
337 conf.msg('Install Geany ' + VERSION + ' in', conf.env['PREFIX'])
338 conf.msg('Using GTK version', gtk_version)
339 conf.msg('Build with plugin support', conf.options.no_plugins and 'no' or 'yes')
340 conf.msg('Use virtual terminal support', conf.options.no_vte and 'no' or 'yes')
341 if revision is not None:
342 conf.msg('Compiling Git revision', revision)
346 # Disable MSVC detection on win32: building Geany with MSVC is currently not supported
347 # If anyone wants to add support for building with MSVC, this hack should be removed.
348 c_compiler['win32'] = ['gcc']
349 cxx_compiler['win32'] = ['g++']
351 opt.load('compiler_cc')
352 opt.load('compiler_cxx')
356 opt.add_option('--no-scm', action='store_true', default=False,
357 help='Disable SCM detection [default: No]', dest='no_scm')
359 opt.add_option('--disable-plugins', action='store_true', default=False,
360 help='compile without plugin support [default: No]', dest='no_plugins')
361 opt.add_option('--disable-socket', action='store_true', default=False,
362 help='compile without support to detect a running instance [[default: No]',
364 opt.add_option('--disable-vte', action='store_true', default=False,
365 help='compile without support for an embedded virtual terminal [[default: No]',
367 opt.add_option('--enable-gtk3', action='store_true', default=False,
368 help='compile with GTK3 support (experimental) [[default: No]',
370 opt.add_option('--enable-mac-integration', action='store_true', default=False,
371 help='use gtk-mac-integration to enable improved OS X integration [[default: No]',
372 dest='enable_mac_integration')
373 opt.add_option('--disable-html-docs', action='store_true', default=False,
374 help='do not generate HTML documentation using rst2html [[default: No]',
377 opt.add_option('--mandir', type='string', default='',
378 help='man documentation', dest='mandir')
379 opt.add_option('--docdir', type='string', default='',
380 help='documentation root', dest='docdir')
381 opt.add_option('--libdir', type='string', default='',
382 help='object code libraries', dest='libdir')
386 is_win32 = _target_is_win32(bld)
388 if bld.cmd == 'clean':
389 _remove_linguas_file()
390 if bld.cmd in ('install', 'uninstall'):
391 bld.add_post_fun(_post_install)
393 def build_plugin(plugin_name, install=True, uselib_add=[]):
395 instpath = '${PREFIX}/lib' if is_win32 else '${LIBDIR}/geany'
400 features = ['c', 'cshlib'],
401 source = 'plugins/%s.c' % plugin_name,
402 includes = ['.', 'src/', 'scintilla/include', 'tagmanager/src'],
403 defines = 'G_LOG_DOMAIN="%s"' % plugin_name,
404 target = plugin_name,
405 uselib = ['GTK', 'GLIB', 'GMODULE'] + uselib_add,
407 install_path = instpath)
411 features = ['c', 'cstlib'],
412 source = ctags_sources,
415 includes = ['.', 'tagmanager', 'tagmanager/ctags'],
416 defines = 'G_LOG_DOMAIN="CTags"',
418 install_path = None) # do not install this library
422 features = ['c', 'cstlib'],
423 source = tagmanager_sources,
425 target = 'tagmanager',
426 includes = ['.', 'tagmanager', 'tagmanager/ctags'],
427 defines = ['GEANY_PRIVATE', 'G_LOG_DOMAIN="Tagmanager"'],
428 uselib = ['GTK', 'GLIB'],
429 install_path = None) # do not install this library
433 features = ['c', 'cstlib'],
434 source = mio_sources,
437 includes = ['.', 'tagmanager/mio/'],
438 defines = 'G_LOG_DOMAIN="MIO"',
439 uselib = ['GTK', 'GLIB'],
440 install_path = None) # do not install this library
443 files = bld.srcnode.ant_glob('scintilla/**/*.cxx', src=True, dir=False)
444 scintilla_sources.update([file.path_from(bld.srcnode) for file in files])
446 features = ['c', 'cxx', 'cxxstlib'],
448 target = 'scintilla',
449 source = scintilla_sources,
450 includes = ['.', 'scintilla/include', 'scintilla/src', 'scintilla/lexlib'],
451 uselib = ['GTK', 'GLIB', 'GMODULE', 'M'],
452 install_path = None) # do not install this library
455 if bld.env['HAVE_VTE'] == 1:
456 geany_sources.add('src/vte.c')
458 geany_sources.add('src/win32.c')
459 geany_sources.add('geany_private.rc')
461 base_uselibs = ['GTK', 'GLIB', 'GMODULE', 'GIO', 'GTHREAD', 'WIN32', 'MAC_INTEGRATION', 'SUNOS_SOCKET', 'M']
464 features = ['c', 'cxx', 'cshlib'],
467 source = geany_sources,
468 includes = ['.', 'scintilla/include', 'tagmanager/src'],
469 defines = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
470 uselib = base_uselibs,
471 use = ['scintilla', 'ctags', 'tagmanager', 'mio'],
472 vnum = GEANY_LIB_VERSION)
476 features = ['c', 'cxx', 'cprogram'],
479 source = ['src/main.c'],
480 includes = ['.', 'scintilla/include', 'tagmanager/src'],
481 defines = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
482 uselib = base_uselibs,
486 if bld.env['HAVE_PLUGINS'] == 1:
487 build_plugin('classbuilder')
488 build_plugin('demoplugin', False)
489 build_plugin('export', uselib_add=['M'])
490 build_plugin('filebrowser')
491 build_plugin('htmlchars')
492 build_plugin('saveactions')
493 build_plugin('splitwindow')
496 if bld.env['INTLTOOL']:
498 features = ['linguas', 'intltool_po'],
500 install_path = '${LOCALEDIR}',
503 # HTML documentation (build if it is not part of the tree already, as it is required for install)
504 html_doc_filename = os.path.join(bld.out_dir, 'doc', 'geany.html')
505 if bld.env['RST2HTML']:
506 rst2html = bld.env['RST2HTML']
508 source = ['doc/geany.txt'],
509 deps = ['doc/geany.css'],
510 target = 'doc/geany.html',
512 cwd = os.path.join(bld.path.abspath(), 'doc'),
513 rule = '%s -stg --stylesheet=geany.css geany.txt %s' % (rst2html, html_doc_filename))
517 # replace backward slashes by forward slashes as they could be interepreted as escape
519 geany_pc_prefix = bld.env['PREFIX'].replace('\\', '/')
521 geany_pc_prefix = bld.env['PREFIX']
523 source = 'geany.pc.in',
524 dct = {'VERSION': VERSION,
525 'DEPENDENCIES': '%s >= %s glib-2.0 >= %s' % \
526 (bld.env['gtk_package_name'],
527 bld.env['minimum_gtk_version'],
528 MINIMUM_GLIB_VERSION),
529 'prefix': geany_pc_prefix,
530 'exec_prefix': '${prefix}',
531 'libdir': '${exec_prefix}/lib',
532 'includedir': '${prefix}/include',
533 'datarootdir': '${prefix}/share',
534 'datadir': '${datarootdir}',
535 'localedir': '${datarootdir}/locale'})
539 if bld.env['INTLTOOL']:
541 features = 'intltool_in',
542 source = 'geany.desktop.in',
543 flags = ['-d', '-q', '-u', '-c'],
544 install_path = '${DATADIR}/applications')
549 source = 'doc/geany.1.in',
551 dct = {'VERSION': VERSION,
552 'GEANY_DATA_DIR': bld.env['DATADIR'] + '/geany'},
553 install_path = '${MANDIR}/man1')
558 source = 'geany.spec.in',
559 target = 'geany.spec',
561 dct = {'VERSION': VERSION})
566 source = 'doc/Doxyfile.in',
567 target = 'doc/Doxyfile',
569 dct = {'VERSION': VERSION,
570 'top_builddir': bld.out_dir,
571 'top_srcdir': bld.top_dir,})
577 bld.install_files('${PREFIX}/include/geany', '''
578 src/app.h src/document.h src/editor.h src/encodings.h src/filetypes.h src/geany.h
579 src/highlighting.h src/keybindings.h src/msgwindow.h src/plugindata.h
580 src/prefs.h src/project.h src/search.h src/stash.h src/support.h
581 src/templates.h src/toolbar.h src/ui_utils.h src/utils.h src/build.h src/gtkcompat.h
582 plugins/geanyplugin.h plugins/geanyfunctions.h''')
583 bld.install_files('${PREFIX}/include/geany/scintilla', '''
584 scintilla/include/SciLexer.h scintilla/include/Scintilla.h
585 scintilla/include/Scintilla.iface scintilla/include/ScintillaWidget.h ''')
586 bld.install_files('${PREFIX}/include/geany/tagmanager', '''
587 tagmanager/src/tm_source_file.h
588 tagmanager/src/tm_tag.h
589 tagmanager/src/tm_tagmanager.h
590 tagmanager/src/tm_workspace.h ''')
592 base_dir = '${PREFIX}' if is_win32 else '${DOCDIR}'
593 ext = '.txt' if is_win32 else ''
594 for filename in 'AUTHORS ChangeLog COPYING README NEWS THANKS TODO'.split():
595 basename = _uc_first(filename, bld)
596 destination_filename = '%s%s' % (basename, ext)
597 destination = os.path.join(base_dir, destination_filename)
598 bld.install_as(destination, filename)
600 # install HTML documentation only if it exists, i.e. it was built before
601 # local_html_doc_filename supports installing HTML doc from in-tree geany.html if it exists
602 local_html_doc_filename = os.path.join(bld.path.abspath(), 'doc', 'geany.html')
603 if os.path.exists(html_doc_filename) or os.path.exists(local_html_doc_filename):
604 html_dir = '' if is_win32 else 'html/'
605 html_name = 'Manual.html' if is_win32 else 'index.html'
606 start_dir = bld.path.find_dir('doc/images')
607 bld.install_files('${DOCDIR}/%simages' % html_dir, start_dir.ant_glob('*.png'), cwd=start_dir)
608 bld.install_as('${DOCDIR}/%s%s' % (html_dir, html_name), 'doc/geany.html')
610 bld.install_as('${DOCDIR}/%s' % _uc_first('manual.txt', bld), 'doc/geany.txt')
611 bld.install_as('${DOCDIR}/ScintillaLicense.txt', 'scintilla/License.txt')
613 bld.install_as('${DOCDIR}/ReadMe.I18n.txt', 'README.I18N')
614 bld.install_as('${DOCDIR}/Hacking.txt', 'HACKING')
616 data_dir = '' if is_win32 else 'geany'
617 start_dir = bld.path.find_dir('data')
618 bld.install_as('${DATADIR}/%s/GPL-2' % data_dir, 'COPYING')
619 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('filetype*'), cwd=start_dir)
620 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('*.tags'), cwd=start_dir)
621 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.glade')
622 bld.install_files('${DATADIR}/%s' % data_dir, 'data/snippets.conf')
623 bld.install_files('${DATADIR}/%s' % data_dir, 'data/ui_toolbar.xml')
624 if bld.env['use_gtk3']:
625 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.css')
627 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.gtkrc')
629 start_dir = bld.path.find_dir('data/colorschemes')
630 template_dest = '${DATADIR}/%s/colorschemes' % data_dir
631 bld.install_files(template_dest, start_dir.ant_glob('*'), cwd=start_dir)
632 start_dir = bld.path.find_dir('data/templates')
633 template_dest = '${DATADIR}/%s/templates' % data_dir
634 bld.install_files(template_dest, start_dir.ant_glob('**/*'), cwd=start_dir, relative_trick=True)
636 for dest, srcs in geany_icons.items():
637 dest_dir = os.path.join('${PREFIX}/share/icons' if is_win32 else '${DATADIR}/icons', dest)
638 bld.install_files(dest_dir, srcs, cwd=bld.path.find_dir('icons'))
639 # install theme indexes on Windows
641 for dest, srcs in geany_icons_indexes.items():
642 bld.install_files(os.path.join('${PREFIX}/share/icons', dest), srcs, cwd=bld.path.find_dir('icons'))
646 Scripting.distclean(ctx)
647 _remove_linguas_file()
650 def _remove_linguas_file():
651 # remove LINGUAS file as well
653 os.unlink(LINGUAS_FILE)
659 @before_method('apply_intltool_po')
660 def write_linguas_file(self):
661 if os.path.exists(LINGUAS_FILE):
664 if 'LINGUAS' in self.env:
665 files = self.env['LINGUAS']
666 for po_filename in files.split(' '):
667 if os.path.exists('po/%s.po' % po_filename):
668 linguas += '%s ' % po_filename
670 files = os.listdir('%s/po' % self.path.abspath())
672 for filename in files:
673 if filename.endswith('.po'):
674 linguas += '%s ' % filename[:-3]
675 file_h = open(LINGUAS_FILE, 'w')
676 file_h.write('# This file is autogenerated. Do not edit.\n%s\n' % linguas)
680 def _post_install(ctx):
681 is_win32 = _target_is_win32(ctx)
684 for d in 'hicolor', 'Tango':
685 theme_dir = Utils.subst_vars('${DATADIR}/icons/' + d, ctx.env)
686 icon_cache_updated = False
687 if not ctx.options.destdir:
688 ctx.exec_command('gtk-update-icon-cache -q -f -t %s' % theme_dir)
689 Logs.pprint('GREEN', 'GTK icon cache updated.')
690 icon_cache_updated = True
691 if not icon_cache_updated:
692 Logs.pprint('YELLOW', 'Icon cache not updated. After install, run this:')
693 Logs.pprint('YELLOW', 'gtk-update-icon-cache -q -f -t %s' % theme_dir)
697 """update the message catalogs for internationalization"""
698 potfile = '%s.pot' % APPNAME
699 os.chdir('%s/po' % top)
702 old_size = os.stat(potfile).st_size
705 ctx.exec_command('intltool-update --pot -g %s' % APPNAME)
706 size_new = os.stat(potfile).st_size
707 if size_new != old_size:
708 Logs.pprint('CYAN', 'Updated POT file.')
709 Logs.pprint('CYAN', 'Updating translations')
710 ret = ctx.exec_command('intltool-update -r -g %s' % APPNAME)
712 Logs.pprint('RED', 'Updating translations failed')
714 Logs.pprint('CYAN', 'POT file is up to date.')
716 Logs.pprint('RED', 'Failed to generate pot file.')
720 """generate API reference documentation"""
721 ctx = BuildContext() # create our own context to have ctx.top_dir
722 basedir = ctx.top_dir
723 doxygen = _find_program(ctx, 'doxygen')
724 doxyfile = '%s/doc/Doxyfile' % ctx.out_dir
725 Logs.pprint('CYAN', 'Generating API documentation')
726 ret = ctx.exec_command('%s %s' % (doxygen, doxyfile))
728 raise WafError('Generating API documentation failed')
732 """generate HACKING documentation"""
733 ctx = BuildContext() # create our own context to have ctx.top_dir
734 Logs.pprint('CYAN', 'Generating HACKING documentation')
735 cmd = _find_rst2html(ctx)
736 hacking_file = os.path.join(ctx.top_dir, 'HACKING')
737 hacking_html_file = os.path.join(ctx.top_dir, 'doc', 'hacking.html')
738 stylesheet = os.path.join(ctx.top_dir, 'doc', 'geany.css')
739 ret = ctx.exec_command('%s -stg --stylesheet=%s %s %s' % (
740 cmd, stylesheet, hacking_file, hacking_html_file))
742 raise WafError('Generating HACKING documentation failed')
745 def _find_program(ctx, cmd, **kw):
749 if ctx is None or not isinstance(ctx, ConfigurationContext):
750 ctx = ConfigurationContext()
753 return ctx.find_program(cmd, **kw)
756 def _find_rst2html(ctx):
757 cmds = ['rst2html', 'rst2html2']
759 cmd = _find_program(ctx, command, mandatory=False, exts=',.py')
764 'rst2html.py could not be found. Please install the Python docutils package.')
768 def _add_define_to_env(conf, key):
769 value = conf.get_define(key)
771 value = value.replace('"', '')
772 conf.env[key] = value
775 def _add_to_env_and_define(conf, key, value, quote=False):
776 conf.define(key, value, quote)
777 conf.env[key] = value
780 def _define_from_opt(conf, define_name, opt_value, default_value, quote=1):
781 value = default_value
783 if isinstance(opt_value, bool):
787 if value is not None:
788 _add_to_env_and_define(conf, define_name, value, quote)
790 conf.undefine(define_name)
793 def _get_git_rev(conf):
794 if conf.options.no_scm:
797 if not os.path.isdir('.git'):
801 cmd = 'git rev-parse --short --revs-only HEAD'
802 revision = conf.cmd_and_log(cmd).strip()
809 def _load_intltool_if_available(conf):
811 conf.load('intltool')
812 if 'LINGUAS' in os.environ:
813 conf.env['LINGUAS'] = os.environ['LINGUAS']
815 # on Windows, we don't hard depend on intltool, on all other platforms raise an error
816 if not _target_is_win32(conf):
820 def _target_is_win32(ctx):
821 if 'is_win32' in ctx.env:
823 return ctx.env['is_win32']
825 if sys.platform == 'win32':
828 if ctx.env and 'CC' in ctx.env:
829 env_cc = ctx.env['CC']
830 if not isinstance(env_cc, str):
831 env_cc = ''.join(env_cc)
832 is_win32 = (env_cc.find('mingw') != -1)
835 # cache for future checks
836 ctx.env['is_win32'] = is_win32
840 def _uc_first(string, ctx):
841 if _target_is_win32(ctx):
842 return string.title()