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 ''')
676 base_dir = '${PREFIX}' if is_win32 else '${DOCDIR}'
677 ext = '.txt' if is_win32 else ''
678 for filename in 'AUTHORS ChangeLog COPYING README NEWS THANKS TODO'.split():
679 basename = _uc_first(filename, bld)
680 destination_filename = '%s%s' % (basename, ext)
681 destination = os.path.join(base_dir, destination_filename)
682 bld.install_as(destination, filename)
684 # install HTML documentation only if it exists, i.e. it was built before
685 # local_html_doc_filename supports installing HTML doc from in-tree geany.html if it exists
686 local_html_doc_filename = os.path.join(bld.path.abspath(), 'doc', 'geany.html')
687 if os.path.exists(html_doc_filename) or os.path.exists(local_html_doc_filename):
688 html_dir = '' if is_win32 else 'html/'
689 html_name = 'Manual.html' if is_win32 else 'index.html'
690 start_dir = bld.path.find_dir('doc/images')
691 bld.install_files('${DOCDIR}/%simages' % html_dir, start_dir.ant_glob('*.png'), cwd=start_dir)
692 bld.install_as('${DOCDIR}/%s%s' % (html_dir, html_name), 'doc/geany.html')
694 bld.install_as('${DOCDIR}/%s' % _uc_first('manual.txt', bld), 'doc/geany.txt')
695 bld.install_as('${DOCDIR}/ScintillaLicense.txt', 'scintilla/License.txt')
697 bld.install_as('${DOCDIR}/ReadMe.I18n.txt', 'README.I18N')
698 bld.install_as('${DOCDIR}/Hacking.txt', 'HACKING')
700 data_dir = '' if is_win32 else 'geany'
701 start_dir = bld.path.find_dir('data')
702 bld.install_as('${DATADIR}/%s/GPL-2' % data_dir, 'COPYING')
703 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('filetype*'), cwd=start_dir)
704 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('*.tags'), cwd=start_dir)
705 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.glade')
706 bld.install_files('${DATADIR}/%s' % data_dir, 'data/snippets.conf')
707 bld.install_files('${DATADIR}/%s' % data_dir, 'data/ui_toolbar.xml')
708 if bld.env['use_gtk3']:
709 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.css')
711 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.gtkrc')
713 start_dir = bld.path.find_dir('data/colorschemes')
714 template_dest = '${DATADIR}/%s/colorschemes' % data_dir
715 bld.install_files(template_dest, start_dir.ant_glob('*'), cwd=start_dir)
716 start_dir = bld.path.find_dir('data/templates')
717 template_dest = '${DATADIR}/%s/templates' % data_dir
718 bld.install_files(template_dest, start_dir.ant_glob('**/*'), cwd=start_dir, relative_trick=True)
720 for dest, srcs in geany_icons.items():
721 dest_dir = os.path.join('${PREFIX}/share/icons' if is_win32 else '${DATADIR}/icons', dest)
722 bld.install_files(dest_dir, srcs, cwd=bld.path.find_dir('icons'))
723 # install theme indexes on Windows
725 for dest, srcs in geany_icons_indexes.items():
726 bld.install_files(os.path.join('${PREFIX}/share/icons', dest), srcs, cwd=bld.path.find_dir('icons'))
730 Scripting.distclean(ctx)
731 _remove_linguas_file()
734 def _remove_linguas_file():
735 # remove LINGUAS file as well
737 os.unlink(LINGUAS_FILE)
743 @before_method('apply_intltool_po')
744 def write_linguas_file(self):
745 if os.path.exists(LINGUAS_FILE):
748 if 'LINGUAS' in self.env:
749 files = self.env['LINGUAS']
750 for po_filename in files.split(' '):
751 if os.path.exists('po/%s.po' % po_filename):
752 linguas += '%s ' % po_filename
754 files = os.listdir('%s/po' % self.path.abspath())
756 for filename in files:
757 if filename.endswith('.po'):
758 linguas += '%s ' % filename[:-3]
759 file_h = open(LINGUAS_FILE, 'w')
760 file_h.write('# This file is autogenerated. Do not edit.\n%s\n' % linguas)
764 def _post_install(ctx):
765 is_win32 = _target_is_win32(ctx)
768 for d in 'hicolor', 'Tango':
769 theme_dir = Utils.subst_vars('${DATADIR}/icons/' + d, ctx.env)
770 icon_cache_updated = False
771 if not ctx.options.destdir:
772 ctx.exec_command('gtk-update-icon-cache -q -f -t %s' % theme_dir)
773 Logs.pprint('GREEN', 'GTK icon cache updated.')
774 icon_cache_updated = True
775 if not icon_cache_updated:
776 Logs.pprint('YELLOW', 'Icon cache not updated. After install, run this:')
777 Logs.pprint('YELLOW', 'gtk-update-icon-cache -q -f -t %s' % theme_dir)
781 """update the message catalogs for internationalization"""
782 potfile = '%s.pot' % APPNAME
783 os.chdir('%s/po' % top)
786 old_size = os.stat(potfile).st_size
789 ctx.exec_command('intltool-update --pot -g %s' % APPNAME)
790 size_new = os.stat(potfile).st_size
791 if size_new != old_size:
792 Logs.pprint('CYAN', 'Updated POT file.')
793 Logs.pprint('CYAN', 'Updating translations')
794 ret = ctx.exec_command('intltool-update -r -g %s' % APPNAME)
796 Logs.pprint('RED', 'Updating translations failed')
798 Logs.pprint('CYAN', 'POT file is up to date.')
800 Logs.pprint('RED', 'Failed to generate pot file.')
804 """generate API reference documentation"""
805 ctx = BuildContext() # create our own context to have ctx.top_dir
806 basedir = ctx.top_dir
807 doxygen = _find_program(ctx, 'doxygen')
808 doxyfile = '%s/doc/Doxyfile' % ctx.out_dir
809 Logs.pprint('CYAN', 'Generating API documentation')
810 ret = ctx.exec_command('%s %s' % (doxygen, doxyfile))
812 raise WafError('Generating API documentation failed')
816 """generate HACKING documentation"""
817 ctx = BuildContext() # create our own context to have ctx.top_dir
818 Logs.pprint('CYAN', 'Generating HACKING documentation')
819 cmd = _find_rst2html(ctx)
820 hacking_file = os.path.join(ctx.top_dir, 'HACKING')
821 hacking_html_file = os.path.join(ctx.top_dir, 'doc', 'hacking.html')
822 stylesheet = os.path.join(ctx.top_dir, 'doc', 'geany.css')
823 ret = ctx.exec_command('%s -stg --stylesheet=%s %s %s' % (
824 cmd, stylesheet, hacking_file, hacking_html_file))
826 raise WafError('Generating HACKING documentation failed')
829 def _find_program(ctx, cmd, **kw):
833 if ctx is None or not isinstance(ctx, ConfigurationContext):
834 ctx = ConfigurationContext()
837 return ctx.find_program(cmd, **kw)
840 def _find_rst2html(ctx):
841 cmds = ['rst2html', 'rst2html2']
843 cmd = _find_program(ctx, command, mandatory=False, exts=',.py')
848 'rst2html.py could not be found. Please install the Python docutils package.')
852 def _add_define_to_env(conf, key):
853 value = conf.get_define(key)
855 value = value.replace('"', '')
856 conf.env[key] = value
859 def _add_to_env_and_define(conf, key, value, quote=False):
860 conf.define(key, value, quote)
861 conf.env[key] = value
864 def _define_from_opt(conf, define_name, opt_value, default_value, quote=1):
865 value = default_value
867 if isinstance(opt_value, bool):
871 if value is not None:
872 _add_to_env_and_define(conf, define_name, value, quote)
874 conf.undefine(define_name)
877 def _get_git_rev(conf):
878 if conf.options.no_scm:
881 if not os.path.isdir('.git'):
885 cmd = 'git rev-parse --short --revs-only HEAD'
886 revision = conf.cmd_and_log(cmd).strip()
893 def _load_intltool_if_available(conf):
895 conf.load('intltool')
896 if 'LINGUAS' in os.environ:
897 conf.env['LINGUAS'] = os.environ['LINGUAS']
899 # on Windows, we don't hard depend on intltool, on all other platforms raise an error
900 if not _target_is_win32(conf):
904 def _target_is_win32(ctx):
905 if 'is_win32' in ctx.env:
907 return ctx.env['is_win32']
909 if sys.platform == 'win32':
912 if ctx.env and 'CC' in ctx.env:
913 env_cc = ctx.env['CC']
914 if not isinstance(env_cc, str):
915 env_cc = ''.join(env_cc)
916 is_win32 = (env_cc.find('mingw') != -1)
919 # cache for future checks
920 ctx.env['is_win32'] = is_win32
924 def _uc_first(string, ctx):
925 if _target_is_win32(ctx):
926 return string.title()
930 # Copied from Geany-Plugins
931 def _check_c99(conf):
932 # FIXME: improve some checks?
933 # TODO: look at Autoconf's C99 checks?
935 // single-line comments
939 struct s { int a, b; };
942 static inline void fun_inline(struct s param) {}
947 // variable declaration in for body
948 for (int i = 0; i < 2; i++);
951 fun_inline((struct s) { 1, 2 });
953 // mixed declarations and code
956 // named initializers
957 struct s name_inited = {
962 return (b || mixed || ! name_inited.a);
967 # list of flags is stolen from Autoconf 2.69
968 flags = ['', '-std=gnu99', '-std=c99', '-c99', '-AC99',
969 '-D_STDC_C99=', '-qlanglvl=extc99']
972 desc = ['with flag %s' % flag, 'with no flags'][not flag]
973 conf.check_cc(fragment=fragment, uselib_store='C99', cflags=flag,
974 msg="Checking for C99 support (%s)" % desc)
977 except ConfigurationError as e: