1 # vi:filetype=python:expandtab:tabstop=4:shiftwidth=4
5 # This file is part of LyX, the document processor.
6 # Licence details can be found in the file COPYING.
9 # Full author contact details are available in file CREDITS.
11 # This is a scons based building system for lyx, please refer
12 # to INSTALL.scons for detailed instructions.
15 import os, sys, copy, cPickle, glob
17 # scons_utils.py defines a few utility function
18 sys.path.append('config')
19 import scons_utils as utils
20 # import all file lists
21 from scons_manifest import *
23 #----------------------------------------------------------
24 # Required runtime environment
25 #----------------------------------------------------------
27 # scons asks for 1.5.2, lyx requires 2.3
28 EnsurePythonVersion(2, 3)
29 # Please use at least 0.96.92 (not 0.96.1)
30 EnsureSConsVersion(0, 96)
31 # also check for minor version number for scons 0.96
32 from SCons import __version__
33 version = map(int, __version__.split('.'))
34 if version[0] == 0 and version[1] == 96 and version[2] < 92:
35 print "Scons >= 0.96.92 is required."
38 # determine where I am ...
40 # called as 'cd development/scons; scons'
41 if os.path.isfile('SConstruct'):
44 # called as 'scons -f development/scons/SConstruct'
47 scons_dir = 'development/scons'
50 #----------------------------------------------------------
52 #----------------------------------------------------------
54 # some global settings
56 package_version = '1.5.0svn'
57 boost_version = '1_33_1'
60 default_build_mode = 'debug'
63 package_bugreport = 'lyx-devel@lists.lyx.org'
65 package_tarname = 'lyx'
66 package_string = '%s %s' % (package_name, package_version)
68 # various cache/log files
69 default_log_file = 'scons_lyx.log'
70 env_cache_file = 'env.cache'
73 #----------------------------------------------------------
74 # platform dependent settings
75 #----------------------------------------------------------
78 platform_name = 'win32'
79 default_frontend = 'qt4'
80 default_prefix = 'c:/program files/lyx'
81 default_with_x = False
82 default_packaging_method = 'windows'
83 elif os.name == 'posix' and sys.platform != 'cygwin':
84 platform_name = sys.platform
85 default_frontend = 'qt3'
86 default_prefix = '/usr/local'
88 default_packaging_method = 'posix'
89 elif os.name == 'posix' and sys.platform == 'cygwin':
90 platform_name = 'cygwin'
91 default_frontend = 'qt3'
92 default_prefix = '/usr'
94 default_packaging_method = 'posix'
95 elif os.name == 'darwin':
96 platform_name = 'macosx'
97 default_frontend = 'qt3'
98 # FIXME: macOSX default prefix?
100 default_with_x = False
101 default_packaging_method = 'macosx'
102 else: # unsupported system, assume posix behavior
103 platform_name = 'others'
104 default_frontend = 'qt3'
106 default_with_x = True
107 default_packaging_method = 'posix'
109 #---------------------------------------------------------
111 #----------------------------------------------------------
113 # You can set perminant default values in config.py
114 if os.path.isfile('config.py'):
115 print "Getting options from config.py..."
116 print open('config.py').read()
118 opts = Options(['config.py'])
121 EnumOption('frontend', 'Main GUI', default_frontend,
122 allowed_values = ('qt3', 'qt4', 'gtk') ),
123 # debug or release build
124 EnumOption('mode', 'Building method', default_build_mode,
125 allowed_values = ('debug', 'release') ),
128 'Use included, system boost library, or try sytem boost first.',
129 'auto', allowed_values = (
130 'auto', # detect boost, if not found, use included
131 'included', # always use included boost
132 'system', # always use system boost, fail if can not find
135 EnumOption('gettext',
136 'Use included, system gettext library, or try sytem gettext first',
137 'auto', allowed_values = (
138 'auto', # detect gettext, if not found, use included
139 'included', # always use included gettext
140 'system', # always use system gettext, fail if can not find
143 EnumOption('spell', 'Choose spell checker to use.', 'auto',
144 allowed_values = ('aspell', 'pspell', 'ispell', 'auto', 'no') ),
146 EnumOption('packaging', 'Packaging method to use.', default_packaging_method,
147 allowed_values = ('windows', 'posix', 'macosx')),
149 BoolOption('fast_start', 'Whether or not use cached tests and keep current config.h', True),
150 # No precompiled header support (too troublesome to make it work for msvc)
151 # BoolOption('pch', 'Whether or not use pch', False),
152 # enable assertion, (config.h has ENABLE_ASSERTIOS
153 BoolOption('assertions', 'Use assertions', True),
154 # enable warning, (config.h has WITH_WARNINGS)
155 # default to False since MSVC does not have #warning
156 BoolOption('warnings', 'Use warnings', False),
157 # config.h define _GLIBCXX_CONCEPT_CHECKS
158 # Note: for earlier version of gcc (3.3) define _GLIBCPP_CONCEPT_CHECKS
159 BoolOption('concept_checks', 'Enable concept checks', True),
161 BoolOption('nls', 'Whether or not use native language support', True),
163 BoolOption('profiling', 'Whether or not enable profiling', False),
164 # config.h define _GLIBCXX_DEBUG and _GLIBCXX_DEBUG_PEDANTIC
165 BoolOption('stdlib_debug', 'Whether or not turn on stdlib debug', False),
167 BoolOption('X11', 'Use x11 windows system', default_with_x),
168 # use MS VC++ to build lyx
169 BoolOption('use_vc', 'Use MS VC++ to build lyx (cl.exe will be probed)', None),
171 PathOption('qt_dir', 'Path to qt directory', None),
173 PathOption('qt_inc_path', 'Path to qt include directory', None),
175 PathOption('qt_lib_path', 'Path to qt library directory', None),
176 # extra include and libpath
177 PathOption('extra_inc_path', 'Extra include path', None),
179 PathOption('extra_lib_path', 'Extra library path', None),
181 PathOption('extra_bin_path', 'A convenient way to add a path to $PATH', None),
183 PathOption('extra_inc_path1', 'Extra include path', None),
185 PathOption('extra_lib_path1', 'Extra library path', None),
186 # rebuild only specifed, comma separated targets
187 ('rebuild', '''rebuild only specifed, comma separated targets.
188 yes or all (default): rebuild everything
189 no or none: rebuild nothing (usually used for installation)
190 comp1,comp2,...: rebuild specified targets''', None),
191 # can be set to a non-existing directory
192 ('prefix', 'install architecture-independent files in PREFIX', default_prefix),
193 # build directory, will use $mode if not set
194 ('build_dir', 'Build directory', None),
196 ('version_suffix', 'install lyx as lyx-suffix', None),
197 # how to load options
198 ('load_option', '''load option from previous scons run. option can be
199 yes (default): load all options
200 no: do not load any option
201 opt1,opt2: load specified options
202 -opt1,opt2: load all options other than specified ones''', 'yes'),
204 ('optimization', 'optimization CCFLAGS option.', None),
206 PathOption('exec_prefix', 'install architecture-independent executable files in PREFIX', None),
208 ('logfile', 'save commands (not outputs) to logfile', default_log_file),
209 # provided for backward compatibility
210 ('dest_dir', 'install to DESTDIR. (Provided for backward compatibility only)', None),
211 # environment variable can be set as options.
212 ('DESTDIR', 'install to DESTDIR', None),
213 ('CC', 'replace default $CC', None),
214 ('LINK', 'replace default $LINK', None),
215 ('CPP', 'replace default $CPP', None),
216 ('CXX', 'replace default $CXX', None),
217 ('CXXCPP', 'replace default $CXXCPP', None),
218 ('CCFLAGS', 'replace default $CCFLAGS', None),
219 ('CPPFLAGS', 'replace default $CPPFLAGS', None),
220 ('LINKFLAGS', 'replace default $LINKFLAGS', None),
224 all_options = [x.key for x in opts.options]
226 # copied from SCons/Options/BoolOption.py
227 # We need to use them before a boolean ARGUMENTS option is available
229 true_strings = ('y', 'yes', 'true', 't', '1', 'on' , 'all' )
230 false_strings = ('n', 'no', 'false', 'f', '0', 'off', 'none')
232 # whether or not use current config.h, and cached tests
234 # if fast_start=yes (default), load variables from env_cache_file
235 if (not ARGUMENTS.has_key('fast_start') or \
236 ARGUMENTS['fast_start'] in true_strings) \
237 and os.path.isfile(env_cache_file):
239 cache_file = open(env_cache_file)
240 env_cache = cPickle.load(cache_file)
242 print '------------ fast_start mode --------------------'
243 print ' Use cached test results and current config.h'
244 print ' use fast_start=no to override'
250 # if load_option=yes (default), load saved comand line options
252 # This option can take value yes/no/opt1,opt2/-opt1,opt2
253 # and tries to be clever in choosing options to load
254 if (not ARGUMENTS.has_key('load_option') or \
255 ARGUMENTS['load_option'] not in false_strings) \
256 and os.path.isfile(env_cache_file):
257 cache_file = open(env_cache_file)
258 opt_cache = cPickle.load(cache_file)['arg_cache']
260 # import cached options, but we should ignore qt_dir when frontend changes
261 if ARGUMENTS.has_key('frontend') and opt_cache.has_key('frontend') \
262 and ARGUMENTS['frontend'] != opt_cache['frontend'] \
263 and opt_cache.has_key('qt_dir'):
264 opt_cache.pop('qt_dir')
265 # some options will require full rebuild
266 # these are in general things that will change config.h
267 for arg in ['version_suffix', 'nls', 'boost', 'spell']:
268 if ARGUMENTS.has_key(arg) and ((not opt_cache.has_key(arg)) or \
269 ARGUMENTS[arg] != opt_cache[arg]):
271 print " ** fast_start is disabled because of the change of option", arg
274 # and we do not cache some options (dest_dir is obsolete)
275 for arg in ['fast_start', 'load_option', 'dest_dir']:
276 if opt_cache.has_key(arg):
278 # remove obsolete cached keys (well, SConstruct is evolving. :-)
279 for arg in opt_cache.keys():
280 if arg not in all_options:
281 print 'Option %s is obsolete, do not load it' % arg
283 # now, if load_option=opt1,opt2 or -opt1,opt2
284 if ARGUMENTS.has_key('load_option') and \
285 ARGUMENTS['load_option'] not in true_strings + false_strings:
286 # if -opt1,opt2 is specified, do not load these options
287 if ARGUMENTS['load_option'][0] == '-':
288 for arg in ARGUMENTS['load_option'][1:].split(','):
289 if opt_cache.has_key(arg):
291 # if opt1,opt2 is specified, only load specified options
293 args = ARGUMENTS['load_option'].split(',')
294 for arg in opt_cache.keys():
297 # now restore options as if entered from command line
298 for key in opt_cache.keys():
299 if not ARGUMENTS.has_key(key):
300 ARGUMENTS[key] = opt_cache[key]
301 print "Restoring cached option %s=%s" % (key, ARGUMENTS[key])
304 # check if there is unused (or misspelled) argument
305 for arg in ARGUMENTS.keys():
306 if arg not in all_options:
308 print "Unknown option '%s'... exiting." % arg
310 print "Available options are (check 'scons -help' for details):"
311 print ' ' + '\n '.join(textwrap.wrap(', '.join(all_options)))
315 env_cache['arg_cache'] = ARGUMENTS
318 #---------------------------------------------------------
319 # Setting up environment
320 #---------------------------------------------------------
322 # I do not really like ENV=os.environ, but you may add it
323 # here if you experience some environment related problem
324 env = Environment(options = opts)
326 # set individual variables since I do not really like ENV = os.environ
327 env['ENV']['PATH'] = os.environ.get('PATH')
328 env['ENV']['HOME'] = os.environ.get('HOME')
329 # these are defined for MSVC
330 env['ENV']['LIB'] = os.environ.get('LIB')
331 env['ENV']['INCLUDE'] = os.environ.get('INCLUDE')
333 # for simplicity, use var instead of env[var]
334 frontend = env['frontend']
335 prefix = env['prefix']
338 if platform_name == 'win32':
339 if env.has_key('use_vc'):
340 use_vc = env['use_vc']
341 if WhereIs('cl.exe') is None:
342 print "cl.exe is not found. Are you using the MSVC environment?"
344 elif WhereIs('cl.exe') is not None:
351 # lyx will be built to $build/build_dir so it is possible
352 # to build multiple build_dirs using the same source
353 # $mode can be debug or release
354 if env.has_key('build_dir') and env['build_dir'] is not None:
355 # create the directory if needed
356 if not os.path.isdir(env['build_dir']):
358 os.makedirs(env['build_dir'])
361 if not os.path.isdir(env['build_dir']):
362 print 'Can not create directory', env['build_dir']
364 env['BUILDDIR'] = env['build_dir']
366 # Determine the name of the build $mode
367 env['BUILDDIR'] = '#' + mode
369 # all built libraries will go to build_dir/libs
370 # (This is different from the make file approach)
371 env['LOCALLIBPATH'] = '$BUILDDIR/libs'
372 env.AppendUnique(LIBPATH = ['$LOCALLIBPATH'])
375 # Here is a summary of variables defined in env
377 # 2. undefined options with a non-None default value
378 # 3. compiler commands and flags like CCFLAGS.
379 # MSGFMT used to process po files
380 # 4. Variables that will be used to replace variables in some_file.in
381 # src/support/package.C.in:
382 # TOP_SRCDIR, LOCALEDIR, LYX_DIR, PROGRAM_SUFFIX
383 # lib/lyx2lyx/lyx2lyx_version.py.in
386 # PACKAGE_VERSION, VERSION_INFO
388 # full path name is used to build msvs project files
389 # and to replace TOP_SRCDIR in package.C
390 env['TOP_SRCDIR'] = Dir(top_src_dir).abspath
391 # needed by src/version.C.in => src/version.C
392 env['PACKAGE_VERSION'] = package_version
394 # determine share_dir etc
395 packaging_method = env.get('packaging')
396 if packaging_method == 'windows':
397 share_dir = 'Resources'
398 man_dir = 'Resources/man/man1'
399 locale_dir = 'Resources/locale'
400 default_prefix = 'c:/program files/lyx'
402 share_dir = 'share/lyx'
404 locale_dir = 'share/locale'
405 default_prefix = '/usr/local/'
407 # install to default_prefix by default
408 # program suffix: can be yes, or a string
409 if env.has_key('version_suffix'):
410 if env['version_suffix'] in true_strings:
411 program_suffix = package_version
412 elif env['version_suffix'] in false_strings:
415 program_suffix = env['version_suffix']
418 # used by package.C.in
419 env['PROGRAM_SUFFIX'] = program_suffix
421 # whether or not add suffix to file and directory names
422 add_suffix = packaging_method != 'windows'
423 # LYX_DIR are different (used in package.C.in)
425 env['LYX_DIR'] = Dir(os.path.join(prefix, share_dir + program_suffix)).abspath
427 env['LYX_DIR'] = Dir(os.path.join(prefix, share_dir)).abspath
428 # we need absolute path for package.C
429 env['LOCALEDIR'] = Dir(os.path.join(prefix, locale_dir)).abspath
432 #---------------------------------------------------------
433 # Setting building environment (Tools, compiler flags etc)
434 #---------------------------------------------------------
436 # Since Tool('mingw') will reset CCFLAGS etc, this should be
437 # done before getEnvVariable
438 if platform_name == 'win32':
444 env.AppendUnique(CPPPATH = ['#c:/MinGW/include'])
446 # we differentiate between hard-coded options and default options
447 # hard-coded options are required and will always be there
448 # default options can be replaced by enviromental variables or command line options
449 CCFLAGS_required = []
450 LINKFLAGS_required = []
453 # under windows, scons is confused by .C/.c and uses gcc instead of
454 # g++. I am forcing the use of g++ here. This is expected to change
455 # after lyx renames all .C files to .cpp
457 # save the old c compiler and CCFLAGS (used by libintl)
458 C_COMPILER = env.subst('$CC')
459 C_CCFLAGS = env.subst('$CCFLAGS').split()
460 # if we use ms vc, the commands are fine (cl.exe and link.exe)
462 # /TP treat all source code as C++
463 # C4819: The file contains a character that cannot be represented
464 # in the current code page (number)
465 # C4996: foo was decleared deprecated
466 CCFLAGS_required.extend(['/TP', '/EHsc'])
467 CCFLAGS_default.extend(['/wd4819', '/wd4996', '/nologo'])
469 if env.has_key('CXX') and env['CXX']:
470 env['CC'] = env.subst('$CXX')
471 env['LINK'] = env.subst('$CXX')
476 # for debug/release mode
477 if env.has_key('optimization') and env['optimization'] is not None:
478 # if user supplies optimization flags, use it anyway
479 CCFLAGS_required.extend(env['optimization'].split())
480 # and do not use default
481 set_default_optimization_flags = False
483 set_default_optimization_flags = True
487 CCFLAGS_required.append('/Zi')
488 LINKFLAGS_required.extend(['/debug', '/map'])
490 CCFLAGS_required.append('-g')
491 CCFLAGS_default.append('-O')
492 elif mode == 'release' and set_default_optimization_flags:
494 CCFLAGS_default.append('/O2')
496 CCFLAGS_default.append('-O2')
498 # msvc uses separate tools for profiling
499 if env.has_key('profiling') and env['profiling']:
501 print 'Visual C++ does not use profiling options'
503 CCFLAGS_required.append('-pg')
504 LINKFLAGS_required.append('-pg')
506 if env.has_key('warnings') and env['warnings']:
508 CCFLAGS_default.append('/W2')
510 # Note: autotools detect gxx version and pass -W for 3.x
511 # and -Wextra for other versions of gcc
512 CCFLAGS_default.append('-Wall')
514 # Now, set the variables as follows:
515 # 1. if command line option exists: replace default
516 # 2. then if s envronment variable exists: replace default
517 # 3. set variable to required + default
518 def setEnvVariable(env, name, required = None, default = None, split = True):
519 ''' env: environment to set variable
521 required: hardcoded options
522 default: default options that can be replaced by command line or
523 environment variables
524 split: whether or not split obtained variable like '-02 -g'
526 # first try command line argument (override environment settings)
527 if ARGUMENTS.has_key(name):
528 default = ARGUMENTS[name]
530 default = default.split()
531 # then use environment default
532 elif os.environ.has_key(name):
533 print "Acquiring varaible %s from system environment: %s" % (name, os.environ[name])
534 default = os.environ[name]
536 default = default.split()
538 if required is not None:
540 if default is not None:
541 if env.has_key(name) and env[name] != default:
546 setEnvVariable(env, 'DESTDIR', split=False)
547 setEnvVariable(env, 'CC')
548 setEnvVariable(env, 'LINK')
549 setEnvVariable(env, 'CPP')
550 setEnvVariable(env, 'CXX')
551 setEnvVariable(env, 'CXXCPP')
552 setEnvVariable(env, 'CCFLAGS', CCFLAGS_required, CCFLAGS_default)
553 setEnvVariable(env, 'CXXFLAGS')
554 setEnvVariable(env, 'CPPFLAGS')
555 setEnvVariable(env, 'LINKFLAGS', LINKFLAGS_required)
557 # if DESTDIR is not set...
558 if env.has_key('dest_dir'):
559 print "This option is obsolete. Please use DESTDIR instead."
560 env['DESTDIR'] = env['dest_dir']
563 #---------------------------------------------------------
564 # Frontend related variables (QTDIR etc)
565 #---------------------------------------------------------
567 if env.has_key('qt_dir') and env['qt_dir']:
568 env['QTDIR'] = env['qt_dir']
569 elif os.path.isdir(os.environ.get('QTDIR', '/usr/lib/qt-3.3')):
570 env['QTDIR'] = os.environ.get('QTDIR', '/usr/lib/qt-3.3')
572 # if there is a valid QTDIR, set path for lib and bin directories
573 if env.has_key('QTDIR'):
574 # add path to the qt tools
575 if os.path.isdir(os.path.join(env['QTDIR'], 'lib')):
576 env.AppendUnique(LIBPATH = [os.path.join(env['QTDIR'], 'lib')])
577 # set environment so that moc etc can be found even if its path is not set properly
578 if os.path.isdir(os.path.join(env['QTDIR'], 'bin')):
579 os.environ['PATH'] += os.pathsep + os.path.join(env['QTDIR'], 'bin')
580 env.PrependENVPath('PATH', os.path.join(env['QTDIR'], 'bin'))
582 if env.has_key('qt_lib_path') and env['qt_lib_path']:
583 qt_lib_path = env.subst('$qt_lib_path')
584 elif env.has_key('QTDIR') and os.path.isdir(os.path.join(env.subst('$QTDIR'), 'lib')):
585 qt_lib_path = env.subst('$QTDIR/lib')
586 # this is the path for cygwin.
587 elif os.path.isdir(os.path.join('/usr/lib/', frontend, 'lib')):
588 qt_lib_path = '/usr/lib/%s/lib' % frontend
590 print "Qt library directory is not found. Please specify it using qt_lib_path"
592 env.AppendUnique(LIBPATH = [qt_lib_path])
593 # qt4 seems to be using pkg_config
594 env.PrependENVPath('PKG_CONFIG_PATH', qt_lib_path)
596 if env.has_key('qt_inc_path') and env['qt_inc_path']:
597 qt_inc_path = env['qt_inc_path']
598 elif env.has_key('QTDIR') and os.path.isdir(os.path.join(env.subst('$QTDIR'), 'include')):
599 qt_inc_path = '$QTDIR/include'
600 # this is the path for cygwin.
601 elif os.path.isdir('/usr/include/' + frontend):
602 qt_inc_path = '/usr/include/' + frontend
604 print "Qt include directory not found. Please specify it using qt_inc_path"
606 # Note that this CPPPATH is for testing only
607 # it will be removed before calling SConscript
608 env['CPPPATH'] = [qt_inc_path]
611 # extra_inc_path and extra_lib_path
614 if env.has_key('extra_inc_path') and env['extra_inc_path']:
615 extra_inc_paths.append(env['extra_inc_path'])
616 if env.has_key('extra_lib_path') and env['extra_lib_path']:
617 env.AppendUnique(LIBPATH = [env['extra_lib_path']])
618 if env.has_key('extra_inc_path1') and env['extra_inc_path1']:
619 extra_inc_paths.append(env['extra_inc_path1'])
620 if env.has_key('extra_lib_path1') and env['extra_lib_path1']:
621 env.AppendUnique(LIBPATH = [env['extra_lib_path1']])
622 if env.has_key('extra_bin_path') and env['extra_bin_path']:
623 # only the first one is needed (a scons bug?)
624 os.environ['PATH'] += os.pathsep + env['extra_bin_path']
625 env.PrependENVPath('PATH', env['extra_bin_path'])
626 # extra_inc_paths will be used later by intlenv etc
627 env.AppendUnique(CPPPATH = extra_inc_paths)
630 #----------------------------------------------------------
632 #----------------------------------------------------------
634 conf = Configure(env,
636 'CheckPkgConfig' : utils.checkPkgConfig,
637 'CheckPackage' : utils.checkPackage,
638 'CheckMkdirOneArg' : utils.checkMkdirOneArg,
639 'CheckSelectArgType' : utils.checkSelectArgType,
640 'CheckBoostLibraries' : utils.checkBoostLibraries,
641 'CheckCommand' : utils.checkCommand,
642 'CheckCXXGlobalCstd' : utils.checkCXXGlobalCstd,
643 'CheckLC_MESSAGES' : utils.checkLC_MESSAGES,
644 'CheckIconvConst' : utils.checkIconvConst,
648 # pkg-config? (if not, we use hard-coded options)
650 if conf.CheckPkgConfig('0.15.0'):
651 env['HAS_PKG_CONFIG'] = True
653 print 'pkg-config >= 0.1.50 is not found'
654 env['HAS_PKG_CONFIG'] = False
655 env_cache['HAS_PKG_CONFIG'] = env['HAS_PKG_CONFIG']
657 env['HAS_PKG_CONFIG'] = env_cache['HAS_PKG_CONFIG']
659 # zlib? This is required. (fast_start assumes the existance of zlib)
661 if (not use_vc and not conf.CheckLibWithHeader('z', 'zlib.h', 'C')) \
662 or (use_vc and not conf.CheckLibWithHeader('zdll', 'zlib.h', 'C')):
663 print 'Did not find zdll.lib or zlib.h, exiting!'
665 has_iconv = conf.CheckLib('iconv')
666 has_libiconv = conf.CheckLib('libiconv')
668 env['ICONV_LIB'] = 'iconv'
670 env['ICONV_LIB'] = 'libiconv'
672 print 'Did not find iconv or libiconv, exiting!'
674 env_cache['ICONV_LIB'] = env['ICONV_LIB']
676 env['ICONV_LIB'] = env_cache['ICONV_LIB']
681 # qt3 does not use pkg_config
682 if frontend == 'qt3':
683 # windows lib name is qt-mt3
684 if not conf.CheckLibWithHeader('qt-mt', 'qapp.h', 'c++', 'QApplication qapp();') \
685 and not conf.CheckLibWithHeader('qt-mt3', 'qapp.h', 'c++', 'QApplication qapp();'):
686 print 'Did not find qt libraries, exiting!'
688 elif frontend == 'qt4':
690 # first: try pkg_config
691 if env['HAS_PKG_CONFIG']:
692 succ = conf.CheckPackage('QtCore') or conf.CheckPackage('QtCore4')
693 # FIXME: use pkg_config information?
694 #env['QT4_PKG_CONFIG'] = succ
695 # second: try to link to it
697 # Under linux, I can test the following perfectly
698 # Under windows, lib names need to passed as libXXX4.a ...
699 succ = conf.CheckLibWithHeader('QtCore', 'QtGui/QApplication', 'c++', 'QApplication qapp();') or \
700 conf.CheckLibWithHeader('QtCore4', 'QtGui/QApplication', 'c++', 'QApplication qapp();')
701 # third: try to look up the path
704 for lib in ['QtCore', 'QtGui']:
705 # windows version has something like QtGui4 ...
706 if not (os.path.isfile(os.path.join(qt_lib_path, 'lib%s.a' % lib)) or \
707 os.path.isfile(os.path.join(qt_lib_path, 'lib%s4.a' % lib))):
710 # still can not find it
712 print "Qt4 libraries are found."
714 print 'Did not find qt libraries, exiting!'
717 # now, if msvc2005 is used, we will need that QT_LIB_PATH/QT_LIB.manifest file
719 if frontend == 'qt3':
720 manifest = os.path.join(qt_lib_path, 'qt-mt3.dll.manifest')
721 elif frontend == 'qt4':
723 manifest = os.path.join(qt_lib_path, 'QtGuid4.dll.manifest')
725 manifest = os.path.join(qt_lib_path, 'QtGui4.dll.manifest')
726 if os.path.isfile(manifest):
727 env['LINKCOM'] = [env['LINKCOM'], 'mt.exe /MANIFEST %s /outputresource:$TARGET;1' % manifest]
732 if conf.CheckLib('socket'):
733 socket_libs.append('socket')
734 # nsl is the network services library and provides a
735 # transport-level interface to networking services.
736 if conf.CheckLib('nsl'):
737 socket_libs.append('nsl')
738 env_cache['SOCKET_LIBS'] = socket_libs
740 socket_libs = env_cache['SOCKET_LIBS']
742 # check available boost libs (since lyx1.4 does not use iostream)
744 for lib in ['signals', 'regex', 'filesystem', 'iostreams']:
745 if os.path.isdir(os.path.join(top_src_dir, 'boost', 'libs', lib)):
746 boost_libs.append(lib)
749 # check boost libraries
750 boost_opt = ARGUMENTS.get('boost', 'auto')
751 # check for system boost
752 lib_paths = env['LIBPATH'] + ['/usr/lib', '/usr/local/lib']
753 inc_paths = env['CPPPATH'] + ['/usr/include', '/usr/local/include']
754 # default to $BUILDDIR/libs (use None since this path will be added anyway)
756 # here I assume that all libraries are in the same directory
757 if boost_opt == 'included':
758 boost_libraries = ['included_boost_%s' % x for x in boost_libs]
759 included_boost = True
760 env['BOOST_INC_PATH'] = '$TOP_SRCDIR/boost'
761 elif boost_opt == 'auto':
762 res = conf.CheckBoostLibraries(boost_libs, lib_paths, inc_paths, boost_version, mode == 'debug')
763 # if not found, use local boost
765 boost_libraries = ['included_boost_%s' % x for x in boost_libs]
766 included_boost = True
767 env['BOOST_INC_PATH'] = '$TOP_SRCDIR/boost'
769 included_boost = False
770 (boost_libraries, boost_libpath, env['BOOST_INC_PATH']) = res
771 elif boost_opt == 'system':
772 res = conf.CheckBoostLibraries(boost_libs, lib_paths, inc_paths, boost_version, mode == 'debug')
774 print "Can not find system boost libraries with version %s " % boost_version
775 print "Please supply a path through extra_lib_path and try again."
776 print "Or use boost=included to use included boost libraries."
779 included_boost = False
780 (boost_libraries, boost_libpath, env['BOOST_INC_PATH']) = res
781 env_cache['BOOST_LIBRARIES'] = boost_libraries
782 env_cache['INCLUDED_BOOST'] = included_boost
783 env_cache['BOOST_INC_PATH'] = env['BOOST_INC_PATH']
784 env_cache['BOOST_LIBPATH'] = boost_libpath
786 boost_libraries = env_cache['BOOST_LIBRARIES']
787 included_boost = env_cache['INCLUDED_BOOST']
788 env['BOOST_INC_PATH'] = env_cache['BOOST_INC_PATH']
789 boost_libpath = env_cache['BOOST_LIBPATH']
791 if boost_libpath is not None:
792 env.AppendUnique(LIBPATH = [boost_libpath])
795 env['ENABLE_NLS'] = env['nls']
798 if not env['ENABLE_NLS']:
800 included_gettext = False
802 # check gettext libraries
803 gettext_opt = ARGUMENTS.get('gettext', 'auto')
804 # check for system gettext
806 if gettext_opt in ['auto', 'system']:
807 if conf.CheckLib('intl'):
808 included_gettext = False
812 if gettext_opt == 'system':
813 print "Can not find system gettext library"
814 print "Please supply a path through extra_lib_path and try again."
815 print "Or use gettext=included to use included gettext libraries."
817 # now, auto and succ = false, or gettext=included
819 # we do not need to set LIBPATH now.
820 included_gettext = True
821 intl_libs = ['included_intl']
822 env_cache['INCLUDED_GETTEXT'] = included_gettext
823 env_cache['INTL_LIBS'] = intl_libs
825 included_gettext = env_cache['INCLUDED_GETTEXT']
826 intl_libs = env_cache['INTL_LIBS']
829 # check for msgfmt command
831 env['MSGFMT'] = conf.CheckCommand('msgfmt')
832 env_cache['MSGFMT'] = env['MSGFMT']
834 env['MSGFMT'] = env_cache['MSGFMT']
836 # check uic and moc commands for qt frontends
838 if frontend[:2] == 'qt' and (conf.CheckCommand('uic') == None \
839 or conf.CheckCommand('moc') == None):
840 print 'uic or moc command is not found for frontend', frontend
844 # Customized builders
846 # install customized builders
847 env['BUILDERS']['substFile'] = Builder(action = utils.env_subst)
850 #----------------------------------------------------------
851 # Generating config.h
852 #----------------------------------------------------------
853 aspell_lib = 'aspell'
854 # assume that we use aspell, aspelld compiled for msvc
855 if platform_name == 'win32' and mode == 'debug' and use_vc:
856 aspell_lib = 'aspelld'
858 # check the existence of config.h
859 config_h = os.path.join(env.Dir('$BUILDDIR/common').path, 'config.h')
860 boost_config_h = os.path.join(env.Dir('$BUILDDIR/boost').path, 'config.h')
861 if not fast_start or not os.path.isfile(boost_config_h) \
862 or not os.path.isfile(config_h):
864 print "Creating %s..." % boost_config_h
866 utils.createConfigFile(conf,
867 config_file = boost_config_h,
868 config_pre = '''/* boost/config.h. Generated by SCons. */
873 * This file is part of LyX, the document processor.
874 * Licence details can be found in the file COPYING.
876 * This is the compilation configuration file for LyX.
877 * It was generated by scon.
878 * You might want to change some of the defaults if something goes wrong
879 * during the compilation.
882 #ifndef _BOOST_CONFIG_H
883 #define _BOOST_CONFIG_H
886 ('ostream', 'HAVE_OSTREAM', 'cxx'),
887 ('locale', 'HAVE_LOCALE', 'cxx'),
888 ('sstream', 'HAVE_SSTREAM', 'cxx'),
889 #('newapis.h', 'HAVE_NEWAPIS_H', 'c'),
892 (env.has_key('assertions') and env['assertions'],
894 'Define if you want assertions to be enabled in the code'
899 #if defined(HAVE_OSTREAM) && defined(HAVE_LOCALE) && defined(HAVE_SSTREAM)
900 # define USE_BOOST_FORMAT 1
902 # define USE_BOOST_FORMAT 0
905 #if !defined(ENABLE_ASSERTIONS)
906 # define BOOST_DISABLE_ASSERTS 1
908 #define BOOST_ENABLE_ASSERT_HANDLER 1
910 #define BOOST_DISABLE_THREADS 1
911 #define BOOST_NO_WSTRING 1
914 # define BOOST_POSIX 1
917 #define BOOST_ALL_NO_LIB 1
919 #if defined(HAVE_NEWAPIS_H)
920 # define WANT_GETFILEATTRIBUTESEX_WRAPPER 1
927 print "\nGenerating %s..." % config_h
929 # AIKSAURUS_H_LOCATION
930 if (conf.CheckCXXHeader("Aiksaurus.h")):
931 aik_location = '<Aiksaurus.h>'
932 elif (conf.CheckCXXHeader("Aiksaurus/Aiksaurus.h")):
933 aik_location = '<Aiksaurus/Aiksaurus.h>'
937 # determine headers to use
938 spell_opt = ARGUMENTS.get('spell', 'auto')
939 env['USE_ASPELL'] = False
940 env['USE_PSPELL'] = False
941 env['USE_ISPELL'] = False
942 if spell_opt in ['auto', 'aspell'] and conf.CheckLib(aspell_lib):
943 spell_engine = 'USE_ASPELL'
944 elif spell_opt in ['auto', 'pspell'] and conf.CheckLib('pspell'):
945 spell_engine = 'USE_PSPELL'
946 elif spell_opt in ['auto', 'ispell'] and conf.CheckLib('ispell'):
947 spell_engine = 'USE_ISPELL'
951 if spell_engine is not None:
952 env[spell_engine] = True
954 if spell_opt == 'auto':
955 print "Warning: Can not locate any spell checker"
956 elif spell_opt != 'no':
957 print "Warning: Can not locate specified spell checker:", spell_opt
960 # check arg types of select function
961 (select_arg1, select_arg234, select_arg5) = conf.CheckSelectArgType()
965 result = utils.createConfigFile(conf,
966 config_file = config_h,
967 config_pre = '''/* config.h. Generated by SCons. */
972 * This file is part of LyX, the document processor.
973 * Licence details can be found in the file COPYING.
975 * This is the compilation configuration file for LyX.
976 * It was generated by scon.
977 * You might want to change some of the defaults if something goes wrong
978 * during the compilation.
985 ('io.h', 'HAVE_IO_H', 'c'),
986 ('limits.h', 'HAVE_LIMITS_H', 'c'),
987 ('locale.h', 'HAVE_LOCALE_H', 'c'),
988 ('process.h', 'HAVE_PROCESS_H', 'c'),
989 ('stdlib.h', 'HAVE_STDLIB_H', 'c'),
990 ('sys/stat.h', 'HAVE_SYS_STAT_H', 'c'),
991 ('sys/time.h', 'HAVE_SYS_TIME_H', 'c'),
992 ('sys/types.h', 'HAVE_SYS_TYPES_H', 'c'),
993 ('sys/utime.h', 'HAVE_SYS_UTIME_H', 'c'),
994 ('sys/socket.h', 'HAVE_SYS_SOCKET_H', 'c'),
995 ('unistd.h', 'HAVE_UNISTD_H', 'c'),
996 ('utime.h', 'HAVE_UTIME_H', 'c'),
997 ('direct.h', 'HAVE_DIRECT_H', 'c'),
998 ('istream', 'HAVE_ISTREAM', 'cxx'),
999 ('ios', 'HAVE_IOS', 'cxx'),
1002 ('open', 'HAVE_OPEN', None),
1003 ('close', 'HAVE_CLOSE', None),
1004 ('popen', 'HAVE_POPEN', None),
1005 ('pclose', 'HAVE_PCLOSE', None),
1006 ('_open', 'HAVE__OPEN', None),
1007 ('_close', 'HAVE__CLOSE', None),
1008 ('_popen', 'HAVE__POPEN', None),
1009 ('_pclose', 'HAVE__PCLOSE', None),
1010 ('getpid', 'HAVE_GETPID', None),
1011 ('_getpid', 'HAVE__GETPID', None),
1012 ('mkdir', 'HAVE_MKDIR', None),
1013 ('_mkdir', 'HAVE__MKDIR', None),
1014 ('mktemp', 'HAVE_MKTEMP', None),
1015 ('mkstemp', 'HAVE_MKSTEMP', None),
1016 ('strerror', 'HAVE_STRERROR', None),
1017 ('count', 'HAVE_STD_COUNT', '''
1018 #include <algorithm>
1022 return std::count(a, a+5, 'l');
1025 ('getcwd', 'HAVE_GETCWD', None),
1026 ('setenv', 'HAVE_SETENV', None),
1027 ('putenv', 'HAVE_PUTENV', None),
1028 ('fcntl', 'HAVE_FCNTL', None),
1031 ('std::istreambuf_iterator<std::istream>', 'HAVE_DECL_ISTREAMBUF_ITERATOR',
1032 '#include <streambuf>\n#include <istream>')
1035 ('gdi32', 'HAVE_LIBGDI32'),
1036 (('Aiksaurus', 'libAiksaurus'), 'HAVE_LIBAIKSAURUS', 'AIKSAURUS_LIB'),
1039 (conf.CheckType('pid_t', includes='#include <sys/types.h>'),
1041 'Define is sys/types.h does not have pid_t',
1043 '#define pid_t int',
1045 (conf.CheckCXXGlobalCstd(),
1047 'Define if your C++ compiler puts C library functions in the global namespace'
1049 (conf.CheckMkdirOneArg(),
1050 'MKDIR_TAKES_ONE_ARG',
1051 'Define if mkdir takes only one argument.'
1053 (conf.CheckIconvConst(),
1055 'Define as const if the declaration of iconv() needs const.',
1056 '#define ICONV_CONST const',
1057 '#define ICONV_CONST',
1059 (conf.CheckLC_MESSAGES(),
1061 'Define if your <locale.h> file defines LC_MESSAGES.'
1063 (devel_version, 'DEVEL_VERSION', 'Whether or not a development version'),
1066 "Define to 1 if translation of program messages to the user's native anguage is requested.",
1068 (env['nls'] and not included_gettext,
1070 'Define to 1 if using system gettext library'
1072 (env.has_key('warnings') and env['warnings'],
1074 'Define this if you want to see the warning directives put here and there by the developpers to get attention'
1076 (env.has_key('concept_checks') and env['concept_checks'],
1077 '_GLIBCXX_CONCEPT_CHECKS',
1078 'libstdc++ concept checking'
1080 (env.has_key('stdlib_debug') and env['stdlib_debug'],
1082 'libstdc++ debug mode'
1084 (env.has_key('stdlib_debug') and env['stdlib_debug'],
1085 '_GLIBCXX_DEBUG_PEDANTIC',
1086 'libstdc++ pedantic debug mode'
1088 (os.name != 'nt', 'BOOST_POSIX',
1089 'Indicates to boost which API to use (posix or windows).'
1091 (spell_engine is not None, spell_engine,
1092 'Spell engine to use'
1096 ('#define PACKAGE "%s%s"' % (package, program_suffix),
1098 ('#define PACKAGE_BUGREPORT "%s"' % package_bugreport,
1099 'Define to the address where bug reports for this package should be sent.'),
1100 ('#define PACKAGE_NAME "%s"' % package_name,
1101 'Define to the full name of this package.'),
1102 ('#define PACKAGE_STRING "%s"' % package_string,
1103 'Define to the full name and version of this package.'),
1104 ('#define PACKAGE_TARNAME "%s"' % package_tarname,
1105 'Define to the one symbol short name of this package.'),
1106 ('#define PACKAGE_VERSION "%s"' % package_version,
1107 'Define to the version of this package.'),
1108 ('#define BOOST_ALL_NO_LIB 1',
1109 'disable automatic linking of boost libraries.'),
1110 ('#define USE_%s_PACKAGING 1' % packaging_method.upper(),
1111 'Packaging method'),
1112 ('#define AIKSAURUS_H_LOCATION ' + aik_location,
1113 'Aiksaurus include file'),
1114 ('#define SELECT_TYPE_ARG1 %s' % select_arg1,
1115 "Define to the type of arg 1 for `select'."),
1116 ('#define SELECT_TYPE_ARG234 %s' % select_arg234,
1117 "Define to the type of arg 2, 3, 4 for `select'."),
1118 ('#define SELECT_TYPE_ARG5 %s' % select_arg5,
1119 "Define to the type of arg 5 for `select'."),
1121 config_post = '''/************************************************************
1122 ** You should not need to change anything beyond this point */
1124 #ifndef HAVE_STRERROR
1125 #if defined(__cplusplus)
1128 char * strerror(int n);
1132 #ifndef HAVE_DECL_MKSTEMP
1133 #if defined(__cplusplus)
1140 #include <../boost/config.h>
1146 # these keys are needed in env
1147 for key in ['USE_ASPELL', 'USE_PSPELL', 'USE_ISPELL', 'HAVE_FCNTL',\
1148 'HAVE_LIBGDI32', 'HAVE_LIBAIKSAURUS', 'AIKSAURUS_LIB']:
1149 # USE_ASPELL etc does not go through result
1150 if result.has_key(key):
1151 env[key] = result[key]
1152 env_cache[key] = env[key]
1155 # if nls=yes and gettext=included, create intl/config.h
1156 # intl/libintl.h etc
1158 intl_config_h = os.path.join(env.Dir('$BUILDDIR/intl').path, 'config.h')
1159 if env['nls'] and included_gettext:
1161 print "Creating %s..." % intl_config_h
1163 # create intl/config.h
1164 result = utils.createConfigFile(conf,
1165 config_file = intl_config_h,
1166 config_pre = '''/* intl/config.h. Generated by SCons. */
1171 * This file is part of LyX, the document processor.
1172 * Licence details can be found in the file COPYING.
1174 * This is the compilation configuration file for LyX.
1175 * It was generated by scon.
1176 * You might want to change some of the defaults if something goes wrong
1177 * during the compilation.
1184 ('unistd.h', 'HAVE_UNISTD_H', 'c'),
1185 ('inttypes.h', 'HAVE_INTTYPES_H', 'c'),
1186 ('string.h', 'HAVE_STRING_H', 'c'),
1187 ('strings.h', 'HAVE_STRINGS_H', 'c'),
1188 ('argz.h', 'HAVE_ARGZ_H', 'c'),
1189 ('limits.h', 'HAVE_LIMITS_H', 'c'),
1190 ('alloca.h', 'HAVE_ALLOCA_H', 'c'),
1191 ('stddef.h', 'HAVE_STDDEF_H', 'c'),
1192 ('stdint.h', 'HAVE_STDINT_H', 'c'),
1193 ('sys/param.h', 'HAVE_SYS_PARAM_H', 'c'),
1196 ('getcwd', 'HAVE_GETCWD', None),
1197 ('stpcpy', 'HAVE_STPCPY', None),
1198 ('strcasecmp', 'HAVE_STRCASECMP', None),
1199 ('strdup', 'HAVE_STRDUP', None),
1200 ('strtoul', 'HAVE_STRTOUL', None),
1201 ('alloca', 'HAVE_ALLOCA', None),
1202 ('__fsetlocking', 'HAVE___FSETLOCKING', None),
1203 ('mempcpy', 'HAVE_MEMPCPY', None),
1204 ('__argz_count', 'HAVE___ARGZ_COUNT', None),
1205 ('__argz_next', 'HAVE___ARGZ_NEXT', None),
1206 ('__argz_stringify', 'HAVE___ARGZ_STRINGIFY', None),
1207 ('setlocale', 'HAVE_SETLOCALE', None),
1208 ('tsearch', 'HAVE_TSEARCH', None),
1209 ('getegid', 'HAVE_GETEGID', None),
1210 ('getgid', 'HAVE_GETGID', None),
1211 ('getuid', 'HAVE_GETUID', None),
1212 ('wcslen', 'HAVE_WCSLEN', None),
1213 ('asprintf', 'HAVE_ASPRINTF', None),
1214 ('wprintf', 'HAVE_WPRINTF', None),
1215 ('snprintf', 'HAVE_SNPRINTF', None),
1216 ('printf', 'HAVE_POSIX_PRINTF', None),
1217 ('fcntl', 'HAVE_FCNTL', None),
1220 ('intmax_t', 'HAVE_INTMAX_T', None),
1221 ('long double', 'HAVE_LONG_DOUBLE', None),
1222 ('long long', 'HAVE_LONG_LONG', None),
1223 ('wchar_t', 'HAVE_WCHAR_T', None),
1224 ('wint_t', 'HAVE_WINT_T', None),
1225 ('uintmax_t', 'HAVE_INTTYPES_H_WITH_UINTMAX', '#include <inttypes.h>'),
1226 ('uintmax_t', 'HAVE_STDINT_H_WITH_UINTMAX', '#include <stdint.h>'),
1232 (conf.CheckLC_MESSAGES(),
1234 'Define if your <locale.h> file defines LC_MESSAGES.'
1236 (conf.CheckIconvConst(),
1238 'Define as const if the declaration of iconv() needs const.',
1239 '#define ICONV_CONST const',
1240 '#define ICONV_CONST',
1242 (conf.CheckType('intmax_t', includes='#include <stdint.h>') or \
1243 conf.CheckType('intmax_t', includes='#include <inttypes.h>'),
1245 "Define to 1 if you have the `intmax_t' type."
1247 (env.has_key('nls') and env['nls'],
1249 "Define to 1 if translation of program messages to the user's native anguage is requested.",
1253 ('#define HAVE_ICONV 1', 'Define if iconv or libiconv is found')
1255 config_post = '#endif'
1258 # these keys are needed in env
1259 for key in ['HAVE_ASPRINTF', 'HAVE_WPRINTF', 'HAVE_SNPRINTF', \
1260 'HAVE_POSIX_PRINTF', 'HAVE_LIBC']:
1261 # USE_ASPELL etc does not go through result
1262 if result.has_key(key):
1263 env[key] = result[key]
1264 env_cache[key] = env[key]
1268 # this comes as a big surprise, without this line
1269 # (doing nothing obvious), adding fast_start=yes
1270 # to a build with fast_start=no will result in a rebuild
1271 # Note that the exact header file to check does not matter
1272 conf.CheckCHeader('io.h')
1273 # only a few variables need to be rescanned
1274 for key in ['USE_ASPELL', 'USE_PSPELL', 'USE_ISPELL', 'HAVE_FCNTL',\
1275 'HAVE_LIBGDI32', 'HAVE_LIBAIKSAURUS', 'AIKSAURUS_LIB']:
1276 env[key] = env_cache[key]
1279 if env['nls'] and included_gettext:
1280 # only a few variables need to be rescanned
1281 for key in ['HAVE_ASPRINTF', 'HAVE_WPRINTF', 'HAVE_SNPRINTF', \
1282 'HAVE_POSIX_PRINTF', 'HAVE_LIBC']:
1283 env[key] = env_cache[key]
1285 # this looks misplaced, but intl/libintl.h is needed by src/message.C
1286 if env['nls'] and included_gettext:
1287 # libgnuintl.h.in => libintl.h
1288 env.substFile('$BUILDDIR/intl/libintl.h', '$TOP_SRCDIR/intl/libgnuintl.h.in')
1289 env.Command('$BUILDDIR/intl/libgnuintl.h', '$BUILDDIR/intl/libintl.h',
1290 [Copy('$TARGET', '$SOURCE')])
1293 # Finish auto-configuration
1296 #----------------------------------------------------------
1297 # Now set up our build process accordingly
1298 #----------------------------------------------------------
1303 # NOTE: Tool('qt') or Tool('qt4') will be loaded later
1304 # in their respective directory and specialized env.
1305 if frontend == 'qt3':
1306 # note: env.Tool('qt') my set QT_LIB to qt
1307 if platform_name == 'win32':
1308 qt_libs = ['qt-mt3']
1311 frontend_libs = qt_libs
1312 elif frontend == 'qt4':
1313 qt_libs = ['QtCore', 'QtGui']
1314 # set the right lib names
1315 if platform_name == 'win32':
1316 if mode == 'debug' and use_vc:
1317 qt_lib_suffix = 'd4'
1322 qt_lib_suffix = '_debug'
1325 frontend_libs = [x + qt_lib_suffix for x in qt_libs]
1328 if platform_name in ['win32', 'cygwin']:
1329 # the final link step needs stdc++ to succeed under mingw
1330 # FIXME: shouldn't g++ automatically link to stdc++?
1332 system_libs = [env['ICONV_LIB'], 'shlwapi', 'shell32', 'advapi32', 'zdll']
1334 system_libs = [env['ICONV_LIB'], 'shlwapi', 'stdc++', 'z']
1335 elif platform_name == 'cygwin' and env['X11']:
1336 system_libs = [env['ICONV_LIB'], 'GL', 'Xmu', 'Xi', 'Xrender', 'Xrandr',
1337 'Xcursor', 'Xft', 'freetype', 'fontconfig', 'Xext', 'X11', 'SM', 'ICE',
1338 'resolv', 'pthread', 'z']
1340 system_libs = [env['ICONV_LIB'], 'z']
1343 ('HAVE_LIBGDI32', 'gdi32'),
1344 ('HAVE_LIBAIKSAURUS', env['AIKSAURUS_LIB']),
1345 ('USE_ASPELL', aspell_lib),
1346 ('USE_ISPELL', 'ispell'),
1347 ('USE_PSPELL', 'pspell'),
1352 system_libs.append(lib[1])
1355 # Build parameters CPPPATH etc
1358 env.AppendUnique(LIBPATH = ['/usr/X11R6/lib'])
1361 # boost: for boost header files
1362 # BUILDDIR/common: for config.h
1363 # TOP_SRCDIR/src: for support/* etc
1365 env['CPPPATH'] += ['$BUILDDIR/common', '$TOP_SRCDIR/src']
1367 # Separating boost directories from CPPPATH stops scons from building
1368 # the dependency tree for boost header files, and effectively reduce
1369 # the null build time of lyx from 29s to 16s. Since lyx may tweak local
1370 # boost headers, this is only done for system boost headers.
1372 env.AppendUnique(CPPPATH = ['$BOOST_INC_PATH'])
1375 env.PrependUnique(CCFLAGS = ['/I$BOOST_INC_PATH'])
1377 env.PrependUnique(CCFLAGS = ['-I$BOOST_INC_PATH'])
1379 # for intl/config.h, intl/libintl.h and intl/libgnuintl.h
1380 if env['nls'] and included_gettext:
1381 env['CPPPATH'].append('$BUILDDIR/intl')
1383 # QT_INC_PATH is not needed for *every* source file
1384 env['CPPPATH'].remove(qt_inc_path)
1387 # A Link script for cygwin see
1388 # http://www.cygwin.com/ml/cygwin/2004-09/msg01101.html
1389 # http://www.cygwin.com/ml/cygwin-apps/2004-09/msg00309.html
1392 if platform_name == 'cygwin':
1393 ld_script_path = '/usr/lib/qt3/mkspecs/cygwin-g++'
1394 ld_script = utils.installCygwinLDScript(ld_script_path)
1395 env.AppendUnique(LINKFLAGS = ['-Wl,--enable-runtime-pseudo-reloc',
1396 '-Wl,--script,%s' % ld_script, '-Wl,-s'])
1401 # fill in the version info
1402 env['VERSION_INFO'] = '''Configuration
1404 Special build flags: %s
1406 C Compiler flags: %s %s
1408 C++ Compiler LyX flags: %s
1409 C++ Compiler flags: %s %s
1411 Linker user flags: %s
1413 Builing directory: %s
1414 Local library directory: %s
1417 Frontend libraries: %s
1418 System libraries: %s
1419 include search path: %s
1425 ''' % (platform_name,
1426 env.subst('$CCFLAGS'), env.subst('$CC'),
1427 env.subst('$CPPFLAGS'), env.subst('$CFLAGS'),
1428 env.subst('$CXX'), env.subst('$CXXFLAGS'),
1429 env.subst('$CPPFLAGS'), env.subst('$CXXFLAGS'),
1430 env.subst('$LINKFLAGS'), env.subst('$LINKFLAGS'),
1431 env.subst('$BUILDDIR'), env.subst('$LOCALLIBPATH'),
1432 str(env['LIBPATH']), str(boost_libraries),
1433 str(frontend_libs), str(system_libs), str(env['CPPPATH']),
1434 frontend, packaging_method,
1435 prefix, env['LYX_DIR'])
1437 if frontend in ['qt3', 'qt4']:
1438 env['VERSION_INFO'] += ''' include dir: %s
1441 ''' % (qt_inc_path, qt_lib_path, env['X11'])
1444 print env['VERSION_INFO']
1447 # Mingw command line may be too short for our link usage,
1448 # Here we use a trick from scons wiki
1449 # http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/LongCmdLinesOnWin32
1451 # I also would like to add logging (commands only) capacity to the
1453 logfile = env.get('logfile', default_log_file)
1454 if logfile != '' or platform_name == 'win32':
1456 utils.setLoggedSpawn(env, logfile, longarg = (platform_name == 'win32'),
1457 info = '''# This is a log of commands used by scons to build lyx
1461 ''' % (time.asctime(), ' '.join(sys.argv),
1462 env['VERSION_INFO'].replace('\n','\n# ')) )
1467 # -h will print out help info
1468 Help(opts.GenerateHelpText(env))
1470 # save environment settings (for fast_start option)
1471 cache_file = open(env_cache_file, 'w')
1472 cPickle.dump(env_cache, cache_file)
1476 #----------------------------------------------------------
1478 #----------------------------------------------------------
1479 # this has been the source of problems on some platforms...
1480 # I find that I need to supply it with full path name
1481 env.SConsignFile(os.path.join(Dir(env['BUILDDIR']).abspath, '.sconsign'))
1482 # this usage needs further investigation.
1483 #env.CacheDir('%s/Cache/%s' % (env['BUILDDIR'], frontend))
1485 print "Building all targets recursively"
1487 if env.has_key('rebuild'):
1488 rebuild_targets = env['rebuild'].split(',')
1489 if 'none' in rebuild_targets or 'no' in rebuild_targets:
1490 rebuild_targets = []
1491 elif 'all' in rebuild_targets or 'yes' in rebuild_targets:
1492 # None: let scons decide which components to build
1493 # Forcing all components to be rebuilt is in theory not necessary
1494 rebuild_targets = None
1496 rebuild_targets = None
1498 def libExists(libname):
1499 ''' Check whether or not lib $LOCALLIBNAME/libname already exists'''
1500 return os.path.isfile(File(env.subst('$LOCALLIBPATH/${LIBPREFIX}%s$LIBSUFFIX'%libname)).abspath)
1502 def appExists(apppath, appname):
1503 ''' Check whether or not application already exists'''
1504 return os.path.isfile(File(env.subst('$BUILDDIR/common/%s/${PROGPREFIX}%s$PROGSUFFIX' % (apppath, appname))).abspath)
1506 targets = BUILD_TARGETS
1507 # msvc need to pass full target name, so I have to look for path/lyx etc
1508 build_lyx = targets == [] or True in ['lyx' in x for x in targets] \
1509 or 'install' in targets or 'all' in targets
1510 build_boost = (included_boost and not libExists('boost_regex')) or 'boost' in targets
1511 build_intl = (included_gettext and not libExists('included_intl')) or 'intl' in targets
1512 build_support = build_lyx or True in [x in targets for x in ['support', 'client', 'tex2lyx']]
1513 build_mathed = build_lyx or 'mathed' in targets
1514 build_insets = build_lyx or 'insets' in targets
1515 build_frontends = build_lyx or 'frontends' in targets
1516 build_graphics = build_lyx or 'graphics' in targets
1517 build_controllers = build_lyx or 'controllers' in targets
1518 build_client = True in ['client' in x for x in targets] \
1519 or 'install' in targets or 'all' in targets
1520 build_tex2lyx = True in ['tex2lyx' in x for x in targets] \
1521 or 'install' in targets or 'all' in targets
1522 build_lyxbase = build_lyx or 'lyxbase' in targets
1523 build_po = 'po' in targets or 'install' in targets or 'all' in targets
1524 build_qt3 = (build_lyx and frontend == 'qt3') or 'qt3' in targets
1525 build_qt4 = (build_lyx and frontend == 'qt4') or 'qt4' in targets
1526 build_msvs_projects = use_vc and 'msvs_projects' in targets
1529 # now, if rebuild_targets is specified, do not rebuild some targets
1530 if rebuild_targets is not None:
1532 def ifBuildLib(name, libname, old_value):
1533 # explicitly asked to rebuild
1534 if name in rebuild_targets:
1536 # else if not rebuild, and if the library already exists
1537 elif libExists(libname):
1539 # do not change the original value
1542 build_boost = ifBuildLib('boost', 'included_boost_filesystem', build_boost)
1543 build_intl = ifBuildLib('intl', 'included_intl', build_intl)
1544 build_support = ifBuildLib('support', 'support', build_support)
1545 build_mathed = ifBuildLib('mathed', 'mathed', build_mathed)
1546 build_insets = ifBuildLib('insets', 'insets', build_insets)
1547 build_frontends = ifBuildLib('frontends', 'frontends', build_frontends)
1548 build_graphics = ifBuildLib('graphics', 'graphics', build_graphics)
1549 build_controllers = ifBuildLib('controllers', 'controllers', build_controllers)
1550 build_lyxbase = ifBuildLib('lyxbase', 'lyxbase_pre', build_lyxbase)
1551 build_qt3 = ifBuildLib('qt3', 'qt3', build_qt3)
1552 build_qt4 = ifBuildLib('qt4', 'qt4', build_qt4)
1554 def ifBuildApp(name, appname, old_value):
1555 # explicitly asked to rebuild
1556 if name in rebuild_targets:
1558 # else if not rebuild, and if the library already exists
1559 elif appExists(name, appname):
1561 # do not change the original value
1564 build_tex2lyx = ifBuildApp('tex2lyx', 'tex2lyx', build_tex2lyx)
1565 build_client = ifBuildApp('client', 'lyxclient', build_client)
1567 # sync frontend and frontend (maybe build qt4 with frontend=qt3)
1579 env.BuildDir('$BUILDDIR/boost', '$TOP_SRCDIR/boost/libs', duplicate = 0)
1581 boostenv = env.Copy()
1583 # boost use its own config.h
1584 boostenv['CPPPATH'] = ['$TOP_SRCDIR/boost', '$BUILDDIR/boost'] + extra_inc_paths
1585 boostenv.AppendUnique(CCFLAGS = ['-DBOOST_USER_CONFIG="<config.h>"'])
1587 for lib in boost_libs:
1588 print 'Processing files in boost/libs/%s/src...' % lib
1589 boostlib = boostenv.StaticLibrary(
1590 target = '$LOCALLIBPATH/included_boost_%s' % lib,
1591 source = ['$BUILDDIR/boost/%s/src/%s' % (lib, x) for x in eval('boost_libs_%s_src_files' % lib)]
1593 Alias('boost', boostlib)
1600 intlenv = env.Copy()
1602 print "Processing files in intl..."
1604 env.BuildDir('$BUILDDIR/intl', '$TOP_SRCDIR/intl', duplicate = 0)
1606 # we need the original C compiler for these files
1607 intlenv['CC'] = C_COMPILER
1608 intlenv['CCFLAGS'] = C_CCFLAGS
1610 intlenv.Append(CCFLAGS=['/Dinline#', '/D__attribute__(x)#', '/Duintmax_t=UINT_MAX'])
1611 # intl does not use global config.h
1612 intlenv['CPPPATH'] = ['$BUILDDIR/intl'] + extra_inc_paths
1614 intlenv.Append(CCFLAGS = [
1615 r'-DLOCALEDIR=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1616 r'-DLOCALE_ALIAS_PATH=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1617 r'-DLIBDIR=\"' + env['TOP_SRCDIR'].replace('\\', '\\\\') + r'/lib\"',
1619 '-DENABLE_RELOCATABLE=1',
1621 r'-DINSTALLDIR=\"' + prefix.replace('\\', '\\\\') + r'/lib\"',
1623 '-Dset_relocation_prefix=libintl_set_relocation_prefix',
1624 '-Drelocate=libintl_relocate',
1625 '-DDEPENDS_ON_LIBICONV=1',
1630 intl = intlenv.StaticLibrary(
1631 target = '$LOCALLIBPATH/included_intl',
1633 source = ['$BUILDDIR/intl/%s' % x for x in intl_files]
1639 # Now, src code under src/
1641 env.BuildDir('$BUILDDIR/common', '$TOP_SRCDIR/src', duplicate = 0)
1648 print "Processing files in src/support..."
1650 env.substFile('$BUILDDIR/common/support/package.C', '$TOP_SRCDIR/src/support/package.C.in')
1652 support = env.StaticLibrary(
1653 target = '$LOCALLIBPATH/support',
1654 source = ['$BUILDDIR/common/support/%s' % x for x in src_support_files]
1656 Alias('support', support)
1663 print "Processing files in src/mathed..."
1665 mathed = env.StaticLibrary(
1666 target = '$LOCALLIBPATH/mathed',
1667 source = ['$BUILDDIR/common/mathed/%s' % x for x in src_mathed_files]
1669 Alias('mathed', mathed)
1676 print "Processing files in src/insets..."
1678 insets = env.StaticLibrary(
1679 target = '$LOCALLIBPATH/insets',
1680 source = ['$BUILDDIR/common/insets/%s' % x for x in src_insets_files]
1682 Alias('insets', insets)
1689 print "Processing files in src/frontends..."
1691 frontends = env.StaticLibrary(
1692 target = '$LOCALLIBPATH/frontends',
1693 source = ['$BUILDDIR/common/frontends/%s' % x for x in src_frontends_files]
1695 Alias('frontends', frontends)
1702 print "Processing files in src/graphics..."
1704 graphics = env.StaticLibrary(
1705 target = '$LOCALLIBPATH/graphics',
1706 source = ['$BUILDDIR/common/graphics/%s' % x for x in src_graphics_files]
1708 Alias('graphics', graphics)
1711 if build_controllers:
1713 # src/frontends/controllers
1715 print "Processing files in src/frontends/controllers..."
1717 controllers = env.StaticLibrary(
1718 target = '$LOCALLIBPATH/controllers',
1719 source = ['$BUILDDIR/common/frontends/controllers/%s' % x for x in src_frontends_controllers_files]
1721 Alias('controllers', controllers)
1725 # src/frontend/qt3/4
1727 if build_qt3 or build_qt4:
1728 env.BuildDir('$BUILDDIR/$frontend', '$TOP_SRCDIR/src/frontend/$frontend', duplicate = 0)
1731 print "Processing files in src/frontends/qt3..."
1734 # disable auto scan to speed up non build time
1735 qt3env['QT_AUTOSCAN'] = 0
1736 qt3env['QT_MOCHPREFIX'] = ''
1741 qt3env.AppendUnique(CPPPATH = [
1743 '$BUILDDIR/common/images',
1744 '$BUILDDIR/common/frontends',
1745 '$BUILDDIR/common/frontends/qt3',
1746 '$BUILDDIR/common/frontends/controllers',
1750 qt3_moc_files = ["$BUILDDIR/common/frontends/qt3/%s" % x for x in src_frontends_qt3_moc_files]
1752 # manually moc and uic files for better performance
1753 qt3_moced_files = [qt3env.Moc(x.replace('.C', '_moc.cpp'), x.replace('.C', '.h')) for x in qt3_moc_files]
1755 qt3_uiced_files = [qt3env.Uic('$BUILDDIR/common/frontends/qt3/ui/'+x) for x in \
1756 src_frontends_qt3_ui_files]
1758 qt3_uiced_cc_files = []
1759 for x in qt3_uiced_files:
1760 qt3_uiced_cc_files.extend(x[1:])
1762 qt3 = qt3env.StaticLibrary(
1763 target = '$LOCALLIBPATH/qt3',
1764 source = ['$BUILDDIR/common/frontends/qt3/%s' % x for x in src_frontends_qt3_files] \
1765 + qt3_uiced_cc_files
1771 print "Processing files in src/frontends/qt4..."
1774 qt4env['QT_AUTOSCAN'] = 0
1776 # local qt4 toolset from
1777 # http://www.iua.upf.es/~dgarcia/Codders/sconstools.html
1779 # NOTE: I have to patch qt4.py since it does not automatically
1780 # process .C file!!! (add to cxx_suffixes )
1782 qt4env.Tool('qt4', [scons_dir])
1783 qt4env.EnableQt4Modules(qt_libs, debug = (mode == 'debug'))
1785 qt4env.AppendUnique(CPPPATH = [
1787 '$BUILDDIR/common/images',
1788 '$BUILDDIR/common/frontends',
1789 '$BUILDDIR/common/frontends/qt4',
1790 '$BUILDDIR/common/frontends/controllers',
1795 # FIXME: replace by something from pkg_config
1796 qt4env.Append(CCFLAGS = [
1798 '-DQT_CLEAN_NAMESPACE',
1807 qt4_moc_files = ["$BUILDDIR/common/frontends/qt4/%s" % x for x in src_frontends_qt4_moc_files]
1812 resources = [qt4env.Uic4(x.split('.')[0]) for x in \
1813 ["$BUILDDIR/common/frontends/qt4/ui/%s" % x for x in src_frontends_qt4_ui_files]]
1816 # moc qt4_moc_files, the moced files are included in the original files
1818 qt4_moced_files = [qt4env.Moc4(x.replace('.C', '_moc.cpp'), x.replace('.C', '.h')) for x in qt4_moc_files]
1820 qt4 = qt4env.StaticLibrary(
1821 target = '$LOCALLIBPATH/qt4',
1822 source = ['$BUILDDIR/common/frontends/qt4/%s' % x for x in src_frontends_qt4_files]
1831 env.BuildDir('$BUILDDIR/common', '$TOP_SRCDIR/src', duplicate = 0)
1833 print "Processing files in src/client..."
1835 if env['HAVE_FCNTL']:
1836 client = env.Program(
1837 target = '$BUILDDIR/common/client/lyxclient',
1838 LIBS = ['support'] + intl_libs + system_libs +
1839 socket_libs + boost_libraries,
1840 source = ['$BUILDDIR/common/client/%s' % x for x in src_client_files]
1842 Alias('client', env.Command(os.path.join('$BUILDDIR', os.path.split(str(client[0]))[1]),
1843 client, [Copy('$TARGET', '$SOURCE')]))
1846 Alias('client', client)
1848 if env['HAVE_FCNTL']:
1849 # define client even if lyxclient is not built with rebuild=no
1850 client = [env.subst('$BUILDDIR/common/client/${PROGPREFIX}lyxclient$PROGSUFFIX')]
1859 print "Processing files in src/tex2lyx..."
1861 tex2lyx_env = env.Copy()
1863 tex2lyx_env.Prepend(CPPPATH = ['$BUILDDIR/common/tex2lyx'])
1864 tex2lyx_env.AppendUnique(LIBPATH = ['#$LOCALLIBPATH'])
1866 for file in ['FloatList.C', 'Floating.C', 'counters.C', 'lyxlayout.h', 'lyxlayout.C',
1867 'lyxtextclass.h', 'lyxtextclass.C', 'lyxlex.C', 'lyxlex_pimpl.C']:
1868 env.Command('$BUILDDIR/common/tex2lyx/'+file, '$TOP_SRCDIR/src/'+file,
1869 [Copy('$TARGET', '$SOURCE')])
1871 tex2lyx = tex2lyx_env.Program(
1872 target = '$BUILDDIR/common/tex2lyx/tex2lyx',
1873 LIBS = ['support'] + boost_libraries + system_libs,
1874 source = ['$BUILDDIR/common/tex2lyx/%s' % x for x in src_tex2lyx_files]
1876 Alias('tex2lyx', env.Command(os.path.join('$BUILDDIR', os.path.split(str(tex2lyx[0]))[1]),
1877 tex2lyx, [Copy('$TARGET', '$SOURCE')]))
1878 Alias('tex2lyx', tex2lyx)
1880 # define tex2lyx even if tex2lyx is not built with rebuild=no
1881 tex2lyx = [env.subst('$BUILDDIR/common/tex2lyx/${PROGPREFIX}tex2lyx$PROGSUFFIX')]
1888 print "Processing files in src..."
1890 env.substFile('$BUILDDIR/common/version.C', '$TOP_SRCDIR/src/version.C.in')
1892 if env.has_key('USE_ASPELL') and env['USE_ASPELL']:
1893 src_post_files.append('aspell.C')
1894 elif env.has_key('USE_PSPELL') and env['USE_PSPELL']:
1895 src_post_files.append('pspell.C')
1896 elif env.has_key('USE_ISPELL') and env['USE_ISPELL']:
1897 src_post_files.append('ispell.C')
1899 # msvc requires at least one source file with main()
1900 # so I exclude main.C from lyxbase
1901 lyxbase_pre = env.StaticLibrary(
1902 target = '$LOCALLIBPATH/lyxbase_pre',
1903 source = ['$BUILDDIR/common/%s' % x for x in src_pre_files]
1905 lyxbase_post = env.StaticLibrary(
1906 target = '$LOCALLIBPATH/lyxbase_post',
1907 source = ["$BUILDDIR/common/%s" % x for x in src_post_files]
1909 Alias('lyxbase', lyxbase_pre)
1910 Alias('lyxbase', lyxbase_post)
1915 # Build lyx with given frontend
1918 target = '$BUILDDIR/$frontend/lyx',
1919 source = ['$BUILDDIR/common/main.C'],
1937 # [/path/to/lyx.ext] => lyx-qt3.ext
1938 target_name = os.path.split(str(lyx[0]))[1].replace('lyx', 'lyx-%s' % frontend)
1939 Alias('lyx', env.Command(os.path.join('$BUILDDIR', target_name), lyx,
1940 [Copy('$TARGET', '$SOURCE')]))
1943 # define lyx even if lyx is not built with rebuild=no
1944 lyx = [env.subst('$BUILDDIR/$frontend/${PROGPREFIX}lyx$PROGSUFFIX')]
1947 if build_msvs_projects:
1948 def build_project(target, full_target = None,
1949 src = [], inc = [], res = [], rebuildTargetOnly = True):
1950 ''' build mavs project files
1951 target: alias (correspond to directory name)
1952 full_target: full path/filename of the target
1956 rebuildTargetOnly: whether or not only rebuild this target
1958 For non-debug-able targets like static libraries, target (alias) is
1959 enough to build the target. For executable targets, msvs need to know
1960 the full path to start debug them.
1962 if rebuildTargetOnly:
1963 cmds = 'fast_start=yes rebuild='+target
1965 cmds = 'fast_start=yes'
1966 if full_target is None:
1967 build_target = target
1969 build_target = full_target
1971 proj = env.MSVSProject(
1972 target = target + env['MSVSPROJECTSUFFIX'],
1973 # this allows easy access to header files (along with source)
1974 srcs = [env.subst(x) for x in src + inc],
1975 incs = [env.subst('$TOP_SRCDIR/src/config.h')],
1976 localincs = [env.subst(x) for x in inc],
1977 resources = [env.subst(x) for x in res],
1978 buildtarget = build_target,
1982 Alias('msvs_projects', proj)
1985 for lib in boost_libs:
1986 boost_src += ['$TOP_SRCDIR/boost/libs/%s/src/%s' % (lib, x) for x in eval('boost_libs_%s_src_files' % lib)]
1987 build_project('boost', src = boost_src)
1989 build_project('intl', src = ['$TOP_SRCDIR/intl/%s' % x for x in intl_files],
1990 inc = ['$TOP_SRCDIR/intl/%s' % x for x in intl_header_files])
1992 build_project('support', src = ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_files],
1993 inc = ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files])
1995 build_project('mathed', src = ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_files],
1996 inc = ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files])
1998 build_project('insets', src = ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_files],
1999 inc = ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files])
2001 build_project('frontends', src = ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_files],
2002 inc = ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files])
2004 build_project('graphics', src = ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_files],
2005 inc = ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files])
2007 build_project('controllers', src = ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files],
2008 inc = ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files])
2010 build_project('qt3', src = ['$TOP_SRCDIR/src/frontends/qt3/%s' % x for x in src_frontends_qt3_files + src_frontends_qt3_moc_files],
2011 inc = ['$TOP_SRCDIR/src/frontends/qt3/%s' % x for x in src_frontends_qt3_header_files],
2012 res = ['$TOP_SRCDIR/src/frontends/qt3/ui/%s' % x for x in src_frontends_qt3_ui_files])
2014 build_project('qt4', src = ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_files + src_frontends_qt4_moc_files],
2015 inc = ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_header_files],
2016 res = ['$TOP_SRCDIR/src/frontends/qt4/ui/%s' % x for x in src_frontends_qt4_ui_files])
2018 build_project('client', src = ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_files],
2019 inc = ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_header_files],
2020 rebuildTargetOnly = False,
2021 full_target = File(env.subst('$BUILDDIR/common/client/lyxclient$PROGSUFFIX')).abspath)
2023 build_project('tex2lyx', src = ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_files],
2024 inc = ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_header_files],
2025 rebuildTargetOnly = False,
2026 full_target = File(env.subst('$BUILDDIR/common/tex2lyx/tex2lyx$PROGSUFFIX')).abspath)
2028 build_project('lyxbase', src = ['$TOP_SRCDIR/src/%s' % x for x in src_pre_files + src_post_files],
2029 inc = ['$TOP_SRCDIR/src/%s' % x for x in src_header_files])
2031 if frontend == 'qt3':
2032 build_project('lyx',
2033 src = ['$TOP_SRCDIR/src/%s' % x for x in src_pre_files + src_post_files] + \
2034 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_files] + \
2035 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_files] + \
2036 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_files] + \
2037 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_files] + \
2038 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_files] + \
2039 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files] + \
2040 ['$TOP_SRCDIR/src/frontends/qt3/%s' % x for x in src_frontends_qt3_files + src_frontends_qt3_moc_files],
2041 inc = ['$TOP_SRCDIR/src/%s' % x for x in src_header_files] + \
2042 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files] + \
2043 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_header_files] + \
2044 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files] + \
2045 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files] + \
2046 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files] + \
2047 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files] + \
2048 ['$TOP_SRCDIR/src/frontends/qt3/%s' % x for x in src_frontends_qt3_header_files],
2049 res = ['$TOP_SRCDIR/src/frontends/qt3/ui/%s' % x for x in src_frontends_qt3_ui_files],
2050 rebuildTargetOnly = False,
2051 full_target = File(env.subst('$BUILDDIR/$frontend/lyx$PROGSUFFIX')).abspath)
2053 build_project('lyx',
2054 src = ['$TOP_SRCDIR/src/%s' % x for x in src_pre_files + src_post_files] + \
2055 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_files] + \
2056 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_files] + \
2057 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_files] + \
2058 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_files] + \
2059 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_files] + \
2060 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files] + \
2061 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_files + src_frontends_qt4_moc_files],
2062 inc = ['$TOP_SRCDIR/src/%s' % x for x in src_header_files] + \
2063 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files] + \
2064 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_header_files] + \
2065 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files] + \
2066 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files] + \
2067 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files] + \
2068 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files] + \
2069 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_header_files],
2070 res = ['$TOP_SRCDIR/src/frontends/qt4/ui/%s' % x for x in src_frontends_qt4_ui_files],
2071 rebuildTargetOnly = False,
2072 full_target = File(env.subst('$BUILDDIR/$frontend/lyx$PROGSUFFIX')).abspath)
2079 print 'Processing files in po...'
2084 # files to translate
2085 transfiles = glob.glob(os.path.join(env.subst('$TOP_SRCDIR'), 'po', '*.po'))
2086 # possibly *only* handle these languages
2088 if env.has_key('languages'):
2089 languages = env.make_list(env['lanauges'])
2090 # use defulat msgfmt
2092 if not env['MSGFMT']:
2093 print 'msgfmt does not exist. Can not process po files'
2096 env['BUILDERS']['Transfiles'] = Builder(action='$MSGFMT $SOURCE -o $TARGET',suffix='.gmo',src_suffix='.po')
2098 for f in transfiles:
2100 fname = os.path.split(f)[1]
2102 country = fname.split('.')[0]
2104 if not languages or country in languages:
2105 gmo_files.extend(env.Transfiles(f))
2108 if 'install' in targets:
2110 # this part is a bit messy right now. Since scons will provide
2111 # --DESTDIR option soon, at least the dest_dir handling can be
2114 # how to join dest_dir and prefix
2115 def joinPaths(path1, path2):
2116 ''' join path1 and path2, do not use os.path.join because
2117 under window, c:\destdir\d:\program is invalid '''
2119 return os.path.normpath(path2)
2120 # separate drive letter
2121 (drive, path) = os.path.splitdrive(os.path.normpath(path2))
2122 # ignore drive letter, so c:\destdir + c:\program = c:\destdir\program
2123 return os.path.join(os.path.normpath(path1), path[1:])
2125 # install to dest_dir/prefix
2126 dest_dir = env.get('DESTDIR', None)
2127 dest_prefix_dir = joinPaths(dest_dir, env.Dir(prefix).abspath)
2128 # create the directory if needed
2129 if not os.path.isdir(dest_prefix_dir):
2131 os.makedirs(dest_prefix_dir)
2134 if not os.path.isdir(dest_prefix_dir):
2135 print 'Can not create directory', dest_prefix_dir
2138 if env.has_key('exec_prefix'):
2139 bin_dest_dir = joinPaths(dest_dir, Dir(env['exec_prefix']).abspath)
2141 bin_dest_dir = os.path.join(dest_prefix_dir, 'bin')
2143 share_dest_dir = os.path.join(dest_prefix_dir, share_dir + program_suffix)
2145 share_dest_dir = os.path.join(dest_prefix_dir, share_dir)
2146 man_dest_dir = os.path.join(dest_prefix_dir, man_dir)
2147 locale_dest_dir = os.path.join(dest_prefix_dir, locale_dir)
2151 # install executables (lyxclient may be None)
2154 version_suffix = program_suffix
2159 target_name = os.path.split(str(lyx[0]))[1].replace('lyx', 'lyx%s' % version_suffix)
2160 target = os.path.join(bin_dest_dir, target_name)
2161 env.InstallAs(target, lyx)
2162 Alias('install', target)
2163 # install lyx as lyx-qt3
2164 target_name = os.path.split(str(lyx[0]))[1].replace('lyx', 'lyx-%s%s' % (frontend, version_suffix))
2165 target = os.path.join(bin_dest_dir, target_name)
2166 env.InstallAs(target, lyx)
2167 Alias('install', target)
2170 target_name = os.path.split(str(tex2lyx[0]))[1].replace('tex2lyx', 'tex2lyx%s' % version_suffix)
2171 target = os.path.join(bin_dest_dir, target_name)
2172 env.InstallAs(target, tex2lyx)
2173 Alias('install', target)
2175 # install lyxclient, may not exist
2177 target_name = os.path.split(str(client[0]))[1].replace('client', 'client%s' % version_suffix)
2178 target = os.path.join(bin_dest_dir, target_name)
2179 env.InstallAs(target, client)
2180 Alias('install', target)
2184 for (dir,files) in [
2186 ('clipart', lib_clipart_files),
2187 ('examples', lib_examples_files),
2188 ('images', lib_images_files),
2189 ('images/math', lib_images_math_files),
2190 ('bind', lib_bind_files),
2191 ('kbd', lib_kbd_files),
2192 ('layouts', lib_layouts_files),
2193 ('scripts', lib_scripts_files),
2194 ('templates', lib_templates_files),
2195 ('tex', lib_tex_files),
2196 ('ui', lib_ui_files),
2197 ('doc', lib_doc_files),
2198 ('lyx2lyx', lib_lyx2lyx_files)]:
2199 dirs.append(env.Install(os.path.join(share_dest_dir, dir),
2200 [env.subst('$TOP_SRCDIR/lib/%s/%s' % (dir, file)) for file in files]))
2202 # lyx1.4.x does not have lyx2lyx_version.py.in
2203 if os.path.isfile(env.subst('$TOP_SRCDIR/lib/lyx2lyx/lyx2lyx_version.py.in')):
2204 # subst and install this file
2205 env.substFile(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py',
2206 '$TOP_SRCDIR/lib/lyx2lyx/lyx2lyx_version.py.in')
2207 Alias('install', share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2208 Alias('install', dirs)
2210 env.InstallAs(os.path.join(man_dest_dir, 'lyx' + version_suffix + '.1'),
2211 env.subst('$TOP_SRCDIR/lyx.man'))
2212 env.InstallAs(os.path.join(man_dest_dir, 'tex2lyx' + version_suffix + '.1'),
2213 env.subst('$TOP_SRCDIR/src/tex2lyx/tex2lyx.man'))
2214 env.InstallAs(os.path.join(man_dest_dir, 'lyxclient' + version_suffix + '.1'),
2215 env.subst('$TOP_SRCDIR/src/client/lyxclient.man'))
2216 Alias('install', [os.path.join(man_dest_dir, x + version_suffix + '.1') for
2217 x in ['lyx', 'tex2lyx', 'lyxclient']])
2219 # ru.gmo ==> ru/LC_MESSAGES/lyxSUFFIX.mo
2220 for gmo in gmo_files:
2221 lan = os.path.split(str(gmo))[1].split('.')[0]
2222 dest_file = os.path.join(locale_dest_dir, lan, 'LC_MESSAGES', 'lyx' + version_suffix + '.mo')
2223 env.InstallAs(dest_file, gmo)
2224 Alias('install', dest_file)
2228 Alias('all', ['lyx', 'client', 'tex2lyx'])