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.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')
191 is_win32 = _target_is_win32(conf)
193 visibility_hidden_supported = conf.check_cc(cflags=['-Werror', '-fvisibility=hidden'], mandatory=False)
194 conf.check_cc(header_name='fcntl.h', mandatory=False)
195 conf.check_cc(header_name='fnmatch.h', mandatory=False)
196 conf.check_cc(header_name='glob.h', mandatory=False)
197 conf.check_cc(header_name='sys/time.h', mandatory=False)
198 conf.check_cc(header_name='sys/types.h', mandatory=False)
199 conf.check_cc(header_name='sys/stat.h', mandatory=False)
200 conf.define('HAVE_STDLIB_H', 1) # are there systems without stdlib.h?
201 conf.define('STDC_HEADERS', 1) # an optimistic guess ;-)
202 _add_to_env_and_define(conf, 'HAVE_REGCOMP', 1) # needed for CTags
204 conf.check_cc(function_name='fgetpos', header_name='stdio.h', mandatory=False)
205 conf.check_cc(function_name='fnmatch', header_name='fnmatch.h', mandatory=False)
206 conf.check_cc(function_name='ftruncate', header_name='unistd.h', mandatory=False)
207 conf.check_cc(function_name='mkstemp', header_name='stdlib.h', mandatory=False)
208 conf.check_cc(function_name='strstr', header_name='string.h')
210 conf.check_cc(function_name='pow', header_name='math.h', lib='m', uselib_store='M')
212 # check sunOS socket support
213 if Options.platform == 'sunos':
214 conf.check_cc(function_name='socket', lib='socket',
215 header_name='sys/socket.h', uselib_store='SUNOS_SOCKET', mandatory=True)
217 # check for cxx after the header and function checks have been done to ensure they are
218 # checked with cc not cxx
219 conf.load('compiler_cxx')
222 _load_intltool_if_available(conf)
224 # GTK / GIO version check
225 gtk_package_name = 'gtk+-3.0' if conf.options.use_gtk3 else 'gtk+-2.0'
226 minimum_gtk_version = MINIMUM_GTK3_VERSION if conf.options.use_gtk3 else MINIMUM_GTK_VERSION
227 conf.check_cfg(package=gtk_package_name, atleast_version=minimum_gtk_version, uselib_store='GTK',
228 mandatory=True, args='--cflags --libs')
229 conf.check_cfg(package='glib-2.0', atleast_version=MINIMUM_GLIB_VERSION, uselib_store='GLIB',
230 mandatory=True, args='--cflags --libs')
231 conf.check_cfg(package='gmodule-2.0', uselib_store='GMODULE',
232 mandatory=True, args='--cflags --libs')
233 conf.check_cfg(package='gio-2.0', uselib_store='GIO', args='--cflags --libs', mandatory=True)
234 gtk_version = conf.check_cfg(modversion=gtk_package_name, uselib_store='GTK') or 'Unknown'
235 conf.check_cfg(package='gthread-2.0', uselib_store='GTHREAD', args='--cflags --libs')
236 if conf.options.enable_mac_integration:
237 pkgname = 'gtk-mac-integration-gtk3' if conf.options.use_gtk3 else 'gtk-mac-integration-gtk2'
238 conf.check_cfg(package=pkgname, uselib_store='MAC_INTEGRATION',
239 mandatory=True, args='--cflags --libs')
240 # remember GTK version for the build step
241 conf.env['gtk_package_name'] = gtk_package_name
242 conf.env['gtk_version'] = gtk_version
243 conf.env['minimum_gtk_version'] = minimum_gtk_version
244 conf.env['use_gtk3'] = conf.options.use_gtk3
246 revision = _get_git_rev(conf)
248 # rst2html for the HTML manual
249 if not conf.options.no_html_doc and revision is not None:
251 conf.env['RST2HTML'] = _find_rst2html(conf)
253 error_msg = '''Documentation enabled but rst2html not found.
254 You can explicitly disable building of the HTML manual with --disable-html-docs,
255 but you then may not have a local copy of the HTML manual.'''
256 raise WafError(error_msg)
260 if conf.env['PREFIX'].lower() == tempfile.gettempdir().lower():
261 # overwrite default prefix on Windows (tempfile.gettempdir() is the Waf default)
262 new_prefix = os.path.join(str(conf.root), '%s-%s' % (APPNAME, VERSION))
263 _add_to_env_and_define(conf, 'PREFIX', new_prefix, quote=True)
264 _add_to_env_and_define(conf, 'BINDIR', os.path.join(new_prefix, 'bin'), quote=True)
265 _add_to_env_and_define(conf, 'DOCDIR', os.path.join(conf.env['PREFIX'], 'doc'), quote=True)
266 _add_to_env_and_define(conf, 'LIBDIR', '%s/lib' % conf.env['PREFIX'], quote=True)
267 conf.define('LOCALEDIR', os.path.join('share' 'locale'), quote=True)
268 # overwrite LOCALEDIR to install message catalogues properly
269 conf.env['LOCALEDIR'] = os.path.join(conf.env['PREFIX'], 'share', 'locale')
270 # DATADIR is defined in objidl.h, so we remove it from config.h but keep it in env
271 conf.undefine('DATADIR')
272 conf.env['DATADIR'] = os.path.join(conf.env['PREFIX'], 'data')
273 conf.env.append_value('LINKFLAGS_cprogram', [
276 '-static-libstdc++'])
277 conf.env.append_value('LIB_WIN32', ['wsock32', 'uuid', 'ole32', 'comdlg32'])
279 conf.env['cshlib_PATTERN'] = '%s.so'
280 # DATADIR and LOCALEDIR are defined by the intltool tool
281 # but they are not added to the environment, so we need to
282 _add_define_to_env(conf, 'DATADIR')
283 _add_define_to_env(conf, 'LOCALEDIR')
284 docdir = os.path.join(conf.env['DATADIR'], 'doc', 'geany')
285 libdir = os.path.join(conf.env['PREFIX'], 'lib')
286 mandir = os.path.join(conf.env['DATADIR'], 'man')
287 _define_from_opt(conf, 'DOCDIR', conf.options.docdir, docdir)
288 _define_from_opt(conf, 'LIBDIR', conf.options.libdir, libdir)
289 _define_from_opt(conf, 'MANDIR', conf.options.mandir, mandir)
291 conf.define('ENABLE_NLS', 1)
292 conf.define('GEANY_LOCALEDIR', '' if is_win32 else conf.env['LOCALEDIR'], quote=True)
293 conf.define('GEANY_DATADIR', 'data' if is_win32 else conf.env['DATADIR'], quote=True)
294 conf.define('GEANY_DOCDIR', conf.env['DOCDIR'], quote=True)
295 conf.define('GEANY_LIBDIR', '' if is_win32 else conf.env['LIBDIR'], quote=True)
296 conf.define('GEANY_PREFIX', '' if is_win32 else conf.env['PREFIX'], quote=True)
297 conf.define('PACKAGE', APPNAME, quote=True)
298 conf.define('VERSION', VERSION, quote=True)
299 conf.define('REVISION', revision or '-1', quote=True)
301 conf.define('GETTEXT_PACKAGE', APPNAME, quote=True)
305 conf.options.no_vte = True
307 _define_from_opt(conf, 'HAVE_PLUGINS', not conf.options.no_plugins, None)
308 _define_from_opt(conf, 'HAVE_SOCKET', not conf.options.no_socket, None)
309 _define_from_opt(conf, 'HAVE_VTE', not conf.options.no_vte, None)
311 conf.write_config_header('config.h', remove=False)
313 # GEANY_EXPORT_SYMBOL and GEANY_API_SYMBOL
315 geanyexport_cflags = []
316 geanyexport_defines = ['GEANY_EXPORT_SYMBOL=__declspec(dllexport)']
317 elif visibility_hidden_supported:
318 geanyexport_cflags = ['-fvisibility=hidden']
319 geanyexport_defines = ['GEANY_EXPORT_SYMBOL=__attribute__((visibility("default")))']
320 else: # unknown, define to nothing
321 geanyexport_cflags = []
322 geanyexport_defines = ['GEANY_EXPORT_SYMBOL=']
323 geanyexport_defines.append('GEANY_API_SYMBOL=GEANY_EXPORT_SYMBOL')
324 conf.env['DEFINES_geanyexport'] = geanyexport_defines
325 conf.env['CFLAGS_geanyexport'] = geanyexport_cflags
326 conf.env['CXXFLAGS_geanyexport'] = geanyexport_cflags
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'])
338 if conf.env['CXX_NAME'] == 'gcc' and '-O' not in ''.join(conf.env['CXXFLAGS']):
339 conf.env.append_value('CXXFLAGS', ['-O2'])
340 if revision is not None:
341 conf.env.append_value('CXXFLAGS', ['-g'])
344 Logs.pprint('BLUE', 'Summary:')
345 conf.msg('Install Geany ' + VERSION + ' in', conf.env['PREFIX'])
346 conf.msg('Using GTK version', gtk_version)
347 conf.msg('Build with plugin support', conf.options.no_plugins and 'no' or 'yes')
348 conf.msg('Use virtual terminal support', conf.options.no_vte and 'no' or 'yes')
349 if revision is not None:
350 conf.msg('Compiling Git revision', revision)
354 # Disable MSVC detection on win32: building Geany with MSVC is currently not supported
355 # If anyone wants to add support for building with MSVC, this hack should be removed.
356 c_compiler['win32'] = ['gcc']
357 cxx_compiler['win32'] = ['g++']
359 opt.load('compiler_cc')
360 opt.load('compiler_cxx')
364 opt.add_option('--no-scm', action='store_true', default=False,
365 help='Disable SCM detection [default: No]', dest='no_scm')
367 opt.add_option('--disable-plugins', action='store_true', default=False,
368 help='compile without plugin support [default: No]', dest='no_plugins')
369 opt.add_option('--disable-socket', action='store_true', default=False,
370 help='compile without support to detect a running instance [[default: No]',
372 opt.add_option('--disable-vte', action='store_true', default=False,
373 help='compile without support for an embedded virtual terminal [[default: No]',
375 opt.add_option('--enable-gtk3', action='store_true', default=False,
376 help='compile with GTK3 support (experimental) [[default: No]',
378 opt.add_option('--enable-mac-integration', action='store_true', default=False,
379 help='use gtk-mac-integration to enable improved OS X integration [[default: No]',
380 dest='enable_mac_integration')
381 opt.add_option('--disable-html-docs', action='store_true', default=False,
382 help='do not generate HTML documentation using rst2html [[default: No]',
385 opt.add_option('--mandir', type='string', default='',
386 help='man documentation', dest='mandir')
387 opt.add_option('--docdir', type='string', default='',
388 help='documentation root', dest='docdir')
389 opt.add_option('--libdir', type='string', default='',
390 help='object code libraries', dest='libdir')
394 is_win32 = _target_is_win32(bld)
396 if bld.cmd == 'clean':
397 _remove_linguas_file()
398 if bld.cmd in ('install', 'uninstall'):
399 bld.add_post_fun(_post_install)
401 def build_plugin(plugin_name, install=True, uselib_add=[]):
403 instpath = '${LIBDIR}/geany'
408 features = ['c', 'cshlib'],
409 source = 'plugins/%s.c' % plugin_name,
410 includes = ['.', 'src/', 'scintilla/include', 'tagmanager/src'],
411 defines = 'G_LOG_DOMAIN="%s"' % plugin_name,
412 target = plugin_name,
413 uselib = ['GTK', 'GLIB', 'GMODULE'] + uselib_add,
415 install_path = instpath)
420 source = ctags_sources,
423 includes = ['.', 'tagmanager', 'tagmanager/ctags'],
424 defines = 'G_LOG_DOMAIN="CTags"',
425 uselib = ['cshlib', 'GLIB', 'geanyexport'])
430 source = tagmanager_sources,
432 target = 'tagmanager',
433 includes = ['.', 'tagmanager', 'tagmanager/ctags'],
434 defines = ['GEANY_PRIVATE', 'G_LOG_DOMAIN="Tagmanager"'],
435 uselib = ['cshlib', 'GTK', 'GLIB', 'geanyexport'])
440 source = mio_sources,
443 includes = ['.', 'tagmanager/mio/'],
444 defines = 'G_LOG_DOMAIN="MIO"',
445 uselib = ['cshlib', 'GTK', 'GLIB', 'geanyexport'])
448 files = bld.srcnode.ant_glob('scintilla/**/*.cxx', src=True, dir=False)
449 scintilla_sources.update([file.path_from(bld.srcnode) for file in files])
451 features = ['c', 'cxx'],
453 target = 'scintilla',
454 source = scintilla_sources,
455 includes = ['.', 'scintilla/include', 'scintilla/src', 'scintilla/lexlib'],
456 uselib = ['cshlib', 'cxxshlib', 'GTK', 'GLIB', 'GMODULE', 'M', 'geanyexport'])
459 if bld.env['HAVE_VTE'] == 1:
460 geany_sources.add('src/vte.c')
462 geany_sources.add('src/win32.c')
463 geany_bin_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 = bld.path.get_bld().make_node('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']
493 features = ['c', 'cxx'],
496 source = geany_sources,
497 includes = ['.', 'scintilla/include', 'tagmanager/src', 'src'],
498 defines = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
499 uselib = base_uselibs + ['geanyexport'],
500 use = ['scintilla', 'ctags', 'tagmanager', 'mio'],
501 linkflags = bld.env['LINKFLAGS_cprogram'],
502 vnum = GEANY_LIB_VERSION,
503 install_path = '${PREFIX}/bin' if is_win32 else '${LIBDIR}')
507 features = ['c', 'cxx'],
510 source = geany_bin_sources,
511 includes = ['.', 'scintilla/include', 'tagmanager/src'],
512 defines = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
513 uselib = base_uselibs + ['geanyexport'],
516 # http://www.freehackers.org/~tnagy/testdoc/single.html#common_c
517 t.rpath = bld.env['LIBDIR']
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 = bld.path.get_bld().make_node('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'})
574 source = 'geany.nsi.in',
575 target = 'geany.nsi',
576 dct = {'VERSION': VERSION,
577 'GTK_VERSION': bld.env['gtk_version']},
582 if bld.env['INTLTOOL']:
584 features = 'intltool_in',
585 source = 'geany.desktop.in',
586 flags = ['-d', '-q', '-u', '-c'],
587 install_path = '${DATADIR}/applications')
592 source = 'doc/geany.1.in',
594 dct = {'VERSION': VERSION,
595 'GEANY_DATA_DIR': bld.env['DATADIR'] + '/geany'},
596 install_path = '${MANDIR}/man1')
601 source = 'geany.spec.in',
602 target = 'geany.spec',
604 dct = {'VERSION': VERSION})
609 source = 'doc/Doxyfile.in',
610 target = 'doc/Doxyfile',
612 dct = {'VERSION': VERSION,
613 'top_builddir': bld.out_dir,
614 'top_srcdir': bld.top_dir,})
616 # disable build/install phase interleaving
623 bld.install_files('${PREFIX}/include/geany', '''
652 plugins/geanyplugin.h
653 plugins/geanyfunctions.h
655 bld.install_files('${PREFIX}/include/geany/scintilla', '''
656 scintilla/include/SciLexer.h scintilla/include/Scintilla.h
657 scintilla/include/Scintilla.iface scintilla/include/ScintillaWidget.h ''')
658 bld.install_files('${PREFIX}/include/geany/tagmanager', '''
659 tagmanager/src/tm_source_file.h
660 tagmanager/src/tm_tag.h
661 tagmanager/src/tm_tagmanager.h
662 tagmanager/src/tm_workspace.h ''')
664 base_dir = '${PREFIX}' if is_win32 else '${DOCDIR}'
665 ext = '.txt' if is_win32 else ''
666 for filename in 'AUTHORS ChangeLog COPYING README NEWS THANKS TODO'.split():
667 basename = _uc_first(filename, bld)
668 destination_filename = '%s%s' % (basename, ext)
669 destination = os.path.join(base_dir, destination_filename)
670 bld.install_as(destination, filename)
672 # install HTML documentation only if it exists, i.e. it was built before
673 # local_html_doc_filename supports installing HTML doc from in-tree geany.html if it exists
674 local_html_doc_filename = os.path.join(bld.path.abspath(), 'doc', 'geany.html')
675 if os.path.exists(html_doc_filename) or os.path.exists(local_html_doc_filename):
676 html_dir = '' if is_win32 else 'html/'
677 html_name = 'Manual.html' if is_win32 else 'index.html'
678 start_dir = bld.path.find_dir('doc/images')
679 bld.install_files('${DOCDIR}/%simages' % html_dir, start_dir.ant_glob('*.png'), cwd=start_dir)
680 bld.install_as('${DOCDIR}/%s%s' % (html_dir, html_name), 'doc/geany.html')
682 bld.install_as('${DOCDIR}/%s' % _uc_first('manual.txt', bld), 'doc/geany.txt')
683 bld.install_as('${DOCDIR}/ScintillaLicense.txt', 'scintilla/License.txt')
685 bld.install_as('${DOCDIR}/ReadMe.I18n.txt', 'README.I18N')
686 bld.install_as('${DOCDIR}/Hacking.txt', 'HACKING')
688 data_dir = '' if is_win32 else 'geany'
689 start_dir = bld.path.find_dir('data')
690 bld.install_as('${DATADIR}/%s/GPL-2' % data_dir, 'COPYING')
691 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('filetype*'), cwd=start_dir)
692 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('*.tags'), cwd=start_dir)
693 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.glade')
694 bld.install_files('${DATADIR}/%s' % data_dir, 'data/snippets.conf')
695 bld.install_files('${DATADIR}/%s' % data_dir, 'data/ui_toolbar.xml')
696 if bld.env['use_gtk3']:
697 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.css')
699 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.gtkrc')
701 start_dir = bld.path.find_dir('data/colorschemes')
702 template_dest = '${DATADIR}/%s/colorschemes' % data_dir
703 bld.install_files(template_dest, start_dir.ant_glob('*'), cwd=start_dir)
704 start_dir = bld.path.find_dir('data/templates')
705 template_dest = '${DATADIR}/%s/templates' % data_dir
706 bld.install_files(template_dest, start_dir.ant_glob('**/*'), cwd=start_dir, relative_trick=True)
708 for dest, srcs in geany_icons.items():
709 dest_dir = os.path.join('${PREFIX}/share/icons' if is_win32 else '${DATADIR}/icons', dest)
710 bld.install_files(dest_dir, srcs, cwd=bld.path.find_dir('icons'))
711 # install theme indexes on Windows
713 for dest, srcs in geany_icons_indexes.items():
714 bld.install_files(os.path.join('${PREFIX}/share/icons', dest), srcs, cwd=bld.path.find_dir('icons'))
718 Scripting.distclean(ctx)
719 _remove_linguas_file()
722 def _remove_linguas_file():
723 # remove LINGUAS file as well
725 os.unlink(LINGUAS_FILE)
731 @before_method('apply_intltool_po')
732 def write_linguas_file(self):
733 if os.path.exists(LINGUAS_FILE):
736 if 'LINGUAS' in self.env:
737 files = self.env['LINGUAS']
738 for po_filename in files.split(' '):
739 if os.path.exists('po/%s.po' % po_filename):
740 linguas += '%s ' % po_filename
742 files = os.listdir('%s/po' % self.path.abspath())
744 for filename in files:
745 if filename.endswith('.po'):
746 linguas += '%s ' % filename[:-3]
747 file_h = open(LINGUAS_FILE, 'w')
748 file_h.write('# This file is autogenerated. Do not edit.\n%s\n' % linguas)
752 def _post_install(ctx):
753 is_win32 = _target_is_win32(ctx)
756 for d in 'hicolor', 'Tango':
757 theme_dir = Utils.subst_vars('${DATADIR}/icons/' + d, ctx.env)
758 icon_cache_updated = False
759 if not ctx.options.destdir:
760 ctx.exec_command('gtk-update-icon-cache -q -f -t %s' % theme_dir)
761 Logs.pprint('GREEN', 'GTK icon cache updated.')
762 icon_cache_updated = True
763 if not icon_cache_updated:
764 Logs.pprint('YELLOW', 'Icon cache not updated. After install, run this:')
765 Logs.pprint('YELLOW', 'gtk-update-icon-cache -q -f -t %s' % theme_dir)
769 """update the message catalogs for internationalization"""
770 potfile = '%s.pot' % APPNAME
771 os.chdir('%s/po' % top)
774 old_size = os.stat(potfile).st_size
777 ctx.exec_command('intltool-update --pot -g %s' % APPNAME)
778 size_new = os.stat(potfile).st_size
779 if size_new != old_size:
780 Logs.pprint('CYAN', 'Updated POT file.')
781 Logs.pprint('CYAN', 'Updating translations')
782 ret = ctx.exec_command('intltool-update -r -g %s' % APPNAME)
784 Logs.pprint('RED', 'Updating translations failed')
786 Logs.pprint('CYAN', 'POT file is up to date.')
788 Logs.pprint('RED', 'Failed to generate pot file.')
792 """generate API reference documentation"""
793 ctx = BuildContext() # create our own context to have ctx.top_dir
794 basedir = ctx.top_dir
795 doxygen = _find_program(ctx, 'doxygen')
796 doxyfile = '%s/doc/Doxyfile' % ctx.out_dir
797 Logs.pprint('CYAN', 'Generating API documentation')
798 ret = ctx.exec_command('%s %s' % (doxygen, doxyfile))
800 raise WafError('Generating API documentation failed')
804 """generate HACKING documentation"""
805 ctx = BuildContext() # create our own context to have ctx.top_dir
806 Logs.pprint('CYAN', 'Generating HACKING documentation')
807 cmd = _find_rst2html(ctx)
808 hacking_file = os.path.join(ctx.top_dir, 'HACKING')
809 hacking_html_file = os.path.join(ctx.top_dir, 'doc', 'hacking.html')
810 stylesheet = os.path.join(ctx.top_dir, 'doc', 'geany.css')
811 ret = ctx.exec_command('%s -stg --stylesheet=%s %s %s' % (
812 cmd, stylesheet, hacking_file, hacking_html_file))
814 raise WafError('Generating HACKING documentation failed')
817 def _find_program(ctx, cmd, **kw):
821 if ctx is None or not isinstance(ctx, ConfigurationContext):
822 ctx = ConfigurationContext()
825 return ctx.find_program(cmd, **kw)
828 def _find_rst2html(ctx):
829 cmds = ['rst2html', 'rst2html2']
831 cmd = _find_program(ctx, command, mandatory=False, exts=',.py')
836 'rst2html.py could not be found. Please install the Python docutils package.')
840 def _add_define_to_env(conf, key):
841 value = conf.get_define(key)
843 value = value.replace('"', '')
844 conf.env[key] = value
847 def _add_to_env_and_define(conf, key, value, quote=False):
848 conf.define(key, value, quote)
849 conf.env[key] = value
852 def _define_from_opt(conf, define_name, opt_value, default_value, quote=1):
853 value = default_value
855 if isinstance(opt_value, bool):
859 if value is not None:
860 _add_to_env_and_define(conf, define_name, value, quote)
862 conf.undefine(define_name)
865 def _get_git_rev(conf):
866 if conf.options.no_scm:
869 if not os.path.isdir('.git'):
873 cmd = 'git rev-parse --short --revs-only HEAD'
874 revision = conf.cmd_and_log(cmd).strip()
881 def _load_intltool_if_available(conf):
883 conf.load('intltool')
884 if 'LINGUAS' in os.environ:
885 conf.env['LINGUAS'] = os.environ['LINGUAS']
887 # on Windows, we don't hard depend on intltool, on all other platforms raise an error
888 if not _target_is_win32(conf):
892 def _target_is_win32(ctx):
893 if 'is_win32' in ctx.env:
895 return ctx.env['is_win32']
897 if sys.platform == 'win32':
900 if ctx.env and 'CC' in ctx.env:
901 env_cc = ctx.env['CC']
902 if not isinstance(env_cc, str):
903 env_cc = ''.join(env_cc)
904 is_win32 = (env_cc.find('mingw') != -1)
907 # cache for future checks
908 ctx.env['is_win32'] = is_win32
912 def _uc_first(string, ctx):
913 if _target_is_win32(ctx):
914 return string.title()