907 lines
36 KiB
Python
907 lines
36 KiB
Python
# -*- coding: utf-8 -*-
|
|
#
|
|
# WAF build script - this file is part of Geany, a fast and lightweight IDE
|
|
#
|
|
# Copyright 2008-2012 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
|
|
# Copyright 2008-2012 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
"""
|
|
This is a WAF build script (http://code.google.com/p/waf/).
|
|
It can be used as an alternative build system to autotools
|
|
for Geany. It does not (yet) cover all of the autotools tests and
|
|
configure options but all important things are working.
|
|
"make dist" should be done with autotools, most other targets and
|
|
functions should work better (regarding performance and flexibility)
|
|
or at least equally.
|
|
|
|
Missing features: --enable-binreloc, make targets: dist, pdf (in doc/)
|
|
Known issues: Dependency handling is buggy, e.g. if src/document.h is
|
|
changed, depending source files are not rebuilt (maybe Waf bug).
|
|
|
|
The code of this file itself loosely follows PEP 8 with some exceptions
|
|
(line width 100 characters and some other minor things).
|
|
|
|
Requires WAF 1.6.1 and Python 2.5 (or later).
|
|
"""
|
|
|
|
|
|
import sys
|
|
import os
|
|
import tempfile
|
|
from waflib import Logs, Options, Scripting, Utils
|
|
from waflib.Build import BuildContext
|
|
from waflib.Configure import ConfigurationContext
|
|
from waflib.Errors import WafError
|
|
from waflib.TaskGen import feature, before_method
|
|
from waflib.Tools.compiler_c import c_compiler
|
|
from waflib.Tools.compiler_cxx import cxx_compiler
|
|
|
|
|
|
APPNAME = 'geany'
|
|
VERSION = '1.25'
|
|
LINGUAS_FILE = os.path.join('po', 'LINGUAS')
|
|
MINIMUM_GTK_VERSION = '2.24.0'
|
|
MINIMUM_GTK3_VERSION = '3.0.0'
|
|
MINIMUM_GLIB_VERSION = '2.28.0'
|
|
|
|
GEANY_LIB_VERSION = '0.0.0'
|
|
|
|
top = '.'
|
|
out = '_build_'
|
|
|
|
mio_sources = set(['tagmanager/mio/mio.c'])
|
|
|
|
ctags_sources = set([
|
|
'tagmanager/ctags/abaqus.c',
|
|
'tagmanager/ctags/args.c',
|
|
'tagmanager/ctags/abc.c',
|
|
'tagmanager/ctags/actionscript.c',
|
|
'tagmanager/ctags/asciidoc.c',
|
|
'tagmanager/ctags/asm.c',
|
|
'tagmanager/ctags/basic.c',
|
|
'tagmanager/ctags/c.c',
|
|
'tagmanager/ctags/cobol.c',
|
|
'tagmanager/ctags/conf.c',
|
|
'tagmanager/ctags/css.c',
|
|
'tagmanager/ctags/ctags.c',
|
|
'tagmanager/ctags/diff.c',
|
|
'tagmanager/ctags/docbook.c',
|
|
'tagmanager/ctags/erlang.c',
|
|
'tagmanager/ctags/entry.c',
|
|
'tagmanager/ctags/fortran.c',
|
|
'tagmanager/ctags/get.c',
|
|
'tagmanager/ctags/go.c',
|
|
'tagmanager/ctags/haskell.c',
|
|
'tagmanager/ctags/haxe.c',
|
|
'tagmanager/ctags/html.c',
|
|
'tagmanager/ctags/js.c',
|
|
'tagmanager/ctags/json.c',
|
|
'tagmanager/ctags/keyword.c',
|
|
'tagmanager/ctags/latex.c',
|
|
'tagmanager/ctags/lregex.c',
|
|
'tagmanager/ctags/lua.c',
|
|
'tagmanager/ctags/make.c',
|
|
'tagmanager/ctags/markdown.c',
|
|
'tagmanager/ctags/matlab.c',
|
|
'tagmanager/ctags/nsis.c',
|
|
'tagmanager/ctags/nestlevel.c',
|
|
'tagmanager/ctags/objc.c',
|
|
'tagmanager/ctags/options.c',
|
|
'tagmanager/ctags/parse.c',
|
|
'tagmanager/ctags/pascal.c',
|
|
'tagmanager/ctags/r.c',
|
|
'tagmanager/ctags/perl.c',
|
|
'tagmanager/ctags/php.c',
|
|
'tagmanager/ctags/python.c',
|
|
'tagmanager/ctags/read.c',
|
|
'tagmanager/ctags/rest.c',
|
|
'tagmanager/ctags/ruby.c',
|
|
'tagmanager/ctags/rust.c',
|
|
'tagmanager/ctags/sh.c',
|
|
'tagmanager/ctags/sort.c',
|
|
'tagmanager/ctags/sql.c',
|
|
'tagmanager/ctags/strlist.c',
|
|
'tagmanager/ctags/txt2tags.c',
|
|
'tagmanager/ctags/tcl.c',
|
|
'tagmanager/ctags/vhdl.c',
|
|
'tagmanager/ctags/verilog.c',
|
|
'tagmanager/ctags/vstring.c'])
|
|
|
|
tagmanager_sources = set([
|
|
'tagmanager/src/tm_source_file.c',
|
|
'tagmanager/src/tm_tag.c',
|
|
'tagmanager/src/tm_workspace.c'])
|
|
|
|
scintilla_sources = set(['scintilla/gtk/scintilla-marshal.c'])
|
|
|
|
geany_sources = set([
|
|
'src/about.c', 'src/build.c', 'src/callbacks.c', 'src/dialogs.c', 'src/document.c',
|
|
'src/editor.c', 'src/encodings.c', 'src/filetypes.c', 'src/geanyentryaction.c',
|
|
'src/geanymenubuttonaction.c', 'src/geanyobject.c', 'src/geanywraplabel.c',
|
|
'src/highlighting.c', 'src/keybindings.c',
|
|
'src/keyfile.c', 'src/log.c', 'src/libmain.c', 'src/msgwindow.c', 'src/navqueue.c', 'src/notebook.c', 'src/osx.c',
|
|
'src/plugins.c', 'src/pluginutils.c', 'src/prefix.c', 'src/prefs.c', 'src/printing.c', 'src/project.c',
|
|
'src/sciwrappers.c', 'src/search.c', 'src/socket.c', 'src/spawn.c', 'src/stash.c',
|
|
'src/symbols.c',
|
|
'src/templates.c', 'src/toolbar.c', 'src/tools.c', 'src/sidebar.c',
|
|
'src/ui_utils.c', 'src/utils.c'])
|
|
|
|
geany_bin_sources = set(['src/main.c'])
|
|
|
|
geany_icons = {
|
|
'hicolor/16x16/apps': ['16x16/classviewer-class.png',
|
|
'16x16/classviewer-macro.png',
|
|
'16x16/classviewer-member.png',
|
|
'16x16/classviewer-method.png',
|
|
'16x16/classviewer-namespace.png',
|
|
'16x16/classviewer-other.png',
|
|
'16x16/classviewer-struct.png',
|
|
'16x16/classviewer-var.png',
|
|
'16x16/geany.png'],
|
|
'hicolor/16x16/actions': ['16x16/geany-build.png',
|
|
'16x16/geany-close-all.png',
|
|
'16x16/geany-save-all.png'],
|
|
'hicolor/24x24/actions': ['24x24/geany-build.png',
|
|
'24x24/geany-close-all.png',
|
|
'24x24/geany-save-all.png'],
|
|
'hicolor/32x32/actions': ['32x32/geany-build.png',
|
|
'32x32/geany-close-all.png',
|
|
'32x32/geany-save-all.png'],
|
|
'hicolor/32x32/apps': ['32x32/geany.png'],
|
|
'hicolor/48x48/actions': ['48x48/geany-build.png',
|
|
'48x48/geany-close-all.png',
|
|
'48x48/geany-save-all.png'],
|
|
'hicolor/48x48/apps': ['48x48/geany.png'],
|
|
'hicolor/scalable/apps': ['scalable/geany.svg'],
|
|
'hicolor/scalable/actions': ['scalable/geany-build.svg',
|
|
'scalable/geany-close-all.svg',
|
|
'scalable/geany-save-all.svg'],
|
|
'Tango/16x16/actions': ['tango/16x16/geany-save-all.png'],
|
|
'Tango/24x24/actions': ['tango/24x24/geany-save-all.png'],
|
|
'Tango/32x32/actions': ['tango/32x32/geany-save-all.png'],
|
|
'Tango/48x48/actions': ['tango/48x48/geany-save-all.png'],
|
|
'Tango/scalable/actions': ['tango/scalable/geany-save-all.svg']
|
|
}
|
|
geany_icons_indexes = {
|
|
'hicolor': ['index.theme'],
|
|
'Tango': ['tango/index.theme']
|
|
}
|
|
|
|
|
|
def configure(conf):
|
|
|
|
conf.check_waf_version(mini='1.6.1')
|
|
|
|
conf.load('compiler_c')
|
|
is_win32 = _target_is_win32(conf)
|
|
|
|
visibility_hidden_supported = conf.check_cc(cflags=['-Werror', '-fvisibility=hidden'], mandatory=False)
|
|
conf.check_cc(header_name='fcntl.h', mandatory=False)
|
|
conf.check_cc(header_name='fnmatch.h', mandatory=False)
|
|
conf.check_cc(header_name='glob.h', mandatory=False)
|
|
conf.check_cc(header_name='sys/time.h', mandatory=False)
|
|
conf.check_cc(header_name='sys/types.h', mandatory=False)
|
|
conf.check_cc(header_name='sys/stat.h', mandatory=False)
|
|
conf.define('HAVE_STDLIB_H', 1) # are there systems without stdlib.h?
|
|
conf.define('STDC_HEADERS', 1) # an optimistic guess ;-)
|
|
_add_to_env_and_define(conf, 'HAVE_REGCOMP', 1) # needed for CTags
|
|
|
|
conf.check_cc(function_name='fgetpos', header_name='stdio.h', mandatory=False)
|
|
conf.check_cc(function_name='fnmatch', header_name='fnmatch.h', mandatory=False)
|
|
conf.check_cc(function_name='ftruncate', header_name='unistd.h', mandatory=False)
|
|
conf.check_cc(function_name='mkstemp', header_name='stdlib.h', mandatory=False)
|
|
conf.check_cc(function_name='strstr', header_name='string.h')
|
|
|
|
conf.check_cc(function_name='pow', header_name='math.h', lib='m', uselib_store='M')
|
|
|
|
# check sunOS socket support
|
|
if Options.platform == 'sunos':
|
|
conf.check_cc(function_name='socket', lib='socket',
|
|
header_name='sys/socket.h', uselib_store='SUNOS_SOCKET', mandatory=True)
|
|
|
|
# check for cxx after the header and function checks have been done to ensure they are
|
|
# checked with cc not cxx
|
|
conf.load('compiler_cxx')
|
|
if is_win32:
|
|
conf.load('winres')
|
|
_load_intltool_if_available(conf)
|
|
|
|
# GTK / GIO version check
|
|
gtk_package_name = 'gtk+-3.0' if conf.options.use_gtk3 else 'gtk+-2.0'
|
|
minimum_gtk_version = MINIMUM_GTK3_VERSION if conf.options.use_gtk3 else MINIMUM_GTK_VERSION
|
|
conf.check_cfg(package=gtk_package_name, atleast_version=minimum_gtk_version, uselib_store='GTK',
|
|
mandatory=True, args='--cflags --libs')
|
|
conf.check_cfg(package='glib-2.0', atleast_version=MINIMUM_GLIB_VERSION, uselib_store='GLIB',
|
|
mandatory=True, args='--cflags --libs')
|
|
conf.check_cfg(package='gmodule-2.0', uselib_store='GMODULE',
|
|
mandatory=True, args='--cflags --libs')
|
|
conf.check_cfg(package='gio-2.0', uselib_store='GIO', args='--cflags --libs', mandatory=True)
|
|
gtk_version = conf.check_cfg(modversion=gtk_package_name, uselib_store='GTK') or 'Unknown'
|
|
conf.check_cfg(package='gthread-2.0', uselib_store='GTHREAD', args='--cflags --libs')
|
|
if conf.options.enable_mac_integration:
|
|
pkgname = 'gtk-mac-integration-gtk3' if conf.options.use_gtk3 else 'gtk-mac-integration-gtk2'
|
|
conf.check_cfg(package=pkgname, uselib_store='MAC_INTEGRATION',
|
|
mandatory=True, args='--cflags --libs')
|
|
# remember GTK version for the build step
|
|
conf.env['gtk_package_name'] = gtk_package_name
|
|
conf.env['minimum_gtk_version'] = minimum_gtk_version
|
|
conf.env['use_gtk3'] = conf.options.use_gtk3
|
|
|
|
revision = _get_git_rev(conf)
|
|
|
|
# rst2html for the HTML manual
|
|
if not conf.options.no_html_doc and revision is not None:
|
|
try:
|
|
conf.env['RST2HTML'] = _find_rst2html(conf)
|
|
except WafError:
|
|
error_msg = '''Documentation enabled but rst2html not found.
|
|
You can explicitly disable building of the HTML manual with --disable-html-docs,
|
|
but you then may not have a local copy of the HTML manual.'''
|
|
raise WafError(error_msg)
|
|
|
|
# Windows specials
|
|
if is_win32:
|
|
if conf.env['PREFIX'].lower() == tempfile.gettempdir().lower():
|
|
# overwrite default prefix on Windows (tempfile.gettempdir() is the Waf default)
|
|
new_prefix = os.path.join(str(conf.root), '%s-%s' % (APPNAME, VERSION))
|
|
_add_to_env_and_define(conf, 'PREFIX', new_prefix, quote=True)
|
|
_add_to_env_and_define(conf, 'BINDIR', os.path.join(new_prefix, 'bin'), quote=True)
|
|
_add_to_env_and_define(conf, 'DOCDIR', os.path.join(conf.env['PREFIX'], 'doc'), quote=True)
|
|
_add_to_env_and_define(conf, 'LIBDIR', '%s/lib' % conf.env['PREFIX'], quote=True)
|
|
conf.define('LOCALEDIR', os.path.join('share' 'locale'), quote=True)
|
|
# overwrite LOCALEDIR to install message catalogues properly
|
|
conf.env['LOCALEDIR'] = os.path.join(conf.env['PREFIX'], 'share', 'locale')
|
|
# DATADIR is defined in objidl.h, so we remove it from config.h but keep it in env
|
|
conf.undefine('DATADIR')
|
|
conf.env['DATADIR'] = os.path.join(conf.env['PREFIX'], 'data')
|
|
conf.env.append_value('LINKFLAGS_cprogram', [
|
|
'-mwindows',
|
|
'-static-libgcc',
|
|
'-static-libstdc++'])
|
|
conf.env.append_value('LIB_WIN32', ['wsock32', 'uuid', 'ole32', 'comdlg32'])
|
|
# explicitly define Windows version for older Mingw environments
|
|
conf.define('WINVER', '0x0501', quote=False) # for SHGetFolderPathAndSubDirW
|
|
conf.define('_WIN32_IE', '0x0500', quote=False) # for SHGFP_TYPE
|
|
else:
|
|
conf.env['cshlib_PATTERN'] = '%s.so'
|
|
# DATADIR and LOCALEDIR are defined by the intltool tool
|
|
# but they are not added to the environment, so we need to
|
|
_add_define_to_env(conf, 'DATADIR')
|
|
_add_define_to_env(conf, 'LOCALEDIR')
|
|
docdir = os.path.join(conf.env['DATADIR'], 'doc', 'geany')
|
|
libdir = os.path.join(conf.env['PREFIX'], 'lib')
|
|
mandir = os.path.join(conf.env['DATADIR'], 'man')
|
|
_define_from_opt(conf, 'DOCDIR', conf.options.docdir, docdir)
|
|
_define_from_opt(conf, 'LIBDIR', conf.options.libdir, libdir)
|
|
_define_from_opt(conf, 'MANDIR', conf.options.mandir, mandir)
|
|
|
|
conf.define('ENABLE_NLS', 1)
|
|
conf.define('GEANY_LOCALEDIR', '' if is_win32 else conf.env['LOCALEDIR'], quote=True)
|
|
conf.define('GEANY_DATADIR', 'data' if is_win32 else conf.env['DATADIR'], quote=True)
|
|
conf.define('GEANY_DOCDIR', conf.env['DOCDIR'], quote=True)
|
|
conf.define('GEANY_LIBDIR', '' if is_win32 else conf.env['LIBDIR'], quote=True)
|
|
conf.define('GEANY_PREFIX', '' if is_win32 else conf.env['PREFIX'], quote=True)
|
|
conf.define('PACKAGE', APPNAME, quote=True)
|
|
conf.define('VERSION', VERSION, quote=True)
|
|
conf.define('REVISION', revision or '-1', quote=True)
|
|
|
|
conf.define('GETTEXT_PACKAGE', APPNAME, quote=True)
|
|
|
|
# no VTE on Windows
|
|
if is_win32:
|
|
conf.options.no_vte = True
|
|
|
|
_define_from_opt(conf, 'HAVE_PLUGINS', not conf.options.no_plugins, None)
|
|
_define_from_opt(conf, 'HAVE_SOCKET', not conf.options.no_socket, None)
|
|
_define_from_opt(conf, 'HAVE_VTE', not conf.options.no_vte, None)
|
|
|
|
conf.write_config_header('config.h', remove=False)
|
|
|
|
# GEANY_EXPORT_SYMBOL and GEANY_API_SYMBOL
|
|
if is_win32:
|
|
geanyexport_cflags = []
|
|
geanyexport_defines = ['GEANY_EXPORT_SYMBOL=__declspec(dllexport)']
|
|
elif visibility_hidden_supported:
|
|
geanyexport_cflags = ['-fvisibility=hidden']
|
|
geanyexport_defines = ['GEANY_EXPORT_SYMBOL=__attribute__((visibility("default")))']
|
|
else: # unknown, define to nothing
|
|
geanyexport_cflags = []
|
|
geanyexport_defines = ['GEANY_EXPORT_SYMBOL=']
|
|
geanyexport_defines.append('GEANY_API_SYMBOL=GEANY_EXPORT_SYMBOL')
|
|
conf.env['DEFINES_geanyexport'] = geanyexport_defines
|
|
conf.env['CFLAGS_geanyexport'] = geanyexport_cflags
|
|
conf.env['CXXFLAGS_geanyexport'] = geanyexport_cflags
|
|
|
|
# some more compiler flags
|
|
conf.env.append_value('CFLAGS', ['-DHAVE_CONFIG_H'])
|
|
if conf.env['CC_NAME'] == 'gcc' and '-O' not in ''.join(conf.env['CFLAGS']):
|
|
conf.env.append_value('CFLAGS', ['-O2'])
|
|
if revision is not None:
|
|
conf.env.append_value('CFLAGS', ['-g', '-DGEANY_DEBUG'])
|
|
# Scintilla flags
|
|
conf.env.append_value('CFLAGS', ['-DGTK'])
|
|
conf.env.append_value('CXXFLAGS',
|
|
['-DNDEBUG', '-DGTK', '-DSCI_LEXER', '-DG_THREADS_IMPL_NONE'])
|
|
if conf.env['CXX_NAME'] == 'gcc' and '-O' not in ''.join(conf.env['CXXFLAGS']):
|
|
conf.env.append_value('CXXFLAGS', ['-O2'])
|
|
if revision is not None:
|
|
conf.env.append_value('CXXFLAGS', ['-g'])
|
|
|
|
# summary
|
|
Logs.pprint('BLUE', 'Summary:')
|
|
conf.msg('Install Geany ' + VERSION + ' in', conf.env['PREFIX'])
|
|
conf.msg('Using GTK version', gtk_version)
|
|
conf.msg('Build with plugin support', conf.options.no_plugins and 'no' or 'yes')
|
|
conf.msg('Use virtual terminal support', conf.options.no_vte and 'no' or 'yes')
|
|
if revision is not None:
|
|
conf.msg('Compiling Git revision', revision)
|
|
|
|
|
|
def options(opt):
|
|
# Disable MSVC detection on win32: building Geany with MSVC is currently not supported
|
|
# If anyone wants to add support for building with MSVC, this hack should be removed.
|
|
c_compiler['win32'] = ['gcc']
|
|
cxx_compiler['win32'] = ['g++']
|
|
|
|
opt.load('compiler_cc')
|
|
opt.load('compiler_cxx')
|
|
opt.load('intltool')
|
|
|
|
# Option
|
|
opt.add_option('--no-scm', action='store_true', default=False,
|
|
help='Disable SCM detection [default: No]', dest='no_scm')
|
|
# Features
|
|
opt.add_option('--disable-plugins', action='store_true', default=False,
|
|
help='compile without plugin support [default: No]', dest='no_plugins')
|
|
opt.add_option('--disable-socket', action='store_true', default=False,
|
|
help='compile without support to detect a running instance [[default: No]',
|
|
dest='no_socket')
|
|
opt.add_option('--disable-vte', action='store_true', default=False,
|
|
help='compile without support for an embedded virtual terminal [[default: No]',
|
|
dest='no_vte')
|
|
opt.add_option('--enable-gtk3', action='store_true', default=False,
|
|
help='compile with GTK3 support (experimental) [[default: No]',
|
|
dest='use_gtk3')
|
|
opt.add_option('--enable-mac-integration', action='store_true', default=False,
|
|
help='use gtk-mac-integration to enable improved OS X integration [[default: No]',
|
|
dest='enable_mac_integration')
|
|
opt.add_option('--disable-html-docs', action='store_true', default=False,
|
|
help='do not generate HTML documentation using rst2html [[default: No]',
|
|
dest='no_html_doc')
|
|
# Paths
|
|
opt.add_option('--mandir', type='string', default='',
|
|
help='man documentation', dest='mandir')
|
|
opt.add_option('--docdir', type='string', default='',
|
|
help='documentation root', dest='docdir')
|
|
opt.add_option('--libdir', type='string', default='',
|
|
help='object code libraries', dest='libdir')
|
|
|
|
|
|
def build(bld):
|
|
is_win32 = _target_is_win32(bld)
|
|
|
|
if bld.cmd == 'clean':
|
|
_remove_linguas_file()
|
|
if bld.cmd in ('install', 'uninstall'):
|
|
bld.add_post_fun(_post_install)
|
|
|
|
def build_plugin(plugin_name, install=True, uselib_add=[]):
|
|
if install:
|
|
instpath = '${PREFIX}/lib' if is_win32 else '${LIBDIR}/geany'
|
|
else:
|
|
instpath = None
|
|
|
|
bld(
|
|
features = ['c', 'cshlib'],
|
|
source = 'plugins/%s.c' % plugin_name,
|
|
includes = ['.', 'src/', 'scintilla/include', 'tagmanager/src'],
|
|
defines = 'G_LOG_DOMAIN="%s"' % plugin_name,
|
|
target = plugin_name,
|
|
uselib = ['GTK', 'GLIB', 'GMODULE'] + uselib_add,
|
|
use = ['geany'],
|
|
install_path = instpath)
|
|
|
|
# CTags
|
|
bld.objects(
|
|
features = ['c'],
|
|
source = ctags_sources,
|
|
name = 'ctags',
|
|
target = 'ctags',
|
|
includes = ['.', 'tagmanager', 'tagmanager/ctags'],
|
|
defines = 'G_LOG_DOMAIN="CTags"',
|
|
uselib = ['cshlib', 'GLIB', 'geanyexport'])
|
|
|
|
# Tagmanager
|
|
bld.objects(
|
|
features = ['c'],
|
|
source = tagmanager_sources,
|
|
name = 'tagmanager',
|
|
target = 'tagmanager',
|
|
includes = ['.', 'tagmanager', 'tagmanager/ctags'],
|
|
defines = ['GEANY_PRIVATE', 'G_LOG_DOMAIN="Tagmanager"'],
|
|
uselib = ['cshlib', 'GTK', 'GLIB', 'geanyexport'])
|
|
|
|
# MIO
|
|
bld.objects(
|
|
features = ['c'],
|
|
source = mio_sources,
|
|
name = 'mio',
|
|
target = 'mio',
|
|
includes = ['.', 'tagmanager/mio/'],
|
|
defines = 'G_LOG_DOMAIN="MIO"',
|
|
uselib = ['cshlib', 'GTK', 'GLIB', 'geanyexport'])
|
|
|
|
# Scintilla
|
|
files = bld.srcnode.ant_glob('scintilla/**/*.cxx', src=True, dir=False)
|
|
scintilla_sources.update([file.path_from(bld.srcnode) for file in files])
|
|
bld.objects(
|
|
features = ['c', 'cxx'],
|
|
name = 'scintilla',
|
|
target = 'scintilla',
|
|
source = scintilla_sources,
|
|
includes = ['.', 'scintilla/include', 'scintilla/src', 'scintilla/lexlib'],
|
|
uselib = ['cshlib', 'cxxshlib', 'GTK', 'GLIB', 'GMODULE', 'M', 'geanyexport'])
|
|
|
|
# Geany
|
|
if bld.env['HAVE_VTE'] == 1:
|
|
geany_sources.add('src/vte.c')
|
|
if is_win32:
|
|
geany_sources.add('src/win32.c')
|
|
geany_bin_sources.add('geany_private.rc')
|
|
|
|
def gen_signallist(task):
|
|
from xml.etree import ElementTree
|
|
|
|
def find_handlers(xml_filename):
|
|
tree = ElementTree.parse(xml_filename)
|
|
signals = tree.getroot().findall(".//signal")
|
|
return [sig.attrib["handler"] for sig in signals]
|
|
|
|
handlers = []
|
|
for node in task.inputs:
|
|
handlers += find_handlers(node.abspath())
|
|
handlers = sorted(set(handlers))
|
|
|
|
for node in task.outputs:
|
|
node.write("/* This file is auto-generated, do not edit. */\n" +
|
|
''.join(["ITEM(%s)\n" % h for h in handlers]))
|
|
|
|
# signallist.i
|
|
bld(
|
|
source = 'data/geany.glade',
|
|
target = bld.path.get_bld().make_node('src/signallist.i'),
|
|
name = 'signallist.i',
|
|
rule = gen_signallist)
|
|
|
|
base_uselibs = ['GTK', 'GLIB', 'GMODULE', 'GIO', 'GTHREAD', 'WIN32', 'MAC_INTEGRATION', 'SUNOS_SOCKET', 'M']
|
|
|
|
# libgeany
|
|
bld.shlib(
|
|
features = ['c', 'cxx'],
|
|
name = 'geany',
|
|
target = 'geany',
|
|
source = geany_sources,
|
|
includes = ['.', 'scintilla/include', 'tagmanager/src', 'src'],
|
|
defines = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
|
|
uselib = base_uselibs + ['geanyexport'],
|
|
use = ['scintilla', 'ctags', 'tagmanager', 'mio'],
|
|
linkflags = bld.env['LINKFLAGS_cprogram'],
|
|
vnum = GEANY_LIB_VERSION,
|
|
install_path = '${PREFIX}/bin' if is_win32 else '${LIBDIR}')
|
|
|
|
# geany executable
|
|
t = bld.program(
|
|
features = ['c', 'cxx'],
|
|
name = 'geany_bin',
|
|
target = 'geany',
|
|
source = geany_bin_sources,
|
|
includes = ['.', 'scintilla/include', 'tagmanager/src'],
|
|
defines = ['G_LOG_DOMAIN="Geany"', 'GEANY_PRIVATE'],
|
|
uselib = base_uselibs + ['geanyexport'],
|
|
use = ['geany'])
|
|
if not is_win32:
|
|
# http://www.freehackers.org/~tnagy/testdoc/single.html#common_c
|
|
t.rpath = bld.env['LIBDIR']
|
|
|
|
# Plugins
|
|
if bld.env['HAVE_PLUGINS'] == 1:
|
|
build_plugin('classbuilder')
|
|
build_plugin('demoplugin', False)
|
|
build_plugin('export', uselib_add=['M'])
|
|
build_plugin('filebrowser')
|
|
build_plugin('htmlchars')
|
|
build_plugin('saveactions')
|
|
build_plugin('splitwindow')
|
|
|
|
# Translations
|
|
if bld.env['INTLTOOL']:
|
|
bld(
|
|
features = ['linguas', 'intltool_po'],
|
|
podir = 'po',
|
|
install_path = '${LOCALEDIR}',
|
|
appname = 'geany')
|
|
|
|
# HTML documentation (build if it is not part of the tree already, as it is required for install)
|
|
html_doc_filename = os.path.join(bld.out_dir, 'doc', 'geany.html')
|
|
if bld.env['RST2HTML']:
|
|
rst2html = bld.env['RST2HTML']
|
|
bld(
|
|
source = ['doc/geany.txt'],
|
|
deps = ['doc/geany.css'],
|
|
target = bld.path.get_bld().make_node('doc/geany.html'),
|
|
name = 'geany.html',
|
|
cwd = os.path.join(bld.path.abspath(), 'doc'),
|
|
rule = '%s -stg --stylesheet=geany.css geany.txt %s' % (rst2html, html_doc_filename))
|
|
|
|
# geany.pc
|
|
if is_win32:
|
|
# replace backward slashes by forward slashes as they could be interepreted as escape
|
|
# characters
|
|
geany_pc_prefix = bld.env['PREFIX'].replace('\\', '/')
|
|
else:
|
|
geany_pc_prefix = bld.env['PREFIX']
|
|
bld(
|
|
source = 'geany.pc.in',
|
|
dct = {'VERSION': VERSION,
|
|
'DEPENDENCIES': '%s >= %s glib-2.0 >= %s' % \
|
|
(bld.env['gtk_package_name'],
|
|
bld.env['minimum_gtk_version'],
|
|
MINIMUM_GLIB_VERSION),
|
|
'prefix': geany_pc_prefix,
|
|
'exec_prefix': '${prefix}',
|
|
'libdir': '${exec_prefix}/lib',
|
|
'includedir': '${prefix}/include',
|
|
'datarootdir': '${prefix}/share',
|
|
'datadir': '${datarootdir}',
|
|
'localedir': '${datarootdir}/locale'})
|
|
|
|
if not is_win32:
|
|
# geany.desktop
|
|
if bld.env['INTLTOOL']:
|
|
bld(
|
|
features = 'intltool_in',
|
|
source = 'geany.desktop.in',
|
|
flags = ['-d', '-q', '-u', '-c'],
|
|
install_path = '${DATADIR}/applications')
|
|
|
|
# geany.1
|
|
bld(
|
|
features = 'subst',
|
|
source = 'doc/geany.1.in',
|
|
target = 'geany.1',
|
|
dct = {'VERSION': VERSION,
|
|
'GEANY_DATA_DIR': bld.env['DATADIR'] + '/geany'},
|
|
install_path = '${MANDIR}/man1')
|
|
|
|
# geany.spec
|
|
bld(
|
|
features = 'subst',
|
|
source = 'geany.spec.in',
|
|
target = 'geany.spec',
|
|
install_path = None,
|
|
dct = {'VERSION': VERSION})
|
|
|
|
# Doxyfile
|
|
bld(
|
|
features = 'subst',
|
|
source = 'doc/Doxyfile.in',
|
|
target = 'doc/Doxyfile',
|
|
install_path = None,
|
|
dct = {'VERSION': VERSION,
|
|
'top_builddir': bld.out_dir,
|
|
'top_srcdir': bld.top_dir,})
|
|
|
|
# disable build/install phase interleaving
|
|
bld.add_group()
|
|
|
|
###
|
|
# Install files
|
|
###
|
|
# Headers
|
|
bld.install_files('${PREFIX}/include/geany', '''
|
|
src/app.h
|
|
src/build.h
|
|
src/dialogs.h
|
|
src/document.h
|
|
src/editor.h
|
|
src/encodings.h
|
|
src/filetypes.h
|
|
src/geany.h
|
|
src/highlighting.h
|
|
src/keybindings.h
|
|
src/main.h
|
|
src/msgwindow.h
|
|
src/navqueue.h
|
|
src/plugindata.h
|
|
src/pluginutils.h
|
|
src/prefs.h
|
|
src/project.h
|
|
src/sciwrappers.h
|
|
src/search.h
|
|
src/stash.h
|
|
src/support.h
|
|
src/symbols.h
|
|
src/templates.h
|
|
src/toolbar.h
|
|
src/ui_utils.h
|
|
src/utils.h
|
|
src/gtkcompat.h
|
|
plugins/geanyplugin.h
|
|
plugins/geanyfunctions.h
|
|
''')
|
|
bld.install_files('${PREFIX}/include/geany/scintilla', '''
|
|
scintilla/include/SciLexer.h scintilla/include/Scintilla.h
|
|
scintilla/include/Scintilla.iface scintilla/include/ScintillaWidget.h ''')
|
|
bld.install_files('${PREFIX}/include/geany/tagmanager', '''
|
|
tagmanager/src/tm_source_file.h
|
|
tagmanager/src/tm_tag.h
|
|
tagmanager/src/tm_tagmanager.h
|
|
tagmanager/src/tm_workspace.h ''')
|
|
# Docs
|
|
base_dir = '${PREFIX}' if is_win32 else '${DOCDIR}'
|
|
ext = '.txt' if is_win32 else ''
|
|
for filename in 'AUTHORS ChangeLog COPYING README NEWS THANKS TODO'.split():
|
|
basename = _uc_first(filename, bld)
|
|
destination_filename = '%s%s' % (basename, ext)
|
|
destination = os.path.join(base_dir, destination_filename)
|
|
bld.install_as(destination, filename)
|
|
|
|
# install HTML documentation only if it exists, i.e. it was built before
|
|
# local_html_doc_filename supports installing HTML doc from in-tree geany.html if it exists
|
|
local_html_doc_filename = os.path.join(bld.path.abspath(), 'doc', 'geany.html')
|
|
if os.path.exists(html_doc_filename) or os.path.exists(local_html_doc_filename):
|
|
html_dir = '' if is_win32 else 'html/'
|
|
html_name = 'Manual.html' if is_win32 else 'index.html'
|
|
start_dir = bld.path.find_dir('doc/images')
|
|
bld.install_files('${DOCDIR}/%simages' % html_dir, start_dir.ant_glob('*.png'), cwd=start_dir)
|
|
bld.install_as('${DOCDIR}/%s%s' % (html_dir, html_name), 'doc/geany.html')
|
|
|
|
bld.install_as('${DOCDIR}/%s' % _uc_first('manual.txt', bld), 'doc/geany.txt')
|
|
bld.install_as('${DOCDIR}/ScintillaLicense.txt', 'scintilla/License.txt')
|
|
if is_win32:
|
|
bld.install_as('${DOCDIR}/ReadMe.I18n.txt', 'README.I18N')
|
|
bld.install_as('${DOCDIR}/Hacking.txt', 'HACKING')
|
|
# Data
|
|
data_dir = '' if is_win32 else 'geany'
|
|
start_dir = bld.path.find_dir('data')
|
|
bld.install_as('${DATADIR}/%s/GPL-2' % data_dir, 'COPYING')
|
|
bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('filetype*'), cwd=start_dir)
|
|
bld.install_files('${DATADIR}/%s' % data_dir, start_dir.ant_glob('*.tags'), cwd=start_dir)
|
|
bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.glade')
|
|
bld.install_files('${DATADIR}/%s' % data_dir, 'data/snippets.conf')
|
|
bld.install_files('${DATADIR}/%s' % data_dir, 'data/ui_toolbar.xml')
|
|
if bld.env['use_gtk3']:
|
|
bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.css')
|
|
else:
|
|
bld.install_files('${DATADIR}/%s' % data_dir, 'data/geany.gtkrc')
|
|
|
|
start_dir = bld.path.find_dir('data/colorschemes')
|
|
template_dest = '${DATADIR}/%s/colorschemes' % data_dir
|
|
bld.install_files(template_dest, start_dir.ant_glob('*'), cwd=start_dir)
|
|
start_dir = bld.path.find_dir('data/templates')
|
|
template_dest = '${DATADIR}/%s/templates' % data_dir
|
|
bld.install_files(template_dest, start_dir.ant_glob('**/*'), cwd=start_dir, relative_trick=True)
|
|
# Icons
|
|
for dest, srcs in geany_icons.items():
|
|
dest_dir = os.path.join('${PREFIX}/share/icons' if is_win32 else '${DATADIR}/icons', dest)
|
|
bld.install_files(dest_dir, srcs, cwd=bld.path.find_dir('icons'))
|
|
# install theme indexes on Windows
|
|
if is_win32:
|
|
for dest, srcs in geany_icons_indexes.items():
|
|
bld.install_files(os.path.join('${PREFIX}/share/icons', dest), srcs, cwd=bld.path.find_dir('icons'))
|
|
|
|
|
|
def distclean(ctx):
|
|
Scripting.distclean(ctx)
|
|
_remove_linguas_file()
|
|
|
|
|
|
def _remove_linguas_file():
|
|
# remove LINGUAS file as well
|
|
try:
|
|
os.unlink(LINGUAS_FILE)
|
|
except OSError:
|
|
pass
|
|
|
|
|
|
@feature('linguas')
|
|
@before_method('apply_intltool_po')
|
|
def write_linguas_file(self):
|
|
if os.path.exists(LINGUAS_FILE):
|
|
return
|
|
linguas = ''
|
|
if 'LINGUAS' in self.env:
|
|
files = self.env['LINGUAS']
|
|
for po_filename in files.split(' '):
|
|
if os.path.exists('po/%s.po' % po_filename):
|
|
linguas += '%s ' % po_filename
|
|
else:
|
|
files = os.listdir('%s/po' % self.path.abspath())
|
|
files.sort()
|
|
for filename in files:
|
|
if filename.endswith('.po'):
|
|
linguas += '%s ' % filename[:-3]
|
|
file_h = open(LINGUAS_FILE, 'w')
|
|
file_h.write('# This file is autogenerated. Do not edit.\n%s\n' % linguas)
|
|
file_h.close()
|
|
|
|
|
|
def _post_install(ctx):
|
|
is_win32 = _target_is_win32(ctx)
|
|
if is_win32:
|
|
return
|
|
for d in 'hicolor', 'Tango':
|
|
theme_dir = Utils.subst_vars('${DATADIR}/icons/' + d, ctx.env)
|
|
icon_cache_updated = False
|
|
if not ctx.options.destdir:
|
|
ctx.exec_command('gtk-update-icon-cache -q -f -t %s' % theme_dir)
|
|
Logs.pprint('GREEN', 'GTK icon cache updated.')
|
|
icon_cache_updated = True
|
|
if not icon_cache_updated:
|
|
Logs.pprint('YELLOW', 'Icon cache not updated. After install, run this:')
|
|
Logs.pprint('YELLOW', 'gtk-update-icon-cache -q -f -t %s' % theme_dir)
|
|
|
|
|
|
def updatepo(ctx):
|
|
"""update the message catalogs for internationalization"""
|
|
potfile = '%s.pot' % APPNAME
|
|
os.chdir('%s/po' % top)
|
|
try:
|
|
try:
|
|
old_size = os.stat(potfile).st_size
|
|
except OSError:
|
|
old_size = 0
|
|
ctx.exec_command('intltool-update --pot -g %s' % APPNAME)
|
|
size_new = os.stat(potfile).st_size
|
|
if size_new != old_size:
|
|
Logs.pprint('CYAN', 'Updated POT file.')
|
|
Logs.pprint('CYAN', 'Updating translations')
|
|
ret = ctx.exec_command('intltool-update -r -g %s' % APPNAME)
|
|
if ret != 0:
|
|
Logs.pprint('RED', 'Updating translations failed')
|
|
else:
|
|
Logs.pprint('CYAN', 'POT file is up to date.')
|
|
except OSError:
|
|
Logs.pprint('RED', 'Failed to generate pot file.')
|
|
|
|
|
|
def apidoc(ctx):
|
|
"""generate API reference documentation"""
|
|
ctx = BuildContext() # create our own context to have ctx.top_dir
|
|
basedir = ctx.top_dir
|
|
doxygen = _find_program(ctx, 'doxygen')
|
|
doxyfile = '%s/doc/Doxyfile' % ctx.out_dir
|
|
Logs.pprint('CYAN', 'Generating API documentation')
|
|
ret = ctx.exec_command('%s %s' % (doxygen, doxyfile))
|
|
if ret != 0:
|
|
raise WafError('Generating API documentation failed')
|
|
|
|
|
|
def hackingdoc(ctx):
|
|
"""generate HACKING documentation"""
|
|
ctx = BuildContext() # create our own context to have ctx.top_dir
|
|
Logs.pprint('CYAN', 'Generating HACKING documentation')
|
|
cmd = _find_rst2html(ctx)
|
|
hacking_file = os.path.join(ctx.top_dir, 'HACKING')
|
|
hacking_html_file = os.path.join(ctx.top_dir, 'doc', 'hacking.html')
|
|
stylesheet = os.path.join(ctx.top_dir, 'doc', 'geany.css')
|
|
ret = ctx.exec_command('%s -stg --stylesheet=%s %s %s' % (
|
|
cmd, stylesheet, hacking_file, hacking_html_file))
|
|
if ret != 0:
|
|
raise WafError('Generating HACKING documentation failed')
|
|
|
|
|
|
def _find_program(ctx, cmd, **kw):
|
|
def noop(*args):
|
|
pass
|
|
|
|
if ctx is None or not isinstance(ctx, ConfigurationContext):
|
|
ctx = ConfigurationContext()
|
|
ctx.to_log = noop
|
|
ctx.msg = noop
|
|
return ctx.find_program(cmd, **kw)
|
|
|
|
|
|
def _find_rst2html(ctx):
|
|
cmds = ['rst2html', 'rst2html2']
|
|
for command in cmds:
|
|
cmd = _find_program(ctx, command, mandatory=False, exts=',.py')
|
|
if cmd:
|
|
break
|
|
if not cmd:
|
|
raise WafError(
|
|
'rst2html.py could not be found. Please install the Python docutils package.')
|
|
return cmd
|
|
|
|
|
|
def _add_define_to_env(conf, key):
|
|
value = conf.get_define(key)
|
|
# strip quotes
|
|
value = value.replace('"', '')
|
|
conf.env[key] = value
|
|
|
|
|
|
def _add_to_env_and_define(conf, key, value, quote=False):
|
|
conf.define(key, value, quote)
|
|
conf.env[key] = value
|
|
|
|
|
|
def _define_from_opt(conf, define_name, opt_value, default_value, quote=1):
|
|
value = default_value
|
|
if opt_value:
|
|
if isinstance(opt_value, bool):
|
|
opt_value = 1
|
|
value = opt_value
|
|
|
|
if value is not None:
|
|
_add_to_env_and_define(conf, define_name, value, quote)
|
|
else:
|
|
conf.undefine(define_name)
|
|
|
|
|
|
def _get_git_rev(conf):
|
|
if conf.options.no_scm:
|
|
return
|
|
|
|
if not os.path.isdir('.git'):
|
|
return
|
|
|
|
try:
|
|
cmd = 'git rev-parse --short --revs-only HEAD'
|
|
revision = conf.cmd_and_log(cmd).strip()
|
|
except WafError:
|
|
return None
|
|
else:
|
|
return revision
|
|
|
|
|
|
def _load_intltool_if_available(conf):
|
|
try:
|
|
conf.load('intltool')
|
|
if 'LINGUAS' in os.environ:
|
|
conf.env['LINGUAS'] = os.environ['LINGUAS']
|
|
except WafError:
|
|
# on Windows, we don't hard depend on intltool, on all other platforms raise an error
|
|
if not _target_is_win32(conf):
|
|
raise
|
|
|
|
|
|
def _target_is_win32(ctx):
|
|
if 'is_win32' in ctx.env:
|
|
# cached
|
|
return ctx.env['is_win32']
|
|
is_win32 = None
|
|
if sys.platform == 'win32':
|
|
is_win32 = True
|
|
if is_win32 is None:
|
|
if ctx.env and 'CC' in ctx.env:
|
|
env_cc = ctx.env['CC']
|
|
if not isinstance(env_cc, str):
|
|
env_cc = ''.join(env_cc)
|
|
is_win32 = (env_cc.find('mingw') != -1)
|
|
if is_win32 is None:
|
|
is_win32 = False
|
|
# cache for future checks
|
|
ctx.env['is_win32'] = is_win32
|
|
return is_win32
|
|
|
|
|
|
def _uc_first(string, ctx):
|
|
if _target_is_win32(ctx):
|
|
return string.title()
|
|
return string
|