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
21 #----------------------------------------------------------
22 # Required runtime environment
23 #----------------------------------------------------------
25 # scons asks for 1.5.2, lyx requires 2.3
26 EnsurePythonVersion(2, 3)
27 # Please use at least 0.96.92 (not 0.96.1)
28 EnsureSConsVersion(0, 96)
29 # also check for minor version number for scons 0.96
30 from SCons import __version__
31 version = map(int, __version__.split('.'))
32 if version[0] == 0 and version[1] == 96 and version[2] < 92:
33 print "Scons >= 0.96.92 is required."
36 # determine where I am ...
38 # called as 'cd development/scons; scons'
39 if os.path.isfile('SConstruct'):
42 # called as 'scons -f development/scons/SConstruct'
45 scons_dir = 'development/scons'
48 #----------------------------------------------------------
50 #----------------------------------------------------------
52 # some global settings
54 # detect version of lyx
55 # only 1.4.x has frontends/qt2
56 if os.path.isdir(os.path.join(top_src_dir, 'src', 'frontends', 'qt2')):
57 package_version = '1.4.2svn'
58 boost_version = '1_32'
60 package_version = '1.5.0svn'
61 boost_version = '1_33_1'
64 default_build_mode = 'debug'
68 package_bugreport = 'lyx-devel@lists.lyx.org'
70 package_tarname = 'lyx'
71 package_string = '%s %s' % (package_name, package_version)
73 # various cache/log files
74 default_log_file = 'scons_lyx.log'
75 env_cache_file = 'env.cache'
78 #----------------------------------------------------------
79 # platform dependent settings
80 #----------------------------------------------------------
83 platform_name = 'win32'
84 default_frontend = 'qt4'
85 default_prefix = 'c:/program files/lyx'
86 default_with_x = False
87 default_packaging_method = 'windows'
88 elif os.name == 'posix' and sys.platform != 'cygwin':
89 platform_name = sys.platform
90 default_frontend = 'qt3'
91 default_prefix = '/usr/local'
93 default_packaging_method = 'posix'
94 elif os.name == 'posix' and sys.platform == 'cygwin':
95 platform_name = 'cygwin'
96 default_frontend = 'qt3'
97 default_prefix = '/usr'
99 default_packaging_method = 'posix'
100 elif os.name == 'darwin':
101 platform_name = 'macosx'
102 default_frontend = 'qt3'
103 # FIXME: macOSX default prefix?
105 default_with_x = False
106 default_packaging_method = 'macosx'
107 else: # unsupported system, assume posix behavior
108 platform_name = 'others'
109 default_frontend = 'qt3'
111 default_with_x = True
112 default_packaging_method = 'posix'
114 # 1.4.2 only has qt2 frontend
115 if package_version == '1.4.2svn':
116 default_frontend = 'qt2'
118 #---------------------------------------------------------
120 #----------------------------------------------------------
122 # You can set perminant default values in config.py
123 if os.path.isfile('config.py'):
124 print "Getting options from config.py..."
125 print open('config.py').read()
127 opts = Options(['config.py'])
130 EnumOption('frontend', 'Main GUI', default_frontend,
131 allowed_values = ('qt2', 'qt3', 'qt4', 'gtk') ),
132 # debug or release build
133 EnumOption('mode', 'Building method', default_build_mode,
134 allowed_values = ('debug', 'release') ),
137 'Use included, system boost library, or try sytem boost first.',
138 'auto', allowed_values = (
139 'auto', # detect boost, if not found, use included
140 'included', # always use included boost
141 'system', # always use system boost, fail if can not find
144 EnumOption('gettext',
145 'Use included, system gettext library, or try sytem gettext first',
146 'auto', allowed_values = (
147 'auto', # detect gettext, if not found, use included
148 'included', # always use included gettext
149 'system', # always use system gettext, fail if can not find
152 EnumOption('spell', 'Choose spell checker to use.', 'auto',
153 allowed_values = ('aspell', 'pspell', 'ispell', 'auto', 'no') ),
155 EnumOption('packaging', 'Packaging method to use.', default_packaging_method,
156 allowed_values = ('windows', 'posix', 'macosx')),
158 BoolOption('fast_start', 'Whether or not use cached tests and keep current config.h', True),
159 # No precompiled header support (too troublesome to make it work for msvc)
160 # BoolOption('pch', 'Whether or not use pch', False),
161 # enable assertion, (config.h has ENABLE_ASSERTIOS
162 BoolOption('assertions', 'Use assertions', True),
163 # enable warning, (config.h has WITH_WARNINGS)
164 # default to False since MSVC does not have #warning
165 BoolOption('warnings', 'Use warnings', False),
166 # config.h define _GLIBCXX_CONCEPT_CHECKS
167 # Note: for earlier version of gcc (3.3) define _GLIBCPP_CONCEPT_CHECKS
168 BoolOption('concept_checks', 'Enable concept checks', True),
170 BoolOption('nls', 'Whether or not use native language support', True),
172 BoolOption('profiling', 'Whether or not enable profiling', False),
173 # config.h define _GLIBCXX_DEBUG and _GLIBCXX_DEBUG_PEDANTIC
174 BoolOption('stdlib_debug', 'Whether or not turn on stdlib debug', False),
176 BoolOption('X11', 'Use x11 windows system', default_with_x),
177 # use MS VC++ to build lyx
178 BoolOption('use_vc', 'Use MS VC++ to build lyx (cl.exe will be probed)', None),
180 PathOption('qt_dir', 'Path to qt directory', None),
182 PathOption('qt_inc_path', 'Path to qt include directory', None),
184 PathOption('qt_lib_path', 'Path to qt library directory', None),
185 # extra include and libpath
186 PathOption('extra_inc_path', 'Extra include path', None),
188 PathOption('extra_lib_path', 'Extra library path', None),
190 PathOption('extra_bin_path', 'A convenient way to add a path to $PATH', None),
192 PathOption('extra_inc_path1', 'Extra include path', None),
194 PathOption('extra_lib_path1', 'Extra library path', None),
195 # rebuild only specifed, comma separated targets
196 ('rebuild', '''rebuild only specifed, comma separated targets.
197 yes or all (default): rebuild everything
198 no or none: rebuild nothing (usually used for installation)
199 comp1,comp2,...: rebuild specified targets''', None),
200 # can be set to a non-existing directory
201 ('prefix', 'install architecture-independent files in PREFIX', default_prefix),
202 # build directory, will use $mode if not set
203 ('build_dir', 'Build directory', None),
205 ('version_suffix', 'install lyx as lyx-suffix', None),
206 # how to load options
207 ('load_option', '''load option from previous scons run. option can be
208 yes (default): load all options
209 no: do not load any option
210 opt1,opt2: load specified options
211 -opt1,opt2: load all options other than specified ones''', 'yes'),
213 ('optimization', 'optimization CCFLAGS option.', None),
215 PathOption('exec_prefix', 'install architecture-independent executable files in PREFIX', None),
217 ('logfile', 'save commands (not outputs) to logfile', default_log_file),
218 # provided for backward compatibility
219 ('dest_dir', 'install to DESTDIR. (Provided for backward compatibility only)', None),
220 # environment variable can be set as options.
221 ('DESTDIR', 'install to DESTDIR', None),
222 ('CC', 'replace default $CC', None),
223 ('LINK', 'replace default $LINK', None),
224 ('CPP', 'replace default $CPP', None),
225 ('CXX', 'replace default $CXX', None),
226 ('CXXCPP', 'replace default $CXXCPP', None),
227 ('CCFLAGS', 'replace default $CCFLAGS', None),
228 ('CPPFLAGS', 'replace default $CPPFLAGS', None),
229 ('LINKFLAGS', 'replace default $LINKFLAGS', None),
233 all_options = [x.key for x in opts.options]
235 # copied from SCons/Options/BoolOption.py
236 # We need to use them before a boolean ARGUMENTS option is available
238 true_strings = ('y', 'yes', 'true', 't', '1', 'on' , 'all' )
239 false_strings = ('n', 'no', 'false', 'f', '0', 'off', 'none')
241 # whether or not use current config.h, and cached tests
243 # if fast_start=yes (default), load variables from env_cache_file
244 if (not ARGUMENTS.has_key('fast_start') or \
245 ARGUMENTS['fast_start'] in true_strings) \
246 and os.path.isfile(env_cache_file):
248 cache_file = open(env_cache_file)
249 env_cache = cPickle.load(cache_file)
251 print '------------ fast_start mode --------------------'
252 print ' Use cached test results and current config.h'
253 print ' use fast_start=no to override'
259 # if load_option=yes (default), load saved comand line options
261 # This option can take value yes/no/opt1,opt2/-opt1,opt2
262 # and tries to be clever in choosing options to load
263 if (not ARGUMENTS.has_key('load_option') or \
264 ARGUMENTS['load_option'] not in false_strings) \
265 and os.path.isfile(env_cache_file):
266 cache_file = open(env_cache_file)
267 opt_cache = cPickle.load(cache_file)['arg_cache']
269 # import cached options, but we should ignore qt_dir when frontend changes
270 if ARGUMENTS.has_key('frontend') and opt_cache.has_key('frontend') \
271 and ARGUMENTS['frontend'] != opt_cache['frontend'] \
272 and opt_cache.has_key('qt_dir'):
273 opt_cache.pop('qt_dir')
274 # some options will require full rebuild
275 # these are in general things that will change config.h
276 for arg in ['version_suffix', 'nls', 'boost', 'spell']:
277 if ARGUMENTS.has_key(arg) and ((not opt_cache.has_key(arg)) or \
278 ARGUMENTS[arg] != opt_cache[arg]):
280 print " ** fast_start is disabled because of the change of option", arg
283 # and we do not cache some options (dest_dir is obsolete)
284 for arg in ['fast_start', 'load_option', 'dest_dir']:
285 if opt_cache.has_key(arg):
287 # remove obsolete cached keys (well, SConstruct is evolving. :-)
288 for arg in opt_cache.keys():
289 if arg not in all_options:
290 print 'Option %s is obsolete, do not load it' % arg
292 # now, if load_option=opt1,opt2 or -opt1,opt2
293 if ARGUMENTS.has_key('load_option') and \
294 ARGUMENTS['load_option'] not in true_strings + false_strings:
295 # if -opt1,opt2 is specified, do not load these options
296 if ARGUMENTS['load_option'][0] == '-':
297 for arg in ARGUMENTS['load_option'][1:].split(','):
298 if opt_cache.has_key(arg):
300 # if opt1,opt2 is specified, only load specified options
302 args = ARGUMENTS['load_option'].split(',')
303 for arg in opt_cache.keys():
306 # now restore options as if entered from command line
307 for key in opt_cache.keys():
308 if not ARGUMENTS.has_key(key):
309 ARGUMENTS[key] = opt_cache[key]
310 print "Restoring cached option %s=%s" % (key, ARGUMENTS[key])
313 # check if there is unused (or misspelled) argument
314 for arg in ARGUMENTS.keys():
315 if arg not in all_options:
317 print "Unknown option '%s'... exiting." % arg
319 print "Available options are (check 'scons -help' for details):"
320 print ' ' + '\n '.join(textwrap.wrap(', '.join(all_options)))
324 env_cache['arg_cache'] = ARGUMENTS
327 #---------------------------------------------------------
328 # Setting up environment
329 #---------------------------------------------------------
331 # I do not really like ENV=os.environ, but you may add it
332 # here if you experience some environment related problem
333 env = Environment(options = opts)
335 # set individual variables since I do not really like ENV = os.environ
336 env['ENV']['PATH'] = os.environ.get('PATH')
337 env['ENV']['HOME'] = os.environ.get('HOME')
338 # these are defined for MSVC
339 env['ENV']['LIB'] = os.environ.get('LIB')
340 env['ENV']['INCLUDE'] = os.environ.get('INCLUDE')
342 # for simplicity, use var instead of env[var]
343 frontend = env['frontend']
344 prefix = env['prefix']
347 if platform_name == 'win32':
348 if env.has_key('use_vc'):
349 use_vc = env['use_vc']
350 if WhereIs('cl.exe') is None:
351 print "cl.exe is not found. Are you using the MSVC environment?"
353 elif WhereIs('cl.exe') is not None:
360 # lyx will be built to $build/build_dir so it is possible
361 # to build multiple build_dirs using the same source
362 # $mode can be debug or release
363 if env.has_key('build_dir') and env['build_dir'] is not None:
364 # create the directory if needed
365 if not os.path.isdir(env['build_dir']):
367 os.makedirs(env['build_dir'])
370 if not os.path.isdir(env['build_dir']):
371 print 'Can not create directory', env['build_dir']
373 env['BUILDDIR'] = env['build_dir']
375 # Determine the name of the build $mode
376 env['BUILDDIR'] = '#' + mode
378 # all built libraries will go to build_dir/libs
379 # (This is different from the make file approach)
380 env['LOCALLIBPATH'] = '$BUILDDIR/libs'
381 env.AppendUnique(LIBPATH = ['$LOCALLIBPATH'])
384 # Here is a summary of variables defined in env
386 # 2. undefined options with a non-None default value
387 # 3. compiler commands and flags like CCFLAGS.
388 # MSGFMT used to process po files
389 # 4. Variables that will be used to replace variables in some_file.in
390 # src/support/package.C.in:
391 # TOP_SRCDIR, LOCALEDIR, LYX_DIR, PROGRAM_SUFFIX
392 # lib/lyx2lyx/lyx2lyx_version.py.in
395 # PACKAGE_VERSION, VERSION_INFO
397 # full path name is used to build msvs project files
398 # and to replace TOP_SRCDIR in package.C
399 env['TOP_SRCDIR'] = Dir(top_src_dir).abspath
400 # needed by src/version.C.in => src/version.C
401 env['PACKAGE_VERSION'] = package_version
403 # determine share_dir etc
404 packaging_method = env.get('packaging')
405 if packaging_method == 'windows':
406 share_dir = 'Resources'
407 man_dir = 'Resources/man/man1'
408 locale_dir = 'Resources/locale'
409 default_prefix = 'c:/program files/lyx'
411 share_dir = 'share/lyx'
413 locale_dir = 'share/locale'
414 default_prefix = '/usr/local/'
416 # install to default_prefix by default
417 # program suffix: can be yes, or a string
418 if env.has_key('version_suffix'):
419 if env['version_suffix'] in true_strings:
420 program_suffix = package_version
421 elif env['version_suffix'] in false_strings:
424 program_suffix = env['version_suffix']
427 # used by package.C.in
428 env['PROGRAM_SUFFIX'] = program_suffix
430 # whether or not add suffix to file and directory names
431 add_suffix = packaging_method != 'windows'
432 # LYX_DIR are different (used in package.C.in)
434 env['LYX_DIR'] = Dir(os.path.join(prefix, share_dir + program_suffix)).abspath
436 env['LYX_DIR'] = Dir(os.path.join(prefix, share_dir)).abspath
437 # we need absolute path for package.C
438 env['LOCALEDIR'] = Dir(os.path.join(prefix, locale_dir)).abspath
441 #---------------------------------------------------------
442 # Setting building environment (Tools, compiler flags etc)
443 #---------------------------------------------------------
445 # Since Tool('mingw') will reset CCFLAGS etc, this should be
446 # done before getEnvVariable
447 if platform_name == 'win32':
453 env.AppendUnique(CPPPATH = ['#c:/MinGW/include'])
455 # we differentiate between hard-coded options and default options
456 # hard-coded options are required and will always be there
457 # default options can be replaced by enviromental variables or command line options
458 CCFLAGS_required = []
459 LINKFLAGS_required = []
462 # under windows, scons is confused by .C/.c and uses gcc instead of
463 # g++. I am forcing the use of g++ here. This is expected to change
464 # after lyx renames all .C files to .cpp
466 # save the old c compiler and CCFLAGS (used by libintl)
467 C_COMPILER = env.subst('$CC')
468 C_CCFLAGS = env.subst('$CCFLAGS').split()
469 # if we use ms vc, the commands are fine (cl.exe and link.exe)
471 # /TP treat all source code as C++
472 # C4819: The file contains a character that cannot be represented
473 # in the current code page (number)
474 # C4996: foo was decleared deprecated
475 CCFLAGS_required.extend(['/TP', '/EHsc'])
476 CCFLAGS_default.extend(['/wd4819', '/wd4996', '/nologo'])
478 if env.has_key('CXX') and env['CXX']:
479 env['CC'] = env.subst('$CXX')
480 env['LINK'] = env.subst('$CXX')
485 # for debug/release mode
486 if env.has_key('optimization') and env['optimization'] is not None:
487 # if user supplies optimization flags, use it anyway
488 CCFLAGS_required.extend(env['optimization'].split())
489 # and do not use default
490 set_default_optimization_flags = False
492 set_default_optimization_flags = True
496 CCFLAGS_required.append('/Zi')
497 LINKFLAGS_required.extend(['/debug', '/map'])
499 CCFLAGS_required.append('-g')
500 CCFLAGS_default.append('-O')
501 elif mode == 'release' and set_default_optimization_flags:
503 CCFLAGS_default.append('/O2')
505 CCFLAGS_default.append('-O2')
507 # msvc uses separate tools for profiling
508 if env.has_key('profiling') and env['profiling']:
510 print 'Visual C++ does not use profiling options'
512 CCFLAGS_required.append('-pg')
513 LINKFLAGS_required.append('-pg')
515 if env.has_key('warnings') and env['warnings']:
517 CCFLAGS_default.append('/W2')
519 # Note: autotools detect gxx version and pass -W for 3.x
520 # and -Wextra for other versions of gcc
521 CCFLAGS_default.append('-Wall')
523 # Now, set the variables as follows:
524 # 1. if command line option exists: replace default
525 # 2. then if s envronment variable exists: replace default
526 # 3. set variable to required + default
527 def setEnvVariable(env, name, required = None, default = None, split = True):
528 ''' env: environment to set variable
530 required: hardcoded options
531 default: default options that can be replaced by command line or
532 environment variables
533 split: whether or not split obtained variable like '-02 -g'
535 # first try command line argument (override environment settings)
536 if ARGUMENTS.has_key(name):
537 default = ARGUMENTS[name]
539 default = default.split()
540 # then use environment default
541 elif os.environ.has_key(name):
542 print "Acquiring varaible %s from system environment: %s" % (name, os.environ[name])
543 default = os.environ[name]
545 default = default.split()
547 if required is not None:
549 if default is not None:
550 if env.has_key(name) and env[name] != default:
555 setEnvVariable(env, 'DESTDIR', split=False)
556 setEnvVariable(env, 'CC')
557 setEnvVariable(env, 'LINK')
558 setEnvVariable(env, 'CPP')
559 setEnvVariable(env, 'CXX')
560 setEnvVariable(env, 'CXXCPP')
561 setEnvVariable(env, 'CCFLAGS', CCFLAGS_required, CCFLAGS_default)
562 setEnvVariable(env, 'CXXFLAGS')
563 setEnvVariable(env, 'CPPFLAGS')
564 setEnvVariable(env, 'LINKFLAGS', LINKFLAGS_required)
566 # if DESTDIR is not set...
567 if env.has_key('dest_dir'):
568 print "This option is obsolete. Please use DESTDIR instead."
569 env['DESTDIR'] = env['dest_dir']
572 #---------------------------------------------------------
573 # Frontend related variables (QTDIR etc)
574 #---------------------------------------------------------
576 if env.has_key('qt_dir') and env['qt_dir']:
577 env['QTDIR'] = env['qt_dir']
578 elif os.path.isdir(os.environ.get('QTDIR', '/usr/lib/qt-3.3')):
579 env['QTDIR'] = os.environ.get('QTDIR', '/usr/lib/qt-3.3')
581 # if there is a valid QTDIR, set path for lib and bin directories
582 if env.has_key('QTDIR'):
583 # add path to the qt tools
584 if os.path.isdir(os.path.join(env['QTDIR'], 'lib')):
585 env.AppendUnique(LIBPATH = [os.path.join(env['QTDIR'], 'lib')])
586 # set environment so that moc etc can be found even if its path is not set properly
587 if os.path.isdir(os.path.join(env['QTDIR'], 'bin')):
588 os.environ['PATH'] += os.pathsep + os.path.join(env['QTDIR'], 'bin')
589 env.PrependENVPath('PATH', os.path.join(env['QTDIR'], 'bin'))
591 # allow qt2 frontend to locate qt3 libs.
592 frontend_lib = {'qt2':'qt3', 'qt3':'qt3', 'qt4':'qt4'}[frontend]
593 if env.has_key('qt_lib_path') and env['qt_lib_path']:
594 qt_lib_path = env.subst('$qt_lib_path')
595 elif env.has_key('QTDIR') and os.path.isdir(os.path.join(env.subst('$QTDIR'), 'lib')):
596 qt_lib_path = env.subst('$QTDIR/lib')
597 # this is the path for cygwin.
598 elif os.path.isdir(os.path.join('/usr/lib/', frontend_lib, 'lib')):
599 qt_lib_path = '/usr/lib/%s/lib' % frontend_lib
601 print "Qt library directory is not found. Please specify it using qt_lib_path"
603 env.AppendUnique(LIBPATH = [qt_lib_path])
604 # qt4 seems to be using pkg_config
605 env.PrependENVPath('PKG_CONFIG_PATH', qt_lib_path)
607 if env.has_key('qt_inc_path') and env['qt_inc_path']:
608 qt_inc_path = env['qt_inc_path']
609 elif env.has_key('QTDIR') and os.path.isdir(os.path.join(env.subst('$QTDIR'), 'include')):
610 qt_inc_path = '$QTDIR/include'
611 # this is the path for cygwin.
612 elif os.path.isdir('/usr/include/' + frontend_lib):
613 qt_inc_path = '/usr/include/' + frontend_lib
615 print "Qt include directory not found. Please specify it using qt_inc_path"
617 # Note that this CPPPATH is for testing only
618 # it will be removed before calling SConscript
619 env['CPPPATH'] = [qt_inc_path]
622 # extra_inc_path and extra_lib_path
625 if env.has_key('extra_inc_path') and env['extra_inc_path']:
626 extra_inc_paths.append(env['extra_inc_path'])
627 if env.has_key('extra_lib_path') and env['extra_lib_path']:
628 env.AppendUnique(LIBPATH = [env['extra_lib_path']])
629 if env.has_key('extra_inc_path1') and env['extra_inc_path1']:
630 extra_inc_paths.append(env['extra_inc_path1'])
631 if env.has_key('extra_lib_path1') and env['extra_lib_path1']:
632 env.AppendUnique(LIBPATH = [env['extra_lib_path1']])
633 if env.has_key('extra_bin_path') and env['extra_bin_path']:
634 # only the first one is needed (a scons bug?)
635 os.environ['PATH'] += os.pathsep + env['extra_bin_path']
636 env.PrependENVPath('PATH', env['extra_bin_path'])
637 # extra_inc_paths will be used later by intlenv etc
638 env.AppendUnique(CPPPATH = extra_inc_paths)
641 #----------------------------------------------------------
643 #----------------------------------------------------------
645 conf = Configure(env,
647 'CheckPkgConfig' : utils.checkPkgConfig,
648 'CheckPackage' : utils.checkPackage,
649 'CheckMkdirOneArg' : utils.checkMkdirOneArg,
650 'CheckSelectArgType' : utils.checkSelectArgType,
651 'CheckBoostLibraries' : utils.checkBoostLibraries,
652 'CheckCommand' : utils.checkCommand,
653 'CheckCXXGlobalCstd' : utils.checkCXXGlobalCstd,
654 'CheckLC_MESSAGES' : utils.checkLC_MESSAGES,
655 'CheckIconvConst' : utils.checkIconvConst,
659 # pkg-config? (if not, we use hard-coded options)
661 if conf.CheckPkgConfig('0.15.0'):
662 env['HAS_PKG_CONFIG'] = True
664 print 'pkg-config >= 0.1.50 is not found'
665 env['HAS_PKG_CONFIG'] = False
666 env_cache['HAS_PKG_CONFIG'] = env['HAS_PKG_CONFIG']
668 env['HAS_PKG_CONFIG'] = env_cache['HAS_PKG_CONFIG']
670 # zlib? This is required. (fast_start assumes the existance of zlib)
672 if (not use_vc and not conf.CheckLibWithHeader('z', 'zlib.h', 'C')) \
673 or (use_vc and not conf.CheckLibWithHeader('zdll', 'zlib.h', 'C')):
674 print 'Did not find zdll.lib or zlib.h, exiting!'
680 # qt3 does not use pkg_config
681 if frontend in ['qt2', 'qt3']:
682 if not conf.CheckLibWithHeader('qt-mt', 'qapp.h', 'c++', 'QApplication qapp();'):
683 print 'Did not find qt libraries, exiting!'
685 elif frontend == 'qt4':
687 # first: try pkg_config
688 if env['HAS_PKG_CONFIG']:
689 succ = conf.CheckPackage('QtCore') or conf.CheckPackage('QtCore4')
690 # FIXME: use pkg_config information?
691 #env['QT4_PKG_CONFIG'] = succ
692 # second: try to link to it
694 # Under linux, I can test the following perfectly
695 # Under windows, lib names need to passed as libXXX4.a ...
696 succ = conf.CheckLibWithHeader('QtCore', 'QtGui/QApplication', 'c++', 'QApplication qapp();') or \
697 conf.CheckLibWithHeader('QtCore4', 'QtGui/QApplication', 'c++', 'QApplication qapp();')
698 # third: try to look up the path
701 for lib in ['QtCore', 'QtGui']:
702 # windows version has something like QtGui4 ...
703 if not (os.path.isfile(os.path.join(qt_lib_path, 'lib%s.a' % lib)) or \
704 os.path.isfile(os.path.join(qt_lib_path, 'lib%s4.a' % lib))):
707 # still can not find it
709 print "Qt4 libraries are found."
711 print 'Did not find qt libraries, exiting!'
714 # now, if msvc2005 is used, we will need that QT_LIB_PATH/QT_LIB.manifest file
717 manifest = os.path.join(qt_lib_path, 'QtGuid4.dll.manifest')
719 manifest = os.path.join(qt_lib_path, 'QtGui4.dll.manifest')
720 if os.path.isfile(manifest):
721 env['LINKCOM'] = [env['LINKCOM'], 'mt.exe /MANIFEST %s /outputresource:$TARGET;1' % manifest]
726 if conf.CheckLib('socket'):
727 socket_libs.append('socket')
728 # nsl is the network services library and provides a
729 # transport-level interface to networking services.
730 if conf.CheckLib('nsl'):
731 socket_libs.append('nsl')
732 env_cache['SOCKET_LIBS'] = socket_libs
734 socket_libs = env_cache['SOCKET_LIBS']
736 # check available boost libs (since lyx1.4 does not use iostream)
738 for lib in ['signals', 'regex', 'filesystem', 'iostreams']:
739 if os.path.isdir(os.path.join(top_src_dir, 'boost', 'libs', lib)):
740 boost_libs.append(lib)
743 # check boost libraries
744 boost_opt = ARGUMENTS.get('boost', 'auto')
745 # check for system boost
746 lib_paths = env['LIBPATH'] + ['/usr/lib', '/usr/local/lib']
747 inc_paths = env['CPPPATH'] + ['/usr/include', '/usr/local/include']
748 # default to $BUILDDIR/libs (use None since this path will be added anyway)
750 # here I assume that all libraries are in the same directory
751 if boost_opt == 'included':
752 boost_libraries = ['included_boost_%s' % x for x in boost_libs]
753 included_boost = True
754 env['BOOST_INC_PATH'] = '$TOP_SRCDIR/boost'
755 elif boost_opt == 'auto':
756 res = conf.CheckBoostLibraries(boost_libs, lib_paths, inc_paths, boost_version, mode == 'debug')
757 # if not found, use local boost
759 boost_libraries = ['included_boost_%s' % x for x in boost_libs]
760 included_boost = True
761 env['BOOST_INC_PATH'] = '$TOP_SRCDIR/boost'
763 included_boost = False
764 (boost_libraries, boost_libpath, env['BOOST_INC_PATH']) = res
765 elif boost_opt == 'system':
766 res = conf.CheckBoostLibraries(boost_libs, lib_paths, inc_paths, boost_version, mode == 'debug')
768 print "Can not find system boost libraries with version %s " % boost_version
769 print "Please supply a path through extra_lib_path and try again."
770 print "Or use boost=included to use included boost libraries."
773 included_boost = False
774 (boost_libraries, boost_libpath, env['BOOST_INC_PATH']) = res
775 env_cache['BOOST_LIBRARIES'] = boost_libraries
776 env_cache['INCLUDED_BOOST'] = included_boost
777 env_cache['BOOST_INC_PATH'] = env['BOOST_INC_PATH']
778 env_cache['BOOST_LIBPATH'] = boost_libpath
780 boost_libraries = env_cache['BOOST_LIBRARIES']
781 included_boost = env_cache['INCLUDED_BOOST']
782 env['BOOST_INC_PATH'] = env_cache['BOOST_INC_PATH']
783 boost_libpath = env_cache['BOOST_LIBPATH']
785 if boost_libpath is not None:
786 env.AppendUnique(LIBPATH = [boost_libpath])
789 env['ENABLE_NLS'] = env['nls']
792 if not env['ENABLE_NLS']:
794 included_gettext = False
796 # check gettext libraries
797 gettext_opt = ARGUMENTS.get('gettext', 'auto')
798 # check for system gettext
800 if gettext_opt in ['auto', 'system']:
801 if conf.CheckLib('intl'):
802 included_gettext = False
806 if gettext_opt == 'system':
807 print "Can not find system gettext library"
808 print "Please supply a path through extra_lib_path and try again."
809 print "Or use gettext=included to use included gettext libraries."
811 # now, auto and succ = false, or gettext=included
813 # we do not need to set LIBPATH now.
814 included_gettext = True
815 intl_libs = ['included_intl']
816 env_cache['INCLUDED_GETTEXT'] = included_gettext
817 env_cache['INTL_LIBS'] = intl_libs
819 included_gettext = env_cache['INCLUDED_GETTEXT']
820 intl_libs = env_cache['INTL_LIBS']
823 # check for msgfmt command
825 env['MSGFMT'] = conf.CheckCommand('msgfmt')
826 env_cache['MSGFMT'] = env['MSGFMT']
828 env['MSGFMT'] = env_cache['MSGFMT']
830 # check uic and moc commands for qt frontends
832 if frontend[:2] == 'qt' and (conf.CheckCommand('uic') == None \
833 or conf.CheckCommand('moc') == None):
834 print 'uic or moc command is not found for frontend', frontend
838 # Customized builders
840 # install customized builders
841 env['BUILDERS']['substFile'] = Builder(action = utils.env_subst)
844 #----------------------------------------------------------
845 # Generating config.h
846 #----------------------------------------------------------
847 aspell_lib = 'aspell'
848 # assume that we use aspell, aspelld compiled for msvc
849 if platform_name == 'win32' and mode == 'debug' and use_vc:
850 aspell_lib = 'aspelld'
852 # check the existence of config.h
853 config_h = os.path.join(env.Dir('$BUILDDIR/common').path, 'config.h')
854 boost_config_h = os.path.join(env.Dir('$BUILDDIR/boost').path, 'config.h')
855 if not fast_start or not os.path.isfile(boost_config_h) \
856 or not os.path.isfile(config_h):
858 print "Creating %s..." % boost_config_h
860 utils.createConfigFile(conf,
861 config_file = boost_config_h,
862 config_pre = '''/* boost/config.h. Generated by SCons. */
867 * This file is part of LyX, the document processor.
868 * Licence details can be found in the file COPYING.
870 * This is the compilation configuration file for LyX.
871 * It was generated by scon.
872 * You might want to change some of the defaults if something goes wrong
873 * during the compilation.
876 #ifndef _BOOST_CONFIG_H
877 #define _BOOST_CONFIG_H
880 ('ostream', 'HAVE_OSTREAM', 'cxx'),
881 ('locale', 'HAVE_LOCALE', 'cxx'),
882 ('sstream', 'HAVE_SSTREAM', 'cxx'),
883 #('newapis.h', 'HAVE_NEWAPIS_H', 'c'),
886 (env.has_key('assertions') and env['assertions'],
888 'Define if you want assertions to be enabled in the code'
893 #if defined(HAVE_OSTREAM) && defined(HAVE_LOCALE) && defined(HAVE_SSTREAM)
894 # define USE_BOOST_FORMAT 1
896 # define USE_BOOST_FORMAT 0
899 #if !defined(ENABLE_ASSERTIONS)
900 # define BOOST_DISABLE_ASSERTS 1
902 #define BOOST_ENABLE_ASSERT_HANDLER 1
904 #define BOOST_DISABLE_THREADS 1
905 #define BOOST_NO_WREGEX 1
906 #define BOOST_NO_WSTRING 1
909 # define BOOST_POSIX 1
912 #define BOOST_ALL_NO_LIB 1
914 #if defined(HAVE_NEWAPIS_H)
915 # define WANT_GETFILEATTRIBUTESEX_WRAPPER 1
922 print "\nGenerating %s..." % config_h
924 # AIKSAURUS_H_LOCATION
925 if (conf.CheckCXXHeader("Aiksaurus.h")):
926 aik_location = '<Aiksaurus.h>'
927 elif (conf.CheckCXXHeader("Aiksaurus/Aiksaurus.h")):
928 aik_location = '<Aiksaurus/Aiksaurus.h>'
932 # determine headers to use
933 spell_opt = ARGUMENTS.get('spell', 'auto')
934 env['USE_ASPELL'] = False
935 env['USE_PSPELL'] = False
936 env['USE_ISPELL'] = False
937 if spell_opt in ['auto', 'aspell'] and conf.CheckLib(aspell_lib):
938 spell_engine = 'USE_ASPELL'
939 elif spell_opt in ['auto', 'pspell'] and conf.CheckLib('pspell'):
940 spell_engine = 'USE_PSPELL'
941 elif spell_opt in ['auto', 'ispell'] and conf.CheckLib('ispell'):
942 spell_engine = 'USE_ISPELL'
946 if spell_engine is not None:
947 env[spell_engine] = True
949 if spell_opt == 'auto':
950 print "Warning: Can not locate any spell checker"
951 elif spell_opt != 'no':
952 print "Warning: Can not locate specified spell checker:", spell_opt
955 # check arg types of select function
956 (select_arg1, select_arg234, select_arg5) = conf.CheckSelectArgType()
960 result = utils.createConfigFile(conf,
961 config_file = config_h,
962 config_pre = '''/* config.h. Generated by SCons. */
967 * This file is part of LyX, the document processor.
968 * Licence details can be found in the file COPYING.
970 * This is the compilation configuration file for LyX.
971 * It was generated by scon.
972 * You might want to change some of the defaults if something goes wrong
973 * during the compilation.
980 ('io.h', 'HAVE_IO_H', 'c'),
981 ('limits.h', 'HAVE_LIMITS_H', 'c'),
982 ('locale.h', 'HAVE_LOCALE_H', 'c'),
983 ('process.h', 'HAVE_PROCESS_H', 'c'),
984 ('stdlib.h', 'HAVE_STDLIB_H', 'c'),
985 ('sys/stat.h', 'HAVE_SYS_STAT_H', 'c'),
986 ('sys/time.h', 'HAVE_SYS_TIME_H', 'c'),
987 ('sys/types.h', 'HAVE_SYS_TYPES_H', 'c'),
988 ('sys/utime.h', 'HAVE_SYS_UTIME_H', 'c'),
989 ('sys/socket.h', 'HAVE_SYS_SOCKET_H', 'c'),
990 ('unistd.h', 'HAVE_UNISTD_H', 'c'),
991 ('utime.h', 'HAVE_UTIME_H', 'c'),
992 ('direct.h', 'HAVE_DIRECT_H', 'c'),
993 ('istream', 'HAVE_ISTREAM', 'cxx'),
994 ('ios', 'HAVE_IOS', 'cxx'),
997 ('open', 'HAVE_OPEN', None),
998 ('close', 'HAVE_CLOSE', None),
999 ('popen', 'HAVE_POPEN', None),
1000 ('pclose', 'HAVE_PCLOSE', None),
1001 ('_open', 'HAVE__OPEN', None),
1002 ('_close', 'HAVE__CLOSE', None),
1003 ('_popen', 'HAVE__POPEN', None),
1004 ('_pclose', 'HAVE__PCLOSE', None),
1005 ('getpid', 'HAVE_GETPID', None),
1006 ('_getpid', 'HAVE__GETPID', None),
1007 ('mkdir', 'HAVE_MKDIR', None),
1008 ('_mkdir', 'HAVE__MKDIR', None),
1009 ('mktemp', 'HAVE_MKTEMP', None),
1010 ('mkstemp', 'HAVE_MKSTEMP', None),
1011 ('strerror', 'HAVE_STRERROR', None),
1012 ('count', 'HAVE_STD_COUNT', '''
1013 #include <algorithm>
1017 return std::count(a, a+5, 'l');
1020 ('getcwd', 'HAVE_GETCWD', None),
1021 ('setenv', 'HAVE_SETENV', None),
1022 ('putenv', 'HAVE_PUTENV', None),
1023 ('fcntl', 'HAVE_FCNTL', None),
1026 ('std::istreambuf_iterator<std::istream>', 'HAVE_DECL_ISTREAMBUF_ITERATOR',
1027 '#include <streambuf>\n#include <istream>')
1030 ('gdi32', 'HAVE_LIBGDI32'),
1031 (('iconv', 'libiconv'), 'HAVE_ICONV', 'ICONV_LIB'),
1032 (('Aiksaurus', 'libAiksaurus'), 'HAVE_LIBAIKSAURUS', 'AIKSAURUS_LIB'),
1035 (conf.CheckType('pid_t', includes='#include <sys/types.h>'),
1037 'Define is sys/types.h does not have pid_t',
1039 '#define pid_t int',
1041 (conf.CheckCXXGlobalCstd(),
1043 'Define if your C++ compiler puts C library functions in the global namespace'
1045 (conf.CheckMkdirOneArg(),
1046 'MKDIR_TAKES_ONE_ARG',
1047 'Define if mkdir takes only one argument.'
1049 (conf.CheckLC_MESSAGES(),
1051 'Define if your <locale.h> file defines LC_MESSAGES.'
1053 (devel_version, 'DEVEL_VERSION', 'Whether or not a development version'),
1056 "Define to 1 if translation of program messages to the user's native anguage is requested.",
1058 (env['nls'] and not included_gettext,
1060 'Define to 1 if using system gettext library'
1062 (env.has_key('warnings') and env['warnings'],
1064 'Define this if you want to see the warning directives put here and there by the developpers to get attention'
1066 (env.has_key('concept_checks') and env['concept_checks'],
1067 '_GLIBCXX_CONCEPT_CHECKS',
1068 'libstdc++ concept checking'
1070 (env.has_key('stdlib_debug') and env['stdlib_debug'],
1072 'libstdc++ debug mode'
1074 (env.has_key('stdlib_debug') and env['stdlib_debug'],
1075 '_GLIBCXX_DEBUG_PEDANTIC',
1076 'libstdc++ pedantic debug mode'
1078 (os.name != 'nt', 'BOOST_POSIX',
1079 'Indicates to boost which API to use (posix or windows).'
1081 (spell_engine is not None, spell_engine,
1082 'Spell engine to use'
1086 ('#define PACKAGE "%s%s"' % (package, program_suffix),
1088 ('#define PACKAGE_BUGREPORT "%s"' % package_bugreport,
1089 'Define to the address where bug reports for this package should be sent.'),
1090 ('#define PACKAGE_NAME "%s"' % package_name,
1091 'Define to the full name of this package.'),
1092 ('#define PACKAGE_STRING "%s"' % package_string,
1093 'Define to the full name and version of this package.'),
1094 ('#define PACKAGE_TARNAME "%s"' % package_tarname,
1095 'Define to the one symbol short name of this package.'),
1096 ('#define PACKAGE_VERSION "%s"' % package_version,
1097 'Define to the version of this package.'),
1098 ('#define BOOST_ALL_NO_LIB 1',
1099 'disable automatic linking of boost libraries.'),
1100 ('#define USE_%s_PACKAGING 1' % packaging_method.upper(),
1101 'Packaging method'),
1102 ('#define AIKSAURUS_H_LOCATION ' + aik_location,
1103 'Aiksaurus include file'),
1104 ('#define SELECT_TYPE_ARG1 %s' % select_arg1,
1105 "Define to the type of arg 1 for `select'."),
1106 ('#define SELECT_TYPE_ARG234 %s' % select_arg234,
1107 "Define to the type of arg 2, 3, 4 for `select'."),
1108 ('#define SELECT_TYPE_ARG5 %s' % select_arg5,
1109 "Define to the type of arg 5 for `select'."),
1111 config_post = '''/************************************************************
1112 ** You should not need to change anything beyond this point */
1114 #ifndef HAVE_STRERROR
1115 #if defined(__cplusplus)
1118 char * strerror(int n);
1122 #ifndef HAVE_DECL_MKSTEMP
1123 #if defined(__cplusplus)
1130 #include <../boost/config.h>
1136 # these keys are needed in env
1137 for key in ['USE_ASPELL', 'USE_PSPELL', 'USE_ISPELL', 'HAVE_FCNTL',\
1138 'HAVE_ICONV', 'HAVE_LIBGDI32', 'HAVE_LIBAIKSAURUS',
1139 'ICONV_LIB', 'AIKSAURUS_LIB']:
1140 # USE_ASPELL etc does not go through result
1141 if result.has_key(key):
1142 env[key] = result[key]
1143 env_cache[key] = env[key]
1146 # if nls=yes and gettext=included, create intl/config.h
1147 # intl/libintl.h etc
1149 intl_config_h = os.path.join(env.Dir('$BUILDDIR/intl').path, 'config.h')
1150 if env['nls'] and included_gettext:
1152 print "Creating %s..." % intl_config_h
1154 # create intl/config.h
1155 result = utils.createConfigFile(conf,
1156 config_file = intl_config_h,
1157 config_pre = '''/* intl/config.h. Generated by SCons. */
1162 * This file is part of LyX, the document processor.
1163 * Licence details can be found in the file COPYING.
1165 * This is the compilation configuration file for LyX.
1166 * It was generated by scon.
1167 * You might want to change some of the defaults if something goes wrong
1168 * during the compilation.
1175 ('unistd.h', 'HAVE_UNISTD_H', 'c'),
1176 ('inttypes.h', 'HAVE_INTTYPES_H', 'c'),
1177 ('string.h', 'HAVE_STRING_H', 'c'),
1178 ('strings.h', 'HAVE_STRINGS_H', 'c'),
1179 ('argz.h', 'HAVE_ARGZ_H', 'c'),
1180 ('limits.h', 'HAVE_LIMITS_H', 'c'),
1181 ('alloca.h', 'HAVE_ALLOCA_H', 'c'),
1182 ('stddef.h', 'HAVE_STDDEF_H', 'c'),
1183 ('stdint.h', 'HAVE_STDINT_H', 'c'),
1184 ('sys/param.h', 'HAVE_SYS_PARAM_H', 'c'),
1187 ('getcwd', 'HAVE_GETCWD', None),
1188 ('stpcpy', 'HAVE_STPCPY', None),
1189 ('strcasecmp', 'HAVE_STRCASECMP', None),
1190 ('strdup', 'HAVE_STRDUP', None),
1191 ('strtoul', 'HAVE_STRTOUL', None),
1192 ('alloca', 'HAVE_ALLOCA', None),
1193 ('__fsetlocking', 'HAVE___FSETLOCKING', None),
1194 ('mempcpy', 'HAVE_MEMPCPY', None),
1195 ('__argz_count', 'HAVE___ARGZ_COUNT', None),
1196 ('__argz_next', 'HAVE___ARGZ_NEXT', None),
1197 ('__argz_stringify', 'HAVE___ARGZ_STRINGIFY', None),
1198 ('setlocale', 'HAVE_SETLOCALE', None),
1199 ('tsearch', 'HAVE_TSEARCH', None),
1200 ('getegid', 'HAVE_GETEGID', None),
1201 ('getgid', 'HAVE_GETGID', None),
1202 ('getuid', 'HAVE_GETUID', None),
1203 ('wcslen', 'HAVE_WCSLEN', None),
1204 ('asprintf', 'HAVE_ASPRINTF', None),
1205 ('wprintf', 'HAVE_WPRINTF', None),
1206 ('snprintf', 'HAVE_SNPRINTF', None),
1207 ('printf', 'HAVE_POSIX_PRINTF', None),
1208 ('fcntl', 'HAVE_FCNTL', None),
1211 ('intmax_t', 'HAVE_INTMAX_T', None),
1212 ('long double', 'HAVE_LONG_DOUBLE', None),
1213 ('long long', 'HAVE_LONG_LONG', None),
1214 ('wchar_t', 'HAVE_WCHAR_T', None),
1215 ('wint_t', 'HAVE_WINT_T', None),
1216 ('uintmax_t', 'HAVE_INTTYPES_H_WITH_UINTMAX', '#include <inttypes.h>'),
1217 ('uintmax_t', 'HAVE_STDINT_H_WITH_UINTMAX', '#include <stdint.h>'),
1220 (('iconv', 'libiconv'), 'HAVE_ICONV', 'ICONV_LIB'),
1224 (conf.CheckLC_MESSAGES(),
1226 'Define if your <locale.h> file defines LC_MESSAGES.'
1228 (conf.CheckIconvConst(),
1230 'Define as const if the declaration of iconv() needs const.',
1231 '#define ICONV_CONST',
1232 '#define ICONV_CONST const',
1234 (conf.CheckType('intmax_t', includes='#include <stdint.h>') or \
1235 conf.CheckType('intmax_t', includes='#include <inttypes.h>'),
1237 "Define to 1 if you have the `intmax_t' type."
1239 (env.has_key('nls') and env['nls'],
1241 "Define to 1 if translation of program messages to the user's native anguage is requested.",
1244 config_post = '#endif'
1247 # these keys are needed in env
1248 for key in ['HAVE_ASPRINTF', 'HAVE_WPRINTF', 'HAVE_SNPRINTF', \
1249 'HAVE_POSIX_PRINTF', 'HAVE_ICONV', 'HAVE_LIBC']:
1250 # USE_ASPELL etc does not go through result
1251 if result.has_key(key):
1252 env[key] = result[key]
1253 env_cache[key] = env[key]
1257 # this comes as a big surprise, without this line
1258 # (doing nothing obvious), adding fast_start=yes
1259 # to a build with fast_start=no will result in a rebuild
1260 # Note that the exact header file to check does not matter
1261 conf.CheckCHeader('io.h')
1262 # only a few variables need to be rescanned
1263 for key in ['USE_ASPELL', 'USE_PSPELL', 'USE_ISPELL', 'HAVE_FCNTL',\
1264 'HAVE_ICONV', 'HAVE_LIBGDI32', 'HAVE_LIBAIKSAURUS',
1265 'ICONV_LIB', 'AIKSAURUS_LIB']:
1266 env[key] = env_cache[key]
1269 if env['nls'] and included_gettext:
1270 # only a few variables need to be rescanned
1271 for key in ['HAVE_ASPRINTF', 'HAVE_WPRINTF', 'HAVE_SNPRINTF', \
1272 'HAVE_POSIX_PRINTF', 'HAVE_ICONV', 'HAVE_LIBC']:
1273 env[key] = env_cache[key]
1275 # this looks misplaced, but intl/libintl.h is needed by src/message.C
1276 if env['nls'] and included_gettext:
1277 # libgnuintl.h.in => libintl.h
1278 env.substFile('$BUILDDIR/intl/libintl.h', '$TOP_SRCDIR/intl/libgnuintl.h.in')
1279 env.Command('$BUILDDIR/intl/libgnuintl.h', '$BUILDDIR/intl/libintl.h',
1280 [Copy('$TARGET', '$SOURCE')])
1283 # Finish auto-configuration
1286 #----------------------------------------------------------
1287 # Now set up our build process accordingly
1288 #----------------------------------------------------------
1293 # NOTE: Tool('qt') or Tool('qt4') will be loaded later
1294 # in their respective directory and specialized env.
1295 if frontend in ['qt2', 'qt3']:
1296 # note: env.Tool('qt') my set QT_LIB to qt
1298 frontend_libs = ['qt-mt']
1299 elif frontend == 'qt4':
1300 qt_libs = ['QtCore', 'QtGui']
1301 # set the right lib names
1302 if platform_name == 'win32':
1303 if mode == 'debug' and use_vc:
1304 qt_lib_suffix = 'd4'
1309 qt_lib_suffix = '_debug'
1312 frontend_libs = [x + qt_lib_suffix for x in qt_libs]
1315 if platform_name in ['win32', 'cygwin']:
1316 # the final link step needs stdc++ to succeed under mingw
1317 # FIXME: shouldn't g++ automatically link to stdc++?
1319 system_libs = ['shlwapi', 'shell32', 'advapi32', 'zdll']
1321 system_libs = ['shlwapi', 'stdc++', 'z']
1322 elif platform_name == 'cygwin' and env['X11']:
1323 system_libs = ['GL', 'Xmu', 'Xi', 'Xrender', 'Xrandr', 'Xcursor',
1324 'Xft', 'freetype', 'fontconfig', 'Xext', 'X11', 'SM', 'ICE', 'resolv',
1330 ('HAVE_ICONV', env['ICONV_LIB']),
1331 ('HAVE_LIBGDI32', 'gdi32'),
1332 ('HAVE_LIBAIKSAURUS', env['AIKSAURUS_LIB']),
1333 ('USE_ASPELL', aspell_lib),
1334 ('USE_ISPELL', 'ispell'),
1335 ('USE_PSPELL', 'pspell'),
1340 system_libs.append(lib[1])
1343 # Build parameters CPPPATH etc
1346 env.AppendUnique(LIBPATH = ['/usr/X11R6/lib'])
1349 # boost: for boost header files
1350 # BUILDDIR/common: for config.h
1351 # TOP_SRCDIR/src: for support/* etc
1353 env['CPPPATH'] += ['$BUILDDIR/common', '$TOP_SRCDIR/src']
1355 # Separating boost directories from CPPPATH stops scons from building
1356 # the dependency tree for boost header files, and effectively reduce
1357 # the null build time of lyx from 29s to 16s. Since lyx may tweak local
1358 # boost headers, this is only done for system boost headers.
1360 env.AppendUnique(CPPPATH = ['$BOOST_INC_PATH'])
1363 env.PrependUnique(CCFLAGS = ['/I$BOOST_INC_PATH'])
1365 env.PrependUnique(CCFLAGS = ['-I$BOOST_INC_PATH'])
1367 # for intl/config.h, intl/libintl.h and intl/libgnuintl.h
1368 if env['nls'] and included_gettext:
1369 env['CPPPATH'].append('$BUILDDIR/intl')
1371 # QT_INC_PATH is not needed for *every* source file
1372 env['CPPPATH'].remove(qt_inc_path)
1375 # A Link script for cygwin see
1376 # http://www.cygwin.com/ml/cygwin/2004-09/msg01101.html
1377 # http://www.cygwin.com/ml/cygwin-apps/2004-09/msg00309.html
1380 if platform_name == 'cygwin':
1381 ld_script_path = '/usr/lib/qt3/mkspecs/cygwin-g++'
1382 ld_script = utils.installCygwinLDScript(ld_script_path)
1383 env.AppendUnique(LINKFLAGS = ['-Wl,--enable-runtime-pseudo-reloc',
1384 '-Wl,--script,%s' % ld_script, '-Wl,-s'])
1389 # fill in the version info
1390 env['VERSION_INFO'] = '''Configuration
1392 Special build flags: %s
1394 C Compiler flags: %s %s
1396 C++ Compiler LyX flags: %s
1397 C++ Compiler flags: %s %s
1399 Linker user flags: %s
1401 Builing directory: %s
1402 Local library directory: %s
1405 Frontend libraries: %s
1406 System libraries: %s
1407 include search path: %s
1413 ''' % (platform_name,
1414 env.subst('$CCFLAGS'), env.subst('$CC'),
1415 env.subst('$CPPFLAGS'), env.subst('$CFLAGS'),
1416 env.subst('$CXX'), env.subst('$CXXFLAGS'),
1417 env.subst('$CPPFLAGS'), env.subst('$CXXFLAGS'),
1418 env.subst('$LINKFLAGS'), env.subst('$LINKFLAGS'),
1419 env.subst('$BUILDDIR'), env.subst('$LOCALLIBPATH'),
1420 str(env['LIBPATH']), str(boost_libraries),
1421 str(frontend_libs), str(system_libs), str(env['CPPPATH']),
1422 frontend, packaging_method,
1423 prefix, env['LYX_DIR'])
1425 if frontend in ['qt2', 'qt3', 'qt4']:
1426 env['VERSION_INFO'] += ''' include dir: %s
1429 ''' % (qt_inc_path, qt_lib_path, env['X11'])
1432 print env['VERSION_INFO']
1435 # Mingw command line may be too short for our link usage,
1436 # Here we use a trick from scons wiki
1437 # http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/LongCmdLinesOnWin32
1439 # I also would like to add logging (commands only) capacity to the
1441 logfile = env.get('logfile', default_log_file)
1442 if logfile != '' or platform_name == 'win32':
1444 utils.setLoggedSpawn(env, logfile, longarg = (platform_name == 'win32'),
1445 info = '''# This is a log of commands used by scons to build lyx
1449 ''' % (time.asctime(), ' '.join(sys.argv),
1450 env['VERSION_INFO'].replace('\n','\n# ')) )
1455 # -h will print out help info
1456 Help(opts.GenerateHelpText(env))
1458 # save environment settings (for fast_start option)
1459 cache_file = open(env_cache_file, 'w')
1460 cPickle.dump(env_cache, cache_file)
1464 #----------------------------------------------------------
1466 #----------------------------------------------------------
1467 # this has been the source of problems on some platforms...
1468 # I find that I need to supply it with full path name
1469 env.SConsignFile(os.path.join(Dir(env['BUILDDIR']).abspath, '.sconsign'))
1470 # this usage needs further investigation.
1471 #env.CacheDir('%s/Cache/%s' % (env['BUILDDIR'], frontend))
1473 print "Building all targets recursively"
1475 if env.has_key('rebuild'):
1476 rebuild_targets = env['rebuild'].split(',')
1477 if 'none' in rebuild_targets or 'no' in rebuild_targets:
1478 rebuild_targets = []
1479 elif 'all' in rebuild_targets or 'yes' in rebuild_targets:
1480 # None: let scons decide which components to build
1481 # Forcing all components to be rebuilt is in theory not necessary
1482 rebuild_targets = None
1484 rebuild_targets = None
1486 def libExists(libname):
1487 ''' Check whether or not lib $LOCALLIBNAME/libname already exists'''
1488 return os.path.isfile(File(env.subst('$LOCALLIBPATH/${LIBPREFIX}%s$LIBSUFFIX'%libname)).abspath)
1490 def appExists(apppath, appname):
1491 ''' Check whether or not application already exists'''
1492 return os.path.isfile(File(env.subst('$BUILDDIR/common/%s/${PROGPREFIX}%s$PROGSUFFIX' % (apppath, appname))).abspath)
1494 targets = BUILD_TARGETS
1495 # msvc need to pass full target name, so I have to look for path/lyx etc
1496 build_lyx = targets == [] or True in ['lyx' in x for x in targets] \
1497 or 'install' in targets or 'all' in targets
1498 build_boost = (included_boost and not libExists('boost_regex')) or 'boost' in targets
1499 build_intl = (included_gettext and not libExists('included_intl')) or 'intl' in targets
1500 build_support = build_lyx or True in [x in targets for x in ['support', 'client', 'tex2lyx']]
1501 build_mathed = build_lyx or 'mathed' in targets
1502 build_insets = build_lyx or 'insets' in targets
1503 build_frontends = build_lyx or 'frontends' in targets
1504 build_graphics = build_lyx or 'graphics' in targets
1505 build_controllers = build_lyx or 'controllers' in targets
1506 build_client = True in ['client' in x for x in targets] \
1507 or 'install' in targets or 'all' in targets
1508 build_tex2lyx = True in ['tex2lyx' in x for x in targets] \
1509 or 'install' in targets or 'all' in targets
1510 build_lyxbase = build_lyx or 'lyxbase' in targets
1511 build_po = 'po' in targets or 'install' in targets or 'all' in targets
1512 build_qt2 = (build_lyx and frontend == 'qt2') or 'qt2' in targets
1513 build_qt3 = (build_lyx and frontend == 'qt3') or 'qt3' in targets
1514 build_qt4 = (build_lyx and frontend == 'qt4') or 'qt4' in targets
1515 build_msvs_projects = use_vc and 'msvs_projects' in targets
1518 # now, if rebuild_targets is specified, do not rebuild some targets
1519 if rebuild_targets is not None:
1521 def ifBuildLib(name, libname, old_value):
1522 # explicitly asked to rebuild
1523 if name in rebuild_targets:
1525 # else if not rebuild, and if the library already exists
1526 elif libExists(libname):
1528 # do not change the original value
1531 build_boost = ifBuildLib('boost', 'included_boost_filesystem', build_boost)
1532 build_intl = ifBuildLib('intl', 'included_intl', build_intl)
1533 build_support = ifBuildLib('support', 'support', build_support)
1534 build_mathed = ifBuildLib('mathed', 'mathed', build_mathed)
1535 build_insets = ifBuildLib('insets', 'insets', build_insets)
1536 build_frontends = ifBuildLib('frontends', 'frontends', build_frontends)
1537 build_graphics = ifBuildLib('graphics', 'graphics', build_graphics)
1538 build_controllers = ifBuildLib('controllers', 'controllers', build_controllers)
1539 build_lyxbase = ifBuildLib('lyxbase', 'lyxbase_pre', build_lyxbase)
1540 build_qt2 = ifBuildLib('qt2', 'qt2', build_qt2)
1541 build_qt3 = ifBuildLib('qt3', 'qt3', build_qt3)
1542 build_qt4 = ifBuildLib('qt4', 'qt4', build_qt4)
1544 def ifBuildApp(name, appname, old_value):
1545 # explicitly asked to rebuild
1546 if name in rebuild_targets:
1548 # else if not rebuild, and if the library already exists
1549 elif appExists(name, appname):
1551 # do not change the original value
1554 build_tex2lyx = ifBuildApp('tex2lyx', 'tex2lyx', build_tex2lyx)
1555 build_client = ifBuildApp('client', 'lyxclient', build_client)
1557 # sync frontend and frontend (maybe build qt4 with frontend=qt3)
1571 env.BuildDir('$BUILDDIR/boost', '$TOP_SRCDIR/boost/libs', duplicate = 0)
1573 boostenv = env.Copy()
1575 # boost use its own config.h
1576 boostenv['CPPPATH'] = ['$TOP_SRCDIR/boost', '$BUILDDIR/boost'] + extra_inc_paths
1577 boostenv.AppendUnique(CCFLAGS = ['-DBOOST_USER_CONFIG="<config.h>"'])
1579 for lib in boost_libs:
1580 print 'Processing files in boost/libs/%s/src...' % lib
1581 boostlib = boostenv.StaticLibrary(
1582 target = '$LOCALLIBPATH/included_boost_%s' % lib,
1583 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/boost/libs/%s/src' % lib),
1584 pattern = '*.cpp', build_dir = '$BUILDDIR/boost/%s/src' % lib)
1586 Alias('boost', boostlib)
1593 intlenv = env.Copy()
1595 print "Processing files in intl..."
1597 env.BuildDir('$BUILDDIR/intl', '$TOP_SRCDIR/intl', duplicate = 0)
1599 # we need the original C compiler for these files
1600 intlenv['CC'] = C_COMPILER
1601 intlenv['CCFLAGS'] = C_CCFLAGS
1603 intlenv.Append(CCFLAGS=['/Dinline#', '/D__attribute__(x)#', '/Duintmax_t=UINT_MAX'])
1604 # intl does not use global config.h
1605 intlenv['CPPPATH'] = ['$BUILDDIR/intl'] + extra_inc_paths
1607 intlenv.Append(CCFLAGS = [
1608 r'-DLOCALEDIR=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1609 r'-DLOCALE_ALIAS_PATH=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1610 r'-DLIBDIR=\"' + env['TOP_SRCDIR'].replace('\\', '\\\\') + r'/lib\"',
1612 '-DENABLE_RELOCATABLE=1',
1614 r'-DINSTALLDIR=\"' + prefix.replace('\\', '\\\\') + r'/lib\"',
1616 '-Dset_relocation_prefix=libintl_set_relocation_prefix',
1617 '-Drelocate=libintl_relocate',
1618 '-DDEPENDS_ON_LIBICONV=1',
1623 intl = intlenv.StaticLibrary(
1624 target = '$LOCALLIBPATH/included_intl',
1626 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/intl'), pattern = '*.c',
1627 exclude = ['vasnprintf.c', 'printf-parse.c', 'printf-args.c', 'os2compat.c'],
1628 build_dir = '$BUILDDIR/intl')
1634 # Now, src code under src/
1636 env.BuildDir('$BUILDDIR/common', '$TOP_SRCDIR/src', duplicate = 0)
1643 print "Processing files in src/support..."
1645 env.substFile('$BUILDDIR/common/support/package.C', '$TOP_SRCDIR/src/support/package.C.in')
1647 support = env.StaticLibrary(
1648 target = '$LOCALLIBPATH/support',
1649 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/support'), pattern = lyx_ext,
1650 exclude = ['os_win32.C', 'os_unix.C', 'os_cygwin.C', 'os_os2.C', 'atexit.c'],
1651 include = ['package.C'], build_dir = '$BUILDDIR/common/support')
1653 Alias('support', support)
1660 print "Processing files in src/mathed..."
1662 mathed = env.StaticLibrary(
1663 target = '$LOCALLIBPATH/mathed',
1664 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/mathed'),
1666 exclude = ['math_xyarrowinset.C', 'math_mboxinset.C', 'formulamacro.C'],
1667 build_dir = '$BUILDDIR/common/mathed')
1669 Alias('mathed', mathed)
1676 print "Processing files in src/insets..."
1678 insets = env.StaticLibrary(
1679 target = '$LOCALLIBPATH/insets',
1680 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/insets'),
1682 exclude = ['insettheorem.C'], build_dir = '$BUILDDIR/common/insets')
1684 Alias('insets', insets)
1691 print "Processing files in src/frontends..."
1693 frontends = env.StaticLibrary(
1694 target = '$LOCALLIBPATH/frontends',
1695 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends'), pattern = lyx_ext,
1696 build_dir = '$BUILDDIR/common/frontends')
1698 Alias('frontends', frontends)
1705 print "Processing files in src/graphics..."
1707 graphics = env.StaticLibrary(
1708 target = '$LOCALLIBPATH/graphics',
1709 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/graphics'), pattern = lyx_ext,
1710 build_dir = '$BUILDDIR/common/graphics')
1712 Alias('graphics', graphics)
1715 if build_controllers:
1717 # src/frontends/controllers
1719 print "Processing files in src/frontends/controllers..."
1721 controllers = env.StaticLibrary(
1722 target = '$LOCALLIBPATH/controllers',
1723 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/controllers'), pattern = lyx_ext,
1724 build_dir = '$BUILDDIR/common/frontends/controllers')
1726 Alias('controllers', controllers)
1730 # src/frontend/qt2/3/4
1732 if build_qt2 or build_qt3 or build_qt4:
1733 env.BuildDir('$BUILDDIR/$frontend', '$TOP_SRCDIR/src/frontend/$frontend', duplicate = 0)
1737 print "Processing files in src/frontends/qt2..."
1740 # disable auto scan to speed up non build time
1741 qt2env['QT_AUTOSCAN'] = 0
1742 qt2env['QT_MOCHPREFIX'] = ''
1747 qt2env.AppendUnique(CPPPATH = [
1749 '$BUILDDIR/common/images',
1750 '$BUILDDIR/common/frontends',
1751 '$BUILDDIR/common/frontends/qt2',
1752 '$BUILDDIR/common/frontends/controllers',
1756 qt2_moc_files = ["$BUILDDIR/common/frontends/qt2/%s" % x for x in Split('''
1759 FileDialog_private.C
1798 QSpellcheckerDialog.C
1800 QTabularCreateDialog.C
1815 # manually moc and uic files for better performance
1816 qt2_moced_files = [qt2env.Moc(x.replace('.C', '_moc.cpp'), x.replace('.C', '.h')) for x in qt2_moc_files]
1818 qt2_uiced_files = [qt2env.Uic('$BUILDDIR/common/frontends/qt2/ui/'+x) for x in \
1819 utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/qt2/ui'), pattern = '*.ui')]
1821 qt2_uiced_cc_files = []
1822 for x in qt2_uiced_files:
1823 qt2_uiced_cc_files.extend(x[1:])
1825 qt2 = qt2env.StaticLibrary(
1826 target = '$LOCALLIBPATH/qt2',
1827 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/qt2/'), pattern = lyx_ext,
1828 build_dir = '$BUILDDIR/common/frontends/qt2') + qt2_moced_files + qt2_uiced_cc_files
1834 print "Processing files in src/frontends/qt3..."
1837 # disable auto scan to speed up non build time
1838 qt3env['QT_AUTOSCAN'] = 0
1839 qt3env['QT_MOCHPREFIX'] = ''
1844 qt3env.AppendUnique(CPPPATH = [
1846 '$BUILDDIR/common/images',
1847 '$BUILDDIR/common/frontends',
1848 '$BUILDDIR/common/frontends/qt3',
1849 '$BUILDDIR/common/frontends/controllers',
1853 qt3_moc_files = ["$BUILDDIR/common/frontends/qt3/%s" % x for x in Split('''
1856 FileDialog_private.C
1896 QSpellcheckerDialog.C
1898 QTabularCreateDialog.C
1913 # manually moc and uic files for better performance
1914 qt3_moced_files = [qt3env.Moc(x.replace('.C', '_moc.cpp'), x.replace('.C', '.h')) for x in qt3_moc_files]
1916 qt3_uiced_files = [qt3env.Uic('$BUILDDIR/common/frontends/qt3/ui/'+x) for x in \
1917 utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/qt3/ui'), pattern = '*.ui')]
1919 qt3_uiced_cc_files = []
1920 for x in qt3_uiced_files:
1921 qt3_uiced_cc_files.extend(x[1:])
1923 qt3 = qt3env.StaticLibrary(
1924 target = '$LOCALLIBPATH/qt3',
1925 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/qt3/'), pattern = lyx_ext,
1926 build_dir = '$BUILDDIR/common/frontends/qt3') + qt3_moced_files + qt3_uiced_cc_files
1932 print "Processing files in src/frontends/qt4..."
1935 qt4env['QT_AUTOSCAN'] = 0
1937 # local qt4 toolset from
1938 # http://www.iua.upf.es/~dgarcia/Codders/sconstools.html
1940 # NOTE: I have to patch qt4.py since it does not automatically
1941 # process .C file!!! (add to cxx_suffixes )
1943 qt4env.Tool('qt4', [scons_dir])
1944 qt4env.EnableQt4Modules(qt_libs, debug = (mode == 'debug'))
1946 qt4env.AppendUnique(CPPPATH = [
1948 '$BUILDDIR/common/images',
1949 '$BUILDDIR/common/frontends',
1950 '$BUILDDIR/common/frontends/qt4',
1951 '$BUILDDIR/common/frontends/controllers',
1956 # FIXME: replace by something from pkg_config
1957 qt4env.Append(CCFLAGS = [
1959 '-DQT_CLEAN_NAMESPACE',
1968 qt4_moc_files = ["$BUILDDIR/common/frontends/qt4/%s" % x for x in Split('''
1971 FileDialog_private.C
2014 QSpellcheckerDialog.C
2016 QTabularCreateDialog.C
2035 resources = [qt4env.Uic4(x.split('.')[0]) for x in \
2036 utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/qt4/ui'), pattern = '*.ui',
2037 build_dir = '$BUILDDIR/common/frontends/qt4/ui')]
2040 # moc qt4_moc_files, the moced files are included in the original files
2042 qt4_moced_files = [qt4env.Moc4(x.replace('.C', '_moc.cpp'), x.replace('.C', '.h')) for x in qt4_moc_files]
2044 qt4 = qt4env.StaticLibrary(
2045 target = '$LOCALLIBPATH/qt4',
2046 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/qt4'), pattern = lyx_ext,
2047 exclude = ['QBrowseBox.C'], build_dir = '$BUILDDIR/common/frontends/qt4')
2056 env.BuildDir('$BUILDDIR/common', '$TOP_SRCDIR/src', duplicate = 0)
2058 print "Processing files in src/client..."
2060 if env['HAVE_FCNTL']:
2061 client = env.Program(
2062 target = '$BUILDDIR/common/client/lyxclient',
2063 LIBS = ['support'] + intl_libs + system_libs +
2064 socket_libs + boost_libraries,
2065 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/client'), pattern = lyx_ext,
2066 build_dir = '$BUILDDIR/common/client')
2068 Alias('client', env.Command(os.path.join('$BUILDDIR', os.path.split(str(client[0]))[1]),
2069 client, [Copy('$TARGET', '$SOURCE')]))
2072 Alias('client', client)
2074 if env['HAVE_FCNTL']:
2075 # define client even if lyxclient is not built with rebuild=no
2076 client = [env.subst('$BUILDDIR/common/client/${PROGPREFIX}lyxclient$PROGSUFFIX')]
2085 print "Processing files in src/tex2lyx..."
2087 tex2lyx_env = env.Copy()
2089 tex2lyx_env.Prepend(CPPPATH = ['$BUILDDIR/common/tex2lyx'])
2090 tex2lyx_env.AppendUnique(LIBPATH = ['#$LOCALLIBPATH'])
2092 for file in ['FloatList.C', 'Floating.C', 'counters.C', 'lyxlayout.h', 'lyxlayout.C',
2093 'lyxtextclass.h', 'lyxtextclass.C', 'lyxlex.C', 'lyxlex_pimpl.C']:
2094 env.Command('$BUILDDIR/common/tex2lyx/'+file, '$TOP_SRCDIR/src/'+file,
2095 [Copy('$TARGET', '$SOURCE')])
2097 tex2lyx = tex2lyx_env.Program(
2098 target = '$BUILDDIR/common/tex2lyx/tex2lyx',
2099 LIBS = ['support'] + boost_libraries + system_libs,
2100 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/tex2lyx'), pattern = lyx_ext,
2101 include = ['FloatList.C', 'Floating.C', 'counters.C', 'lyxlayout.C',
2102 'lyxtextclass.C', 'lyxlex.C', 'lyxlex_pimpl.C'],
2103 build_dir = '$BUILDDIR/common/tex2lyx')
2105 Alias('tex2lyx', env.Command(os.path.join('$BUILDDIR', os.path.split(str(tex2lyx[0]))[1]),
2106 tex2lyx, [Copy('$TARGET', '$SOURCE')]))
2107 Alias('tex2lyx', tex2lyx)
2109 # define tex2lyx even if tex2lyx is not built with rebuild=no
2110 tex2lyx = [env.subst('$BUILDDIR/common/tex2lyx/${PROGPREFIX}tex2lyx$PROGSUFFIX')]
2117 print "Processing files in src..."
2119 env.substFile('$BUILDDIR/common/version.C', '$TOP_SRCDIR/src/version.C.in')
2121 lyx_post_source = Split('''
2130 if env.has_key('USE_ASPELL') and env['USE_ASPELL']:
2131 lyx_post_source.append('aspell.C')
2132 elif env.has_key('USE_PSPELL') and env['USE_PSPELL']:
2133 lyx_post_source.append('pspell.C')
2134 elif env.has_key('USE_ISPELL') and env['USE_ISPELL']:
2135 lyx_post_source.append('ispell.C')
2137 # msvc requires at least one source file with main()
2138 # so I exclude main.C from lyxbase
2139 lyxbase_pre = env.StaticLibrary(
2140 target = '$LOCALLIBPATH/lyxbase_pre',
2141 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src'), pattern = lyx_ext,
2142 exclude = lyx_post_source + ['main.C', 'aspell.C', 'pspell.C',
2143 'ispell.C', 'Variables.C', 'Sectioning.C'],
2144 include = ['version.C'], build_dir = '$BUILDDIR/common')
2146 lyxbase_post = env.StaticLibrary(
2147 target = '$LOCALLIBPATH/lyxbase_post',
2148 source = ["$BUILDDIR/common/%s" % x for x in lyx_post_source]
2150 Alias('lyxbase', lyxbase_pre)
2151 Alias('lyxbase', lyxbase_post)
2156 # Build lyx with given frontend
2159 target = '$BUILDDIR/$frontend/lyx',
2160 source = ['$BUILDDIR/common/main.C'],
2178 # [/path/to/lyx.ext] => lyx-qt3.ext
2179 target_name = os.path.split(str(lyx[0]))[1].replace('lyx', 'lyx-%s' % frontend)
2180 Alias('lyx', env.Command(os.path.join('$BUILDDIR', target_name), lyx,
2181 [Copy('$TARGET', '$SOURCE')]))
2184 # define lyx even if lyx is not built with rebuild=no
2185 lyx = [env.subst('$BUILDDIR/$frontend/${PROGPREFIX}lyx$PROGSUFFIX')]
2188 if build_msvs_projects:
2189 def build_project(target, dir, full_target = None,
2190 src_pattern = lyx_ext, include = [], resource = None, rebuildTargetOnly = True):
2191 ''' build mavs project files
2192 target: alias (correspond to directory name)
2193 dir: source directory or directories (a list)
2194 full_target: full path/filename of the target
2195 src_pattern: glob pattern
2196 include: files to include into source
2197 resource: directory or directories with resource (.ui) files
2198 rebuildTargetOnly: whether or not only rebuild this target
2200 For non-debug-able targets like static libraries, target (alias) is
2201 enough to build the target. For executable targets, msvs need to know
2202 the full path to start debug them.
2204 if resource is not None:
2205 res = utils.globSource(dir = env.subst('$TOP_SRCDIR/'+resource), pattern = '*.ui',
2206 build_dir = env.subst('$TOP_SRCDIR/'+resource))
2209 if rebuildTargetOnly:
2210 cmds = 'fast_start=yes rebuild='+target
2212 cmds = 'fast_start=yes'
2213 if type(dir) == type([]):
2217 src.extend(utils.globSource(dir = env.subst('$TOP_SRCDIR/' + d),
2218 pattern = src_pattern, include = include,
2219 build_dir = env.subst('$TOP_SRCDIR/' + d) ))
2220 inc.extend(utils.globSource(dir = env.subst('$TOP_SRCDIR/' + d),
2222 build_dir = env.subst('$TOP_SRCDIR/' + d) ))
2224 src = utils.globSource(dir = env.subst('$TOP_SRCDIR/' + dir),
2225 pattern = src_pattern, include = include,
2226 build_dir = env.subst('$TOP_SRCDIR/' + dir) )
2227 inc = utils.globSource(dir = env.subst('$TOP_SRCDIR/' + dir),
2229 build_dir = env.subst('$TOP_SRCDIR/' + dir) )
2230 if full_target is None:
2231 build_target = target
2233 build_target = full_target
2235 proj = env.MSVSProject(
2236 target = target + env['MSVSPROJECTSUFFIX'],
2238 incs = [env.subst('$TOP_SRCDIR/src/config.h')],
2241 buildtarget = build_target,
2245 Alias('msvs_projects', proj)
2247 build_project('boost', ['boost/libs/%s/src' % x for x in boost_libs],
2248 src_pattern = '*.cpp')
2250 build_project('intl', 'intl', src_pattern = '*.c')
2252 build_project('support', 'src/support', include=['package.C.in'])
2254 build_project('mathed', 'src/mathed')
2256 build_project('insets', 'src/insets')
2258 build_project('frontends', 'src/frontends')
2260 build_project('graphics', 'src/graphics')
2262 build_project('controllers', 'src/frontends/controllers')
2264 build_project('qt3', 'src/frontends/qt3', resource = 'src/frontends/qt3/ui')
2266 build_project('qt4', 'src/frontends/qt4', resource = 'src/frontends/qt4/ui')
2268 build_project('client', 'src/client', rebuildTargetOnly = False,
2269 full_target = File(env.subst('$BUILDDIR/common/client/lyxclient$PROGSUFFIX')).abspath)
2271 build_project('tex2lyx', 'src/tex2lyx', rebuildTargetOnly = False,
2272 full_target = File(env.subst('$BUILDDIR/common/tex2lyx/tex2lyx$PROGSUFFIX')).abspath)
2274 build_project('lyxbase', 'src')
2276 if frontend == 'qt3':
2277 build_project('lyx', ['src', 'src/support', 'src/mathed', 'src/insets',
2278 'src/frontends', 'src/graphics', 'src/frontends/controllers',
2279 'src/frontends/qt3'], resource = 'src/frontends/qt3/ui',
2280 rebuildTargetOnly = False,
2281 full_target = File(env.subst('$BUILDDIR/$frontend/lyx$PROGSUFFIX')).abspath)
2283 build_project('lyx', ['src', 'src/support', 'src/mathed', 'src/insets',
2284 'src/frontends', 'src/graphics', 'src/frontends/controllers',
2285 'src/frontends/qt4'], resource = 'src/frontends/qt4/ui',
2286 rebuildTargetOnly = False,
2287 full_target = File(env.subst('$BUILDDIR/$frontend/lyx$PROGSUFFIX')).abspath)
2294 print 'Processing files in po...'
2299 # files to translate
2300 transfiles = glob.glob(os.path.join(env.subst('$TOP_SRCDIR'), 'po', '*.po'))
2301 # possibly *only* handle these languages
2303 if env.has_key('languages'):
2304 languages = env.make_list(env['lanauges'])
2305 # use defulat msgfmt
2307 if not env['MSGFMT']:
2308 print 'msgfmt does not exist. Can not process po files'
2311 env['BUILDERS']['Transfiles'] = Builder(action='$MSGFMT $SOURCE -o $TARGET',suffix='.gmo',src_suffix='.po')
2313 for f in transfiles:
2315 fname = os.path.split(f)[1]
2317 country = fname.split('.')[0]
2319 if not languages or country in languages:
2320 gmo_files.extend(env.Transfiles(f))
2323 if 'install' in targets:
2325 # this part is a bit messy right now. Since scons will provide
2326 # --DESTDIR option soon, at least the dest_dir handling can be
2329 # how to join dest_dir and prefix
2330 def joinPaths(path1, path2):
2331 ''' join path1 and path2, do not use os.path.join because
2332 under window, c:\destdir\d:\program is invalid '''
2334 return os.path.normpath(path2)
2335 # separate drive letter
2336 (drive, path) = os.path.splitdrive(os.path.normpath(path2))
2337 # ignore drive letter, so c:\destdir + c:\program = c:\destdir\program
2338 return os.path.join(os.path.normpath(path1), path[1:])
2340 # install to dest_dir/prefix
2341 dest_dir = env.get('DESTDIR', None)
2342 dest_prefix_dir = joinPaths(dest_dir, env.Dir(prefix).abspath)
2343 # create the directory if needed
2344 if not os.path.isdir(dest_prefix_dir):
2346 os.makedirs(dest_prefix_dir)
2349 if not os.path.isdir(dest_prefix_dir):
2350 print 'Can not create directory', dest_prefix_dir
2353 if env.has_key('exec_prefix'):
2354 bin_dest_dir = joinPaths(dest_dir, Dir(env['exec_prefix']).abspath)
2356 bin_dest_dir = os.path.join(dest_prefix_dir, 'bin')
2358 share_dest_dir = os.path.join(dest_prefix_dir, share_dir + program_suffix)
2360 share_dest_dir = os.path.join(dest_prefix_dir, share_dir)
2361 man_dest_dir = os.path.join(dest_prefix_dir, man_dir)
2362 locale_dest_dir = os.path.join(dest_prefix_dir, locale_dir)
2366 # do not install these files
2367 exclude_list = ['Makefile.am', 'Makefile.in', 'Makefile',
2368 'lyx2lyx_version.py.in']
2370 def install(dest, src):
2371 ''' recusive installation of src to dest '''
2372 # separate file and directory
2373 files = filter(lambda x: os.path.isfile(x) and not os.path.split(x)[1] in exclude_list, src)
2374 dirs = filter(os.path.isdir, src)
2376 env.Install(dest, files)
2380 ins_dir.extend(install(os.path.join(dest, os.path.basename(dir)),
2381 glob.glob(os.path.join(dir, '*'))) )
2384 # install executables (lyxclient may be None)
2387 version_suffix = program_suffix
2392 target_name = os.path.split(str(lyx[0]))[1].replace('lyx', 'lyx%s' % version_suffix)
2393 target = os.path.join(bin_dest_dir, target_name)
2394 env.InstallAs(target, lyx)
2395 Alias('install', target)
2396 # install lyx as lyx-qt3
2397 target_name = os.path.split(str(lyx[0]))[1].replace('lyx', 'lyx-%s%s' % (frontend, version_suffix))
2398 target = os.path.join(bin_dest_dir, target_name)
2399 env.InstallAs(target, lyx)
2400 Alias('install', target)
2403 target_name = os.path.split(str(tex2lyx[0]))[1].replace('tex2lyx', 'tex2lyx%s' % version_suffix)
2404 target = os.path.join(bin_dest_dir, target_name)
2405 env.InstallAs(target, tex2lyx)
2406 Alias('install', target)
2408 # install lyxclient, may not exist
2410 target_name = os.path.split(str(client[0]))[1].replace('client', 'client%s' % version_suffix)
2411 target = os.path.join(bin_dest_dir, target_name)
2412 env.InstallAs(target, client)
2413 Alias('install', target)
2416 dirs = install(share_dest_dir,
2417 [env.subst('$TOP_SRCDIR/lib/') + file for file in ['configure.py', 'encodings',
2418 'chkconfig.ltx', 'CREDITS', 'external_templates', 'symbols', 'languages',
2419 'lyxrc.example', 'syntax.default', 'bind', 'images', 'layouts', 'scripts',
2420 'templates', 'examples', 'kbd', 'lyx2lyx', 'tex', 'clipart', 'doc', 'ui']]
2422 # lyx1.4.x does not have lyx2lyx_version.py.in
2423 if os.path.isfile(env.subst('$TOP_SRCDIR/lib/lyx2lyx/lyx2lyx_version.py.in')):
2424 # subst and install this file
2425 env.substFile(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py',
2426 '$TOP_SRCDIR/lib/lyx2lyx/lyx2lyx_version.py.in')
2427 Alias('install', share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2428 Alias('install', dirs)
2430 env.InstallAs(os.path.join(man_dest_dir, 'lyx' + version_suffix + '.1'),
2431 env.subst('$TOP_SRCDIR/lyx.man'))
2432 env.InstallAs(os.path.join(man_dest_dir, 'tex2lyx' + version_suffix + '.1'),
2433 env.subst('$TOP_SRCDIR/src/tex2lyx/tex2lyx.man'))
2434 env.InstallAs(os.path.join(man_dest_dir, 'lyxclient' + version_suffix + '.1'),
2435 env.subst('$TOP_SRCDIR/src/client/lyxclient.man'))
2436 Alias('install', [os.path.join(man_dest_dir, x + version_suffix + '.1') for
2437 x in ['lyx', 'tex2lyx', 'lyxclient']])
2439 # ru.gmo ==> ru/LC_MESSAGES/lyxSUFFIX.mo
2440 for gmo in gmo_files:
2441 lan = os.path.split(str(gmo))[1].split('.')[0]
2442 dest_file = os.path.join(locale_dest_dir, lan, 'LC_MESSAGES', 'lyx' + version_suffix + '.mo')
2443 env.InstallAs(dest_file, gmo)
2444 Alias('install', dest_file)
2448 Alias('all', ['lyx', 'client', 'tex2lyx'])