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 ConfigurationError, 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.24.0'
58 MINIMUM_GTK3_VERSION = '3.0.0'
59 MINIMUM_GLIB_VERSION = '2.28.0'
61 GEANY_LIB_VERSION = '0.0.0'
66 mio_sources = set(['tagmanager/mio/mio.c'])
69 'tagmanager/ctags/abaqus.c',
70 'tagmanager/ctags/args.c',
71 'tagmanager/ctags/abc.c',
72 'tagmanager/ctags/actionscript.c',
73 'tagmanager/ctags/asciidoc.c',
74 'tagmanager/ctags/asm.c',
75 'tagmanager/ctags/basic.c',
76 'tagmanager/ctags/c.c',
77 'tagmanager/ctags/cobol.c',
78 'tagmanager/ctags/conf.c',
79 'tagmanager/ctags/css.c',
80 'tagmanager/ctags/ctags.c',
81 'tagmanager/ctags/diff.c',
82 'tagmanager/ctags/docbook.c',
83 'tagmanager/ctags/erlang.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/powershell.c',
110 'tagmanager/ctags/python.c',
111 'tagmanager/ctags/read.c',
112 'tagmanager/ctags/rest.c',
113 'tagmanager/ctags/ruby.c',
114 'tagmanager/ctags/rust.c',
115 'tagmanager/ctags/sh.c',
116 'tagmanager/ctags/sort.c',
117 'tagmanager/ctags/sql.c',
118 'tagmanager/ctags/strlist.c',
119 'tagmanager/ctags/txt2tags.c',
120 'tagmanager/ctags/tcl.c',
121 'tagmanager/ctags/vhdl.c',
122 'tagmanager/ctags/verilog.c',
123 'tagmanager/ctags/vstring.c'])
125 tagmanager_sources = set([
126 'tagmanager/src/tm_source_file.c',
127 'tagmanager/src/tm_tag.c',
128 'tagmanager/src/tm_workspace.c'])
130 scintilla_sources = set(['scintilla/gtk/scintilla-marshal.c'])
132 geany_sources = set([
133 'src/about.c', 'src/build.c', 'src/callbacks.c', 'src/dialogs.c', 'src/document.c',
134 'src/editor.c', 'src/encodings.c', 'src/filetypes.c', 'src/geanyentryaction.c',
135 'src/geanymenubuttonaction.c', 'src/geanyobject.c', 'src/geanywraplabel.c',
136 'src/highlighting.c', 'src/keybindings.c',
137 'src/keyfile.c', 'src/log.c', 'src/libmain.c', 'src/msgwindow.c', 'src/navqueue.c', 'src/notebook.c', 'src/osx.c',
138 'src/plugins.c', 'src/pluginutils.c', 'src/prefix.c', 'src/prefs.c', 'src/printing.c', 'src/project.c',
139 'src/sciwrappers.c', 'src/search.c', 'src/socket.c', 'src/spawn.c', 'src/stash.c',
141 'src/templates.c', 'src/toolbar.c', 'src/tools.c', 'src/sidebar.c',
142 'src/ui_utils.c', 'src/utils.c'])
144 geany_bin_sources = set(['src/main.c'])
147 'hicolor/16x16/apps': ['16x16/classviewer-class.png',
148 '16x16/classviewer-macro.png',
149 '16x16/classviewer-member.png',
150 '16x16/classviewer-method.png',
151 '16x16/classviewer-namespace.png',
152 '16x16/classviewer-other.png',
153 '16x16/classviewer-struct.png',
154 '16x16/classviewer-var.png',
156 'hicolor/16x16/actions': ['16x16/geany-build.png',
157 '16x16/geany-close-all.png',
158 '16x16/geany-save-all.png'],
159 'hicolor/24x24/actions': ['24x24/geany-build.png',
160 '24x24/geany-close-all.png',
161 '24x24/geany-save-all.png'],
162 'hicolor/32x32/actions': ['32x32/geany-build.png',
163 '32x32/geany-close-all.png',
164 '32x32/geany-save-all.png'],
165 'hicolor/32x32/apps': ['32x32/geany.png'],
166 'hicolor/48x48/actions': ['48x48/geany-build.png',
167 '48x48/geany-close-all.png',
168 '48x48/geany-save-all.png'],
169 'hicolor/48x48/apps': ['48x48/geany.png'],
170 'hicolor/scalable/apps': ['scalable/geany.svg'],
171 'hicolor/scalable/actions': ['scalable/geany-build.svg',
172 'scalable/geany-close-all.svg',
173 'scalable/geany-save-all.svg'],
174 'Tango/16x16/actions': ['tango/16x16/geany-save-all.png'],
175 'Tango/24x24/actions': ['tango/24x24/geany-save-all.png'],
176 'Tango/32x32/actions': ['tango/32x32/geany-save-all.png'],
177 'Tango/48x48/actions': ['tango/48x48/geany-save-all.png'],
178 'Tango/scalable/actions': ['tango/scalable/geany-save-all.svg']
180 geany_icons_indexes = {
181 'hicolor': ['index.theme'],
182 'Tango': ['tango/index.theme']
188 conf.check_waf_version(mini='1.6.1')
190 conf.load('compiler_c')
192 is_win32 = _target_is_win32(conf)
194 visibility_hidden_supported = conf.check_cc(cflags=['-Werror', '-fvisibility=hidden'], mandatory=False)
195 conf.check_cc(header_name='fcntl.h', mandatory=False)
196 conf.check_cc(header_name='fnmatch.h', mandatory=False)
197 conf.check_cc(header_name='glob.h', mandatory=False)
198 conf.check_cc(header_name='sys/time.h', mandatory=False)
199 conf.check_cc(header_name='sys/types.h', mandatory=False)
200 conf.check_cc(header_name='sys/stat.h', mandatory=False)
201 conf.define('HAVE_STDLIB_H', 1) # are there systems without stdlib.h?
202 conf.define('STDC_HEADERS', 1) # an optimistic guess ;-)
203 _add_to_env_and_define(conf, 'HAVE_REGCOMP', 1) # needed for CTags
205 conf.check_cc(function_name='fgetpos', header_name='stdio.h', mandatory=False)
206 conf.check_cc(function_name='fnmatch', header_name='fnmatch.h', mandatory=False)
207 conf.check_cc(function_name='ftruncate', header_name='unistd.h', mandatory=False)
208 conf.check_cc(function_name='mkstemp', header_name='stdlib.h', mandatory=False)
209 conf.check_cc(function_name='strstr', header_name='string.h')
211 conf.check_cc(function_name='pow', header_name='math.h', lib='m', uselib_store='M')
213 # check sunOS socket support
214 if Options.platform == 'sunos':
215 conf.check_cc(function_name='socket', lib='socket',
216 header_name='sys/socket.h', uselib_store='SUNOS_SOCKET', mandatory=True)
218 # check for cxx after the header and function checks have been done to ensure they are
219 # checked with cc not cxx
220 conf.load('compiler_cxx')
223 _load_intltool_if_available(conf)
225 # GTK / GIO version check
226 gtk_package_name = 'gtk+-3.0' if conf.options.use_gtk3 else 'gtk+-2.0'
227 minimum_gtk_version = MINIMUM_GTK3_VERSION if conf.options.use_gtk3 else MINIMUM_GTK_VERSION
228 conf.check_cfg(package=gtk_package_name, atleast_version=minimum_gtk_version, uselib_store='GTK',
229 mandatory=True, args='--cflags --libs')
230 conf.check_cfg(package='glib-2.0', atleast_version=MINIMUM_GLIB_VERSION, uselib_store='GLIB',
231 mandatory=True, args='--cflags --libs')
232 conf.check_cfg(package='gmodule-2.0', uselib_store='GMODULE',
233 mandatory=True, args='--cflags --libs')
234 conf.check_cfg(package='gio-2.0', uselib_store='GIO', args='--cflags --libs', mandatory=True)
235 gtk_version = conf.check_cfg(modversion=gtk_package_name, uselib_store='GTK') or 'Unknown'
236 conf.check_cfg(package='gthread-2.0', uselib_store='GTHREAD', args='--cflags --libs')
237 if conf.options.enable_mac_integration:
238 pkgname = 'gtk-mac-integration-gtk3' if conf.options.use_gtk3 else 'gtk-mac-integration-gtk2'
239 conf.check_cfg(package=pkgname, uselib_store='MAC_INTEGRATION',
240 mandatory=True, args='--cflags --libs')
241 # remember GTK version for the build step
242 conf.env['gtk_package_name'] = gtk_package_name
243 conf.env['gtk_version'] = gtk_version
244 conf.env['minimum_gtk_version'] = minimum_gtk_version
245 conf.env['use_gtk3'] = conf.options.use_gtk3
247 revision = _get_git_rev(conf)
249 # rst2html for the HTML manual
250 if not conf.options.no_html_doc and revision is not None:
252 conf.env['RST2HTML'] = _find_rst2html(conf)
254 error_msg = '''Documentation enabled but rst2html not found.
255 You can explicitly disable building of the HTML manual with --disable-html-docs,
256 but you then may not have a local copy of the HTML manual.'''
257 raise WafError(error_msg)
261 if conf.env['PREFIX'].lower() == tempfile.gettempdir().lower():
262 # overwrite default prefix on Windows (tempfile.gettempdir() is the Waf default)
263 new_prefix = os.path.join(str(conf.root), '%s-%s' % (APPNAME, VERSION))
264 _add_to_env_and_define(conf, 'PREFIX', new_prefix, quote=True)
265 _add_to_env_and_define(conf, 'BINDIR', os.path.join(new_prefix, 'bin'), quote=True)
266 _add_to_env_and_define(conf, 'DOCDIR', os.path.join(conf.env['PREFIX'], 'doc'), quote=True)
267 _add_to_env_and_define(conf, 'LIBDIR', '%s/lib' % conf.env['PREFIX'], quote=True)
268 conf.define('LOCALEDIR', os.path.join('share' 'locale'), quote=True)
269 # overwrite LOCALEDIR to install message catalogues properly
270 conf.env['LOCALEDIR'] = os.path.join(conf.env['PREFIX'], 'share', 'locale')
271 # DATADIR is defined in objidl.h, so we remove it from config.h but keep it in env
272 conf.undefine('DATADIR')
273 conf.env['DATADIR'] = os.path.join(conf.env['PREFIX'], 'data')
274 conf.env.append_value('LINKFLAGS_cprogram', [
277 '-static-libstdc++'])
278 conf.env.append_value('LIB_WIN32', ['wsock32', 'uuid', 'ole32', 'comdlg32'])
280 conf.env['cshlib_PATTERN'] = '%s.so'
281 # DATADIR and LOCALEDIR are defined by the intltool tool
282 # but they are not added to the environment, so we need to
283 _add_define_to_env(conf, 'DATADIR')
284 _add_define_to_env(conf, 'LOCALEDIR')
285 docdir = os.path.join(conf.env['DATADIR'], 'doc', 'geany')
286 libdir = os.path.join(conf.env['PREFIX'], 'lib')
287 mandir = os.path.join(conf.env['DATADIR'], 'man')
288 _define_from_opt(conf, 'DOCDIR', conf.options.docdir, docdir)
289 _define_from_opt(conf, 'LIBDIR', conf.options.libdir, libdir)
290 _define_from_opt(conf, 'MANDIR', conf.options.mandir, mandir)
292 conf.define('ENABLE_NLS', 1)
293 conf.define('GEANY_LOCALEDIR', '' if is_win32 else conf.env['LOCALEDIR'], quote=True)
294 conf.define('GEANY_DATADIR', 'data' if is_win32 else conf.env['DATADIR'], quote=True)
295 conf.define('GEANY_DOCDIR', conf.env['DOCDIR'], quote=True)
296 conf.define('GEANY_LIBDIR', '' if is_win32 else conf.env['LIBDIR'], quote=True)
297 conf.define('GEANY_PREFIX', '' if is_win32 else conf.env['PREFIX'], quote=True)
298 conf.define('PACKAGE', APPNAME, quote=True)
299 conf.define('VERSION', VERSION, quote=True)
300 conf.define('REVISION', revision or '-1', quote=True)
302 conf.define('GETTEXT_PACKAGE', APPNAME, quote=True)
306 conf.options.no_vte = True
308 _define_from_opt(conf, 'HAVE_PLUGINS', not conf.options.no_plugins, None)
309 _define_from_opt(conf, 'HAVE_SOCKET', not conf.options.no_socket, None)
310 _define_from_opt(conf, 'HAVE_VTE', not conf.options.no_vte, None)
312 conf.write_config_header('config.h', remove=False)
314 # GEANY_EXPORT_SYMBOL and GEANY_API_SYMBOL
316 geanyexport_cflags = []
317 geanyexport_defines = ['GEANY_EXPORT_SYMBOL=__declspec(dllexport)']
318 elif visibility_hidden_supported:
319 geanyexport_cflags = ['-fvisibility=hidden']
320 geanyexport_defines = ['GEANY_EXPORT_SYMBOL=__attribute__((visibility("default")))']
321 else: # unknown, define to nothing
322 geanyexport_cflags = []
323 geanyexport_defines = ['GEANY_EXPORT_SYMBOL=']
324 geanyexport_defines.append('GEANY_API_SYMBOL=GEANY_EXPORT_SYMBOL')
325 conf.env['DEFINES_geanyexport'] = geanyexport_defines
326 conf.env['CFLAGS_geanyexport'] = geanyexport_cflags
327 conf.env['CXXFLAGS_geanyexport'] = geanyexport_cflags
329 # some more compiler flags
330 conf.env.append_value('CFLAGS', ['-DHAVE_CONFIG_H'])
331 if conf.env['CC_NAME'] == 'gcc' and '-O' not in ''.join(conf.env['CFLAGS']):
332 conf.env.append_value('CFLAGS', ['-O2'])
333 if revision is not None:
334 conf.env.append_value('CFLAGS', ['-g', '-DGEANY_DEBUG'])
336 conf.env.append_value('CFLAGS', ['-DGTK'])
337 conf.env.append_value('CXXFLAGS',
338 ['-DNDEBUG', '-DGTK', '-DSCI_LEXER', '-DG_THREADS_IMPL_NONE'])
339 if conf.env['CXX_NAME'] == 'gcc' and '-O' not in ''.join(conf.env['CXXFLAGS']):
340 conf.env.append_value('CXXFLAGS', ['-O2'])
341 if revision is not None:
342 conf.env.append_value('CXXFLAGS', ['-g'])
345 Logs.pprint('BLUE', 'Summary:')
346 conf.msg('Install Geany ' + VERSION + ' in', conf.env['PREFIX'])
347 conf.msg('Using GTK version', gtk_version)
348 conf.msg('Build with plugin support', conf.options.no_plugins and 'no' or 'yes')
349 conf.msg('Use virtual terminal support', conf.options.no_vte and 'no' or 'yes')
350 if revision is not None:
351 conf.msg('Compiling Git revision', revision)
352 # deprecation warning
353 _show_deprecation_warning(conf)
356 def _show_deprecation_warning(ctx):
359 'The Waf build system is deprecated and will be removed in the removed in Geany 1.27. '
360 'Please use the Autotools build system.')
364 # Disable MSVC detection on win32: building Geany with MSVC is currently not supported
365 # If anyone wants to add support for building with MSVC, this hack should be removed.
366 c_compiler['win32'] = ['gcc']
367 cxx_compiler['win32'] = ['g++']
369 opt.load('compiler_cc')
370 opt.load('compiler_cxx')
374 opt.add_option('--no-scm', action='store_true', default=False,
375 help='Disable SCM detection [default: No]', dest='no_scm')
377 opt.add_option('--disable-plugins', action='store_true', default=False,
378 help='compile without plugin support [default: No]', dest='no_plugins')
379 opt.add_option('--disable-socket', action='store_true', default=False,
380 help='compile without support to detect a running instance [[default: No]',
382 opt.add_option('--disable-vte', action='store_true', default=False,
383 help='compile without support for an embedded virtual terminal [[default: No]',
385 opt.add_option('--enable-gtk3', action='store_true', default=False,
386 help='compile with GTK3 support (experimental) [[default: No]',
388 opt.add_option('--enable-mac-integration', action='store_true', default=False,
389 help='use gtk-mac-integration to enable improved OS X integration [[default: No]',
390 dest='enable_mac_integration')
391 opt.add_option('--disable-html-docs', action='store_true', default=False,
392 help='do not generate HTML documentation using rst2html [[default: No]',
395 opt.add_option('--mandir', type='string', default='',
396 help='man documentation', dest='mandir')
397 opt.add_option('--docdir', type='string', default='',
398 help='documentation root', dest='docdir')
399 opt.add_option('--libdir', type='string', default='',
400 help='object code libraries', dest='libdir')
404 is_win32 = _target_is_win32(bld)
405 bld.add_post_fun(_show_deprecation_warning)
407 if bld.cmd == 'clean':
408 _remove_linguas_file()
409 if bld.cmd in ('install', 'uninstall'):
410 bld.add_post_fun(_post_install)
412 def build_plugin(plugin_name, install=True, uselib_add=[]):
414 instpath = '${LIBDIR}/geany'
419 features = ['c', 'cshlib'],
420 source = 'plugins/%s.c' % plugin_name,
421 includes = ['.', 'src/', 'scintilla/include', 'tagmanager/src'],
422 defines = 'G_LOG_DOMAIN="%s"' % plugin_name,
423 target = plugin_name,
424 uselib = ['GTK', 'GLIB', 'GMODULE', 'C99'] + uselib_add,
426 install_path = instpath)
431 source = ctags_sources,
434 includes = ['.', 'tagmanager', 'tagmanager/ctags'],
435 defines = 'G_LOG_DOMAIN="CTags"',
436 uselib = ['cshlib', 'GLIB', 'geanyexport', 'C99'])
441 source = tagmanager_sources,
443 target = 'tagmanager',
444 includes = ['.', 'tagmanager', 'tagmanager/ctags'],
445 defines = ['GEANY_PRIVATE', 'G_LOG_DOMAIN="Tagmanager"'],
446 uselib = ['cshlib', 'GTK', 'GLIB', 'geanyexport', 'C99'])
451 source = mio_sources,
454 includes = ['.', 'tagmanager/mio/'],
455 defines = 'G_LOG_DOMAIN="MIO"',
456 uselib = ['cshlib', 'GTK', 'GLIB', 'geanyexport'])
459 files = bld.srcnode.ant_glob('scintilla/**/*.cxx', src=True, dir=False)
460 scintilla_sources.update([file.path_from(bld.srcnode) for file in files])
462 features = ['c', 'cxx'],
464 target = 'scintilla',
465 source = scintilla_sources,
466 includes = ['.', 'scintilla/include', 'scintilla/src', 'scintilla/lexlib'],
467 uselib = ['cshlib', 'cxxshlib', 'GTK', 'GLIB', 'GMODULE', 'M', 'geanyexport'])
470 if bld.env['HAVE_VTE'] == 1:
471 geany_sources.add('src/vte.c')
473 geany_sources.add('src/win32.c')
474 geany_bin_sources.add('geany_private.rc')
476 def gen_signallist(task):
477 from xml.etree import ElementTree
479 def find_handlers(xml_filename):
480 tree = ElementTree.parse(xml_filename)
481 signals = tree.getroot().findall(".//signal")
482 return [sig.attrib["handler"] for sig in signals]
485 for node in task.inputs:
486 handlers += find_handlers(node.abspath())
487 handlers = sorted(set(handlers))
489 for node in task.outputs:
490 node.write("/* This file is auto-generated, do not edit. */\n" +
491 ''.join(["ITEM(%s)\n" % h for h in handlers]))
495 source = 'data/geany.glade',
496 target = bld.path.get_bld().make_node('src/signallist.i'),
497 name = 'signallist.i',
498 rule = gen_signallist)
500 base_uselibs = ['GTK', 'GLIB', 'GMODULE', 'GIO', 'GTHREAD', 'WIN32', 'MAC_INTEGRATION', 'SUNOS_SOCKET', 'M', 'C99']
504 features = ['c', 'cxx'],
507 source = geany_sources,
508 includes = ['.', 'scintilla/include', 'tagmanager/src', 'src'],
509 defines = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
510 uselib = base_uselibs + ['geanyexport'],
511 use = ['scintilla', 'ctags', 'tagmanager', 'mio'],
512 linkflags = bld.env['LINKFLAGS_cprogram'],
513 vnum = GEANY_LIB_VERSION,
514 install_path = '${PREFIX}/bin' if is_win32 else '${LIBDIR}')
518 features = ['c', 'cxx'],
521 source = geany_bin_sources,
522 includes = ['.', 'scintilla/include', 'tagmanager/src'],
523 defines = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
524 uselib = base_uselibs + ['geanyexport'],
527 # http://www.freehackers.org/~tnagy/testdoc/single.html#common_c
528 t.rpath = bld.env['LIBDIR']
531 if bld.env['HAVE_PLUGINS'] == 1:
532 build_plugin('classbuilder')
533 build_plugin('demoplugin', False)
534 build_plugin('export', uselib_add=['M'])
535 build_plugin('filebrowser')
536 build_plugin('htmlchars')
537 build_plugin('saveactions')
538 build_plugin('splitwindow')
541 if bld.env['INTLTOOL']:
543 features = ['linguas', 'intltool_po'],
545 install_path = '${LOCALEDIR}',
548 # HTML documentation (build if it is not part of the tree already, as it is required for install)
549 html_doc_filename = os.path.join(bld.out_dir, 'doc', 'geany.html')
550 if bld.env['RST2HTML']:
551 rst2html = bld.env['RST2HTML']
553 source = ['doc/geany.txt'],
554 deps = ['doc/geany.css'],
555 target = bld.path.get_bld().make_node('doc/geany.html'),
557 cwd = os.path.join(bld.path.abspath(), 'doc'),
558 rule = '%s -stg --stylesheet=geany.css geany.txt %s' % (rst2html, html_doc_filename))
562 # replace backward slashes by forward slashes as they could be interepreted as escape
564 geany_pc_prefix = bld.env['PREFIX'].replace('\\', '/')
566 geany_pc_prefix = bld.env['PREFIX']
568 source = 'geany.pc.in',
569 dct = {'VERSION': VERSION,
570 'DEPENDENCIES': '%s >= %s glib-2.0 >= %s' % \
571 (bld.env['gtk_package_name'],
572 bld.env['minimum_gtk_version'],
573 MINIMUM_GLIB_VERSION),
574 'prefix': geany_pc_prefix,
575 'exec_prefix': '${prefix}',
576 'libdir': '${exec_prefix}/lib',
577 'includedir': '${prefix}/include',
578 'datarootdir': '${prefix}/share',
579 'datadir': '${datarootdir}',
580 'localedir': '${datarootdir}/locale'})
585 source = 'geany.nsi.in',
586 target = 'geany.nsi',
587 dct = {'VERSION': VERSION,
588 'GTK_VERSION': bld.env['gtk_version']},
593 if bld.env['INTLTOOL']:
595 features = 'intltool_in',
596 source = 'geany.desktop.in',
597 flags = ['-d', '-q', '-u', '-c'],
598 install_path = '${DATADIR}/applications')
603 source = 'doc/geany.1.in',
605 dct = {'VERSION': VERSION,
606 'GEANY_DATA_DIR': bld.env['DATADIR'] + '/geany'},
607 install_path = '${MANDIR}/man1')
612 source = 'geany.spec.in',
613 target = 'geany.spec',
615 dct = {'VERSION': VERSION})
620 source = 'doc/Doxyfile.in',
621 target = 'doc/Doxyfile',
623 dct = {'VERSION': VERSION,
624 'top_builddir': bld.out_dir,
625 'top_srcdir': bld.top_dir,})
627 # disable build/install phase interleaving
634 bld.install_files('${PREFIX}/include/geany', '''
663 plugins/geanyplugin.h
664 plugins/geanyfunctions.h
666 bld.install_files('${PREFIX}/include/geany/scintilla', '''
667 scintilla/include/SciLexer.h scintilla/include/Scintilla.h
668 scintilla/include/Scintilla.iface scintilla/include/ScintillaWidget.h
669 scintilla/include/Sci_Position.h ''')
670 bld.install_files('${PREFIX}/include/geany/tagmanager', '''
671 tagmanager/src/tm_source_file.h
672 tagmanager/src/tm_tag.h
673 tagmanager/src/tm_tagmanager.h
674 tagmanager/src/tm_workspace.h
675 tagmanager/src/tm_parser.h ''')
677 base_dir = '${DOCDIR}'
678 ext = '.txt' if is_win32 else ''
679 for filename in 'AUTHORS ChangeLog COPYING README NEWS THANKS TODO'.split():
680 basename = _uc_first(filename, bld)
681 destination_filename = '%s%s' % (basename, ext)
682 destination = os.path.join(base_dir, destination_filename)
683 bld.install_as(destination, filename)
685 # install HTML documentation only if it exists, i.e. it was built before
686 # local_html_doc_filename supports installing HTML doc from in-tree geany.html if it exists
687 local_html_doc_filename = os.path.join(bld.path.abspath(), 'doc', 'geany.html')
688 if os.path.exists(html_doc_filename) or os.path.exists(local_html_doc_filename):
689 start_dir = bld.path.find_dir('doc/images')
690 bld.install_files('${DOCDIR}/html/images', start_dir.ant_glob('*.png'), cwd=start_dir)
691 bld.install_as('${DOCDIR}/html/index.html', 'doc/geany.html')
693 bld.install_as('${DOCDIR}/%s' % _uc_first('manual.txt', bld), 'doc/geany.txt')
694 bld.install_as('${DOCDIR}/ScintillaLicense.txt', 'scintilla/License.txt')
696 bld.install_as('${DOCDIR}/ReadMe.I18n.txt', 'README.I18N')
697 bld.install_as('${DOCDIR}/Hacking.txt', 'HACKING')
699 data_dir = '' if is_win32 else 'geany'
700 start_dir = bld.path.find_dir('data')
701 bld.install_as('${DATADIR}/%s/GPL-2' % data_dir, 'COPYING')
702 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('filetype*'), cwd=start_dir)
703 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('*.tags'), cwd=start_dir)
704 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.glade')
705 bld.install_files('${DATADIR}/%s' % data_dir, 'data/snippets.conf')
706 bld.install_files('${DATADIR}/%s' % data_dir, 'data/ui_toolbar.xml')
707 if bld.env['use_gtk3']:
708 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.css')
710 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.gtkrc')
712 start_dir = bld.path.find_dir('data/colorschemes')
713 template_dest = '${DATADIR}/%s/colorschemes' % data_dir
714 bld.install_files(template_dest, start_dir.ant_glob('*'), cwd=start_dir)
715 start_dir = bld.path.find_dir('data/templates')
716 template_dest = '${DATADIR}/%s/templates' % data_dir
717 bld.install_files(template_dest, start_dir.ant_glob('**/*'), cwd=start_dir, relative_trick=True)
719 for dest, srcs in geany_icons.items():
720 dest_dir = os.path.join('${PREFIX}/share/icons' if is_win32 else '${DATADIR}/icons', dest)
721 bld.install_files(dest_dir, srcs, cwd=bld.path.find_dir('icons'))
722 # install theme indexes on Windows
724 for dest, srcs in geany_icons_indexes.items():
725 bld.install_files(os.path.join('${PREFIX}/share/icons', dest), srcs, cwd=bld.path.find_dir('icons'))
729 Scripting.distclean(ctx)
730 _remove_linguas_file()
733 def _remove_linguas_file():
734 # remove LINGUAS file as well
736 os.unlink(LINGUAS_FILE)
742 @before_method('apply_intltool_po')
743 def write_linguas_file(self):
744 if os.path.exists(LINGUAS_FILE):
747 if 'LINGUAS' in self.env:
748 files = self.env['LINGUAS']
749 for po_filename in files.split(' '):
750 if os.path.exists('po/%s.po' % po_filename):
751 linguas += '%s ' % po_filename
753 files = os.listdir('%s/po' % self.path.abspath())
755 for filename in files:
756 if filename.endswith('.po'):
757 linguas += '%s ' % filename[:-3]
758 file_h = open(LINGUAS_FILE, 'w')
759 file_h.write('# This file is autogenerated. Do not edit.\n%s\n' % linguas)
763 def _post_install(ctx):
764 is_win32 = _target_is_win32(ctx)
767 for d in 'hicolor', 'Tango':
768 theme_dir = Utils.subst_vars('${DATADIR}/icons/' + d, ctx.env)
769 icon_cache_updated = False
770 if not ctx.options.destdir:
771 ctx.exec_command('gtk-update-icon-cache -q -f -t %s' % theme_dir)
772 Logs.pprint('GREEN', 'GTK icon cache updated.')
773 icon_cache_updated = True
774 if not icon_cache_updated:
775 Logs.pprint('YELLOW', 'Icon cache not updated. After install, run this:')
776 Logs.pprint('YELLOW', 'gtk-update-icon-cache -q -f -t %s' % theme_dir)
780 """update the message catalogs for internationalization"""
781 potfile = '%s.pot' % APPNAME
782 os.chdir('%s/po' % top)
785 old_size = os.stat(potfile).st_size
788 ctx.exec_command('intltool-update --pot -g %s' % APPNAME)
789 size_new = os.stat(potfile).st_size
790 if size_new != old_size:
791 Logs.pprint('CYAN', 'Updated POT file.')
792 Logs.pprint('CYAN', 'Updating translations')
793 ret = ctx.exec_command('intltool-update -r -g %s' % APPNAME)
795 Logs.pprint('RED', 'Updating translations failed')
797 Logs.pprint('CYAN', 'POT file is up to date.')
799 Logs.pprint('RED', 'Failed to generate pot file.')
803 """generate API reference documentation"""
804 ctx = BuildContext() # create our own context to have ctx.top_dir
805 basedir = ctx.top_dir
806 doxygen = _find_program(ctx, 'doxygen')
807 doxyfile = '%s/doc/Doxyfile' % ctx.out_dir
808 Logs.pprint('CYAN', 'Generating API documentation')
809 ret = ctx.exec_command('%s %s' % (doxygen, doxyfile))
811 raise WafError('Generating API documentation failed')
815 """generate HACKING documentation"""
816 ctx = BuildContext() # create our own context to have ctx.top_dir
817 Logs.pprint('CYAN', 'Generating HACKING documentation')
818 cmd = _find_rst2html(ctx)
819 hacking_file = os.path.join(ctx.top_dir, 'HACKING')
820 hacking_html_file = os.path.join(ctx.top_dir, 'doc', 'hacking.html')
821 stylesheet = os.path.join(ctx.top_dir, 'doc', 'geany.css')
822 ret = ctx.exec_command('%s -stg --stylesheet=%s %s %s' % (
823 cmd, stylesheet, hacking_file, hacking_html_file))
825 raise WafError('Generating HACKING documentation failed')
828 def _find_program(ctx, cmd, **kw):
832 if ctx is None or not isinstance(ctx, ConfigurationContext):
833 ctx = ConfigurationContext()
836 return ctx.find_program(cmd, **kw)
839 def _find_rst2html(ctx):
840 cmds = ['rst2html', 'rst2html2']
842 cmd = _find_program(ctx, command, mandatory=False, exts=',.py')
847 'rst2html.py could not be found. Please install the Python docutils package.')
851 def _add_define_to_env(conf, key):
852 value = conf.get_define(key)
854 value = value.replace('"', '')
855 conf.env[key] = value
858 def _add_to_env_and_define(conf, key, value, quote=False):
859 conf.define(key, value, quote)
860 conf.env[key] = value
863 def _define_from_opt(conf, define_name, opt_value, default_value, quote=1):
864 value = default_value
866 if isinstance(opt_value, bool):
870 if value is not None:
871 _add_to_env_and_define(conf, define_name, value, quote)
873 conf.undefine(define_name)
876 def _get_git_rev(conf):
877 if conf.options.no_scm:
880 if not os.path.isdir('.git'):
884 cmd = 'git rev-parse --short --revs-only HEAD'
885 revision = conf.cmd_and_log(cmd).strip()
892 def _load_intltool_if_available(conf):
894 conf.load('intltool')
895 if 'LINGUAS' in os.environ:
896 conf.env['LINGUAS'] = os.environ['LINGUAS']
898 # on Windows, we don't hard depend on intltool, on all other platforms raise an error
899 if not _target_is_win32(conf):
903 def _target_is_win32(ctx):
904 if 'is_win32' in ctx.env:
906 return ctx.env['is_win32']
908 if sys.platform == 'win32':
911 if ctx.env and 'CC' in ctx.env:
912 env_cc = ctx.env['CC']
913 if not isinstance(env_cc, str):
914 env_cc = ''.join(env_cc)
915 is_win32 = (env_cc.find('mingw') != -1)
918 # cache for future checks
919 ctx.env['is_win32'] = is_win32
923 def _uc_first(string, ctx):
924 if _target_is_win32(ctx):
925 return string.title()
929 # Copied from Geany-Plugins
930 def _check_c99(conf):
931 # FIXME: improve some checks?
932 # TODO: look at Autoconf's C99 checks?
934 // single-line comments
938 struct s { int a, b; };
941 static inline void fun_inline(struct s param) {}
946 // variable declaration in for body
947 for (int i = 0; i < 2; i++);
950 fun_inline((struct s) { 1, 2 });
952 // mixed declarations and code
955 // named initializers
956 struct s name_inited = {
961 return (b || mixed || ! name_inited.a);
966 # list of flags is stolen from Autoconf 2.69
967 flags = ['', '-std=gnu99', '-std=c99', '-c99', '-AC99',
968 '-D_STDC_C99=', '-qlanglvl=extc99']
971 desc = ['with flag %s' % flag, 'with no flags'][not flag]
972 conf.check_cc(fragment=fragment, uselib_store='C99', cflags=flag,
973 msg="Checking for C99 support (%s)" % desc)
976 except ConfigurationError as e: