Bump plugin API version
[geany-mirror.git] / wscript
blob8102de08c505304a46069a50331c6eb7705d8a17
1 # -*- coding: utf-8 -*-
3 # WAF build script - this file is part of Geany, a fast and lightweight IDE
5 # Copyright 2008-2011 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
6 # Copyright 2008-2011 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.
22 # $Id$
24 """
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)
31 or at least equally.
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).
41 """
44 import sys
45 import os
46 import tempfile
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
54 APPNAME = 'geany'
55 VERSION = '0.21'
56 LINGUAS_FILE = 'po/LINGUAS'
58 top = '.'
59 out = '_build_'
62 mio_sources = set(['tagmanager/mio/mio.c'])
64 tagmanager_sources = set([
65     'tagmanager/args.c', 'tagmanager/abc.c', 'tagmanager/actionscript.c', 'tagmanager/asm.c',
66     'tagmanager/basic.c', 'tagmanager/c.c', 'tagmanager/cobol.c',
67     'tagmanager/conf.c', 'tagmanager/css.c', 'tagmanager/ctags.c', 'tagmanager/diff.c',
68     'tagmanager/docbook.c', 'tagmanager/entry.c', 'tagmanager/fortran.c', 'tagmanager/get.c',
69     'tagmanager/haskell.c', 'tagmanager/haxe.c', 'tagmanager/html.c', 'tagmanager/js.c',
70     'tagmanager/keyword.c', 'tagmanager/latex.c', 'tagmanager/lregex.c', 'tagmanager/lua.c',
71     'tagmanager/make.c', 'tagmanager/markdown.c', 'tagmanager/matlab.c', 'tagmanager/nsis.c',
72     'tagmanager/nestlevel.c', 'tagmanager/options.c',
73     'tagmanager/parse.c', 'tagmanager/pascal.c', 'tagmanager/r.c',
74     'tagmanager/perl.c', 'tagmanager/php.c', 'tagmanager/python.c', 'tagmanager/read.c',
75     'tagmanager/rest.c', 'tagmanager/ruby.c', 'tagmanager/sh.c', 'tagmanager/sort.c',
76     'tagmanager/sql.c', 'tagmanager/strlist.c', 'tagmanager/txt2tags.c', 'tagmanager/tcl.c',
77     'tagmanager/tm_file_entry.c',
78     'tagmanager/tm_project.c', 'tagmanager/tm_source_file.c', 'tagmanager/tm_symbol.c',
79     'tagmanager/tm_tag.c', 'tagmanager/tm_tagmanager.c', 'tagmanager/tm_work_object.c',
80     'tagmanager/tm_workspace.c', 'tagmanager/vhdl.c', 'tagmanager/verilog.c', 'tagmanager/vstring.c'])
82 scintilla_sources = set(['scintilla/gtk/scintilla-marshal.c'])
84 geany_sources = set([
85     'src/about.c', 'src/build.c', 'src/callbacks.c', 'src/dialogs.c', 'src/document.c',
86     'src/editor.c', 'src/encodings.c', 'src/filetypes.c', 'src/geanyentryaction.c',
87     'src/geanymenubuttonaction.c', 'src/geanyobject.c', 'src/geanywraplabel.c',
88     'src/highlighting.c', 'src/interface.c', 'src/keybindings.c',
89     'src/keyfile.c', 'src/log.c', 'src/main.c', 'src/msgwindow.c', 'src/navqueue.c', 'src/notebook.c',
90     'src/plugins.c', 'src/pluginutils.c', 'src/prefix.c', 'src/prefs.c', 'src/printing.c', 'src/project.c',
91     'src/sciwrappers.c', 'src/search.c', 'src/socket.c', 'src/stash.c',
92     'src/symbols.c',
93     'src/templates.c', 'src/toolbar.c', 'src/tools.c', 'src/sidebar.c',
94     'src/ui_utils.c', 'src/utils.c'])
98 def configure(conf):
100     conf.check_waf_version(mini='1.6.1')
102     conf.load('compiler_c')
103     is_win32 = _target_is_win32(conf)
105     conf.check_cc(header_name='fcntl.h', mandatory=False)
106     conf.check_cc(header_name='fnmatch.h', mandatory=False)
107     conf.check_cc(header_name='glob.h', mandatory=False)
108     conf.check_cc(header_name='sys/time.h', mandatory=False)
109     conf.check_cc(header_name='sys/types.h', mandatory=False)
110     conf.check_cc(header_name='sys/stat.h', mandatory=False)
111     conf.define('HAVE_STDLIB_H', 1) # are there systems without stdlib.h?
112     conf.define('STDC_HEADERS', 1) # an optimistic guess ;-)
114     if conf.options.gnu_regex:
115         _add_to_env_and_define(conf, 'HAVE_REGCOMP', 1)
116         _add_to_env_and_define(conf, 'USE_INCLUDED_REGEX', 1)
117     else:
118         try:
119             conf.check_cc(header_name='regex.h')
120             conf.check_cc(function_name='regcomp', header_name='regex.h')
121         except ConfigurationError:
122             _add_to_env_and_define(conf, 'HAVE_REGCOMP', 1)
123             _add_to_env_and_define(conf, 'USE_INCLUDED_REGEX', 1)
125     conf.check_cc(function_name='fgetpos', header_name='stdio.h', mandatory=False)
126     conf.check_cc(function_name='ftruncate', header_name='unistd.h', mandatory=False)
127     conf.check_cc(function_name='gethostname', header_name='unistd.h', mandatory=False)
128     conf.check_cc(function_name='mkstemp', header_name='stdlib.h', mandatory=False)
129     conf.check_cc(function_name='strstr', header_name='string.h')
131     # check sunOS socket support
132     if Options.platform == 'sunos':
133         conf.check_cc(function_name='socket', lib='socket',
134                       header_name='sys/socket.h', uselib_store='SUNOS_SOCKET', mandatory=True)
136     # check for cxx after the header and function checks have been done to ensure they are
137     # checked with cc not cxx
138     conf.load('compiler_cxx')
139     if is_win32:
140         conf.load('winres')
141     _load_intltool_if_available(conf)
143     # GTK / GIO version check
144     conf.check_cfg(package='gtk+-2.0', atleast_version='2.8.0', uselib_store='GTK',
145         mandatory=True, args='--cflags --libs')
146     have_gtk_210 = False
147     gtk_version = conf.check_cfg(modversion='gtk+-2.0', uselib_store='GTK')
148     if gtk_version:
149         if version.LooseVersion(gtk_version) >= version.LooseVersion('2.10.0'):
150             have_gtk_210 = True
151     else:
152         gtk_version = 'Unknown'
153     conf.check_cfg(package='gthread-2.0', uselib_store='GTHREAD', args='--cflags --libs')
154     conf.check_cfg(package='gio-2.0', uselib_store='GIO', args='--cflags --libs', mandatory=False)
156     # Windows specials
157     if is_win32:
158         if conf.env['PREFIX'].lower() == tempfile.gettempdir().lower():
159             # overwrite default prefix on Windows (tempfile.gettempdir() is the Waf default)
160             new_prefix = os.path.join(str(conf.root), '%s-%s' % (APPNAME, VERSION))
161             _add_to_env_and_define(conf, 'PREFIX', new_prefix, quote=True)
162             _add_to_env_and_define(conf, 'BINDIR', os.path.join(new_prefix, 'bin'), quote=True)
163         _add_to_env_and_define(conf, 'DOCDIR', os.path.join(conf.env['PREFIX'], 'doc'), quote=True)
164         _add_to_env_and_define(conf, 'LIBDIR', conf.env['PREFIX'], quote=True)
165         conf.define('LOCALEDIR', os.path.join('share' 'locale'), quote=True)
166         # overwrite LOCALEDIR to install message catalogues properly
167         conf.env['LOCALEDIR'] = os.path.join(conf.env['PREFIX'], 'share/locale')
168         # DATADIR is defined in objidl.h, so we remove it from config.h but keep it in env
169         conf.undefine('DATADIR')
170         conf.env['DATADIR'] = os.path.join(conf.env['PREFIX'], 'data')
171         conf.env.append_value('LINKFLAGS_cprogram', ['-mwindows'])
172         conf.env.append_value('LIB_WIN32', ['wsock32', 'uuid', 'ole32', 'iberty'])
173     else:
174         conf.env['cshlib_PATTERN'] = '%s.so'
175         # DATADIR and LOCALEDIR are defined by the intltool tool
176         # but they are not added to the environment, so we need to
177         _add_define_to_env(conf, 'DATADIR')
178         _add_define_to_env(conf, 'LOCALEDIR')
179         docdir = os.path.join(conf.env['DATADIR'], 'doc', 'geany')
180         libdir = os.path.join(conf.env['PREFIX'], 'lib')
181         mandir = os.path.join(conf.env['DATADIR'], 'man')
182         _define_from_opt(conf, 'DOCDIR', conf.options.docdir, docdir)
183         _define_from_opt(conf, 'LIBDIR', conf.options.libdir, libdir)
184         _define_from_opt(conf, 'MANDIR', conf.options.mandir, mandir)
186     svn_rev = _get_svn_rev(conf)
188     conf.define('ENABLE_NLS', 1)
189     conf.define('GEANY_LOCALEDIR', '' if is_win32 else conf.env['LOCALEDIR'], quote=True)
190     conf.define('GEANY_DATADIR', 'data' if is_win32 else conf.env['DATADIR'], quote=True)
191     conf.define('GEANY_DOCDIR', conf.env['DOCDIR'], quote=True)
192     conf.define('GEANY_LIBDIR', '' if is_win32 else conf.env['LIBDIR'], quote=True)
193     conf.define('GEANY_PREFIX', '' if is_win32 else conf.env['PREFIX'], quote=True)
194     conf.define('PACKAGE', APPNAME, quote=True)
195     conf.define('VERSION', VERSION, quote=True)
196     conf.define('REVISION', str(svn_rev), quote=True)
198     conf.define('GETTEXT_PACKAGE', APPNAME, quote=True)
200     # no VTE on Windows
201     if is_win32:
202         conf.options.no_vte = True
204     _define_from_opt(conf, 'HAVE_PLUGINS', not conf.options.no_plugins, None)
205     _define_from_opt(conf, 'HAVE_SOCKET', not conf.options.no_socket, None)
206     _define_from_opt(conf, 'HAVE_VTE', not conf.options.no_vte, None)
208     conf.write_config_header('config.h', remove=False)
210     # some more compiler flags
211     conf.env.append_value('CFLAGS', ['-DHAVE_CONFIG_H'])
212     if svn_rev > -1:
213         conf.env.append_value('CFLAGS', ['-g', '-DGEANY_DEBUG'])
214     # Scintilla flags
215     conf.env.append_value('CFLAGS', ['-DGTK'])
216     conf.env.append_value('CXXFLAGS',
217         ['-DNDEBUG', '-DGTK', '-DSCI_LEXER', '-DG_THREADS_IMPL_NONE'])
219     # summary
220     Logs.pprint('BLUE', 'Summary:')
221     conf.msg('Install Geany ' + VERSION + ' in', conf.env['PREFIX'])
222     conf.msg('Using GTK version', gtk_version)
223     conf.msg('Build with GTK printing support', have_gtk_210 and 'yes' or 'no')
224     conf.msg('Build with plugin support', conf.options.no_plugins and 'no' or 'yes')
225     conf.msg('Use virtual terminal support', conf.options.no_vte and 'no' or 'yes')
226     conf.msg('GNU regex library', conf.env['USE_INCLUDED_REGEX'] and 'built-in' or 'system')
227     if svn_rev > -1:
228         conf.msg('Compiling Subversion revision', svn_rev)
231 def options(opt):
232     opt.tool_options('compiler_cc')
233     opt.tool_options('compiler_cxx')
234     opt.tool_options('intltool')
236     # Features
237     opt.add_option('--disable-plugins', action='store_true', default=False,
238         help='compile without plugin support [default: No]', dest='no_plugins')
239     opt.add_option('--disable-socket', action='store_true', default=False,
240         help='compile without support to detect a running instance [[default: No]',
241         dest='no_socket')
242     opt.add_option('--disable-vte', action='store_true', default=False,
243         help='compile without support for an embedded virtual terminal [[default: No]',
244         dest='no_vte')
245     opt.add_option('--enable-gnu-regex', action='store_true', default=False,
246         help='compile with included GNU regex library [default: No]', dest='gnu_regex')
247     # Paths
248     opt.add_option('--mandir', type='string', default='',
249         help='man documentation', dest='mandir')
250     opt.add_option('--docdir', type='string', default='',
251         help='documentation root', dest='docdir')
252     opt.add_option('--libdir', type='string', default='',
253         help='object code libraries', dest='libdir')
254     # Actions
255     opt.add_option('--hackingdoc', action='store_true', default=False,
256         help='generate HTML documentation from HACKING file', dest='hackingdoc')
259 def build(bld):
260     is_win32 = _target_is_win32(bld)
262     if bld.cmd == 'clean':
263         _remove_linguas_file()
264     if bld.cmd in ('install', 'uninstall'):
265         bld.add_post_fun(_post_install)
267     def build_plugin(plugin_name, install=True):
268         if install:
269             instpath = '${PREFIX}/lib' if is_win32 else '${LIBDIR}/geany'
270         else:
271             instpath = None
273         bld.new_task_gen(
274             features                = ['c', 'cshlib'],
275             source                  = 'plugins/%s.c' % plugin_name,
276             includes                = ['.', 'src/', 'scintilla/include', 'tagmanager/include'],
277             defines                 = 'G_LOG_DOMAIN="%s"' % plugin_name,
278             target                  = plugin_name,
279             uselib                  = 'GTK',
280             install_path            = instpath)
283     # Tagmanager
284     if bld.env['USE_INCLUDED_REGEX'] == 1:
285         tagmanager_sources.add('tagmanager/regex.c')
286     bld.new_task_gen(
287         features        = ['c', 'cstlib'],
288         source          = tagmanager_sources,
289         name            = 'tagmanager',
290         target          = 'tagmanager',
291         includes        = ['.', 'tagmanager', 'tagmanager/include'],
292         defines         = 'G_LOG_DOMAIN="Tagmanager"',
293         uselib          = 'GTK',
294         install_path    = None) # do not install this library
297     # MIO
298     bld.new_task_gen(
299         features        = ['c', 'cstlib'],
300         source          = mio_sources,
301         name            = 'mio',
302         target          = 'mio',
303         includes        = ['.', 'tagmanager/mio/'],
304         defines         = 'G_LOG_DOMAIN="MIO"',
305         uselib          = 'GTK',
306         install_path    = None) # do not install this library
309     # Scintilla
310     files = bld.srcnode.ant_glob('scintilla/**/*.cxx', src=True, dir=False)
311     scintilla_sources.update(files)
312     bld.new_task_gen(
313         features        = ['c', 'cxx', 'cxxstlib'],
314         name            = 'scintilla',
315         target          = 'scintilla',
316         source          = scintilla_sources,
317         includes        = ['.', 'scintilla/include', 'scintilla/src', 'scintilla/lexlib'],
318         uselib          = 'GTK',
319         install_path    = None) # do not install this library
322     # Geany
323     if bld.env['HAVE_VTE'] == 1:
324         geany_sources.add('src/vte.c')
325     if is_win32:
326         geany_sources.add('src/win32.c')
327         geany_sources.add('geany_private.rc')
329     bld.new_task_gen(
330         features        = ['c', 'cxx', 'cprogram'],
331         name            = 'geany',
332         target          = 'geany',
333         source          = geany_sources,
334         includes        = ['.', 'scintilla/include/', 'tagmanager/include/'],
335         defines         = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
336         uselib          = ['GTK', 'GIO', 'GTHREAD', 'WIN32', 'SUNOS_SOCKET'],
337         use             = ['scintilla', 'tagmanager', 'mio'])
339     # geanyfunctions.h
340     bld.new_task_gen(
341         source  = ['plugins/genapi.py', 'src/plugins.c'],
342         name    = 'geanyfunctions.h',
343         before  = ['c', 'cxx'],
344         cwd     = '%s/plugins' % bld.path.abspath(),
345         rule    = 'python genapi.py -q')
347     # Plugins
348     if bld.env['HAVE_PLUGINS'] == 1:
349         build_plugin('classbuilder')
350         build_plugin('demoplugin', False)
351         build_plugin('export')
352         build_plugin('filebrowser')
353         build_plugin('htmlchars')
354         build_plugin('saveactions')
355         build_plugin('splitwindow', not is_win32)
357     # Translations
358     if bld.env['INTLTOOL']:
359         bld.new_task_gen(
360             features        = ['linguas', 'intltool_po'],
361             podir           = 'po',
362             install_path    = '${LOCALEDIR}',
363             appname         = 'geany')
365     # geany.pc
366     task = bld.new_task_gen(
367         source          = 'geany.pc.in',
368         dct             = {'VERSION' : VERSION,
369                            'prefix': bld.env['PREFIX'],
370                            'exec_prefix': '${prefix}',
371                            'libdir': '${exec_prefix}/lib',
372                            'includedir': '${prefix}/include',
373                            'datarootdir': '${prefix}/share',
374                            'datadir': '${datarootdir}',
375                            'localedir': '${datarootdir}/locale'})
377     if not is_win32:
378         # geany.desktop
379         if bld.env['INTLTOOL']:
380             bld.new_task_gen(
381                 features        = 'intltool_in',
382                 source          = 'geany.desktop.in',
383                 flags           = [ '-d', '-q', '-u', '-c' ],
384                 install_path    = '${DATADIR}/applications')
386         # geany.1
387         bld.new_task_gen(
388             features        = 'subst',
389             source          = 'doc/geany.1.in',
390             target          = 'geany.1',
391             dct             = {'VERSION' : VERSION,
392                                 'GEANY_DATA_DIR': bld.env['DATADIR'] + '/geany'},
393             install_path    = '${MANDIR}/man1')
395         # geany.spec
396         bld.new_task_gen(
397             features        = 'subst',
398             source          = 'geany.spec.in',
399             target          = 'geany.spec',
400             install_path    = None,
401             dct             = {'VERSION' : VERSION})
403         # Doxyfile
404         bld.new_task_gen(
405             features        = 'subst',
406             source          = 'doc/Doxyfile.in',
407             target          = 'doc/Doxyfile',
408             install_path    = None,
409             dct             = {'VERSION' : VERSION})
411     ###
412     # Install files
413     ###
414     if not is_win32:
415         # Headers
416         bld.install_files('${PREFIX}/include/geany', '''
417             src/document.h src/editor.h src/encodings.h src/filetypes.h src/geany.h
418             src/highlighting.h src/keybindings.h src/msgwindow.h src/plugindata.h
419             src/prefs.h src/project.h src/search.h src/stash.h src/support.h
420             src/templates.h src/toolbar.h src/ui_utils.h src/utils.h
421             plugins/geanyplugin.h plugins/geanyfunctions.h''')
422         bld.install_files('${PREFIX}/include/geany/scintilla', '''
423             scintilla/include/SciLexer.h scintilla/include/Scintilla.h
424             scintilla/include/Scintilla.iface scintilla/include/ScintillaWidget.h ''')
425         bld.install_files('${PREFIX}/include/geany/tagmanager', '''
426             tagmanager/include/tm_file_entry.h tagmanager/include/tm_project.h
427             tagmanager/include/tm_source_file.h
428             tagmanager/include/tm_symbol.h tagmanager/include/tm_tag.h
429             tagmanager/include/tm_tagmanager.h tagmanager/include/tm_work_object.h
430             tagmanager/include/tm_workspace.h ''')
431     # Docs
432     base_dir = '${PREFIX}' if is_win32 else '${DOCDIR}'
433     ext = '.txt' if is_win32 else ''
434     html_dir = '' if is_win32 else 'html/'
435     html_name = 'Manual.html' if is_win32 else 'index.html'
436     for filename in 'AUTHORS ChangeLog COPYING README NEWS THANKS TODO'.split():
437         basename = _uc_first(filename, bld)
438         destination_filename = '%s%s' % (basename, ext)
439         destination = os.path.join(base_dir, destination_filename)
440         bld.install_as(destination, filename)
442     start_dir = bld.path.find_dir('doc/images')
443     bld.install_files('${DOCDIR}/%simages' % html_dir, start_dir.ant_glob('*.png'), cwd=start_dir)
444     bld.install_as('${DOCDIR}/%s' % _uc_first('manual.txt', bld), 'doc/geany.txt')
445     bld.install_as('${DOCDIR}/%s%s' % (html_dir, html_name), 'doc/geany.html')
446     bld.install_as('${DOCDIR}/ScintillaLicense.txt', 'scintilla/License.txt')
447     if is_win32:
448         bld.install_as('${DOCDIR}/ReadMe.I18n.txt', 'README.I18N')
449         bld.install_as('${DOCDIR}/Hacking.txt', 'HACKING')
450     # Data
451     data_dir = '' if is_win32 else 'geany'
452     start_dir = bld.path.find_dir('data')
453     bld.install_as('${DATADIR}/%s/GPL-2' % data_dir, 'COPYING')
454     bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('filetype*'), cwd=start_dir)
455     bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('*.tags'), cwd=start_dir)
456     bld.install_files('${DATADIR}/%s' % data_dir, 'data/snippets.conf')
457     bld.install_files('${DATADIR}/%s' % data_dir, 'data/ui_toolbar.xml')
458     start_dir = bld.path.find_dir('data/colorschemes')
459     template_dest = '${DATADIR}/%s/colorschemes' % data_dir
460     bld.install_files(template_dest, start_dir.ant_glob('*'), cwd=start_dir)
461     start_dir = bld.path.find_dir('data/templates')
462     template_dest = '${DATADIR}/%s/templates' % data_dir
463     bld.install_files(template_dest, start_dir.ant_glob('**/*'), cwd=start_dir, relative_trick=True)
464     # Icons
465     icon_dest = '${PREFIX}/share/icons' if is_win32 else '${DATADIR}/icons/hicolor/16x16/apps'
466     start_dir = bld.path.find_dir('icons/16x16')
467     bld.install_files(icon_dest, start_dir.ant_glob('*.png'), cwd=start_dir)
468     if not is_win32:
469         start_dir = bld.path.find_dir('icons/48x48')
470         icon_dest = '${DATADIR}/icons/hicolor/48x48/apps'
471         bld.install_files(icon_dest, start_dir.ant_glob('*.png'), cwd=start_dir)
472         start_dir = bld.path.find_dir('icons/scalable')
473         scalable_dest = '${DATADIR}/icons/hicolor/scalable/apps'
474         bld.install_files(scalable_dest, start_dir.ant_glob('*.svg'), cwd=start_dir)
477 def distclean(ctx):
478     Scripting.distclean(ctx)
479     _remove_linguas_file()
482 def _remove_linguas_file():
483     # remove LINGUAS file as well
484     try:
485         os.unlink(LINGUAS_FILE)
486     except OSError:
487         pass
490 @feature('linguas')
491 def write_linguas_file(self):
492     if os.path.exists(LINGUAS_FILE):
493         return
494     linguas = ''
495     if 'LINGUAS' in self.env:
496         files = self.env['LINGUAS']
497         for po_filename in files.split(' '):
498             if os.path.exists ('po/%s.po' % po_filename):
499                 linguas += '%s ' % po_filename
500     else:
501         files = os.listdir('%s/po' % self.path.abspath())
502         files.sort()
503         for filename in files:
504             if filename.endswith('.po'):
505                 linguas += '%s ' % filename[:-3]
506     file_h = open(LINGUAS_FILE, 'w')
507     file_h.write('# This file is autogenerated. Do not edit.\n%s\n' % linguas)
508     file_h.close()
511 def _post_install(ctx):
512     is_win32 = _target_is_win32(ctx)
513     if is_win32:
514         return
515     theme_dir = Utils.subst_vars('${DATADIR}/icons/hicolor', ctx.env)
516     icon_cache_updated = False
517     if not ctx.options.destdir:
518         ctx.exec_command('gtk-update-icon-cache -q -f -t %s' % theme_dir)
519         Logs.pprint('GREEN', 'GTK icon cache updated.')
520         icon_cache_updated = True
521     if not icon_cache_updated:
522         Logs.pprint('YELLOW', 'Icon cache not updated. After install, run this:')
523         Logs.pprint('YELLOW', 'gtk-update-icon-cache -q -f -t %s' % theme_dir)
526 def updatepo(ctx):
527     """update the message catalogs for internationalization"""
528     potfile = '%s.pot' % APPNAME
529     os.chdir('%s/po' % top)
530     try:
531         try:
532             old_size = os.stat(potfile).st_size
533         except OSError:
534             old_size = 0
535         ctx.exec_command('intltool-update --pot -g %s' % APPNAME)
536         size_new = os.stat(potfile).st_size
537         if size_new != old_size:
538             Logs.pprint('CYAN', 'Updated POT file.')
539             Logs.pprint('CYAN', 'Updating translations')
540             ret = ctx.exec_command('intltool-update -r -g %s' % APPNAME)
541             if ret != 0:
542                 Logs.pprint('RED', 'Updating translations failed')
543         else:
544             Logs.pprint('CYAN', 'POT file is up to date.')
545     except OSError:
546         Logs.pprint('RED', 'Failed to generate pot file.')
549 def apidoc(ctx):
550     """generate API reference documentation"""
551     basedir = ctx.path.abspath()
552     doxygen = _find_program(ctx, 'doxygen')
553     doxyfile = '%s/%s/doc/Doxyfile' % (basedir, out)
554     os.chdir('doc')
555     Logs.pprint('CYAN', 'Generating API documentation')
556     ret = ctx.exec_command('%s %s' % (doxygen, doxyfile))
557     if ret != 0:
558         raise WafError('Generating API documentation failed')
559     # update hacking.html
560     cmd = _find_rst2html(ctx)
561     ctx.exec_command('%s  -stg --stylesheet=geany.css %s %s' % (cmd, '../HACKING', 'hacking.html'))
562     os.chdir('..')
565 def htmldoc(ctx):
566     """generate HTML documentation"""
567     # first try rst2html.py as it is the upstream default, fall back to rst2html
568     cmd = _find_rst2html(ctx)
569     os.chdir('doc')
570     Logs.pprint('CYAN', 'Generating HTML documentation')
571     ctx.exec_command('%s  -stg --stylesheet=geany.css %s %s' % (cmd, 'geany.txt', 'geany.html'))
572     os.chdir('..')
575 def _find_program(ctx, cmd, **kw):
576     def noop(*args):
577         pass
579     ctx = ConfigurationContext()
580     ctx.to_log = noop
581     ctx.msg = noop
582     return ctx.find_program(cmd, **kw)
585 def _find_rst2html(ctx):
586     cmds = ['rst2html.py', 'rst2html']
587     for command in cmds:
588         cmd = _find_program(ctx, command, mandatory=False)
589         if cmd:
590             break
591     if not cmd:
592         raise WafError(
593             'rst2html.py could not be found. Please install the Python docutils package.')
594     return cmd
597 def _add_define_to_env(conf, key):
598     value = conf.get_define(key)
599     # strip quotes
600     value = value.replace('"', '')
601     conf.env[key] = value
604 def _add_to_env_and_define(conf, key, value, quote=False):
605     conf.define(key, value, quote)
606     conf.env[key] = value
609 def _define_from_opt(conf, define_name, opt_value, default_value, quote=1):
610     value = default_value
611     if opt_value:
612         if isinstance(opt_value, bool):
613             opt_value = 1
614         value = opt_value
616     if value is not None:
617         _add_to_env_and_define(conf, define_name, value, quote)
618     else:
619         conf.undefine(define_name)
622 def _get_svn_rev(conf):
623     def in_git():
624         cmd = 'git ls-files >/dev/null 2>&1'
625         return (conf.exec_command(cmd) == 0)
627     def in_svn():
628         return os.path.exists('.svn')
630     # try GIT
631     if in_git():
632         cmds = [ 'git svn find-rev HEAD 2>/dev/null',
633                  'git svn find-rev origin/trunk 2>/dev/null',
634                  'git svn find-rev trunk 2>/dev/null',
635                  'git svn find-rev master 2>/dev/null'
636                 ]
637         for cmd in cmds:
638             try:
639                 stdout = conf.cmd_and_log(cmd)
640                 if stdout:
641                     return int(stdout.strip())
642             except WafError:
643                 pass
644             except ValueError:
645                 Logs.pprint('RED', 'Unparseable revision number')
646     # try SVN
647     elif in_svn():
648         try:
649             _env = None if _target_is_win32(conf) else dict(LANG='C')
650             stdout = conf.cmd_and_log(cmd='svn info --non-interactive', env=_env)
651             lines = stdout.splitlines(True)
652             for line in lines:
653                 if line.startswith('Last Changed Rev'):
654                     value = line.split(': ', 1)[1]
655                     return int(value.strip())
656         except WafError:
657             pass
658         except (IndexError, ValueError):
659             Logs.pprint('RED', 'Unparseable revision number')
660     return 0
663 def _load_intltool_if_available(conf):
664     try:
665         conf.check_tool('intltool')
666         if 'LINGUAS' in os.environ:
667             conf.env['LINGUAS'] = os.environ['LINGUAS']
668     except WafError:
669         # on Windows, we don't hard depend on intltool, on all other platforms raise an error
670         if not _target_is_win32(conf):
671             raise
674 def _target_is_win32(ctx):
675     if 'is_win32' in ctx.env:
676         # cached
677         return ctx.env['is_win32']
678     is_win32 = None
679     if sys.platform == 'win32':
680         is_win32 = True
681     if is_win32 is None:
682         if ctx.env and 'CC' in ctx.env:
683             env_cc = ctx.env['CC']
684             if not isinstance(env_cc, str):
685                 env_cc = ''.join(env_cc)
686             is_win32 = (env_cc.find('mingw') != -1)
687     if is_win32 is None:
688         is_win32 = False
689     # cache for future checks
690     ctx.env['is_win32'] = is_win32
691     return is_win32
694 def _uc_first(string, ctx):
695     if _target_is_win32(ctx):
696         return string.title()
697     return string