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'
65 mio_sources = set(['tagmanager/mio/mio.c'])
68 'tagmanager/ctags/abaqus.c',
69 'tagmanager/ctags/args.c',
70 'tagmanager/ctags/abc.c',
71 'tagmanager/ctags/actionscript.c',
72 'tagmanager/ctags/asciidoc.c',
73 'tagmanager/ctags/asm.c',
74 'tagmanager/ctags/basic.c',
75 'tagmanager/ctags/c.c',
76 'tagmanager/ctags/cobol.c',
77 'tagmanager/ctags/conf.c',
78 'tagmanager/ctags/css.c',
79 'tagmanager/ctags/ctags.c',
80 'tagmanager/ctags/diff.c',
81 'tagmanager/ctags/docbook.c',
82 'tagmanager/ctags/entry.c',
83 'tagmanager/ctags/fortran.c',
84 'tagmanager/ctags/get.c',
85 'tagmanager/ctags/haskell.c',
86 'tagmanager/ctags/haxe.c',
87 'tagmanager/ctags/html.c',
88 'tagmanager/ctags/js.c',
89 'tagmanager/ctags/keyword.c',
90 'tagmanager/ctags/latex.c',
91 'tagmanager/ctags/lregex.c',
92 'tagmanager/ctags/lua.c',
93 'tagmanager/ctags/make.c',
94 'tagmanager/ctags/markdown.c',
95 'tagmanager/ctags/matlab.c',
96 'tagmanager/ctags/nsis.c',
97 'tagmanager/ctags/nestlevel.c',
98 'tagmanager/ctags/objc.c',
99 'tagmanager/ctags/options.c',
100 'tagmanager/ctags/parse.c',
101 'tagmanager/ctags/pascal.c',
102 'tagmanager/ctags/r.c',
103 'tagmanager/ctags/perl.c',
104 'tagmanager/ctags/php.c',
105 'tagmanager/ctags/python.c',
106 'tagmanager/ctags/read.c',
107 'tagmanager/ctags/rest.c',
108 'tagmanager/ctags/ruby.c',
109 'tagmanager/ctags/rust.c',
110 'tagmanager/ctags/sh.c',
111 'tagmanager/ctags/sort.c',
112 'tagmanager/ctags/sql.c',
113 'tagmanager/ctags/strlist.c',
114 'tagmanager/ctags/txt2tags.c',
115 'tagmanager/ctags/tcl.c',
116 'tagmanager/ctags/vhdl.c',
117 'tagmanager/ctags/verilog.c',
118 'tagmanager/ctags/vstring.c'])
120 tagmanager_sources = set([
121 'tagmanager/src/tm_source_file.c',
122 'tagmanager/src/tm_tag.c',
123 'tagmanager/src/tm_workspace.c'])
125 scintilla_sources = set(['scintilla/gtk/scintilla-marshal.c'])
127 geany_sources = set([
128 'src/about.c', 'src/build.c', 'src/callbacks.c', 'src/dialogs.c', 'src/document.c',
129 'src/editor.c', 'src/encodings.c', 'src/filetypes.c', 'src/geanyentryaction.c',
130 'src/geanymenubuttonaction.c', 'src/geanyobject.c', 'src/geanywraplabel.c',
131 'src/highlighting.c', 'src/keybindings.c',
132 'src/keyfile.c', 'src/log.c', 'src/main.c', 'src/msgwindow.c', 'src/navqueue.c', 'src/notebook.c',
133 'src/plugins.c', 'src/pluginutils.c', 'src/prefix.c', 'src/prefs.c', 'src/printing.c', 'src/project.c',
134 'src/sciwrappers.c', 'src/search.c', 'src/socket.c', 'src/stash.c',
136 'src/templates.c', 'src/toolbar.c', 'src/tools.c', 'src/sidebar.c',
137 'src/ui_utils.c', 'src/utils.c'])
140 'hicolor/16x16/apps': ['16x16/classviewer-class.png',
141 '16x16/classviewer-macro.png',
142 '16x16/classviewer-member.png',
143 '16x16/classviewer-method.png',
144 '16x16/classviewer-namespace.png',
145 '16x16/classviewer-other.png',
146 '16x16/classviewer-struct.png',
147 '16x16/classviewer-var.png',
149 'hicolor/16x16/actions': ['16x16/geany-build.png',
150 '16x16/geany-close-all.png',
151 '16x16/geany-save-all.png'],
152 'hicolor/24x24/actions': ['24x24/geany-build.png',
153 '24x24/geany-close-all.png',
154 '24x24/geany-save-all.png'],
155 'hicolor/32x32/actions': ['32x32/geany-build.png',
156 '32x32/geany-close-all.png',
157 '32x32/geany-save-all.png'],
158 'hicolor/48x48/actions': ['48x48/geany-build.png',
159 '48x48/geany-close-all.png',
160 '48x48/geany-save-all.png'],
161 'hicolor/48x48/apps': ['48x48/geany.png'],
162 'hicolor/scalable/apps': ['scalable/geany.svg'],
163 'hicolor/scalable/actions': ['scalable/geany-build.svg',
164 'scalable/geany-close-all.svg',
165 'scalable/geany-save-all.svg'],
166 'Tango/16x16/actions': ['tango/16x16/geany-save-all.png'],
167 'Tango/24x24/actions': ['tango/24x24/geany-save-all.png'],
168 'Tango/32x32/actions': ['tango/32x32/geany-save-all.png'],
169 'Tango/48x48/actions': ['tango/48x48/geany-save-all.png'],
170 'Tango/scalable/actions': ['tango/scalable/geany-save-all.svg']
172 geany_icons_indexes = {
173 'hicolor': ['index.theme'],
174 'Tango': ['tango/index.theme']
180 conf.check_waf_version(mini='1.6.1')
182 conf.load('compiler_c')
183 is_win32 = _target_is_win32(conf)
185 conf.check_cc(header_name='fcntl.h', mandatory=False)
186 conf.check_cc(header_name='fnmatch.h', mandatory=False)
187 conf.check_cc(header_name='glob.h', mandatory=False)
188 conf.check_cc(header_name='sys/time.h', mandatory=False)
189 conf.check_cc(header_name='sys/types.h', mandatory=False)
190 conf.check_cc(header_name='sys/stat.h', mandatory=False)
191 conf.define('HAVE_STDLIB_H', 1) # are there systems without stdlib.h?
192 conf.define('STDC_HEADERS', 1) # an optimistic guess ;-)
193 _add_to_env_and_define(conf, 'HAVE_REGCOMP', 1) # needed for CTags
195 conf.check_cc(function_name='fgetpos', header_name='stdio.h', mandatory=False)
196 conf.check_cc(function_name='ftruncate', header_name='unistd.h', mandatory=False)
197 conf.check_cc(function_name='mkstemp', header_name='stdlib.h', mandatory=False)
198 conf.check_cc(function_name='strstr', header_name='string.h')
200 conf.check_cc(function_name='pow', header_name='math.h', lib='m', uselib_store='M')
202 # check sunOS socket support
203 if Options.platform == 'sunos':
204 conf.check_cc(function_name='socket', lib='socket',
205 header_name='sys/socket.h', uselib_store='SUNOS_SOCKET', mandatory=True)
207 # check for cxx after the header and function checks have been done to ensure they are
208 # checked with cc not cxx
209 conf.load('compiler_cxx')
212 _load_intltool_if_available(conf)
214 # GTK / GIO version check
215 gtk_package_name = 'gtk+-3.0' if conf.options.use_gtk3 else 'gtk+-2.0'
216 minimum_gtk_version = MINIMUM_GTK3_VERSION if conf.options.use_gtk3 else MINIMUM_GTK_VERSION
217 conf.check_cfg(package=gtk_package_name, atleast_version=minimum_gtk_version, uselib_store='GTK',
218 mandatory=True, args='--cflags --libs')
219 conf.check_cfg(package='glib-2.0', atleast_version=MINIMUM_GLIB_VERSION, uselib_store='GLIB',
220 mandatory=True, args='--cflags --libs')
221 conf.check_cfg(package='gmodule-2.0', uselib_store='GMODULE',
222 mandatory=True, args='--cflags --libs')
223 conf.check_cfg(package='gio-2.0', uselib_store='GIO', args='--cflags --libs', mandatory=True)
224 gtk_version = conf.check_cfg(modversion=gtk_package_name, uselib_store='GTK') or 'Unknown'
225 conf.check_cfg(package='gthread-2.0', uselib_store='GTHREAD', args='--cflags --libs')
226 # remember GTK version for the build step
227 conf.env['gtk_package_name'] = gtk_package_name
228 conf.env['minimum_gtk_version'] = minimum_gtk_version
229 conf.env['use_gtk3'] = conf.options.use_gtk3
231 revision = _get_git_rev(conf)
233 # rst2html for the HTML manual
234 if not conf.options.no_html_doc and revision is not None:
236 conf.env['RST2HTML'] = _find_rst2html(conf)
238 error_msg = '''Documentation enabled but rst2html not found.
239 You can explicitly disable building of the HTML manual with --disable-html-docs,
240 but you then may not have a local copy of the HTML manual.'''
241 raise WafError(error_msg)
245 if conf.env['PREFIX'].lower() == tempfile.gettempdir().lower():
246 # overwrite default prefix on Windows (tempfile.gettempdir() is the Waf default)
247 new_prefix = os.path.join(str(conf.root), '%s-%s' % (APPNAME, VERSION))
248 _add_to_env_and_define(conf, 'PREFIX', new_prefix, quote=True)
249 _add_to_env_and_define(conf, 'BINDIR', os.path.join(new_prefix, 'bin'), quote=True)
250 _add_to_env_and_define(conf, 'DOCDIR', os.path.join(conf.env['PREFIX'], 'doc'), quote=True)
251 _add_to_env_and_define(conf, 'LIBDIR', '%s/lib' % conf.env['PREFIX'], quote=True)
252 conf.define('LOCALEDIR', os.path.join('share' 'locale'), quote=True)
253 # overwrite LOCALEDIR to install message catalogues properly
254 conf.env['LOCALEDIR'] = os.path.join(conf.env['PREFIX'], 'share', 'locale')
255 # DATADIR is defined in objidl.h, so we remove it from config.h but keep it in env
256 conf.undefine('DATADIR')
257 conf.env['DATADIR'] = os.path.join(conf.env['PREFIX'], 'data')
258 conf.env.append_value('LINKFLAGS_cprogram', [
261 '-static-libstdc++'])
262 conf.env.append_value('LIB_WIN32', ['wsock32', 'uuid', 'ole32', 'iberty'])
263 # explicitly define Windows version for older Mingw environments
264 conf.define('WINVER', '0x0501', quote=False) # for SHGetFolderPathAndSubDirW
265 conf.define('_WIN32_IE', '0x0500', quote=False) # for SHGFP_TYPE
267 conf.env['cshlib_PATTERN'] = '%s.so'
268 # DATADIR and LOCALEDIR are defined by the intltool tool
269 # but they are not added to the environment, so we need to
270 _add_define_to_env(conf, 'DATADIR')
271 _add_define_to_env(conf, 'LOCALEDIR')
272 docdir = os.path.join(conf.env['DATADIR'], 'doc', 'geany')
273 libdir = os.path.join(conf.env['PREFIX'], 'lib')
274 mandir = os.path.join(conf.env['DATADIR'], 'man')
275 _define_from_opt(conf, 'DOCDIR', conf.options.docdir, docdir)
276 _define_from_opt(conf, 'LIBDIR', conf.options.libdir, libdir)
277 _define_from_opt(conf, 'MANDIR', conf.options.mandir, mandir)
279 conf.define('ENABLE_NLS', 1)
280 conf.define('GEANY_LOCALEDIR', '' if is_win32 else conf.env['LOCALEDIR'], quote=True)
281 conf.define('GEANY_DATADIR', 'data' if is_win32 else conf.env['DATADIR'], quote=True)
282 conf.define('GEANY_DOCDIR', conf.env['DOCDIR'], quote=True)
283 conf.define('GEANY_LIBDIR', '' if is_win32 else conf.env['LIBDIR'], quote=True)
284 conf.define('GEANY_PREFIX', '' if is_win32 else conf.env['PREFIX'], quote=True)
285 conf.define('PACKAGE', APPNAME, quote=True)
286 conf.define('VERSION', VERSION, quote=True)
287 conf.define('REVISION', revision or '-1', quote=True)
289 conf.define('GETTEXT_PACKAGE', APPNAME, quote=True)
293 conf.options.no_vte = True
295 _define_from_opt(conf, 'HAVE_PLUGINS', not conf.options.no_plugins, None)
296 _define_from_opt(conf, 'HAVE_SOCKET', not conf.options.no_socket, None)
297 _define_from_opt(conf, 'HAVE_VTE', not conf.options.no_vte, None)
299 conf.write_config_header('config.h', remove=False)
301 # some more compiler flags
302 conf.env.append_value('CFLAGS', ['-DHAVE_CONFIG_H'])
303 if revision is not None:
304 conf.env.append_value('CFLAGS', ['-g', '-DGEANY_DEBUG'])
306 conf.env.append_value('CFLAGS', ['-DGTK'])
307 conf.env.append_value('CXXFLAGS',
308 ['-DNDEBUG', '-DGTK', '-DSCI_LEXER', '-DG_THREADS_IMPL_NONE'])
311 Logs.pprint('BLUE', 'Summary:')
312 conf.msg('Install Geany ' + VERSION + ' in', conf.env['PREFIX'])
313 conf.msg('Using GTK version', gtk_version)
314 conf.msg('Build with plugin support', conf.options.no_plugins and 'no' or 'yes')
315 conf.msg('Use virtual terminal support', conf.options.no_vte and 'no' or 'yes')
316 if revision is not None:
317 conf.msg('Compiling Git revision', revision)
321 # Disable MSVC detection on win32: building Geany with MSVC is currently not supported
322 # If anyone wants to add support for building with MSVC, this hack should be removed.
323 c_compiler['win32'] = ['gcc']
324 cxx_compiler['win32'] = ['g++']
326 opt.load('compiler_cc')
327 opt.load('compiler_cxx')
331 opt.add_option('--no-scm', action='store_true', default=False,
332 help='Disable SCM detection [default: No]', dest='no_scm')
334 opt.add_option('--disable-plugins', action='store_true', default=False,
335 help='compile without plugin support [default: No]', dest='no_plugins')
336 opt.add_option('--disable-socket', action='store_true', default=False,
337 help='compile without support to detect a running instance [[default: No]',
339 opt.add_option('--disable-vte', action='store_true', default=False,
340 help='compile without support for an embedded virtual terminal [[default: No]',
342 opt.add_option('--enable-gtk3', action='store_true', default=False,
343 help='compile with GTK3 support (experimental) [[default: No]',
345 opt.add_option('--disable-html-docs', action='store_true', default=False,
346 help='do not generate HTML documentation using rst2html [[default: No]',
349 opt.add_option('--mandir', type='string', default='',
350 help='man documentation', dest='mandir')
351 opt.add_option('--docdir', type='string', default='',
352 help='documentation root', dest='docdir')
353 opt.add_option('--libdir', type='string', default='',
354 help='object code libraries', dest='libdir')
358 is_win32 = _target_is_win32(bld)
360 if bld.cmd == 'clean':
361 _remove_linguas_file()
362 if bld.cmd in ('install', 'uninstall'):
363 bld.add_post_fun(_post_install)
365 def build_plugin(plugin_name, install=True, uselib_add=[]):
367 instpath = '${PREFIX}/lib' if is_win32 else '${LIBDIR}/geany'
372 features = ['c', 'cshlib'],
373 source = 'plugins/%s.c' % plugin_name,
374 includes = ['.', 'src/', 'scintilla/include', 'tagmanager/src'],
375 defines = 'G_LOG_DOMAIN="%s"' % plugin_name,
376 target = plugin_name,
377 uselib = ['GTK', 'GLIB', 'GMODULE'] + uselib_add,
378 install_path = instpath)
382 features = ['c', 'cstlib'],
383 source = ctags_sources,
386 includes = ['.', 'tagmanager', 'tagmanager/ctags'],
387 defines = 'G_LOG_DOMAIN="CTags"',
389 install_path = None) # do not install this library
393 features = ['c', 'cstlib'],
394 source = tagmanager_sources,
396 target = 'tagmanager',
397 includes = ['.', 'tagmanager', 'tagmanager/ctags'],
398 defines = ['GEANY_PRIVATE', 'G_LOG_DOMAIN="Tagmanager"'],
399 uselib = ['GTK', 'GLIB'],
400 install_path = None) # do not install this library
404 features = ['c', 'cstlib'],
405 source = mio_sources,
408 includes = ['.', 'tagmanager/mio/'],
409 defines = 'G_LOG_DOMAIN="MIO"',
410 uselib = ['GTK', 'GLIB'],
411 install_path = None) # do not install this library
414 files = bld.srcnode.ant_glob('scintilla/**/*.cxx', src=True, dir=False)
415 scintilla_sources.update(files)
417 features = ['c', 'cxx', 'cxxstlib'],
419 target = 'scintilla',
420 source = scintilla_sources,
421 includes = ['.', 'scintilla/include', 'scintilla/src', 'scintilla/lexlib'],
422 uselib = ['GTK', 'GLIB', 'GMODULE', 'M'],
423 install_path = None) # do not install this library
426 if bld.env['HAVE_VTE'] == 1:
427 geany_sources.add('src/vte.c')
429 geany_sources.add('src/win32.c')
430 geany_sources.add('geany_private.rc')
433 features = ['c', 'cxx', 'cprogram'],
436 source = geany_sources,
437 includes = ['.', 'scintilla/include', 'tagmanager/src'],
438 defines = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
439 uselib = ['GTK', 'GLIB', 'GMODULE', 'GIO', 'GTHREAD', 'WIN32', 'SUNOS_SOCKET', 'M'],
440 use = ['scintilla', 'ctags', 'tagmanager', 'mio'])
444 source = ['plugins/genapi.py', 'src/plugins.c'],
445 name = 'geanyfunctions.h',
446 before = ['c', 'cxx'],
447 cwd = '%s/plugins' % bld.path.abspath(),
448 rule = '%s genapi.py -q' % sys.executable)
451 if bld.env['HAVE_PLUGINS'] == 1:
452 build_plugin('classbuilder')
453 build_plugin('demoplugin', False)
454 build_plugin('export', uselib_add=['M'])
455 build_plugin('filebrowser')
456 build_plugin('htmlchars')
457 build_plugin('saveactions')
458 build_plugin('splitwindow')
461 if bld.env['INTLTOOL']:
463 features = ['linguas', 'intltool_po'],
465 install_path = '${LOCALEDIR}',
468 # HTML documentation (build if it is not part of the tree already, as it is required for install)
469 html_doc_filename = os.path.join(bld.out_dir, 'doc', 'geany.html')
470 if bld.env['RST2HTML']:
471 rst2html = bld.env['RST2HTML']
473 source = ['doc/geany.txt'],
474 deps = ['doc/geany.css'],
475 target = 'doc/geany.html',
477 cwd = os.path.join(bld.path.abspath(), 'doc'),
478 rule = '%s -stg --stylesheet=geany.css geany.txt %s' % (rst2html, html_doc_filename))
482 # replace backward slashes by forward slashes as they could be interepreted as escape
484 geany_pc_prefix = bld.env['PREFIX'].replace('\\', '/')
486 geany_pc_prefix = bld.env['PREFIX']
488 source = 'geany.pc.in',
489 dct = {'VERSION': VERSION,
490 'DEPENDENCIES': '%s >= %s glib-2.0 >= %s' % \
491 (bld.env['gtk_package_name'],
492 bld.env['minimum_gtk_version'],
493 MINIMUM_GLIB_VERSION),
494 'prefix': geany_pc_prefix,
495 'exec_prefix': '${prefix}',
496 'libdir': '${exec_prefix}/lib',
497 'includedir': '${prefix}/include',
498 'datarootdir': '${prefix}/share',
499 'datadir': '${datarootdir}',
500 'localedir': '${datarootdir}/locale'})
504 if bld.env['INTLTOOL']:
506 features = 'intltool_in',
507 source = 'geany.desktop.in',
508 flags = ['-d', '-q', '-u', '-c'],
509 install_path = '${DATADIR}/applications')
514 source = 'doc/geany.1.in',
516 dct = {'VERSION': VERSION,
517 'GEANY_DATA_DIR': bld.env['DATADIR'] + '/geany'},
518 install_path = '${MANDIR}/man1')
523 source = 'geany.spec.in',
524 target = 'geany.spec',
526 dct = {'VERSION': VERSION})
531 source = 'doc/Doxyfile.in',
532 target = 'doc/Doxyfile',
534 dct = {'VERSION': VERSION,
535 'top_builddir': bld.out_dir,
536 'top_srcdir': bld.top_dir,})
542 bld.install_files('${PREFIX}/include/geany', '''
543 src/app.h src/document.h src/editor.h src/encodings.h src/filetypes.h src/geany.h
544 src/highlighting.h src/keybindings.h src/msgwindow.h src/plugindata.h
545 src/prefs.h src/project.h src/search.h src/stash.h src/support.h
546 src/templates.h src/toolbar.h src/ui_utils.h src/utils.h src/build.h src/gtkcompat.h
547 plugins/geanyplugin.h plugins/geanyfunctions.h''')
548 bld.install_files('${PREFIX}/include/geany/scintilla', '''
549 scintilla/include/SciLexer.h scintilla/include/Scintilla.h
550 scintilla/include/Scintilla.iface scintilla/include/ScintillaWidget.h ''')
551 bld.install_files('${PREFIX}/include/geany/tagmanager', '''
552 tagmanager/src/tm_source_file.h
553 tagmanager/src/tm_tag.h
554 tagmanager/src/tm_tagmanager.h
555 tagmanager/src/tm_workspace.h ''')
557 base_dir = '${PREFIX}' if is_win32 else '${DOCDIR}'
558 ext = '.txt' if is_win32 else ''
559 for filename in 'AUTHORS ChangeLog COPYING README NEWS THANKS TODO'.split():
560 basename = _uc_first(filename, bld)
561 destination_filename = '%s%s' % (basename, ext)
562 destination = os.path.join(base_dir, destination_filename)
563 bld.install_as(destination, filename)
565 # install HTML documentation only if it exists, i.e. it was built before
566 # local_html_doc_filename supports installing HTML doc from in-tree geany.html if it exists
567 local_html_doc_filename = os.path.join(bld.path.abspath(), 'doc', 'geany.html')
568 if os.path.exists(html_doc_filename) or os.path.exists(local_html_doc_filename):
569 html_dir = '' if is_win32 else 'html/'
570 html_name = 'Manual.html' if is_win32 else 'index.html'
571 start_dir = bld.path.find_dir('doc/images')
572 bld.install_files('${DOCDIR}/%simages' % html_dir, start_dir.ant_glob('*.png'), cwd=start_dir)
573 bld.install_as('${DOCDIR}/%s%s' % (html_dir, html_name), 'doc/geany.html')
575 bld.install_as('${DOCDIR}/%s' % _uc_first('manual.txt', bld), 'doc/geany.txt')
576 bld.install_as('${DOCDIR}/ScintillaLicense.txt', 'scintilla/License.txt')
578 bld.install_as('${DOCDIR}/ReadMe.I18n.txt', 'README.I18N')
579 bld.install_as('${DOCDIR}/Hacking.txt', 'HACKING')
581 data_dir = '' if is_win32 else 'geany'
582 start_dir = bld.path.find_dir('data')
583 bld.install_as('${DATADIR}/%s/GPL-2' % data_dir, 'COPYING')
584 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('filetype*'), cwd=start_dir)
585 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('*.tags'), cwd=start_dir)
586 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.glade')
587 bld.install_files('${DATADIR}/%s' % data_dir, 'data/snippets.conf')
588 bld.install_files('${DATADIR}/%s' % data_dir, 'data/ui_toolbar.xml')
589 if bld.env['use_gtk3']:
590 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.css')
592 bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.gtkrc')
594 start_dir = bld.path.find_dir('data/colorschemes')
595 template_dest = '${DATADIR}/%s/colorschemes' % data_dir
596 bld.install_files(template_dest, start_dir.ant_glob('*'), cwd=start_dir)
597 start_dir = bld.path.find_dir('data/templates')
598 template_dest = '${DATADIR}/%s/templates' % data_dir
599 bld.install_files(template_dest, start_dir.ant_glob('**/*'), cwd=start_dir, relative_trick=True)
601 for dest, srcs in geany_icons.items():
602 dest_dir = os.path.join('${PREFIX}/share/icons' if is_win32 else '${DATADIR}/icons', dest)
603 bld.install_files(dest_dir, srcs, cwd=bld.path.find_dir('icons'))
604 # install theme indexes on Windows
606 for dest, srcs in geany_icons_indexes.items():
607 bld.install_files(os.path.join('${PREFIX}/share/icons', dest), srcs, cwd=bld.path.find_dir('icons'))
611 Scripting.distclean(ctx)
612 _remove_linguas_file()
615 def _remove_linguas_file():
616 # remove LINGUAS file as well
618 os.unlink(LINGUAS_FILE)
624 @before_method('apply_intltool_po')
625 def write_linguas_file(self):
626 if os.path.exists(LINGUAS_FILE):
629 if 'LINGUAS' in self.env:
630 files = self.env['LINGUAS']
631 for po_filename in files.split(' '):
632 if os.path.exists('po/%s.po' % po_filename):
633 linguas += '%s ' % po_filename
635 files = os.listdir('%s/po' % self.path.abspath())
637 for filename in files:
638 if filename.endswith('.po'):
639 linguas += '%s ' % filename[:-3]
640 file_h = open(LINGUAS_FILE, 'w')
641 file_h.write('# This file is autogenerated. Do not edit.\n%s\n' % linguas)
645 def _post_install(ctx):
646 is_win32 = _target_is_win32(ctx)
649 for d in 'hicolor', 'Tango':
650 theme_dir = Utils.subst_vars('${DATADIR}/icons/' + d, ctx.env)
651 icon_cache_updated = False
652 if not ctx.options.destdir:
653 ctx.exec_command('gtk-update-icon-cache -q -f -t %s' % theme_dir)
654 Logs.pprint('GREEN', 'GTK icon cache updated.')
655 icon_cache_updated = True
656 if not icon_cache_updated:
657 Logs.pprint('YELLOW', 'Icon cache not updated. After install, run this:')
658 Logs.pprint('YELLOW', 'gtk-update-icon-cache -q -f -t %s' % theme_dir)
662 """update the message catalogs for internationalization"""
663 potfile = '%s.pot' % APPNAME
664 os.chdir('%s/po' % top)
667 old_size = os.stat(potfile).st_size
670 ctx.exec_command('intltool-update --pot -g %s' % APPNAME)
671 size_new = os.stat(potfile).st_size
672 if size_new != old_size:
673 Logs.pprint('CYAN', 'Updated POT file.')
674 Logs.pprint('CYAN', 'Updating translations')
675 ret = ctx.exec_command('intltool-update -r -g %s' % APPNAME)
677 Logs.pprint('RED', 'Updating translations failed')
679 Logs.pprint('CYAN', 'POT file is up to date.')
681 Logs.pprint('RED', 'Failed to generate pot file.')
685 """generate API reference documentation"""
686 ctx = BuildContext() # create our own context to have ctx.top_dir
687 basedir = ctx.top_dir
688 doxygen = _find_program(ctx, 'doxygen')
689 doxyfile = '%s/doc/Doxyfile' % ctx.out_dir
690 Logs.pprint('CYAN', 'Generating API documentation')
691 ret = ctx.exec_command('%s %s' % (doxygen, doxyfile))
693 raise WafError('Generating API documentation failed')
697 """generate HACKING documentation"""
698 ctx = BuildContext() # create our own context to have ctx.top_dir
699 Logs.pprint('CYAN', 'Generating HACKING documentation')
700 cmd = _find_rst2html(ctx)
701 hacking_file = os.path.join(ctx.top_dir, 'HACKING')
702 hacking_html_file = os.path.join(ctx.top_dir, 'doc', 'hacking.html')
703 stylesheet = os.path.join(ctx.top_dir, 'doc', 'geany.css')
704 ret = ctx.exec_command('%s -stg --stylesheet=%s %s %s' % (
705 cmd, stylesheet, hacking_file, hacking_html_file))
707 raise WafError('Generating HACKING documentation failed')
710 def _find_program(ctx, cmd, **kw):
714 if ctx is None or not isinstance(ctx, ConfigurationContext):
715 ctx = ConfigurationContext()
718 return ctx.find_program(cmd, **kw)
721 def _find_rst2html(ctx):
722 cmds = ['rst2html', 'rst2html2']
724 cmd = _find_program(ctx, command, mandatory=False, exts=',.py')
729 'rst2html.py could not be found. Please install the Python docutils package.')
733 def _add_define_to_env(conf, key):
734 value = conf.get_define(key)
736 value = value.replace('"', '')
737 conf.env[key] = value
740 def _add_to_env_and_define(conf, key, value, quote=False):
741 conf.define(key, value, quote)
742 conf.env[key] = value
745 def _define_from_opt(conf, define_name, opt_value, default_value, quote=1):
746 value = default_value
748 if isinstance(opt_value, bool):
752 if value is not None:
753 _add_to_env_and_define(conf, define_name, value, quote)
755 conf.undefine(define_name)
758 def _get_git_rev(conf):
759 if conf.options.no_scm:
762 if not os.path.isdir('.git'):
766 cmd = 'git rev-parse --short --revs-only HEAD'
767 revision = conf.cmd_and_log(cmd).strip()
774 def _load_intltool_if_available(conf):
776 conf.load('intltool')
777 if 'LINGUAS' in os.environ:
778 conf.env['LINGUAS'] = os.environ['LINGUAS']
780 # on Windows, we don't hard depend on intltool, on all other platforms raise an error
781 if not _target_is_win32(conf):
785 def _target_is_win32(ctx):
786 if 'is_win32' in ctx.env:
788 return ctx.env['is_win32']
790 if sys.platform == 'win32':
793 if ctx.env and 'CC' in ctx.env:
794 env_cc = ctx.env['CC']
795 if not isinstance(env_cc, str):
796 env_cc = ''.join(env_cc)
797 is_win32 = (env_cc.find('mingw') != -1)
800 # cache for future checks
801 ctx.env['is_win32'] = is_win32
805 def _uc_first(string, ctx):
806 if _target_is_win32(ctx):
807 return string.title()