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'
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/entry.c',
84 'tagmanager/ctags/fortran.c',
85 'tagmanager/ctags/get.c',
86 'tagmanager/ctags/go.c',
87 'tagmanager/ctags/haskell.c',
88 'tagmanager/ctags/haxe.c',
89 'tagmanager/ctags/html.c',
90 'tagmanager/ctags/js.c',
91 'tagmanager/ctags/json.c',
92 'tagmanager/ctags/keyword.c',
93 'tagmanager/ctags/latex.c',
94 'tagmanager/ctags/lregex.c',
95 'tagmanager/ctags/lua.c',
96 'tagmanager/ctags/make.c',
97 'tagmanager/ctags/markdown.c',
98 'tagmanager/ctags/matlab.c',
99 'tagmanager/ctags/nsis.c',
100 'tagmanager/ctags/nestlevel.c',
101 'tagmanager/ctags/objc.c',
102 'tagmanager/ctags/options.c',
103 'tagmanager/ctags/parse.c',
104 'tagmanager/ctags/pascal.c',
105 'tagmanager/ctags/r.c',
106 'tagmanager/ctags/perl.c',
107 'tagmanager/ctags/php.c',
108 'tagmanager/ctags/python.c',
109 'tagmanager/ctags/read.c',
110 'tagmanager/ctags/rest.c',
111 'tagmanager/ctags/ruby.c',
112 'tagmanager/ctags/rust.c',
113 'tagmanager/ctags/sh.c',
114 'tagmanager/ctags/sort.c',
115 'tagmanager/ctags/sql.c',
116 'tagmanager/ctags/strlist.c',
117 'tagmanager/ctags/txt2tags.c',
118 'tagmanager/ctags/tcl.c',
119 'tagmanager/ctags/vhdl.c',
120 'tagmanager/ctags/verilog.c',
121 'tagmanager/ctags/vstring.c'])
123 tagmanager_sources = set([
124 'tagmanager/src/tm_source_file.c',
125 'tagmanager/src/tm_tag.c',
126 'tagmanager/src/tm_workspace.c'])
128 scintilla_sources = set(['scintilla/gtk/scintilla-marshal.c'])
130 geany_sources = set([
131 'src/about.c', 'src/build.c', 'src/callbacks.c', 'src/dialogs.c', 'src/document.c',
132 'src/editor.c', 'src/encodings.c', 'src/filetypes.c', 'src/geanyentryaction.c',
133 'src/geanymenubuttonaction.c', 'src/geanyobject.c', 'src/geanywraplabel.c',
134 'src/highlighting.c', 'src/keybindings.c',
135 'src/keyfile.c', 'src/log.c', 'src/libmain.c', 'src/msgwindow.c', 'src/navqueue.c', 'src/notebook.c', 'src/osx.c',
136 'src/plugins.c', 'src/pluginutils.c', 'src/prefix.c', 'src/prefs.c', 'src/printing.c', 'src/project.c',
137 'src/sciwrappers.c', 'src/search.c', 'src/socket.c', 'src/stash.c',
139 'src/templates.c', 'src/toolbar.c', 'src/tools.c', 'src/sidebar.c',
140 'src/ui_utils.c', 'src/utils.c'])
143 'hicolor/16x16/apps': ['16x16/classviewer-class.png',
144 '16x16/classviewer-macro.png',
145 '16x16/classviewer-member.png',
146 '16x16/classviewer-method.png',
147 '16x16/classviewer-namespace.png',
148 '16x16/classviewer-other.png',
149 '16x16/classviewer-struct.png',
150 '16x16/classviewer-var.png',
152 'hicolor/16x16/actions': ['16x16/geany-build.png',
153 '16x16/geany-close-all.png',
154 '16x16/geany-save-all.png'],
155 'hicolor/24x24/actions': ['24x24/geany-build.png',
156 '24x24/geany-close-all.png',
157 '24x24/geany-save-all.png'],
158 'hicolor/32x32/actions': ['32x32/geany-build.png',
159 '32x32/geany-close-all.png',
160 '32x32/geany-save-all.png'],
161 'hicolor/48x48/actions': ['48x48/geany-build.png',
162 '48x48/geany-close-all.png',
163 '48x48/geany-save-all.png'],
164 'hicolor/48x48/apps': ['48x48/geany.png'],
165 'hicolor/scalable/apps': ['scalable/geany.svg'],
166 'hicolor/scalable/actions': ['scalable/geany-build.svg',
167 'scalable/geany-close-all.svg',
168 'scalable/geany-save-all.svg'],
169 'Tango/16x16/actions': ['tango/16x16/geany-save-all.png'],
170 'Tango/24x24/actions': ['tango/24x24/geany-save-all.png'],
171 'Tango/32x32/actions': ['tango/32x32/geany-save-all.png'],
172 'Tango/48x48/actions': ['tango/48x48/geany-save-all.png'],
173 'Tango/scalable/actions': ['tango/scalable/geany-save-all.svg']
175 geany_icons_indexes = {
176 'hicolor': ['index.theme'],
177 'Tango': ['tango/index.theme']
183 conf.check_waf_version(mini='1.6.1')
185 conf.load('compiler_c')
186 is_win32 = _target_is_win32(conf)
188 visibility_hidden_supported = conf.check_cc(cflags=['-Werror', '-fvisibility=hidden'], mandatory=False)
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', 'comdlg32'])
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)
287 # The check could be improved, -fPIC iso only really necessary on 64bit linux
288 # It is needed because waf doesn't realize the static files go into
290 conf.env.append_value('CFLAGS_cstlib', '-fPIC')
291 conf.env.append_value('CFLAGS_cxxstlib', '-fPIC')
292 conf.env.append_value('CXXFLAGS_cxxstlib', '-fPIC')
294 conf.define('ENABLE_NLS', 1)
295 conf.define('GEANY_LOCALEDIR', '' if is_win32 else conf.env['LOCALEDIR'], quote=True)
296 conf.define('GEANY_DATADIR', 'data' if is_win32 else conf.env['DATADIR'], quote=True)
297 conf.define('GEANY_DOCDIR', conf.env['DOCDIR'], quote=True)
298 conf.define('GEANY_LIBDIR', '' if is_win32 else conf.env['LIBDIR'], quote=True)
299 conf.define('GEANY_PREFIX', '' if is_win32 else conf.env['PREFIX'], quote=True)
300 conf.define('PACKAGE', APPNAME, quote=True)
301 conf.define('VERSION', VERSION, quote=True)
302 conf.define('REVISION', revision or '-1', quote=True)
304 conf.define('GETTEXT_PACKAGE', APPNAME, quote=True)
308 conf.options.no_vte = True
310 _define_from_opt(conf, 'HAVE_PLUGINS', not conf.options.no_plugins, None)
311 _define_from_opt(conf, 'HAVE_SOCKET', not conf.options.no_socket, None)
312 _define_from_opt(conf, 'HAVE_VTE', not conf.options.no_vte, None)
314 conf.write_config_header('config.h', remove=False)
316 # GEANY_EXPORT_SYMBOL and GEANY_API_SYMBOL
318 geany_symbol_flags = ['-DGEANY_EXPORT_SYMBOL=__declspec(dllexport)']
319 elif visibility_hidden_supported:
320 geany_symbol_flags = ['-fvisibility=hidden',
321 '-DGEANY_EXPORT_SYMBOL=__attribute__((visibility("default")))']
322 else: # unknown, define to nothing
323 geany_symbol_flags = ['-DGEANY_EXPORT_SYMBOL=']
324 geany_symbol_flags.append('-DGEANY_API_SYMBOL=GEANY_EXPORT_SYMBOL')
325 conf.env.append_value('CFLAGS', geany_symbol_flags)
326 conf.env.append_value('CXXFLAGS', geany_symbol_flags)
328 # some more compiler flags
329 conf.env.append_value('CFLAGS', ['-DHAVE_CONFIG_H'])
330 if conf.env['CC_NAME'] == 'gcc' and '-O' not in ''.join(conf.env['CFLAGS']):
331 conf.env.append_value('CFLAGS', ['-O2'])
332 if revision is not None:
333 conf.env.append_value('CFLAGS', ['-g', '-DGEANY_DEBUG'])
335 conf.env.append_value('CFLAGS', ['-DGTK'])
336 conf.env.append_value('CXXFLAGS',
337 ['-DNDEBUG', '-DGTK', '-DSCI_LEXER', '-DG_THREADS_IMPL_NONE'])
340 Logs.pprint('BLUE', 'Summary:')
341 conf.msg('Install Geany ' + VERSION + ' in', conf.env['PREFIX'])
342 conf.msg('Using GTK version', gtk_version)
343 conf.msg('Build with plugin support', conf.options.no_plugins and 'no' or 'yes')
344 conf.msg('Use virtual terminal support', conf.options.no_vte and 'no' or 'yes')
345 if revision is not None:
346 conf.msg('Compiling Git revision', revision)
350 # Disable MSVC detection on win32: building Geany with MSVC is currently not supported
351 # If anyone wants to add support for building with MSVC, this hack should be removed.
352 c_compiler['win32'] = ['gcc']
353 cxx_compiler['win32'] = ['g++']
355 opt.load('compiler_cc')
356 opt.load('compiler_cxx')
360 opt.add_option('--no-scm', action='store_true', default=False,
361 help='Disable SCM detection [default: No]', dest='no_scm')
363 opt.add_option('--disable-plugins', action='store_true', default=False,
364 help='compile without plugin support [default: No]', dest='no_plugins')
365 opt.add_option('--disable-socket', action='store_true', default=False,
366 help='compile without support to detect a running instance [[default: No]',
368 opt.add_option('--disable-vte', action='store_true', default=False,
369 help='compile without support for an embedded virtual terminal [[default: No]',
371 opt.add_option('--enable-gtk3', action='store_true', default=False,
372 help='compile with GTK3 support (experimental) [[default: No]',
374 opt.add_option('--enable-mac-integration', action='store_true', default=False,
375 help='use gtk-mac-integration to enable improved OS X integration [[default: No]',
376 dest='enable_mac_integration')
377 opt.add_option('--disable-html-docs', action='store_true', default=False,
378 help='do not generate HTML documentation using rst2html [[default: No]',
381 opt.add_option('--mandir', type='string', default='',
382 help='man documentation', dest='mandir')
383 opt.add_option('--docdir', type='string', default='',
384 help='documentation root', dest='docdir')
385 opt.add_option('--libdir', type='string', default='',
386 help='object code libraries', dest='libdir')
390 is_win32 = _target_is_win32(bld)
392 if bld.cmd == 'clean':
393 _remove_linguas_file()
394 if bld.cmd in ('install', 'uninstall'):
395 bld.add_post_fun(_post_install)
397 def build_plugin(plugin_name, install=True, uselib_add=[]):
399 instpath = '${PREFIX}/lib' if is_win32 else '${LIBDIR}/geany'
404 features = ['c', 'cshlib'],
405 source = 'plugins/%s.c' % plugin_name,
406 includes = ['.', 'src/', 'scintilla/include', 'tagmanager/src'],
407 defines = 'G_LOG_DOMAIN="%s"' % plugin_name,
408 target = plugin_name,
409 uselib = ['GTK', 'GLIB', 'GMODULE'] + uselib_add,
411 install_path = instpath)
415 features = ['c', 'cstlib'],
416 source = ctags_sources,
419 includes = ['.', 'tagmanager', 'tagmanager/ctags'],
420 defines = 'G_LOG_DOMAIN="CTags"',
422 install_path = None) # do not install this library
426 features = ['c', 'cstlib'],
427 source = tagmanager_sources,
429 target = 'tagmanager',
430 includes = ['.', 'tagmanager', 'tagmanager/ctags'],
431 defines = ['GEANY_PRIVATE', 'G_LOG_DOMAIN="Tagmanager"'],
432 uselib = ['GTK', 'GLIB'],
433 install_path = None) # do not install this library
437 features = ['c', 'cstlib'],
438 source = mio_sources,
441 includes = ['.', 'tagmanager/mio/'],
442 defines = 'G_LOG_DOMAIN="MIO"',
443 uselib = ['GTK', 'GLIB'],
444 install_path = None) # do not install this library
447 files = bld.srcnode.ant_glob('scintilla/**/*.cxx', src=True, dir=False)
448 scintilla_sources.update([file.path_from(bld.srcnode) for file in files])
450 features = ['c', 'cxx', 'cxxstlib'],
452 target = 'scintilla',
453 source = scintilla_sources,
454 includes = ['.', 'scintilla/include', 'scintilla/src', 'scintilla/lexlib'],
455 uselib = ['GTK', 'GLIB', 'GMODULE', 'M'],
456 install_path = None) # do not install this library
459 if bld.env['HAVE_VTE'] == 1:
460 geany_sources.add('src/vte.c')
462 geany_sources.add('src/win32.c')
463 geany_sources.add('geany_private.rc')
465 def gen_signallist(task):
466 from xml.etree import ElementTree
468 def find_handlers(xml_filename):
469 tree = ElementTree.parse(xml_filename)
470 signals = tree.getroot().findall(".//signal")
471 return [sig.attrib["handler"] for sig in signals]
474 for node in task.inputs:
475 handlers += find_handlers(node.abspath())
476 handlers = sorted(set(handlers))
478 for node in task.outputs:
479 node.write("/* This file is auto-generated, do not edit. */\n" +
480 ''.join(["ITEM(%s)\n" % h for h in handlers]))
484 source = 'data/geany.glade',
485 target = 'src/signallist.i',
486 name = 'signallist.i',
487 rule = gen_signallist)
489 base_uselibs = ['GTK', 'GLIB', 'GMODULE', 'GIO', 'GTHREAD', 'WIN32', 'MAC_INTEGRATION', 'SUNOS_SOCKET', 'M']
492 instpath = '${PREFIX}/bin' if is_win32 else '${LIBDIR}'
493 linkflags = bld.env['LINKFLAGS_cprogram']
496 features = ['c', 'cxx', 'cshlib'],
499 source = geany_sources,
500 includes = ['.', 'scintilla/include', 'tagmanager/src', 'src'],
501 defines = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
502 uselib = base_uselibs,
503 use = ['scintilla', 'ctags', 'tagmanager', 'mio'],
504 linkflags = linkflags,
505 vnum = GEANY_LIB_VERSION,
506 install_path = instpath)
510 features = ['c', 'cxx', 'cprogram'],
513 source = ['src/main.c'],
514 includes = ['.', 'scintilla/include', 'tagmanager/src'],
515 defines = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
516 uselib = base_uselibs,
520 if bld.env['HAVE_PLUGINS'] == 1:
521 build_plugin('classbuilder')
522 build_plugin('demoplugin', False)
523 build_plugin('export', uselib_add=['M'])
524 build_plugin('filebrowser')
525 build_plugin('htmlchars')
526 build_plugin('saveactions')
527 build_plugin('splitwindow')
530 if bld.env['INTLTOOL']:
532 features = ['linguas', 'intltool_po'],
534 install_path = '${LOCALEDIR}',
537 # HTML documentation (build if it is not part of the tree already, as it is required for install)
538 html_doc_filename = os.path.join(bld.out_dir, 'doc', 'geany.html')
539 if bld.env['RST2HTML']:
540 rst2html = bld.env['RST2HTML']
542 source = ['doc/geany.txt'],
543 deps = ['doc/geany.css'],
544 target = 'doc/geany.html',
546 cwd = os.path.join(bld.path.abspath(), 'doc'),
547 rule = '%s -stg --stylesheet=geany.css geany.txt %s' % (rst2html, html_doc_filename))
551 # replace backward slashes by forward slashes as they could be interepreted as escape
553 geany_pc_prefix = bld.env['PREFIX'].replace('\\', '/')
555 geany_pc_prefix = bld.env['PREFIX']
557 source = 'geany.pc.in',
558 dct = {'VERSION': VERSION,
559 'DEPENDENCIES': '%s >= %s glib-2.0 >= %s' % \
560 (bld.env['gtk_package_name'],
561 bld.env['minimum_gtk_version'],
562 MINIMUM_GLIB_VERSION),
563 'prefix': geany_pc_prefix,
564 'exec_prefix': '${prefix}',
565 'libdir': '${exec_prefix}/lib',
566 'includedir': '${prefix}/include',
567 'datarootdir': '${prefix}/share',
568 'datadir': '${datarootdir}',
569 'localedir': '${datarootdir}/locale'})
573 if bld.env['INTLTOOL']:
575 features = 'intltool_in',
576 source = 'geany.desktop.in',
577 flags = ['-d', '-q', '-u', '-c'],
578 install_path = '${DATADIR}/applications')
583 source = 'doc/geany.1.in',
585 dct = {'VERSION': VERSION,
586 'GEANY_DATA_DIR': bld.env['DATADIR'] + '/geany'},
587 install_path = '${MANDIR}/man1')
592 source = 'geany.spec.in',
593 target = 'geany.spec',
595 dct = {'VERSION': VERSION})
600 source = 'doc/Doxyfile.in',
601 target = 'doc/Doxyfile',
603 dct = {'VERSION': VERSION,
604 'top_builddir': bld.out_dir,
605 'top_srcdir': bld.top_dir,})
611 bld.install_files('${PREFIX}/include/geany', '''
639 plugins/geanyplugin.h
640 plugins/geanyfunctions.h
642 bld.install_files('${PREFIX}/include/geany/scintilla', '''
643 scintilla/include/SciLexer.h scintilla/include/Scintilla.h
644 scintilla/include/Scintilla.iface scintilla/include/ScintillaWidget.h ''')
645 bld.install_files('${PREFIX}/include/geany/tagmanager', '''
646 tagmanager/src/tm_source_file.h
647 tagmanager/src/tm_tag.h
648 tagmanager/src/tm_tagmanager.h
649 tagmanager/src/tm_workspace.h ''')
651 base_dir = '${PREFIX}' if is_win32 else '${DOCDIR}'
652 ext = '.txt' if is_win32 else ''
653 for filename in 'AUTHORS ChangeLog COPYING README NEWS THANKS TODO'.split():
654 basename = _uc_first(filename, bld)
655 destination_filename = '%s%s' % (basename, ext)
656 destination = os.path.join(base_dir, destination_filename)
657 bld.install_as(destination, filename)
659 # install HTML documentation only if it exists, i.e. it was built before
660 # local_html_doc_filename supports installing HTML doc from in-tree geany.html if it exists
661 local_html_doc_filename = os.path.join(bld.path.abspath(), 'doc', 'geany.html')
662 if os.path.exists(html_doc_filename) or os.path.exists(local_html_doc_filename):
663 html_dir = '' if is_win32 else 'html/'
664 html_name = 'Manual.html' if is_win32 else 'index.html'
665 start_dir = bld.path.find_dir('doc/images')
666 bld.install_files('${DOCDIR}/%simages' % html_dir, start_dir.ant_glob('*.png'), cwd=start_dir)
667 bld.install_as('${DOCDIR}/%s%s' % (html_dir, html_name), 'doc/geany.html')
669 bld.install_as('${DOCDIR}/%s' % _uc_first('manual.txt', bld), 'doc/geany.txt')
670 bld.install_as('${DOCDIR}/ScintillaLicense.txt', 'scintilla/License.txt')
672 bld.install_as('${DOCDIR}/ReadMe.I18n.txt', 'README.I18N')
673 bld.install_as('${DOCDIR}/Hacking.txt', 'HACKING')
675 data_dir = '' if is_win32 else 'geany'
676 start_dir = bld.path.find_dir('data')
677 bld.install_as('${DATADIR}/%s/GPL-2' % data_dir, 'COPYING')
678 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('filetype*'), cwd=start_dir)
679 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('*.tags'), cwd=start_dir)
680 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.glade')
681 bld.install_files('${DATADIR}/%s' % data_dir, 'data/snippets.conf')
682 bld.install_files('${DATADIR}/%s' % data_dir, 'data/ui_toolbar.xml')
683 if bld.env['use_gtk3']:
684 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.css')
686 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.gtkrc')
688 start_dir = bld.path.find_dir('data/colorschemes')
689 template_dest = '${DATADIR}/%s/colorschemes' % data_dir
690 bld.install_files(template_dest, start_dir.ant_glob('*'), cwd=start_dir)
691 start_dir = bld.path.find_dir('data/templates')
692 template_dest = '${DATADIR}/%s/templates' % data_dir
693 bld.install_files(template_dest, start_dir.ant_glob('**/*'), cwd=start_dir, relative_trick=True)
695 for dest, srcs in geany_icons.items():
696 dest_dir = os.path.join('${PREFIX}/share/icons' if is_win32 else '${DATADIR}/icons', dest)
697 bld.install_files(dest_dir, srcs, cwd=bld.path.find_dir('icons'))
698 # install theme indexes on Windows
700 for dest, srcs in geany_icons_indexes.items():
701 bld.install_files(os.path.join('${PREFIX}/share/icons', dest), srcs, cwd=bld.path.find_dir('icons'))
705 Scripting.distclean(ctx)
706 _remove_linguas_file()
709 def _remove_linguas_file():
710 # remove LINGUAS file as well
712 os.unlink(LINGUAS_FILE)
718 @before_method('apply_intltool_po')
719 def write_linguas_file(self):
720 if os.path.exists(LINGUAS_FILE):
723 if 'LINGUAS' in self.env:
724 files = self.env['LINGUAS']
725 for po_filename in files.split(' '):
726 if os.path.exists('po/%s.po' % po_filename):
727 linguas += '%s ' % po_filename
729 files = os.listdir('%s/po' % self.path.abspath())
731 for filename in files:
732 if filename.endswith('.po'):
733 linguas += '%s ' % filename[:-3]
734 file_h = open(LINGUAS_FILE, 'w')
735 file_h.write('# This file is autogenerated. Do not edit.\n%s\n' % linguas)
739 def _post_install(ctx):
740 is_win32 = _target_is_win32(ctx)
743 for d in 'hicolor', 'Tango':
744 theme_dir = Utils.subst_vars('${DATADIR}/icons/' + d, ctx.env)
745 icon_cache_updated = False
746 if not ctx.options.destdir:
747 ctx.exec_command('gtk-update-icon-cache -q -f -t %s' % theme_dir)
748 Logs.pprint('GREEN', 'GTK icon cache updated.')
749 icon_cache_updated = True
750 if not icon_cache_updated:
751 Logs.pprint('YELLOW', 'Icon cache not updated. After install, run this:')
752 Logs.pprint('YELLOW', 'gtk-update-icon-cache -q -f -t %s' % theme_dir)
756 """update the message catalogs for internationalization"""
757 potfile = '%s.pot' % APPNAME
758 os.chdir('%s/po' % top)
761 old_size = os.stat(potfile).st_size
764 ctx.exec_command('intltool-update --pot -g %s' % APPNAME)
765 size_new = os.stat(potfile).st_size
766 if size_new != old_size:
767 Logs.pprint('CYAN', 'Updated POT file.')
768 Logs.pprint('CYAN', 'Updating translations')
769 ret = ctx.exec_command('intltool-update -r -g %s' % APPNAME)
771 Logs.pprint('RED', 'Updating translations failed')
773 Logs.pprint('CYAN', 'POT file is up to date.')
775 Logs.pprint('RED', 'Failed to generate pot file.')
779 """generate API reference documentation"""
780 ctx = BuildContext() # create our own context to have ctx.top_dir
781 basedir = ctx.top_dir
782 doxygen = _find_program(ctx, 'doxygen')
783 doxyfile = '%s/doc/Doxyfile' % ctx.out_dir
784 Logs.pprint('CYAN', 'Generating API documentation')
785 ret = ctx.exec_command('%s %s' % (doxygen, doxyfile))
787 raise WafError('Generating API documentation failed')
791 """generate HACKING documentation"""
792 ctx = BuildContext() # create our own context to have ctx.top_dir
793 Logs.pprint('CYAN', 'Generating HACKING documentation')
794 cmd = _find_rst2html(ctx)
795 hacking_file = os.path.join(ctx.top_dir, 'HACKING')
796 hacking_html_file = os.path.join(ctx.top_dir, 'doc', 'hacking.html')
797 stylesheet = os.path.join(ctx.top_dir, 'doc', 'geany.css')
798 ret = ctx.exec_command('%s -stg --stylesheet=%s %s %s' % (
799 cmd, stylesheet, hacking_file, hacking_html_file))
801 raise WafError('Generating HACKING documentation failed')
804 def _find_program(ctx, cmd, **kw):
808 if ctx is None or not isinstance(ctx, ConfigurationContext):
809 ctx = ConfigurationContext()
812 return ctx.find_program(cmd, **kw)
815 def _find_rst2html(ctx):
816 cmds = ['rst2html', 'rst2html2']
818 cmd = _find_program(ctx, command, mandatory=False, exts=',.py')
823 'rst2html.py could not be found. Please install the Python docutils package.')
827 def _add_define_to_env(conf, key):
828 value = conf.get_define(key)
830 value = value.replace('"', '')
831 conf.env[key] = value
834 def _add_to_env_and_define(conf, key, value, quote=False):
835 conf.define(key, value, quote)
836 conf.env[key] = value
839 def _define_from_opt(conf, define_name, opt_value, default_value, quote=1):
840 value = default_value
842 if isinstance(opt_value, bool):
846 if value is not None:
847 _add_to_env_and_define(conf, define_name, value, quote)
849 conf.undefine(define_name)
852 def _get_git_rev(conf):
853 if conf.options.no_scm:
856 if not os.path.isdir('.git'):
860 cmd = 'git rev-parse --short --revs-only HEAD'
861 revision = conf.cmd_and_log(cmd).strip()
868 def _load_intltool_if_available(conf):
870 conf.load('intltool')
871 if 'LINGUAS' in os.environ:
872 conf.env['LINGUAS'] = os.environ['LINGUAS']
874 # on Windows, we don't hard depend on intltool, on all other platforms raise an error
875 if not _target_is_win32(conf):
879 def _target_is_win32(ctx):
880 if 'is_win32' in ctx.env:
882 return ctx.env['is_win32']
884 if sys.platform == 'win32':
887 if ctx.env and 'CC' in ctx.env:
888 env_cc = ctx.env['CC']
889 if not isinstance(env_cc, str):
890 env_cc = ''.join(env_cc)
891 is_win32 = (env_cc.find('mingw') != -1)
894 # cache for future checks
895 ctx.env['is_win32'] = is_win32
899 def _uc_first(string, ctx):
900 if _target_is_win32(ctx):
901 return string.title()