1 # -*- coding: utf-8 -*-
3 # WAF build script - this file is part of Geany, a fast and lightweight IDE
5 # Copyright 2008-2010 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
6 # Copyright 2008-2010 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.
25 This is a WAF build script (http://code.google.com/p/waf/).
26 It can be used as an alternative build system to autotools
27 for Geany. It does not (yet) cover all of the autotools tests and
28 configure options but all important things are working.
29 "make dist" should be done with autotools, most other targets and
30 functions should work better (regarding performance and flexibility)
33 Missing features: --enable-binreloc, make targets: dist, pdf (in doc/)
34 Known issues: Dependency handling is buggy, e.g. if src/document.h is
35 changed, depending source files are not rebuilt (maybe Waf bug).
37 The code of this file itself loosely follows PEP 8 with some exceptions
38 (line width 100 characters and some other minor things).
40 Requires WAF 1.6.1 and Python 2.5 (or later).
47 from distutils import version
48 from waflib import Logs, Options, Scripting, Utils
49 from waflib.Configure import ConfigurationContext
50 from waflib.Errors import ConfigurationError, WafError
51 from waflib.TaskGen import feature
56 LINGUAS_FILE = 'po/LINGUAS'
62 tagmanager_sources = set([
63 'tagmanager/args.c', 'tagmanager/abc.c', 'tagmanager/actionscript.c', 'tagmanager/asm.c',
64 'tagmanager/basic.c', 'tagmanager/c.c',
65 'tagmanager/conf.c', 'tagmanager/css.c', 'tagmanager/ctags.c', 'tagmanager/diff.c',
66 'tagmanager/docbook.c', 'tagmanager/entry.c', 'tagmanager/fortran.c', 'tagmanager/get.c',
67 'tagmanager/haskell.c', 'tagmanager/haxe.c', 'tagmanager/html.c', 'tagmanager/js.c',
68 'tagmanager/keyword.c', 'tagmanager/latex.c', 'tagmanager/lregex.c', 'tagmanager/lua.c',
69 'tagmanager/make.c', 'tagmanager/markdown.c', 'tagmanager/matlab.c', 'tagmanager/nsis.c',
70 'tagmanager/nestlevel.c', 'tagmanager/options.c',
71 'tagmanager/parse.c', 'tagmanager/pascal.c', 'tagmanager/r.c',
72 'tagmanager/perl.c', 'tagmanager/php.c', 'tagmanager/python.c', 'tagmanager/read.c',
73 'tagmanager/rest.c', 'tagmanager/ruby.c', 'tagmanager/sh.c', 'tagmanager/sort.c',
74 'tagmanager/sql.c', 'tagmanager/strlist.c', 'tagmanager/txt2tags.c', 'tagmanager/tcl.c',
75 'tagmanager/tm_file_entry.c',
76 'tagmanager/tm_project.c', 'tagmanager/tm_source_file.c', 'tagmanager/tm_symbol.c',
77 'tagmanager/tm_tag.c', 'tagmanager/tm_tagmanager.c', 'tagmanager/tm_work_object.c',
78 'tagmanager/tm_workspace.c', 'tagmanager/vhdl.c', 'tagmanager/verilog.c', 'tagmanager/vstring.c'])
80 scintilla_sources = set([
81 'scintilla/AutoComplete.cxx', 'scintilla/CallTip.cxx', 'scintilla/CellBuffer.cxx',
82 'scintilla/CharClassify.cxx', 'scintilla/ContractionState.cxx', 'scintilla/Decoration.cxx',
83 'scintilla/DocumentAccessor.cxx', 'scintilla/Document.cxx', 'scintilla/Editor.cxx',
84 'scintilla/ExternalLexer.cxx', 'scintilla/Indicator.cxx', 'scintilla/KeyMap.cxx',
85 'scintilla/KeyWords.cxx',
86 'scintilla/LexAda.cxx', 'scintilla/LexAsm.cxx', 'scintilla/LexBash.cxx',
87 'scintilla/LexBasic.cxx', 'scintilla/LexCaml.cxx', 'scintilla/LexCmake.cxx', 'scintilla/LexCPP.cxx',
88 'scintilla/LexCSS.cxx', 'scintilla/LexD.cxx', 'scintilla/LexErlang.cxx', 'scintilla/LexForth.cxx',
89 'scintilla/LexFortran.cxx', 'scintilla/LexHaskell.cxx', 'scintilla/LexHTML.cxx', 'scintilla/LexLisp.cxx',
90 'scintilla/LexLua.cxx', 'scintilla/LexMarkdown.cxx', 'scintilla/LexMatlab.cxx',
91 'scintilla/LexNsis.cxx', 'scintilla/LexOthers.cxx',
92 'scintilla/LexPascal.cxx', 'scintilla/LexPerl.cxx', 'scintilla/LexPython.cxx',
93 'scintilla/LexR.cxx', 'scintilla/LexRuby.cxx', 'scintilla/LexSQL.cxx',
94 'scintilla/LexTCL.cxx', 'scintilla/LexTxt2tags.cxx',
95 'scintilla/LexVHDL.cxx', 'scintilla/LexVerilog.cxx', 'scintilla/LexYAML.cxx',
96 'scintilla/LineMarker.cxx', 'scintilla/PerLine.cxx',
97 'scintilla/PlatGTK.cxx',
98 'scintilla/PositionCache.cxx', 'scintilla/PropSet.cxx', 'scintilla/RESearch.cxx',
99 'scintilla/RunStyles.cxx', 'scintilla/ScintillaBase.cxx', 'scintilla/ScintillaGTK.cxx',
100 'scintilla/scintilla-marshal.c', 'scintilla/Selection.cxx', 'scintilla/StyleContext.cxx', 'scintilla/Style.cxx',
101 'scintilla/UniConversion.cxx', 'scintilla/ViewStyle.cxx', 'scintilla/WindowAccessor.cxx',
102 'scintilla/XPM.cxx'])
104 geany_sources = set([
105 'src/about.c', 'src/build.c', 'src/callbacks.c', 'src/dialogs.c', 'src/document.c',
106 'src/editor.c', 'src/encodings.c', 'src/filetypes.c', 'src/geanyentryaction.c',
107 'src/geanymenubuttonaction.c', 'src/geanyobject.c', 'src/geanywraplabel.c',
108 'src/highlighting.c', 'src/interface.c', 'src/keybindings.c',
109 'src/keyfile.c', 'src/log.c', 'src/main.c', 'src/msgwindow.c', 'src/navqueue.c', 'src/notebook.c',
110 'src/plugins.c', 'src/pluginutils.c', 'src/prefix.c', 'src/prefs.c', 'src/printing.c', 'src/project.c',
111 'src/sciwrappers.c', 'src/search.c', 'src/socket.c', 'src/stash.c',
113 'src/templates.c', 'src/toolbar.c', 'src/tools.c', 'src/sidebar.c',
114 'src/ui_utils.c', 'src/utils.c'])
120 conf.check_waf_version(mini='1.6.1')
122 conf.load('compiler_c')
123 is_win32 = _target_is_win32(conf)
125 conf.check_cc(header_name='fcntl.h', mandatory=False)
126 conf.check_cc(header_name='fnmatch.h', mandatory=False)
127 conf.check_cc(header_name='glob.h', mandatory=False)
128 conf.check_cc(header_name='sys/time.h', mandatory=False)
129 conf.check_cc(header_name='sys/types.h', mandatory=False)
130 conf.check_cc(header_name='sys/stat.h', mandatory=False)
131 conf.define('HAVE_STDLIB_H', 1) # are there systems without stdlib.h?
132 conf.define('STDC_HEADERS', 1) # an optimistic guess ;-)
134 if conf.options.gnu_regex:
135 _add_to_env_and_define(conf, 'HAVE_REGCOMP', 1)
136 _add_to_env_and_define(conf, 'USE_INCLUDED_REGEX', 1)
139 conf.check_cc(header_name='regex.h')
140 conf.check_cc(function_name='regcomp', header_name='regex.h')
141 except ConfigurationError:
142 _add_to_env_and_define(conf, 'HAVE_REGCOMP', 1)
143 _add_to_env_and_define(conf, 'USE_INCLUDED_REGEX', 1)
145 conf.check_cc(function_name='fgetpos', header_name='stdio.h', mandatory=False)
146 conf.check_cc(function_name='ftruncate', header_name='unistd.h', mandatory=False)
147 conf.check_cc(function_name='gethostname', header_name='unistd.h', mandatory=False)
148 conf.check_cc(function_name='mkstemp', header_name='stdlib.h', mandatory=False)
149 conf.check_cc(function_name='strstr', header_name='string.h')
151 # check sunOS socket support
152 if Options.platform == 'sunos':
153 conf.check_cc(function_name='socket', lib='socket',
154 header_name='sys/socket.h', uselib_store='SUNOS_SOCKET', mandatory=True)
156 # check for cxx after the header and function checks have been done to ensure they are
157 # checked with cc not cxx
158 conf.load('compiler_cxx')
161 _load_intltool_if_available(conf)
163 # GTK / GIO version check
164 conf.check_cfg(package='gtk+-2.0', atleast_version='2.8.0', uselib_store='GTK',
165 mandatory=True, args='--cflags --libs')
167 gtk_version = conf.check_cfg(modversion='gtk+-2.0', uselib_store='GTK')
169 if version.LooseVersion(gtk_version) >= version.LooseVersion('2.10.0'):
172 gtk_version = 'Unknown'
173 conf.check_cfg(package='gio-2.0', uselib_store='GIO', args='--cflags --libs', mandatory=False)
177 if conf.env['PREFIX'].lower() == tempfile.gettempdir().lower():
178 # overwrite default prefix on Windows (tempfile.gettempdir() is the Waf default)
179 new_prefix = os.path.join(str(conf.root), '%s-%s' % (APPNAME, VERSION))
180 _add_to_env_and_define(conf, 'PREFIX', new_prefix, quote=True)
181 _add_to_env_and_define(conf, 'BINDIR', os.path.join(new_prefix, 'bin'), quote=True)
182 _add_to_env_and_define(conf, 'DOCDIR', os.path.join(conf.env['PREFIX'], 'doc'), quote=True)
183 _add_to_env_and_define(conf, 'LIBDIR', conf.env['PREFIX'], quote=True)
184 conf.define('LOCALEDIR', os.path.join('share' 'locale'), quote=True)
185 # overwrite LOCALEDIR to install message catalogues properly
186 conf.env['LOCALEDIR'] = os.path.join(conf.env['PREFIX'], 'share/locale')
187 # DATADIR is defined in objidl.h, so we remove it from config.h but keep it in env
188 conf.undefine('DATADIR')
189 conf.env['DATADIR'] = os.path.join(conf.env['PREFIX'], 'data')
190 conf.env.append_value('LINKFLAGS_cprogram', ['-mwindows'])
191 conf.env.append_value('LIB_WIN32', ['wsock32', 'uuid', 'ole32', 'iberty'])
193 conf.env['cshlib_PATTERN'] = '%s.so'
194 # DATADIR and LOCALEDIR are defined by the intltool tool
195 # but they are not added to the environment, so we need to
196 _add_define_to_env(conf, 'DATADIR')
197 _add_define_to_env(conf, 'LOCALEDIR')
198 docdir = os.path.join(conf.env['DATADIR'], 'doc', 'geany')
199 libdir = os.path.join(conf.env['PREFIX'], 'lib')
200 mandir = os.path.join(conf.env['DATADIR'], 'man')
201 _define_from_opt(conf, 'DOCDIR', conf.options.docdir, docdir)
202 _define_from_opt(conf, 'LIBDIR', conf.options.libdir, libdir)
203 _define_from_opt(conf, 'MANDIR', conf.options.mandir, mandir)
205 svn_rev = _get_svn_rev(conf)
207 conf.define('ENABLE_NLS', 1)
208 conf.define('GEANY_LOCALEDIR', '' if is_win32 else conf.env['LOCALEDIR'], quote=True)
209 conf.define('GEANY_DATADIR', 'data' if is_win32 else conf.env['DATADIR'], quote=True)
210 conf.define('GEANY_DOCDIR', conf.env['DOCDIR'], quote=True)
211 conf.define('GEANY_LIBDIR', '' if is_win32 else conf.env['LIBDIR'], quote=True)
212 conf.define('GEANY_PREFIX', '' if is_win32 else conf.env['PREFIX'], quote=True)
213 conf.define('PACKAGE', APPNAME, quote=True)
214 conf.define('VERSION', VERSION, quote=True)
215 conf.define('REVISION', str(svn_rev), quote=True)
217 conf.define('GETTEXT_PACKAGE', APPNAME, quote=True)
221 conf.options.no_vte = True
223 _define_from_opt(conf, 'HAVE_PLUGINS', not conf.options.no_plugins, None)
224 _define_from_opt(conf, 'HAVE_SOCKET', not conf.options.no_socket, None)
225 _define_from_opt(conf, 'HAVE_VTE', not conf.options.no_vte, None)
227 conf.write_config_header('config.h', remove=False)
229 # some more compiler flags
230 conf.env.append_value('CFLAGS', ['-DHAVE_CONFIG_H'])
232 conf.env.append_value('CFLAGS', ['-g', '-DGEANY_DEBUG'])
234 conf.env.append_value('CFLAGS', ['-DGTK'])
235 conf.env.append_value('CXXFLAGS',
236 ['-DNDEBUG', '-DGTK', '-DGTK2', '-DSCI_LEXER', '-DG_THREADS_IMPL_NONE'])
239 Logs.pprint('BLUE', 'Summary:')
240 conf.msg('Install Geany ' + VERSION + ' in', conf.env['PREFIX'])
241 conf.msg('Using GTK version', gtk_version)
242 conf.msg('Build with GTK printing support', have_gtk_210 and 'yes' or 'no')
243 conf.msg('Build with plugin support', conf.options.no_plugins and 'no' or 'yes')
244 conf.msg('Use virtual terminal support', conf.options.no_vte and 'no' or 'yes')
245 conf.msg('GNU regex library', conf.env['USE_INCLUDED_REGEX'] and 'built-in' or 'system')
247 conf.msg('Compiling Subversion revision', svn_rev)
251 opt.tool_options('compiler_cc')
252 opt.tool_options('compiler_cxx')
253 opt.tool_options('intltool')
256 opt.add_option('--disable-plugins', action='store_true', default=False,
257 help='compile without plugin support [default: No]', dest='no_plugins')
258 opt.add_option('--disable-socket', action='store_true', default=False,
259 help='compile without support to detect a running instance [[default: No]',
261 opt.add_option('--disable-vte', action='store_true', default=False,
262 help='compile without support for an embedded virtual terminal [[default: No]',
264 opt.add_option('--enable-gnu-regex', action='store_true', default=False,
265 help='compile with included GNU regex library [default: No]', dest='gnu_regex')
267 opt.add_option('--mandir', type='string', default='',
268 help='man documentation', dest='mandir')
269 opt.add_option('--docdir', type='string', default='',
270 help='documentation root', dest='docdir')
271 opt.add_option('--libdir', type='string', default='',
272 help='object code libraries', dest='libdir')
274 opt.add_option('--hackingdoc', action='store_true', default=False,
275 help='generate HTML documentation from HACKING file', dest='hackingdoc')
279 is_win32 = _target_is_win32(bld)
281 if bld.cmd == 'clean':
282 _remove_linguas_file()
283 if bld.cmd in ('install', 'uninstall'):
284 bld.add_post_fun(_post_install)
286 def build_plugin(plugin_name, install=True):
288 instpath = '${PREFIX}/lib' if is_win32 else '${LIBDIR}/geany'
293 features = ['c', 'cshlib'],
294 source = 'plugins/%s.c' % plugin_name,
295 includes = ['.', 'src/', 'scintilla/include', 'tagmanager/include'],
296 defines = 'G_LOG_DOMAIN="%s"' % plugin_name,
297 target = plugin_name,
299 install_path = instpath)
303 if bld.env['USE_INCLUDED_REGEX'] == 1:
304 tagmanager_sources.add('tagmanager/regex.c')
306 features = ['c', 'cstlib'],
307 source = tagmanager_sources,
309 target = 'tagmanager',
310 includes = ['.', 'tagmanager/include/'],
311 defines = 'G_LOG_DOMAIN="Tagmanager"',
313 install_path = None) # do not install this library
318 features = ['c', 'cxx', 'cxxstlib'],
320 target = 'scintilla',
321 source = scintilla_sources,
322 includes = ['.', 'scintilla/include/'],
324 install_path = None) # do not install this library
328 if bld.env['HAVE_VTE'] == 1:
329 geany_sources.add('src/vte.c')
331 geany_sources.add('src/win32.c')
332 geany_sources.add('geany_private.rc')
335 features = ['c', 'cxx', 'cprogram'],
338 source = geany_sources,
339 includes = ['.', 'scintilla/include/', 'tagmanager/include/'],
340 defines = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
341 uselib = ['GTK', 'GIO', 'WIN32', 'SUNOS_SOCKET'],
342 use = ['scintilla', 'tagmanager'])
346 source = ['plugins/genapi.py', 'src/plugins.c'],
347 name = 'geanyfunctions.h',
348 before = ['c', 'cxx'],
349 cwd = '%s/plugins' % bld.path.abspath(),
350 rule = 'python genapi.py -q')
353 if bld.env['HAVE_PLUGINS'] == 1:
354 build_plugin('classbuilder')
355 build_plugin('demoplugin', False)
356 build_plugin('export')
357 build_plugin('filebrowser')
358 build_plugin('htmlchars')
359 build_plugin('saveactions')
360 build_plugin('splitwindow', not is_win32)
363 if bld.env['INTLTOOL']:
365 features = ['linguas', 'intltool_po'],
367 install_path = '${LOCALEDIR}',
371 task = bld.new_task_gen(
372 source = 'geany.pc.in',
373 dct = {'VERSION' : VERSION,
374 'prefix': bld.env['PREFIX'],
375 'exec_prefix': '${prefix}',
376 'libdir': '${exec_prefix}/lib',
377 'includedir': '${prefix}/include',
378 'datarootdir': '${prefix}/share',
379 'datadir': '${datarootdir}',
380 'localedir': '${datarootdir}/locale'})
384 if bld.env['INTLTOOL']:
386 features = 'intltool_in',
387 source = 'geany.desktop.in',
388 flags = [ '-d', '-q', '-u', '-c' ],
389 install_path = '${DATADIR}/applications')
394 source = 'doc/geany.1.in',
396 dct = {'VERSION' : VERSION,
397 'GEANY_DATA_DIR': bld.env['DATADIR'] + '/geany'},
398 install_path = '${MANDIR}/man1')
403 source = 'geany.spec.in',
404 target = 'geany.spec',
406 dct = {'VERSION' : VERSION})
411 source = 'doc/Doxyfile.in',
412 target = 'doc/Doxyfile',
414 dct = {'VERSION' : VERSION})
421 bld.install_files('${PREFIX}/include/geany', '''
422 src/document.h src/editor.h src/encodings.h src/filetypes.h src/geany.h
423 src/highlighting.h src/keybindings.h src/msgwindow.h src/plugindata.h
424 src/prefs.h src/project.h src/search.h src/stash.h src/support.h
425 src/templates.h src/toolbar.h src/ui_utils.h src/utils.h
426 plugins/geanyplugin.h plugins/geanyfunctions.h''')
427 bld.install_files('${PREFIX}/include/geany/scintilla', '''
428 scintilla/include/SciLexer.h scintilla/include/Scintilla.h
429 scintilla/include/Scintilla.iface scintilla/include/ScintillaWidget.h ''')
430 bld.install_files('${PREFIX}/include/geany/tagmanager', '''
431 tagmanager/include/tm_file_entry.h tagmanager/include/tm_project.h
432 tagmanager/include/tm_source_file.h
433 tagmanager/include/tm_symbol.h tagmanager/include/tm_tag.h
434 tagmanager/include/tm_tagmanager.h tagmanager/include/tm_work_object.h
435 tagmanager/include/tm_workspace.h ''')
437 base_dir = '${PREFIX}' if is_win32 else '${DOCDIR}'
438 ext = '.txt' if is_win32 else ''
439 html_dir = '' if is_win32 else 'html/'
440 html_name = 'Manual.html' if is_win32 else 'index.html'
441 for filename in 'AUTHORS ChangeLog COPYING README NEWS THANKS TODO'.split():
442 basename = _uc_first(filename, bld)
443 destination_filename = '%s%s' % (basename, ext)
444 destination = os.path.join(base_dir, destination_filename)
445 bld.install_as(destination, filename)
447 start_dir = bld.path.find_dir('doc/images')
448 bld.install_files('${DOCDIR}/%simages' % html_dir, start_dir.ant_glob('*.png'), cwd=start_dir)
449 bld.install_as('${DOCDIR}/%s' % _uc_first('manual.txt', bld), 'doc/geany.txt')
450 bld.install_as('${DOCDIR}/%s%s' % (html_dir, html_name), 'doc/geany.html')
451 bld.install_as('${DOCDIR}/ScintillaLicense.txt', 'scintilla/License.txt')
453 bld.install_as('${DOCDIR}/ReadMe.I18n.txt', 'README.I18N')
454 bld.install_as('${DOCDIR}/Hacking.txt', 'HACKING')
456 data_dir = '' if is_win32 else 'geany'
457 start_dir = bld.path.find_dir('data')
458 bld.install_as('${DATADIR}/%s/GPL-2' % data_dir, 'COPYING')
459 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('filetype*'), cwd=start_dir)
460 bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('*.tags'), cwd=start_dir)
461 bld.install_files('${DATADIR}/%s' % data_dir, 'data/snippets.conf')
462 bld.install_files('${DATADIR}/%s' % data_dir, 'data/ui_toolbar.xml')
463 start_dir = bld.path.find_dir('data/colorschemes')
464 template_dest = '${DATADIR}/%s/colorschemes' % data_dir
465 bld.install_files(template_dest, start_dir.ant_glob('*'), cwd=start_dir)
466 start_dir = bld.path.find_dir('data/templates')
467 template_dest = '${DATADIR}/%s/templates' % data_dir
468 bld.install_files(template_dest, start_dir.ant_glob('**/*'), cwd=start_dir, relative_trick=True)
470 icon_dest = '${PREFIX}/share/icons' if is_win32 else '${DATADIR}/icons/hicolor/16x16/apps'
471 start_dir = bld.path.find_dir('icons/16x16')
472 bld.install_files(icon_dest, start_dir.ant_glob('*.png'), cwd=start_dir)
474 start_dir = bld.path.find_dir('icons/48x48')
475 icon_dest = '${DATADIR}/icons/hicolor/48x48/apps'
476 bld.install_files(icon_dest, start_dir.ant_glob('*.png'), cwd=start_dir)
477 start_dir = bld.path.find_dir('icons/scalable')
478 scalable_dest = '${DATADIR}/icons/hicolor/scalable/apps'
479 bld.install_files(scalable_dest, start_dir.ant_glob('*.svg'), cwd=start_dir)
483 Scripting.distclean(ctx)
484 _remove_linguas_file()
487 def _remove_linguas_file():
488 # remove LINGUAS file as well
490 os.unlink(LINGUAS_FILE)
496 def write_linguas_file(self):
497 if os.path.exists(LINGUAS_FILE):
500 if 'LINGUAS' in self.env:
501 files = self.env['LINGUAS']
502 for po_filename in files.split(' '):
503 if os.path.exists ('po/%s.po' % po_filename):
504 linguas += '%s ' % po_filename
506 files = os.listdir('%s/po' % self.path.abspath())
508 for filename in files:
509 if filename.endswith('.po'):
510 linguas += '%s ' % filename[:-3]
511 file_h = open(LINGUAS_FILE, 'w')
512 file_h.write('# This file is autogenerated. Do not edit.\n%s\n' % linguas)
516 def _post_install(ctx):
517 is_win32 = _target_is_win32(ctx)
520 theme_dir = Utils.subst_vars('${DATADIR}/icons/hicolor', ctx.env)
521 icon_cache_updated = False
522 if not ctx.options.destdir:
523 ctx.exec_command('gtk-update-icon-cache -q -f -t %s' % theme_dir)
524 Logs.pprint('GREEN', 'GTK icon cache updated.')
525 icon_cache_updated = True
526 if not icon_cache_updated:
527 Logs.pprint('YELLOW', 'Icon cache not updated. After install, run this:')
528 Logs.pprint('YELLOW', 'gtk-update-icon-cache -q -f -t %s' % theme_dir)
532 """update the message catalogs for internationalization"""
533 potfile = '%s.pot' % APPNAME
534 os.chdir('%s/po' % top)
537 old_size = os.stat(potfile).st_size
540 ctx.exec_command('intltool-update --pot -g %s' % APPNAME)
541 size_new = os.stat(potfile).st_size
542 if size_new != old_size:
543 Logs.pprint('CYAN', 'Updated POT file.')
544 Logs.pprint('CYAN', 'Updating translations')
545 ret = ctx.exec_command('intltool-update -r -g %s' % APPNAME)
547 Logs.pprint('RED', 'Updating translations failed')
549 Logs.pprint('CYAN', 'POT file is up to date.')
551 Logs.pprint('RED', 'Failed to generate pot file.')
555 """generate API reference documentation"""
556 basedir = ctx.path.abspath()
557 doxygen = _find_program(ctx, 'doxygen')
558 doxyfile = '%s/%s/doc/Doxyfile' % (basedir, out)
560 Logs.pprint('CYAN', 'Generating API documentation')
561 ret = ctx.exec_command('%s %s' % (doxygen, doxyfile))
563 raise WafError('Generating API documentation failed')
564 # update hacking.html
565 cmd = _find_rst2html(ctx)
566 ctx.exec_command('%s -stg --stylesheet=geany.css %s %s' % (cmd, '../HACKING', 'hacking.html'))
571 """generate HTML documentation"""
572 # first try rst2html.py as it is the upstream default, fall back to rst2html
573 cmd = _find_rst2html(ctx)
575 Logs.pprint('CYAN', 'Generating HTML documentation')
576 ctx.exec_command('%s -stg --stylesheet=geany.css %s %s' % (cmd, 'geany.txt', 'geany.html'))
580 def _find_program(ctx, cmd, **kw):
584 ctx = ConfigurationContext()
587 return ctx.find_program(cmd, **kw)
590 def _find_rst2html(ctx):
591 cmds = ['rst2html.py', 'rst2html']
593 cmd = _find_program(ctx, command, mandatory=False)
598 'rst2html.py could not be found. Please install the Python docutils package.')
602 def _add_define_to_env(conf, key):
603 value = conf.get_define(key)
605 value = value.replace('"', '')
606 conf.env[key] = value
609 def _add_to_env_and_define(conf, key, value, quote=False):
610 conf.define(key, value, quote)
611 conf.env[key] = value
614 def _define_from_opt(conf, define_name, opt_value, default_value, quote=1):
615 value = default_value
617 if isinstance(opt_value, bool):
621 if value is not None:
622 _add_to_env_and_define(conf, define_name, value, quote)
624 conf.undefine(define_name)
627 def _get_svn_rev(conf):
629 cmd = 'git ls-files >/dev/null 2>&1'
630 return (conf.exec_command(cmd) == 0)
633 return os.path.exists('.svn')
637 cmds = [ 'git svn find-rev HEAD 2>/dev/null',
638 'git svn find-rev origin/trunk 2>/dev/null',
639 'git svn find-rev trunk 2>/dev/null',
640 'git svn find-rev master 2>/dev/null'
644 stdout = conf.cmd_and_log(cmd)
646 return int(stdout.strip())
650 Logs.pprint('RED', 'Unparseable revision number')
654 _env = None if _target_is_win32(conf) else dict(LANG='C')
655 stdout = conf.cmd_and_log(cmd='svn info --non-interactive', env=_env)
656 lines = stdout.splitlines(True)
658 if line.startswith('Last Changed Rev'):
659 value = line.split(': ', 1)[1]
660 return int(value.strip())
663 except (IndexError, ValueError):
664 Logs.pprint('RED', 'Unparseable revision number')
668 def _load_intltool_if_available(conf):
670 conf.check_tool('intltool')
671 if 'LINGUAS' in os.environ:
672 conf.env['LINGUAS'] = os.environ['LINGUAS']
674 # on Windows, we don't hard depend on intltool, on all other platforms raise an error
675 if not _target_is_win32(conf):
679 def _target_is_win32(ctx):
680 if 'is_win32' in ctx.env:
682 return ctx.env['is_win32']
684 if sys.platform == 'win32':
687 if ctx.env and 'CC' in ctx.env:
688 env_cc = ctx.env['CC']
689 if not isinstance(env_cc, str):
690 env_cc = ''.join(env_cc)
691 is_win32 = (env_cc.find('mingw') != -1)
694 # cache for future checks
695 ctx.env['is_win32'] = is_win32
699 def _uc_first(string, ctx):
700 if _target_is_win32(ctx):
701 return string.title()