# scons asks for 1.5.2, lyx requires 2.3
EnsurePythonVersion(2, 3)
-# Please use at least 0.96.91 (not 0.96.1)
+# Please use at least 0.96.92 (not 0.96.1)
EnsureSConsVersion(0, 96)
+# also check for minor version number for scons 0.96
+from SCons import __version__
+version = map(int, __version__.split('.'))
+if version[0] == 0 and version[1] == 96 and version[2] < 92:
+ print "Scons >= 0.96.92 is required."
+ Exit(1)
# determine where I am ...
#
# only 1.4.x has frontends/qt2
if os.path.isdir(os.path.join(top_src_dir, 'src', 'frontends', 'qt2')):
package_version = '1.4.2svn'
+ boost_version = '1_32'
else:
package_version = '1.5.0svn'
+ boost_version = '1_33_1'
devel_version = True
default_build_mode = 'debug'
elif os.name == 'posix' and sys.platform == 'cygwin':
platform_name = 'cygwin'
default_frontend = 'qt3'
- default_prefix = '/usr/local'
+ default_prefix = '/usr'
default_with_x = True
default_packaging_method = 'posix'
elif os.name == 'darwin':
default_with_x = True
default_packaging_method = 'posix'
+# 1.4.2 only has qt2 frontend
+if package_version == '1.4.2svn':
+ default_frontend = 'qt2'
#---------------------------------------------------------
# Handling options
opts.AddOptions(
# frontend
EnumOption('frontend', 'Main GUI', default_frontend,
- allowed_values = ('xform', 'qt2', 'qt3', 'qt4', 'gtk') ),
+ allowed_values = ('qt2', 'qt3', 'qt4', 'gtk') ),
# debug or release build
EnumOption('mode', 'Building method', default_build_mode,
allowed_values = ('debug', 'release') ),
#
PathOption('qt_dir', 'Path to qt directory', None),
#
- PathOption('qt_include_path', 'Path to qt include directory', None),
+ PathOption('qt_inc_path', 'Path to qt include directory', None),
#
PathOption('qt_lib_path', 'Path to qt library directory', None),
- # build directory, will use $mode if not set
- PathOption('build_dir', 'Build directory', None),
# extra include and libpath
PathOption('extra_inc_path', 'Extra include path', None),
#
#
PathOption('extra_lib_path1', 'Extra library path', None),
# rebuild only specifed, comma separated targets
- ('rebuild', 'rebuild only specifed, comma separated targets', None),
+ ('rebuild', '''rebuild only specifed, comma separated targets.
+ yes or all (default): rebuild everything
+ no or none: rebuild nothing (usually used for installation)
+ comp1,comp2,...: rebuild specified targets''', None),
# can be set to a non-existing directory
('prefix', 'install architecture-independent files in PREFIX', default_prefix),
+ # build directory, will use $mode if not set
+ ('build_dir', 'Build directory', None),
# version suffix
('version_suffix', 'install lyx as lyx-suffix', None),
# how to load options
('LINKFLAGS', 'replace default $LINKFLAGS', None),
)
+# allowed options
+all_options = [x.key for x in opts.options]
+
# copied from SCons/Options/BoolOption.py
# We need to use them before a boolean ARGUMENTS option is available
# in env as bool.
print " ** fast_start is disabled because of the change of option", arg
print
fast_start = False
- # and we do not cache some options
- for arg in ['fast_start', 'load_option']:
+ # and we do not cache some options (dest_dir is obsolete)
+ for arg in ['fast_start', 'load_option', 'dest_dir']:
if opt_cache.has_key(arg):
opt_cache.pop(arg)
+ # remove obsolete cached keys (well, SConstruct is evolving. :-)
+ for arg in opt_cache.keys():
+ if arg not in all_options:
+ print 'Option %s is obsolete, do not load it' % arg
+ opt_cache.pop(arg)
# now, if load_option=opt1,opt2 or -opt1,opt2
if ARGUMENTS.has_key('load_option') and \
ARGUMENTS['load_option'] not in true_strings + false_strings:
print "Restoring cached option %s=%s" % (key, ARGUMENTS[key])
print
+# check if there is unused (or misspelled) argument
+for arg in ARGUMENTS.keys():
+ if arg not in all_options:
+ import textwrap
+ print "Unknown option '%s'... exiting." % arg
+ print
+ print "Available options are (check 'scons -help' for details):"
+ print ' ' + '\n '.join(textwrap.wrap(', '.join(all_options)))
+ Exit(1)
+
# save arguments
env_cache['arg_cache'] = ARGUMENTS
# to build multiple build_dirs using the same source
# $mode can be debug or release
if env.has_key('build_dir') and env['build_dir'] is not None:
+ # create the directory if needed
+ if not os.path.isdir(env['build_dir']):
+ try:
+ os.makedirs(env['build_dir'])
+ except:
+ pass
+ if not os.path.isdir(env['build_dir']):
+ print 'Can not create directory', env['build_dir']
+ Exit(3)
env['BUILDDIR'] = env['build_dir']
else:
# Determine the name of the build $mode
# PACKAGE_VERSION
# src/version.C.in
# PACKAGE_VERSION, VERSION_INFO
-# src/frontends/xforms/lyx_xpm.h.in
-# XPM_H_LOCATION
-# src/frontends/xforms/lyx_forms.h.in
-# FORMS_H_LOCATION
# full path name is used to build msvs project files
# and to replace TOP_SRCDIR in package.C
if env.has_key('qt_dir') and env['qt_dir']:
env['QTDIR'] = env['qt_dir']
+elif os.path.isdir(os.environ.get('QTDIR', '/usr/lib/qt-3.3')):
+ env['QTDIR'] = os.environ.get('QTDIR', '/usr/lib/qt-3.3')
+
+# if there is a valid QTDIR, set path for lib and bin directories
+if env.has_key('QTDIR'):
# add path to the qt tools
- env.AppendUnique(LIBPATH = [os.path.join(env['qt_dir'], 'lib')])
+ if os.path.isdir(os.path.join(env['QTDIR'], 'lib')):
+ env.AppendUnique(LIBPATH = [os.path.join(env['QTDIR'], 'lib')])
# set environment so that moc etc can be found even if its path is not set properly
- env.PrependENVPath('PATH', os.path.join(env['qt_dir'], 'bin'))
-else:
- env['QTDIR'] = os.environ.get('QTDIR', '/usr/lib/qt-3.3')
+ if os.path.isdir(os.path.join(env['QTDIR'], 'bin')):
+ os.environ['PATH'] += os.pathsep + os.path.join(env['QTDIR'], 'bin')
+ env.PrependENVPath('PATH', os.path.join(env['QTDIR'], 'bin'))
+# allow qt2 frontend to locate qt3 libs.
+frontend_lib = {'qt2':'qt3', 'qt3':'qt3', 'qt4':'qt4'}[frontend]
if env.has_key('qt_lib_path') and env['qt_lib_path']:
qt_lib_path = env.subst('$qt_lib_path')
-else:
+elif env.has_key('QTDIR') and os.path.isdir(os.path.join(env.subst('$QTDIR'), 'lib')):
qt_lib_path = env.subst('$QTDIR/lib')
+# this is the path for cygwin.
+elif os.path.isdir(os.path.join('/usr/lib/', frontend_lib, 'lib')):
+ qt_lib_path = '/usr/lib/%s/lib' % frontend_lib
+else:
+ print "Qt library directory is not found. Please specify it using qt_lib_path"
+ Exit(1)
env.AppendUnique(LIBPATH = [qt_lib_path])
# qt4 seems to be using pkg_config
env.PrependENVPath('PKG_CONFIG_PATH', qt_lib_path)
if env.has_key('qt_inc_path') and env['qt_inc_path']:
qt_inc_path = env['qt_inc_path']
-elif os.path.isdir(os.path.join(env.subst('$QTDIR'), 'include')):
+elif env.has_key('QTDIR') and os.path.isdir(os.path.join(env.subst('$QTDIR'), 'include')):
qt_inc_path = '$QTDIR/include'
# this is the path for cygwin.
-elif os.path.isdir('/usr/include/' + frontend):
- qt_inc_path = '/usr/include/$frontend'
+elif os.path.isdir('/usr/include/' + frontend_lib):
+ qt_inc_path = '/usr/include/' + frontend_lib
else:
print "Qt include directory not found. Please specify it using qt_inc_path"
Exit(1)
if env.has_key('extra_lib_path1') and env['extra_lib_path1']:
env.AppendUnique(LIBPATH = [env['extra_lib_path1']])
if env.has_key('extra_bin_path') and env['extra_bin_path']:
- # maybe only one of them is needed
+ # only the first one is needed (a scons bug?)
os.environ['PATH'] += os.pathsep + env['extra_bin_path']
- env['ENV']['PATH'] += os.pathsep + env['extra_bin_path']
+ env.PrependENVPath('PATH', env['extra_bin_path'])
# extra_inc_paths will be used later by intlenv etc
env.AppendUnique(CPPPATH = extra_inc_paths)
# check boost libraries
boost_opt = ARGUMENTS.get('boost', 'auto')
# check for system boost
- paths = env['LIBPATH'] + ['/usr/lib', '/usr/local/lib']
- # real libraries (included or system)
- boost_libraries = []
+ lib_paths = env['LIBPATH'] + ['/usr/lib', '/usr/local/lib']
+ inc_paths = env['CPPPATH'] + ['/usr/include', '/usr/local/include']
+ # default to $BUILDDIR/libs (use None since this path will be added anyway)
boost_libpath = None
# here I assume that all libraries are in the same directory
- for lib in boost_libs:
- if boost_opt == 'included':
- boost_libraries.append('included_boost_%s' % lib)
- env['INCLUDED_BOOST'] = True
- elif boost_opt == 'auto':
- res = conf.CheckBoostLibraries('boost_%s' % lib , paths)
- # if not found
- if res[0] == '':
- boost_libraries.append('included_boost_%s' % lib)
- env['INCLUDED_BOOST'] = True
- else:
- boost_libraries.append(res[1])
- env['INCLUDED_BOOST'] = False
- boost_libpath = res[0]
- elif boost_opt == 'system':
- res = conf.CheckBoostLibraries('boost_%s' % lib , paths)
- if res[0] == '':
- print "Can not find system boost libraries"
- print "Please supply a path through extra_lib_path and try again."
- print "Or use boost=included to use included boost libraries."
- Exit(2)
- else:
- boost_libraries.append(res[1])
- env.AppendUnique(LIBPATH = [res[0]])
- boost_libpath = res[0]
+ if boost_opt == 'included':
+ boost_libraries = ['included_boost_%s' % x for x in boost_libs]
+ included_boost = True
+ env['BOOST_INC_PATH'] = '$TOP_SRCDIR/boost'
+ elif boost_opt == 'auto':
+ res = conf.CheckBoostLibraries(boost_libs, lib_paths, inc_paths, boost_version, mode == 'debug')
+ # if not found, use local boost
+ if res[0] is None:
+ boost_libraries = ['included_boost_%s' % x for x in boost_libs]
+ included_boost = True
+ env['BOOST_INC_PATH'] = '$TOP_SRCDIR/boost'
+ else:
+ included_boost = False
+ (boost_libraries, boost_libpath, env['BOOST_INC_PATH']) = res
+ elif boost_opt == 'system':
+ res = conf.CheckBoostLibraries(boost_libs, lib_paths, inc_paths, boost_version, mode == 'debug')
+ if res[0] is None:
+ print "Can not find system boost libraries with version %s " % boost_version
+ print "Please supply a path through extra_lib_path and try again."
+ print "Or use boost=included to use included boost libraries."
+ Exit(2)
+ else:
+ included_boost = False
+ (boost_libraries, boost_libpath, env['BOOST_INC_PATH']) = res
env_cache['BOOST_LIBRARIES'] = boost_libraries
- env_cache['INCLUDED_BOOST'] = env['INCLUDED_BOOST']
+ env_cache['INCLUDED_BOOST'] = included_boost
+ env_cache['BOOST_INC_PATH'] = env['BOOST_INC_PATH']
env_cache['BOOST_LIBPATH'] = boost_libpath
else:
boost_libraries = env_cache['BOOST_LIBRARIES']
- env['INCLUDED_BOOST'] = env_cache['INCLUDED_BOOST']
+ included_boost = env_cache['INCLUDED_BOOST']
+ env['BOOST_INC_PATH'] = env_cache['BOOST_INC_PATH']
boost_libpath = env_cache['BOOST_LIBPATH']
if boost_libpath is not None:
else:
env['MSGFMT'] = env_cache['MSGFMT']
+# check uic and moc commands for qt frontends
+if not fast_start:
+ if frontend[:2] == 'qt' and (conf.CheckCommand('uic') == None \
+ or conf.CheckCommand('moc') == None):
+ print 'uic or moc command is not found for frontend', frontend
+ Exit(1)
+
#
# Customized builders
#
#
# NOTE: Tool('qt') or Tool('qt4') will be loaded later
# in their respective directory and specialized env.
-try:
- if frontend in ['qt2', 'qt3']:
- # note: env.Tool('qt') my set QT_LIB to qt
- qt_libs = ['qt-mt']
- frontend_libs = ['qt-mt']
- elif frontend == 'qt4':
- qt_libs = ['QtCore', 'QtGui']
- # set the right lib names
- if platform_name == 'win32':
- if mode == 'debug' and use_vc:
- qt_lib_suffix = 'd4'
- else:
- qt_lib_suffix = '4'
+if frontend in ['qt2', 'qt3']:
+ # note: env.Tool('qt') my set QT_LIB to qt
+ qt_libs = ['qt-mt']
+ frontend_libs = ['qt-mt']
+elif frontend == 'qt4':
+ qt_libs = ['QtCore', 'QtGui']
+ # set the right lib names
+ if platform_name == 'win32':
+ if mode == 'debug' and use_vc:
+ qt_lib_suffix = 'd4'
+ else:
+ qt_lib_suffix = '4'
+ else:
+ if mode == 'debug':
+ qt_lib_suffix = '_debug'
else:
- if mode == 'debug':
- qt_lib_suffix = '_debug'
- else:
- qt_lib_suffix = ''
- frontend_libs = [x + qt_lib_suffix for x in qt_libs]
-except:
- print "Can not locate qt tools"
- print "What I get is "
- print " QTDIR: ", env['QTDIR']
+ qt_lib_suffix = ''
+ frontend_libs = [x + qt_lib_suffix for x in qt_libs]
if platform_name in ['win32', 'cygwin']:
# BUILDDIR/common: for config.h
# TOP_SRCDIR/src: for support/* etc
#
-env['CPPPATH'] += ['$TOP_SRCDIR/boost', '$BUILDDIR/common', '$TOP_SRCDIR/src']
+env['CPPPATH'] += ['$BUILDDIR/common', '$TOP_SRCDIR/src']
+#
+# Separating boost directories from CPPPATH stops scons from building
+# the dependency tree for boost header files, and effectively reduce
+# the null build time of lyx from 29s to 16s. Since lyx may tweak local
+# boost headers, this is only done for system boost headers.
+if included_boost:
+ env.AppendUnique(CPPPATH = ['$BOOST_INC_PATH'])
+else:
+ if use_vc:
+ env.PrependUnique(CCFLAGS = ['/I$BOOST_INC_PATH'])
+ else:
+ env.PrependUnique(CCFLAGS = ['-I$BOOST_INC_PATH'])
+
# for intl/config.h, intl/libintl.h and intl/libgnuintl.h
if env['nls'] and included_gettext:
env['CPPPATH'].append('$BUILDDIR/intl')
if env.has_key('rebuild'):
rebuild_targets = env['rebuild'].split(',')
+ if 'none' in rebuild_targets or 'no' in rebuild_targets:
+ rebuild_targets = []
+ elif 'all' in rebuild_targets or 'yes' in rebuild_targets:
+ # None: let scons decide which components to build
+ # Forcing all components to be rebuilt is in theory not necessary
+ rebuild_targets = None
else:
rebuild_targets = None
''' Check whether or not lib $LOCALLIBNAME/libname already exists'''
return os.path.isfile(File(env.subst('$LOCALLIBPATH/${LIBPREFIX}%s$LIBSUFFIX'%libname)).abspath)
+def appExists(apppath, appname):
+ ''' Check whether or not application already exists'''
+ return os.path.isfile(File(env.subst('$BUILDDIR/common/%s/${PROGPREFIX}%s$PROGSUFFIX' % (apppath, appname))).abspath)
+
targets = BUILD_TARGETS
# msvc need to pass full target name, so I have to look for path/lyx etc
build_lyx = targets == [] or True in ['lyx' in x for x in targets] \
or 'install' in targets or 'all' in targets
-build_boost = (env['INCLUDED_BOOST'] and not libExists('boost_regex')) or 'boost' in targets
+build_boost = (included_boost and not libExists('boost_regex')) or 'boost' in targets
build_intl = (included_gettext and not libExists('included_intl')) or 'intl' in targets
build_support = build_lyx or True in [x in targets for x in ['support', 'client', 'tex2lyx']]
build_mathed = build_lyx or 'mathed' in targets
# now, if rebuild_targets is specified, do not rebuild some targets
-rebuild_targets = rebuild_targets
-if rebuild_targets:
+if rebuild_targets is not None:
+ #
def ifBuildLib(name, libname, old_value):
# explicitly asked to rebuild
if name in rebuild_targets:
build_qt2 = ifBuildLib('qt2', 'qt2', build_qt2)
build_qt3 = ifBuildLib('qt3', 'qt3', build_qt3)
build_qt4 = ifBuildLib('qt4', 'qt4', build_qt4)
+ #
+ def ifBuildApp(name, appname, old_value):
+ # explicitly asked to rebuild
+ if name in rebuild_targets:
+ return True
+ # else if not rebuild, and if the library already exists
+ elif appExists(name, appname):
+ return False
+ # do not change the original value
+ else:
+ return old_value
+ build_tex2lyx = ifBuildApp('tex2lyx', 'tex2lyx', build_tex2lyx)
+ build_client = ifBuildApp('client', 'lyxclient', build_client)
# sync frontend and frontend (maybe build qt4 with frontend=qt3)
if build_qt2:
'-DQT_GENUINE_STR',
'-DQT_NO_STL',
'-DQT3_SUPPORT',
+ '-DQT_NO_KEYWORDS',
]
)
else:
client = None
Alias('client', client)
+else:
+ if env['HAVE_FCNTL']:
+ # define client even if lyxclient is not built with rebuild=no
+ client = [env.subst('$BUILDDIR/common/client/${PROGPREFIX}lyxclient$PROGSUFFIX')]
+ else:
+ client = None
if build_tex2lyx:
Alias('tex2lyx', env.Command(os.path.join('$BUILDDIR', os.path.split(str(tex2lyx[0]))[1]),
tex2lyx, [Copy('$TARGET', '$SOURCE')]))
Alias('tex2lyx', tex2lyx)
+else:
+ # define tex2lyx even if tex2lyx is not built with rebuild=no
+ tex2lyx = [env.subst('$BUILDDIR/common/tex2lyx/${PROGPREFIX}tex2lyx$PROGSUFFIX')]
if build_lyxbase:
Alias('lyx', env.Command(os.path.join('$BUILDDIR', target_name), lyx,
[Copy('$TARGET', '$SOURCE')]))
Alias('lyx', lyx)
+else:
+ # define lyx even if lyx is not built with rebuild=no
+ lyx = [env.subst('$BUILDDIR/$frontend/${PROGPREFIX}lyx$PROGSUFFIX')]
if build_msvs_projects:
else:
res = []
if rebuildTargetOnly:
- cmds = 'faststart=yes rebuild='+target
+ cmds = 'fast_start=yes rebuild='+target
else:
- cmds = 'faststart=yes'
+ cmds = 'fast_start=yes'
if type(dir) == type([]):
src = []
inc = []
if env.has_key('languages'):
languages = env.make_list(env['lanauges'])
# use defulat msgfmt
+ gmo_files = []
if not env['MSGFMT']:
print 'msgfmt does not exist. Can not process po files'
else:
# create a builder
env['BUILDERS']['Transfiles'] = Builder(action='$MSGFMT $SOURCE -o $TARGET',suffix='.gmo',src_suffix='.po')
#
- gmo_files = []
for f in transfiles:
# get filename
fname = os.path.split(f)[1]
if 'install' in targets:
#
- # install to DESTDIR or prefix
- dest_dir = env.Dir(env.get('DESTDIR', prefix)).abspath
- # if dest_dir is different from prefix.
- if env.has_key('exec_prefix'):
- bin_dest_dir = Dir(env['exec_prefix']).abspath
- else:
- bin_dest_dir = os.path.join(dest_dir, 'bin')
- if add_suffix:
- share_dest_dir = os.path.join(dest_dir, share_dir + program_suffix)
- else:
- share_dest_dir = os.path.join(dest_dir, share_dir)
- man_dest_dir = os.path.join(dest_dir, man_dir)
- locale_dest_dir = os.path.join(dest_dir, locale_dir)
+ # this part is a bit messy right now. Since scons will provide
+ # --DESTDIR option soon, at least the dest_dir handling can be
+ # removed later.
+ #
+ # how to join dest_dir and prefix
+ def joinPaths(path1, path2):
+ ''' join path1 and path2, do not use os.path.join because
+ under window, c:\destdir\d:\program is invalid '''
+ if path1 is None:
+ return os.path.normpath(path2)
+ # separate drive letter
+ (drive, path) = os.path.splitdrive(os.path.normpath(path2))
+ # ignore drive letter, so c:\destdir + c:\program = c:\destdir\program
+ return os.path.join(os.path.normpath(path1), path[1:])
+ #
+ # install to dest_dir/prefix
+ dest_dir = env.get('DESTDIR', None)
+ dest_prefix_dir = joinPaths(dest_dir, env.Dir(prefix).abspath)
# create the directory if needed
- if not os.path.isdir(dest_dir):
+ if not os.path.isdir(dest_prefix_dir):
try:
- os.makedirs(dest_dir)
+ os.makedirs(dest_prefix_dir)
except:
pass
- if not os.path.isdir(dest_dir):
- print 'Can not create directory', dest_dir
+ if not os.path.isdir(dest_prefix_dir):
+ print 'Can not create directory', dest_prefix_dir
Exit(3)
#
+ if env.has_key('exec_prefix'):
+ bin_dest_dir = joinPaths(dest_dir, Dir(env['exec_prefix']).abspath)
+ else:
+ bin_dest_dir = os.path.join(dest_prefix_dir, 'bin')
+ if add_suffix:
+ share_dest_dir = os.path.join(dest_prefix_dir, share_dir + program_suffix)
+ else:
+ share_dest_dir = os.path.join(dest_prefix_dir, share_dir)
+ man_dest_dir = os.path.join(dest_prefix_dir, man_dir)
+ locale_dest_dir = os.path.join(dest_prefix_dir, locale_dir)
+ #
import glob
#
# do not install these files
exclude_list = ['Makefile.am', 'Makefile.in', 'Makefile',
- 'lyx2lyx_version.py', 'lyx2lyx_version.py.in']
+ 'lyx2lyx_version.py.in']
def install(dest, src):
''' recusive installation of src to dest '''
glob.glob(os.path.join(dir, '*'))) )
return ins_dir
#
- # executables (some of them may be none)
+ # install executables (lyxclient may be None)
#
if add_suffix:
version_suffix = program_suffix
'lyxrc.example', 'syntax.default', 'bind', 'images', 'layouts', 'scripts',
'templates', 'examples', 'kbd', 'lyx2lyx', 'tex', 'clipart', 'doc', 'ui']]
)
- env.substFile(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py',
- '$TOP_SRCDIR/lib/lyx2lyx/lyx2lyx_version.py.in')
+ # lyx1.4.x does not have lyx2lyx_version.py.in
+ if os.path.isfile(env.subst('$TOP_SRCDIR/lib/lyx2lyx/lyx2lyx_version.py.in')):
+ # subst and install this file
+ env.substFile(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py',
+ '$TOP_SRCDIR/lib/lyx2lyx/lyx2lyx_version.py.in')
+ Alias('install', share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
Alias('install', dirs)
# man
env.InstallAs(os.path.join(man_dest_dir, 'lyx' + version_suffix + '.1'),