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.91 (not 0.96.1)
28 EnsureSConsVersion(0, 96)
30 # determine where I am ...
32 # called as 'cd development/scons; scons'
33 if os.path.isfile('SConstruct'):
36 # called as 'scons -f development/scons/SConstruct'
39 scons_dir = 'development/scons'
42 #----------------------------------------------------------
44 #----------------------------------------------------------
46 # some global settings
48 # detect version of lyx
49 # only 1.4.x has frontends/qt2
50 if os.path.isdir(os.path.join(top_src_dir, 'src', 'frontends', 'qt2')):
51 package_version = '1.4.2svn'
52 boost_version = '1_32'
54 package_version = '1.5.0svn'
55 boost_version = '1_33_1'
58 default_build_mode = 'debug'
62 package_bugreport = 'lyx-devel@lists.lyx.org'
64 package_tarname = 'lyx'
65 package_string = '%s %s' % (package_name, package_version)
67 # various cache/log files
68 default_log_file = 'scons_lyx.log'
69 env_cache_file = 'env.cache'
72 #----------------------------------------------------------
73 # platform dependent settings
74 #----------------------------------------------------------
77 platform_name = 'win32'
78 default_frontend = 'qt4'
79 default_prefix = 'c:/program files/lyx'
80 default_with_x = False
81 default_packaging_method = 'windows'
82 elif os.name == 'posix' and sys.platform != 'cygwin':
83 platform_name = sys.platform
84 default_frontend = 'qt3'
85 default_prefix = '/usr/local'
87 default_packaging_method = 'posix'
88 elif os.name == 'posix' and sys.platform == 'cygwin':
89 platform_name = 'cygwin'
90 default_frontend = 'qt3'
91 default_prefix = '/usr'
93 default_packaging_method = 'posix'
94 elif os.name == 'darwin':
95 platform_name = 'macosx'
96 default_frontend = 'qt3'
97 # FIXME: macOSX default prefix?
99 default_with_x = False
100 default_packaging_method = 'macosx'
101 else: # unsupported system, assume posix behavior
102 platform_name = 'others'
103 default_frontend = 'qt3'
105 default_with_x = True
106 default_packaging_method = 'posix'
108 # 1.4.2 only has qt2 frontend
109 if package_version == '1.4.2svn':
110 default_frontend = 'qt2'
112 #---------------------------------------------------------
114 #----------------------------------------------------------
116 # You can set perminant default values in config.py
117 if os.path.isfile('config.py'):
118 print "Getting options from config.py..."
119 print open('config.py').read()
121 opts = Options(['config.py'])
124 EnumOption('frontend', 'Main GUI', default_frontend,
125 allowed_values = ('qt2', 'qt3', 'qt4', 'gtk') ),
126 # debug or release build
127 EnumOption('mode', 'Building method', default_build_mode,
128 allowed_values = ('debug', 'release') ),
131 'Use included, system boost library, or try sytem boost first.',
132 'auto', allowed_values = (
133 'auto', # detect boost, if not found, use included
134 'included', # always use included boost
135 'system', # always use system boost, fail if can not find
138 EnumOption('gettext',
139 'Use included, system gettext library, or try sytem gettext first',
140 'auto', allowed_values = (
141 'auto', # detect gettext, if not found, use included
142 'included', # always use included gettext
143 'system', # always use system gettext, fail if can not find
146 EnumOption('spell', 'Choose spell checker to use.', 'auto',
147 allowed_values = ('aspell', 'pspell', 'ispell', 'auto', 'no') ),
149 EnumOption('packaging', 'Packaging method to use.', default_packaging_method,
150 allowed_values = ('windows', 'posix', 'macosx')),
152 BoolOption('fast_start', 'Whether or not use cached tests and keep current config.h', True),
153 # No precompiled header support (too troublesome to make it work for msvc)
154 # BoolOption('pch', 'Whether or not use pch', False),
155 # enable assertion, (config.h has ENABLE_ASSERTIOS
156 BoolOption('assertions', 'Use assertions', True),
157 # enable warning, (config.h has WITH_WARNINGS)
158 # default to False since MSVC does not have #warning
159 BoolOption('warnings', 'Use warnings', False),
160 # config.h define _GLIBCXX_CONCEPT_CHECKS
161 # Note: for earlier version of gcc (3.3) define _GLIBCPP_CONCEPT_CHECKS
162 BoolOption('concept_checks', 'Enable concept checks', True),
164 BoolOption('nls', 'Whether or not use native language support', True),
166 BoolOption('profiling', 'Whether or not enable profiling', False),
167 # config.h define _GLIBCXX_DEBUG and _GLIBCXX_DEBUG_PEDANTIC
168 BoolOption('stdlib_debug', 'Whether or not turn on stdlib debug', False),
170 BoolOption('X11', 'Use x11 windows system', default_with_x),
171 # use MS VC++ to build lyx
172 BoolOption('use_vc', 'Use MS VC++ to build lyx (cl.exe will be probed)', None),
174 PathOption('qt_dir', 'Path to qt directory', None),
176 PathOption('qt_inc_path', 'Path to qt include directory', None),
178 PathOption('qt_lib_path', 'Path to qt library directory', None),
179 # extra include and libpath
180 PathOption('extra_inc_path', 'Extra include path', None),
182 PathOption('extra_lib_path', 'Extra library path', None),
184 PathOption('extra_bin_path', 'A convenient way to add a path to $PATH', None),
186 PathOption('extra_inc_path1', 'Extra include path', None),
188 PathOption('extra_lib_path1', 'Extra library path', None),
189 # rebuild only specifed, comma separated targets
190 ('rebuild', '''rebuild only specifed, comma separated targets.
191 yes or all (default): rebuild everything
192 no or none: rebuild nothing (usually used for installation)
193 comp1,comp2,...: rebuild specified targets''', None),
194 # can be set to a non-existing directory
195 ('prefix', 'install architecture-independent files in PREFIX', default_prefix),
196 # build directory, will use $mode if not set
197 ('build_dir', 'Build directory', None),
199 ('version_suffix', 'install lyx as lyx-suffix', None),
200 # how to load options
201 ('load_option', '''load option from previous scons run. option can be
202 yes (default): load all options
203 no: do not load any option
204 opt1,opt2: load specified options
205 -opt1,opt2: load all options other than specified ones''', 'yes'),
207 ('optimization', 'optimization CCFLAGS option.', None),
209 PathOption('exec_prefix', 'install architecture-independent executable files in PREFIX', None),
211 ('logfile', 'save commands (not outputs) to logfile', default_log_file),
212 # provided for backward compatibility
213 ('dest_dir', 'install to DESTDIR. (Provided for backward compatibility only)', None),
214 # environment variable can be set as options.
215 ('DESTDIR', 'install to DESTDIR', None),
216 ('CC', 'replace default $CC', None),
217 ('LINK', 'replace default $LINK', None),
218 ('CPP', 'replace default $CPP', None),
219 ('CXX', 'replace default $CXX', None),
220 ('CXXCPP', 'replace default $CXXCPP', None),
221 ('CCFLAGS', 'replace default $CCFLAGS', None),
222 ('CPPFLAGS', 'replace default $CPPFLAGS', None),
223 ('LINKFLAGS', 'replace default $LINKFLAGS', None),
227 all_options = [x.key for x in opts.options]
229 # copied from SCons/Options/BoolOption.py
230 # We need to use them before a boolean ARGUMENTS option is available
232 true_strings = ('y', 'yes', 'true', 't', '1', 'on' , 'all' )
233 false_strings = ('n', 'no', 'false', 'f', '0', 'off', 'none')
235 # whether or not use current config.h, and cached tests
237 # if fast_start=yes (default), load variables from env_cache_file
238 if (not ARGUMENTS.has_key('fast_start') or \
239 ARGUMENTS['fast_start'] in true_strings) \
240 and os.path.isfile(env_cache_file):
242 cache_file = open(env_cache_file)
243 env_cache = cPickle.load(cache_file)
245 print '------------ fast_start mode --------------------'
246 print ' Use cached test results and current config.h'
247 print ' use fast_start=no to override'
253 # if load_option=yes (default), load saved comand line options
255 # This option can take value yes/no/opt1,opt2/-opt1,opt2
256 # and tries to be clever in choosing options to load
257 if (not ARGUMENTS.has_key('load_option') or \
258 ARGUMENTS['load_option'] not in false_strings) \
259 and os.path.isfile(env_cache_file):
260 cache_file = open(env_cache_file)
261 opt_cache = cPickle.load(cache_file)['arg_cache']
263 # import cached options, but we should ignore qt_dir when frontend changes
264 if ARGUMENTS.has_key('frontend') and opt_cache.has_key('frontend') \
265 and ARGUMENTS['frontend'] != opt_cache['frontend'] \
266 and opt_cache.has_key('qt_dir'):
267 opt_cache.pop('qt_dir')
268 # some options will require full rebuild
269 # these are in general things that will change config.h
270 for arg in ['version_suffix', 'nls', 'boost', 'spell']:
271 if ARGUMENTS.has_key(arg) and ((not opt_cache.has_key(arg)) or \
272 ARGUMENTS[arg] != opt_cache[arg]):
274 print " ** fast_start is disabled because of the change of option", arg
277 # and we do not cache some options (dest_dir is obsolete)
278 for arg in ['fast_start', 'load_option', 'dest_dir']:
279 if opt_cache.has_key(arg):
281 # remove obsolete cached keys (well, SConstruct is evolving. :-)
282 for arg in opt_cache.keys():
283 if arg not in all_options:
284 print 'Option %s is obsolete, do not load it' % arg
286 # now, if load_option=opt1,opt2 or -opt1,opt2
287 if ARGUMENTS.has_key('load_option') and \
288 ARGUMENTS['load_option'] not in true_strings + false_strings:
289 # if -opt1,opt2 is specified, do not load these options
290 if ARGUMENTS['load_option'][0] == '-':
291 for arg in ARGUMENTS['load_option'][1:].split(','):
292 if opt_cache.has_key(arg):
294 # if opt1,opt2 is specified, only load specified options
296 args = ARGUMENTS['load_option'].split(',')
297 for arg in opt_cache.keys():
300 # now restore options as if entered from command line
301 for key in opt_cache.keys():
302 if not ARGUMENTS.has_key(key):
303 ARGUMENTS[key] = opt_cache[key]
304 print "Restoring cached option %s=%s" % (key, ARGUMENTS[key])
307 # check if there is unused (or misspelled) argument
308 for arg in ARGUMENTS.keys():
309 if arg not in all_options:
311 print "Unknown option '%s'... exiting." % arg
313 print "Available options are (check 'scons -help' for details):"
314 print ' ' + '\n '.join(textwrap.wrap(', '.join(all_options)))
318 env_cache['arg_cache'] = ARGUMENTS
321 #---------------------------------------------------------
322 # Setting up environment
323 #---------------------------------------------------------
325 # I do not really like ENV=os.environ, but you may add it
326 # here if you experience some environment related problem
327 env = Environment(options = opts)
329 # set individual variables since I do not really like ENV = os.environ
330 env['ENV']['PATH'] = os.environ.get('PATH')
331 env['ENV']['HOME'] = os.environ.get('HOME')
332 # these are defined for MSVC
333 env['ENV']['LIB'] = os.environ.get('LIB')
334 env['ENV']['INCLUDE'] = os.environ.get('INCLUDE')
336 # for simplicity, use var instead of env[var]
337 frontend = env['frontend']
338 prefix = env['prefix']
341 if platform_name == 'win32':
342 if env.has_key('use_vc'):
343 use_vc = env['use_vc']
344 if WhereIs('cl.exe') is None:
345 print "cl.exe is not found. Are you using the MSVC environment?"
347 elif WhereIs('cl.exe') is not None:
354 # lyx will be built to $build/build_dir so it is possible
355 # to build multiple build_dirs using the same source
356 # $mode can be debug or release
357 if env.has_key('build_dir') and env['build_dir'] is not None:
358 # create the directory if needed
359 if not os.path.isdir(env['build_dir']):
361 os.makedirs(env['build_dir'])
364 if not os.path.isdir(env['build_dir']):
365 print 'Can not create directory', env['build_dir']
367 env['BUILDDIR'] = env['build_dir']
369 # Determine the name of the build $mode
370 env['BUILDDIR'] = '#' + mode
372 # all built libraries will go to build_dir/libs
373 # (This is different from the make file approach)
374 env['LOCALLIBPATH'] = '$BUILDDIR/libs'
375 env.AppendUnique(LIBPATH = ['$LOCALLIBPATH'])
378 # Here is a summary of variables defined in env
380 # 2. undefined options with a non-None default value
381 # 3. compiler commands and flags like CCFLAGS.
382 # MSGFMT used to process po files
383 # 4. Variables that will be used to replace variables in some_file.in
384 # src/support/package.C.in:
385 # TOP_SRCDIR, LOCALEDIR, LYX_DIR, PROGRAM_SUFFIX
386 # lib/lyx2lyx/lyx2lyx_version.py.in
389 # PACKAGE_VERSION, VERSION_INFO
391 # full path name is used to build msvs project files
392 # and to replace TOP_SRCDIR in package.C
393 env['TOP_SRCDIR'] = Dir(top_src_dir).abspath
394 # needed by src/version.C.in => src/version.C
395 env['PACKAGE_VERSION'] = package_version
397 # determine share_dir etc
398 packaging_method = env.get('packaging')
399 if packaging_method == 'windows':
400 share_dir = 'Resources'
401 man_dir = 'Resources/man/man1'
402 locale_dir = 'Resources/locale'
403 default_prefix = 'c:/program files/lyx'
405 share_dir = 'share/lyx'
407 locale_dir = 'share/locale'
408 default_prefix = '/usr/local/'
410 # install to default_prefix by default
411 # program suffix: can be yes, or a string
412 if env.has_key('version_suffix'):
413 if env['version_suffix'] in true_strings:
414 program_suffix = package_version
415 elif env['version_suffix'] in false_strings:
418 program_suffix = env['version_suffix']
421 # used by package.C.in
422 env['PROGRAM_SUFFIX'] = program_suffix
424 # whether or not add suffix to file and directory names
425 add_suffix = packaging_method != 'windows'
426 # LYX_DIR are different (used in package.C.in)
428 env['LYX_DIR'] = Dir(os.path.join(prefix, share_dir + program_suffix)).abspath
430 env['LYX_DIR'] = Dir(os.path.join(prefix, share_dir)).abspath
431 # we need absolute path for package.C
432 env['LOCALEDIR'] = Dir(os.path.join(prefix, locale_dir)).abspath
435 #---------------------------------------------------------
436 # Setting building environment (Tools, compiler flags etc)
437 #---------------------------------------------------------
439 # Since Tool('mingw') will reset CCFLAGS etc, this should be
440 # done before getEnvVariable
441 if platform_name == 'win32':
447 env.AppendUnique(CPPPATH = ['#c:/MinGW/include'])
449 # we differentiate between hard-coded options and default options
450 # hard-coded options are required and will always be there
451 # default options can be replaced by enviromental variables or command line options
452 CCFLAGS_required = []
453 LINKFLAGS_required = []
456 # under windows, scons is confused by .C/.c and uses gcc instead of
457 # g++. I am forcing the use of g++ here. This is expected to change
458 # after lyx renames all .C files to .cpp
460 # save the old c compiler and CCFLAGS (used by libintl)
461 C_COMPILER = env.subst('$CC')
462 C_CCFLAGS = env.subst('$CCFLAGS').split()
463 # if we use ms vc, the commands are fine (cl.exe and link.exe)
465 # /TP treat all source code as C++
466 # C4819: The file contains a character that cannot be represented
467 # in the current code page (number)
468 # C4996: foo was decleared deprecated
469 CCFLAGS_required.extend(['/TP', '/EHsc'])
470 CCFLAGS_default.extend(['/wd4819', '/wd4996', '/nologo'])
472 if env.has_key('CXX') and env['CXX']:
473 env['CC'] = env.subst('$CXX')
474 env['LINK'] = env.subst('$CXX')
479 # for debug/release mode
480 if env.has_key('optimization') and env['optimization'] is not None:
481 # if user supplies optimization flags, use it anyway
482 CCFLAGS_required.extend(env['optimization'].split())
483 # and do not use default
484 set_default_optimization_flags = False
486 set_default_optimization_flags = True
490 CCFLAGS_required.append('/Zi')
491 LINKFLAGS_required.extend(['/debug', '/map'])
493 CCFLAGS_required.append('-g')
494 CCFLAGS_default.append('-O')
495 elif mode == 'release' and set_default_optimization_flags:
497 CCFLAGS_default.append('/O2')
499 CCFLAGS_default.append('-O2')
501 # msvc uses separate tools for profiling
502 if env.has_key('profiling') and env['profiling']:
504 print 'Visual C++ does not use profiling options'
506 CCFLAGS_required.append('-pg')
507 LINKFLAGS_required.append('-pg')
509 if env.has_key('warnings') and env['warnings']:
511 CCFLAGS_default.append('/W2')
513 # Note: autotools detect gxx version and pass -W for 3.x
514 # and -Wextra for other versions of gcc
515 CCFLAGS_default.append('-Wall')
517 # Now, set the variables as follows:
518 # 1. if command line option exists: replace default
519 # 2. then if s envronment variable exists: replace default
520 # 3. set variable to required + default
521 def setEnvVariable(env, name, required = None, default = None, split = True):
522 ''' env: environment to set variable
524 required: hardcoded options
525 default: default options that can be replaced by command line or
526 environment variables
527 split: whether or not split obtained variable like '-02 -g'
529 # first try command line argument (override environment settings)
530 if ARGUMENTS.has_key(name):
531 default = ARGUMENTS[name]
533 default = default.split()
534 # then use environment default
535 elif os.environ.has_key(name):
536 print "Acquiring varaible %s from system environment: %s" % (name, os.environ[name])
537 default = os.environ[name]
539 default = default.split()
541 if required is not None:
543 if default is not None:
544 if env.has_key(name) and env[name] != default:
549 setEnvVariable(env, 'DESTDIR', split=False)
550 setEnvVariable(env, 'CC')
551 setEnvVariable(env, 'LINK')
552 setEnvVariable(env, 'CPP')
553 setEnvVariable(env, 'CXX')
554 setEnvVariable(env, 'CXXCPP')
555 setEnvVariable(env, 'CCFLAGS', CCFLAGS_required, CCFLAGS_default)
556 setEnvVariable(env, 'CXXFLAGS')
557 setEnvVariable(env, 'CPPFLAGS')
558 setEnvVariable(env, 'LINKFLAGS', LINKFLAGS_required)
560 # if DESTDIR is not set...
561 if env.has_key('dest_dir'):
562 print "This option is obsolete. Please use DESTDIR instead."
563 env['DESTDIR'] = env['dest_dir']
566 #---------------------------------------------------------
567 # Frontend related variables (QTDIR etc)
568 #---------------------------------------------------------
570 if env.has_key('qt_dir') and env['qt_dir']:
571 env['QTDIR'] = env['qt_dir']
572 elif os.path.isdir(os.environ.get('QTDIR', '/usr/lib/qt-3.3')):
573 env['QTDIR'] = os.environ.get('QTDIR', '/usr/lib/qt-3.3')
575 # if there is a valid QTDIR, set path for lib and bin directories
576 if env.has_key('QTDIR'):
577 # add path to the qt tools
578 if os.path.isdir(os.path.join(env['QTDIR'], 'lib')):
579 env.AppendUnique(LIBPATH = [os.path.join(env['QTDIR'], 'lib')])
580 # set environment so that moc etc can be found even if its path is not set properly
581 if os.path.isdir(os.path.join(env['QTDIR'], 'bin')):
582 os.environ['PATH'] += os.pathsep + os.path.join(env['QTDIR'], 'bin')
583 env.PrependENVPath('PATH', os.path.join(env['QTDIR'], 'bin'))
585 # allow qt2 frontend to locate qt3 libs.
586 frontend_lib = {'qt2':'qt3', 'qt3':'qt3', 'qt4':'qt4'}[frontend]
587 if env.has_key('qt_lib_path') and env['qt_lib_path']:
588 qt_lib_path = env.subst('$qt_lib_path')
589 elif env.has_key('QTDIR') and os.path.isdir(os.path.join(env.subst('$QTDIR'), 'lib')):
590 qt_lib_path = env.subst('$QTDIR/lib')
591 # this is the path for cygwin.
592 elif os.path.isdir(os.path.join('/usr/lib/', frontend_lib, 'lib')):
593 qt_lib_path = '/usr/lib/%s/lib' % frontend_lib
595 print "Qt library directory is not found. Please specify it using qt_lib_path"
597 env.AppendUnique(LIBPATH = [qt_lib_path])
598 # qt4 seems to be using pkg_config
599 env.PrependENVPath('PKG_CONFIG_PATH', qt_lib_path)
601 if env.has_key('qt_inc_path') and env['qt_inc_path']:
602 qt_inc_path = env['qt_inc_path']
603 elif env.has_key('QTDIR') and os.path.isdir(os.path.join(env.subst('$QTDIR'), 'include')):
604 qt_inc_path = '$QTDIR/include'
605 # this is the path for cygwin.
606 elif os.path.isdir('/usr/include/' + frontend_lib):
607 qt_inc_path = '/usr/include/' + frontend_lib
609 print "Qt include directory not found. Please specify it using qt_inc_path"
611 # Note that this CPPPATH is for testing only
612 # it will be removed before calling SConscript
613 env['CPPPATH'] = [qt_inc_path]
616 # extra_inc_path and extra_lib_path
619 if env.has_key('extra_inc_path') and env['extra_inc_path']:
620 extra_inc_paths.append(env['extra_inc_path'])
621 if env.has_key('extra_lib_path') and env['extra_lib_path']:
622 env.AppendUnique(LIBPATH = [env['extra_lib_path']])
623 if env.has_key('extra_inc_path1') and env['extra_inc_path1']:
624 extra_inc_paths.append(env['extra_inc_path1'])
625 if env.has_key('extra_lib_path1') and env['extra_lib_path1']:
626 env.AppendUnique(LIBPATH = [env['extra_lib_path1']])
627 if env.has_key('extra_bin_path') and env['extra_bin_path']:
628 # only the first one is needed (a scons bug?)
629 os.environ['PATH'] += os.pathsep + env['extra_bin_path']
630 env.PrependENVPath('PATH', env['extra_bin_path'])
631 # extra_inc_paths will be used later by intlenv etc
632 env.AppendUnique(CPPPATH = extra_inc_paths)
635 #----------------------------------------------------------
637 #----------------------------------------------------------
639 conf = Configure(env,
641 'CheckPkgConfig' : utils.checkPkgConfig,
642 'CheckPackage' : utils.checkPackage,
643 'CheckMkdirOneArg' : utils.checkMkdirOneArg,
644 'CheckSelectArgType' : utils.checkSelectArgType,
645 'CheckBoostLibraries' : utils.checkBoostLibraries,
646 'CheckCommand' : utils.checkCommand,
647 'CheckCXXGlobalCstd' : utils.checkCXXGlobalCstd,
648 'CheckLC_MESSAGES' : utils.checkLC_MESSAGES,
649 'CheckIconvConst' : utils.checkIconvConst,
653 # pkg-config? (if not, we use hard-coded options)
655 if conf.CheckPkgConfig('0.15.0'):
656 env['HAS_PKG_CONFIG'] = True
658 print 'pkg-config >= 0.1.50 is not found'
659 env['HAS_PKG_CONFIG'] = False
660 env_cache['HAS_PKG_CONFIG'] = env['HAS_PKG_CONFIG']
662 env['HAS_PKG_CONFIG'] = env_cache['HAS_PKG_CONFIG']
664 # zlib? This is required. (fast_start assumes the existance of zlib)
666 if (not use_vc and not conf.CheckLibWithHeader('z', 'zlib.h', 'C')) \
667 or (use_vc and not conf.CheckLibWithHeader('zdll', 'zlib.h', 'C')):
668 print 'Did not find zdll.lib or zlib.h, exiting!'
674 # qt3 does not use pkg_config
675 if frontend in ['qt2', 'qt3']:
676 if not conf.CheckLibWithHeader('qt-mt', 'qapp.h', 'c++', 'QApplication qapp();'):
677 print 'Did not find qt libraries, exiting!'
679 elif frontend == 'qt4':
681 # first: try pkg_config
682 if env['HAS_PKG_CONFIG']:
683 succ = conf.CheckPackage('QtCore') or conf.CheckPackage('QtCore4')
684 # FIXME: use pkg_config information?
685 #env['QT4_PKG_CONFIG'] = succ
686 # second: try to link to it
688 # Under linux, I can test the following perfectly
689 # Under windows, lib names need to passed as libXXX4.a ...
690 succ = conf.CheckLibWithHeader('QtCore', 'QtGui/QApplication', 'c++', 'QApplication qapp();') or \
691 conf.CheckLibWithHeader('QtCore4', 'QtGui/QApplication', 'c++', 'QApplication qapp();')
692 # third: try to look up the path
695 for lib in ['QtCore', 'QtGui']:
696 # windows version has something like QtGui4 ...
697 if not (os.path.isfile(os.path.join(qt_lib_path, 'lib%s.a' % lib)) or \
698 os.path.isfile(os.path.join(qt_lib_path, 'lib%s4.a' % lib))):
701 # still can not find it
703 print "Qt4 libraries are found."
705 print 'Did not find qt libraries, exiting!'
708 # now, if msvc2005 is used, we will need that QT_LIB_PATH/QT_LIB.manifest file
711 manifest = os.path.join(qt_lib_path, 'QtGuid4.dll.manifest')
713 manifest = os.path.join(qt_lib_path, 'QtGui4.dll.manifest')
714 if os.path.isfile(manifest):
715 env['LINKCOM'] = [env['LINKCOM'], 'mt.exe /MANIFEST %s /outputresource:$TARGET;1' % manifest]
720 if conf.CheckLib('socket'):
721 socket_libs.append('socket')
722 # nsl is the network services library and provides a
723 # transport-level interface to networking services.
724 if conf.CheckLib('nsl'):
725 socket_libs.append('nsl')
726 env_cache['SOCKET_LIBS'] = socket_libs
728 socket_libs = env_cache['SOCKET_LIBS']
730 # check available boost libs (since lyx1.4 does not use iostream)
732 for lib in ['signals', 'regex', 'filesystem', 'iostreams']:
733 if os.path.isdir(os.path.join(top_src_dir, 'boost', 'libs', lib)):
734 boost_libs.append(lib)
737 # check boost libraries
738 boost_opt = ARGUMENTS.get('boost', 'auto')
739 # check for system boost
740 lib_paths = env['LIBPATH'] + ['/usr/lib', '/usr/local/lib']
741 inc_paths = env['CPPPATH'] + ['/usr/include', '/usr/local/include']
742 # default to $BUILDDIR/libs (use None since this path will be added anyway)
744 # here I assume that all libraries are in the same directory
745 if boost_opt == 'included':
746 boost_libraries = ['included_boost_%s' % x for x in boost_libs]
747 included_boost = True
748 env['BOOST_INC_PATH'] = '$TOP_SRCDIR/boost'
749 elif boost_opt == 'auto':
750 res = conf.CheckBoostLibraries(boost_libs, lib_paths, inc_paths, boost_version, mode == 'debug')
751 # if not found, use local boost
753 boost_libraries = ['included_boost_%s' % x for x in boost_libs]
754 included_boost = True
755 env['BOOST_INC_PATH'] = '$TOP_SRCDIR/boost'
757 included_boost = False
758 (boost_libraries, boost_libpath, env['BOOST_INC_PATH']) = res
759 elif boost_opt == 'system':
760 res = conf.CheckBoostLibraries(boost_libs, lib_paths, inc_paths, boost_version, mode == 'debug')
762 print "Can not find system boost libraries with version %s " % boost_version
763 print "Please supply a path through extra_lib_path and try again."
764 print "Or use boost=included to use included boost libraries."
767 included_boost = False
768 (boost_libraries, boost_libpath, env['BOOST_INC_PATH']) = res
769 env_cache['BOOST_LIBRARIES'] = boost_libraries
770 env_cache['INCLUDED_BOOST'] = included_boost
771 env_cache['BOOST_INC_PATH'] = env['BOOST_INC_PATH']
772 env_cache['BOOST_LIBPATH'] = boost_libpath
774 boost_libraries = env_cache['BOOST_LIBRARIES']
775 included_boost = env_cache['INCLUDED_BOOST']
776 env['BOOST_INC_PATH'] = env_cache['BOOST_INC_PATH']
777 boost_libpath = env_cache['BOOST_LIBPATH']
779 if boost_libpath is not None:
780 env.AppendUnique(LIBPATH = [boost_libpath])
783 env['ENABLE_NLS'] = env['nls']
786 if not env['ENABLE_NLS']:
788 included_gettext = False
790 # check gettext libraries
791 gettext_opt = ARGUMENTS.get('gettext', 'auto')
792 # check for system gettext
794 if gettext_opt in ['auto', 'system']:
795 if conf.CheckLib('intl'):
796 included_gettext = False
800 if gettext_opt == 'system':
801 print "Can not find system gettext library"
802 print "Please supply a path through extra_lib_path and try again."
803 print "Or use gettext=included to use included gettext libraries."
805 # now, auto and succ = false, or gettext=included
807 # we do not need to set LIBPATH now.
808 included_gettext = True
809 intl_libs = ['included_intl']
810 env_cache['INCLUDED_GETTEXT'] = included_gettext
811 env_cache['INTL_LIBS'] = intl_libs
813 included_gettext = env_cache['INCLUDED_GETTEXT']
814 intl_libs = env_cache['INTL_LIBS']
817 # check for msgfmt command
819 env['MSGFMT'] = conf.CheckCommand('msgfmt')
820 env_cache['MSGFMT'] = env['MSGFMT']
822 env['MSGFMT'] = env_cache['MSGFMT']
824 # check uic and moc commands for qt frontends
826 if frontend[:2] == 'qt' and (conf.CheckCommand('uic') == None \
827 or conf.CheckCommand('moc') == None):
828 print 'uic or moc command is not found for frontend', frontend
832 # Customized builders
834 # install customized builders
835 env['BUILDERS']['substFile'] = Builder(action = utils.env_subst)
838 #----------------------------------------------------------
839 # Generating config.h
840 #----------------------------------------------------------
841 aspell_lib = 'aspell'
842 # assume that we use aspell, aspelld compiled for msvc
843 if platform_name == 'win32' and mode == 'debug' and use_vc:
844 aspell_lib = 'aspelld'
846 # check the existence of config.h
847 config_h = os.path.join(env.Dir('$BUILDDIR/common').path, 'config.h')
848 boost_config_h = os.path.join(env.Dir('$BUILDDIR/boost').path, 'config.h')
849 if not fast_start or not os.path.isfile(boost_config_h) \
850 or not os.path.isfile(config_h):
852 print "Creating %s..." % boost_config_h
854 utils.createConfigFile(conf,
855 config_file = boost_config_h,
856 config_pre = '''/* boost/config.h. Generated by SCons. */
861 * This file is part of LyX, the document processor.
862 * Licence details can be found in the file COPYING.
864 * This is the compilation configuration file for LyX.
865 * It was generated by scon.
866 * You might want to change some of the defaults if something goes wrong
867 * during the compilation.
870 #ifndef _BOOST_CONFIG_H
871 #define _BOOST_CONFIG_H
874 ('ostream', 'HAVE_OSTREAM', 'cxx'),
875 ('locale', 'HAVE_LOCALE', 'cxx'),
876 ('sstream', 'HAVE_SSTREAM', 'cxx'),
877 #('newapis.h', 'HAVE_NEWAPIS_H', 'c'),
880 (env.has_key('assertions') and env['assertions'],
882 'Define if you want assertions to be enabled in the code'
887 #if defined(HAVE_OSTREAM) && defined(HAVE_LOCALE) && defined(HAVE_SSTREAM)
888 # define USE_BOOST_FORMAT 1
890 # define USE_BOOST_FORMAT 0
893 #if !defined(ENABLE_ASSERTIONS)
894 # define BOOST_DISABLE_ASSERTS 1
896 #define BOOST_ENABLE_ASSERT_HANDLER 1
898 #define BOOST_DISABLE_THREADS 1
899 #define BOOST_NO_WREGEX 1
900 #define BOOST_NO_WSTRING 1
903 # define BOOST_POSIX 1
906 #define BOOST_ALL_NO_LIB 1
908 #if defined(HAVE_NEWAPIS_H)
909 # define WANT_GETFILEATTRIBUTESEX_WRAPPER 1
916 print "\nGenerating %s..." % config_h
918 # AIKSAURUS_H_LOCATION
919 if (conf.CheckCXXHeader("Aiksaurus.h")):
920 aik_location = '<Aiksaurus.h>'
921 elif (conf.CheckCXXHeader("Aiksaurus/Aiksaurus.h")):
922 aik_location = '<Aiksaurus/Aiksaurus.h>'
926 # determine headers to use
927 spell_opt = ARGUMENTS.get('spell', 'auto')
928 env['USE_ASPELL'] = False
929 env['USE_PSPELL'] = False
930 env['USE_ISPELL'] = False
931 if spell_opt in ['auto', 'aspell'] and conf.CheckLib(aspell_lib):
932 spell_engine = 'USE_ASPELL'
933 elif spell_opt in ['auto', 'pspell'] and conf.CheckLib('pspell'):
934 spell_engine = 'USE_PSPELL'
935 elif spell_opt in ['auto', 'ispell'] and conf.CheckLib('ispell'):
936 spell_engine = 'USE_ISPELL'
940 if spell_engine is not None:
941 env[spell_engine] = True
943 if spell_opt == 'auto':
944 print "Warning: Can not locate any spell checker"
945 elif spell_opt != 'no':
946 print "Warning: Can not locate specified spell checker:", spell_opt
949 # check arg types of select function
950 (select_arg1, select_arg234, select_arg5) = conf.CheckSelectArgType()
954 result = utils.createConfigFile(conf,
955 config_file = config_h,
956 config_pre = '''/* config.h. Generated by SCons. */
961 * This file is part of LyX, the document processor.
962 * Licence details can be found in the file COPYING.
964 * This is the compilation configuration file for LyX.
965 * It was generated by scon.
966 * You might want to change some of the defaults if something goes wrong
967 * during the compilation.
974 ('io.h', 'HAVE_IO_H', 'c'),
975 ('limits.h', 'HAVE_LIMITS_H', 'c'),
976 ('locale.h', 'HAVE_LOCALE_H', 'c'),
977 ('process.h', 'HAVE_PROCESS_H', 'c'),
978 ('stdlib.h', 'HAVE_STDLIB_H', 'c'),
979 ('sys/stat.h', 'HAVE_SYS_STAT_H', 'c'),
980 ('sys/time.h', 'HAVE_SYS_TIME_H', 'c'),
981 ('sys/types.h', 'HAVE_SYS_TYPES_H', 'c'),
982 ('sys/utime.h', 'HAVE_SYS_UTIME_H', 'c'),
983 ('sys/socket.h', 'HAVE_SYS_SOCKET_H', 'c'),
984 ('unistd.h', 'HAVE_UNISTD_H', 'c'),
985 ('utime.h', 'HAVE_UTIME_H', 'c'),
986 ('direct.h', 'HAVE_DIRECT_H', 'c'),
987 ('istream', 'HAVE_ISTREAM', 'cxx'),
988 ('ios', 'HAVE_IOS', 'cxx'),
991 ('open', 'HAVE_OPEN', None),
992 ('close', 'HAVE_CLOSE', None),
993 ('popen', 'HAVE_POPEN', None),
994 ('pclose', 'HAVE_PCLOSE', None),
995 ('_open', 'HAVE__OPEN', None),
996 ('_close', 'HAVE__CLOSE', None),
997 ('_popen', 'HAVE__POPEN', None),
998 ('_pclose', 'HAVE__PCLOSE', None),
999 ('getpid', 'HAVE_GETPID', None),
1000 ('_getpid', 'HAVE__GETPID', None),
1001 ('mkdir', 'HAVE_MKDIR', None),
1002 ('_mkdir', 'HAVE__MKDIR', None),
1003 ('mktemp', 'HAVE_MKTEMP', None),
1004 ('mkstemp', 'HAVE_MKSTEMP', None),
1005 ('strerror', 'HAVE_STRERROR', None),
1006 ('count', 'HAVE_STD_COUNT', '''
1007 #include <algorithm>
1011 return std::count(a, a+5, 'l');
1014 ('getcwd', 'HAVE_GETCWD', None),
1015 ('setenv', 'HAVE_SETENV', None),
1016 ('putenv', 'HAVE_PUTENV', None),
1017 ('fcntl', 'HAVE_FCNTL', None),
1020 ('std::istreambuf_iterator<std::istream>', 'HAVE_DECL_ISTREAMBUF_ITERATOR',
1021 '#include <streambuf>\n#include <istream>')
1024 ('gdi32', 'HAVE_LIBGDI32'),
1025 (('iconv', 'libiconv'), 'HAVE_ICONV', 'ICONV_LIB'),
1026 (('Aiksaurus', 'libAiksaurus'), 'HAVE_LIBAIKSAURUS', 'AIKSAURUS_LIB'),
1029 (conf.CheckType('pid_t', includes='#include <sys/types.h>'),
1031 'Define is sys/types.h does not have pid_t',
1033 '#define pid_t int',
1035 (conf.CheckCXXGlobalCstd(),
1037 'Define if your C++ compiler puts C library functions in the global namespace'
1039 (conf.CheckMkdirOneArg(),
1040 'MKDIR_TAKES_ONE_ARG',
1041 'Define if mkdir takes only one argument.'
1043 (conf.CheckLC_MESSAGES(),
1045 'Define if your <locale.h> file defines LC_MESSAGES.'
1047 (devel_version, 'DEVEL_VERSION', 'Whether or not a development version'),
1050 "Define to 1 if translation of program messages to the user's native anguage is requested.",
1052 (env['nls'] and not included_gettext,
1054 'Define to 1 if using system gettext library'
1056 (env.has_key('warnings') and env['warnings'],
1058 'Define this if you want to see the warning directives put here and there by the developpers to get attention'
1060 (env.has_key('concept_checks') and env['concept_checks'],
1061 '_GLIBCXX_CONCEPT_CHECKS',
1062 'libstdc++ concept checking'
1064 (env.has_key('stdlib_debug') and env['stdlib_debug'],
1066 'libstdc++ debug mode'
1068 (env.has_key('stdlib_debug') and env['stdlib_debug'],
1069 '_GLIBCXX_DEBUG_PEDANTIC',
1070 'libstdc++ pedantic debug mode'
1072 (os.name != 'nt', 'BOOST_POSIX',
1073 'Indicates to boost which API to use (posix or windows).'
1075 (spell_engine is not None, spell_engine,
1076 'Spell engine to use'
1080 ('#define PACKAGE "%s%s"' % (package, program_suffix),
1082 ('#define PACKAGE_BUGREPORT "%s"' % package_bugreport,
1083 'Define to the address where bug reports for this package should be sent.'),
1084 ('#define PACKAGE_NAME "%s"' % package_name,
1085 'Define to the full name of this package.'),
1086 ('#define PACKAGE_STRING "%s"' % package_string,
1087 'Define to the full name and version of this package.'),
1088 ('#define PACKAGE_TARNAME "%s"' % package_tarname,
1089 'Define to the one symbol short name of this package.'),
1090 ('#define PACKAGE_VERSION "%s"' % package_version,
1091 'Define to the version of this package.'),
1092 ('#define BOOST_ALL_NO_LIB 1',
1093 'disable automatic linking of boost libraries.'),
1094 ('#define USE_%s_PACKAGING 1' % packaging_method.upper(),
1095 'Packaging method'),
1096 ('#define AIKSAURUS_H_LOCATION ' + aik_location,
1097 'Aiksaurus include file'),
1098 ('#define SELECT_TYPE_ARG1 %s' % select_arg1,
1099 "Define to the type of arg 1 for `select'."),
1100 ('#define SELECT_TYPE_ARG234 %s' % select_arg234,
1101 "Define to the type of arg 2, 3, 4 for `select'."),
1102 ('#define SELECT_TYPE_ARG5 %s' % select_arg5,
1103 "Define to the type of arg 5 for `select'."),
1105 config_post = '''/************************************************************
1106 ** You should not need to change anything beyond this point */
1108 #ifndef HAVE_STRERROR
1109 #if defined(__cplusplus)
1112 char * strerror(int n);
1116 #ifndef HAVE_DECL_MKSTEMP
1117 #if defined(__cplusplus)
1124 #include <../boost/config.h>
1130 # these keys are needed in env
1131 for key in ['USE_ASPELL', 'USE_PSPELL', 'USE_ISPELL', 'HAVE_FCNTL',\
1132 'HAVE_ICONV', 'HAVE_LIBGDI32', 'HAVE_LIBAIKSAURUS',
1133 'ICONV_LIB', 'AIKSAURUS_LIB']:
1134 # USE_ASPELL etc does not go through result
1135 if result.has_key(key):
1136 env[key] = result[key]
1137 env_cache[key] = env[key]
1140 # if nls=yes and gettext=included, create intl/config.h
1141 # intl/libintl.h etc
1143 intl_config_h = os.path.join(env.Dir('$BUILDDIR/intl').path, 'config.h')
1144 if env['nls'] and included_gettext:
1146 print "Creating %s..." % intl_config_h
1148 # create intl/config.h
1149 result = utils.createConfigFile(conf,
1150 config_file = intl_config_h,
1151 config_pre = '''/* intl/config.h. Generated by SCons. */
1156 * This file is part of LyX, the document processor.
1157 * Licence details can be found in the file COPYING.
1159 * This is the compilation configuration file for LyX.
1160 * It was generated by scon.
1161 * You might want to change some of the defaults if something goes wrong
1162 * during the compilation.
1169 ('unistd.h', 'HAVE_UNISTD_H', 'c'),
1170 ('inttypes.h', 'HAVE_INTTYPES_H', 'c'),
1171 ('string.h', 'HAVE_STRING_H', 'c'),
1172 ('strings.h', 'HAVE_STRINGS_H', 'c'),
1173 ('argz.h', 'HAVE_ARGZ_H', 'c'),
1174 ('limits.h', 'HAVE_LIMITS_H', 'c'),
1175 ('alloca.h', 'HAVE_ALLOCA_H', 'c'),
1176 ('stddef.h', 'HAVE_STDDEF_H', 'c'),
1177 ('stdint.h', 'HAVE_STDINT_H', 'c'),
1178 ('sys/param.h', 'HAVE_SYS_PARAM_H', 'c'),
1181 ('getcwd', 'HAVE_GETCWD', None),
1182 ('stpcpy', 'HAVE_STPCPY', None),
1183 ('strcasecmp', 'HAVE_STRCASECMP', None),
1184 ('strdup', 'HAVE_STRDUP', None),
1185 ('strtoul', 'HAVE_STRTOUL', None),
1186 ('alloca', 'HAVE_ALLOCA', None),
1187 ('__fsetlocking', 'HAVE___FSETLOCKING', None),
1188 ('mempcpy', 'HAVE_MEMPCPY', None),
1189 ('__argz_count', 'HAVE___ARGZ_COUNT', None),
1190 ('__argz_next', 'HAVE___ARGZ_NEXT', None),
1191 ('__argz_stringify', 'HAVE___ARGZ_STRINGIFY', None),
1192 ('setlocale', 'HAVE_SETLOCALE', None),
1193 ('tsearch', 'HAVE_TSEARCH', None),
1194 ('getegid', 'HAVE_GETEGID', None),
1195 ('getgid', 'HAVE_GETGID', None),
1196 ('getuid', 'HAVE_GETUID', None),
1197 ('wcslen', 'HAVE_WCSLEN', None),
1198 ('asprintf', 'HAVE_ASPRINTF', None),
1199 ('wprintf', 'HAVE_WPRINTF', None),
1200 ('snprintf', 'HAVE_SNPRINTF', None),
1201 ('printf', 'HAVE_POSIX_PRINTF', None),
1202 ('fcntl', 'HAVE_FCNTL', None),
1205 ('intmax_t', 'HAVE_INTMAX_T', None),
1206 ('long double', 'HAVE_LONG_DOUBLE', None),
1207 ('long long', 'HAVE_LONG_LONG', None),
1208 ('wchar_t', 'HAVE_WCHAR_T', None),
1209 ('wint_t', 'HAVE_WINT_T', None),
1210 ('uintmax_t', 'HAVE_INTTYPES_H_WITH_UINTMAX', '#include <inttypes.h>'),
1211 ('uintmax_t', 'HAVE_STDINT_H_WITH_UINTMAX', '#include <stdint.h>'),
1214 (('iconv', 'libiconv'), 'HAVE_ICONV', 'ICONV_LIB'),
1218 (conf.CheckLC_MESSAGES(),
1220 'Define if your <locale.h> file defines LC_MESSAGES.'
1222 (conf.CheckIconvConst(),
1224 'Define as const if the declaration of iconv() needs const.',
1225 '#define ICONV_CONST',
1226 '#define ICONV_CONST const',
1228 (conf.CheckType('intmax_t', includes='#include <stdint.h>') or \
1229 conf.CheckType('intmax_t', includes='#include <inttypes.h>'),
1231 "Define to 1 if you have the `intmax_t' type."
1233 (env.has_key('nls') and env['nls'],
1235 "Define to 1 if translation of program messages to the user's native anguage is requested.",
1238 config_post = '#endif'
1241 # these keys are needed in env
1242 for key in ['HAVE_ASPRINTF', 'HAVE_WPRINTF', 'HAVE_SNPRINTF', \
1243 'HAVE_POSIX_PRINTF', 'HAVE_ICONV', 'HAVE_LIBC']:
1244 # USE_ASPELL etc does not go through result
1245 if result.has_key(key):
1246 env[key] = result[key]
1247 env_cache[key] = env[key]
1251 # this comes as a big surprise, without this line
1252 # (doing nothing obvious), adding fast_start=yes
1253 # to a build with fast_start=no will result in a rebuild
1254 # Note that the exact header file to check does not matter
1255 conf.CheckCHeader('io.h')
1256 # only a few variables need to be rescanned
1257 for key in ['USE_ASPELL', 'USE_PSPELL', 'USE_ISPELL', 'HAVE_FCNTL',\
1258 'HAVE_ICONV', 'HAVE_LIBGDI32', 'HAVE_LIBAIKSAURUS',
1259 'ICONV_LIB', 'AIKSAURUS_LIB']:
1260 env[key] = env_cache[key]
1263 if env['nls'] and included_gettext:
1264 # only a few variables need to be rescanned
1265 for key in ['HAVE_ASPRINTF', 'HAVE_WPRINTF', 'HAVE_SNPRINTF', \
1266 'HAVE_POSIX_PRINTF', 'HAVE_ICONV', 'HAVE_LIBC']:
1267 env[key] = env_cache[key]
1269 # this looks misplaced, but intl/libintl.h is needed by src/message.C
1270 if env['nls'] and included_gettext:
1271 # libgnuintl.h.in => libintl.h
1272 env.substFile('$BUILDDIR/intl/libintl.h', '$TOP_SRCDIR/intl/libgnuintl.h.in')
1273 env.Command('$BUILDDIR/intl/libgnuintl.h', '$BUILDDIR/intl/libintl.h',
1274 [Copy('$TARGET', '$SOURCE')])
1277 # Finish auto-configuration
1280 #----------------------------------------------------------
1281 # Now set up our build process accordingly
1282 #----------------------------------------------------------
1287 # NOTE: Tool('qt') or Tool('qt4') will be loaded later
1288 # in their respective directory and specialized env.
1289 if frontend in ['qt2', 'qt3']:
1290 # note: env.Tool('qt') my set QT_LIB to qt
1292 frontend_libs = ['qt-mt']
1293 elif frontend == 'qt4':
1294 qt_libs = ['QtCore', 'QtGui']
1295 # set the right lib names
1296 if platform_name == 'win32':
1297 if mode == 'debug' and use_vc:
1298 qt_lib_suffix = 'd4'
1303 qt_lib_suffix = '_debug'
1306 frontend_libs = [x + qt_lib_suffix for x in qt_libs]
1309 if platform_name in ['win32', 'cygwin']:
1310 # the final link step needs stdc++ to succeed under mingw
1311 # FIXME: shouldn't g++ automatically link to stdc++?
1313 system_libs = ['shlwapi', 'shell32', 'advapi32', 'zdll']
1315 system_libs = ['shlwapi', 'stdc++', 'z']
1316 elif platform_name == 'cygwin' and env['X11']:
1317 system_libs = ['GL', 'Xmu', 'Xi', 'Xrender', 'Xrandr', 'Xcursor',
1318 'Xft', 'freetype', 'fontconfig', 'Xext', 'X11', 'SM', 'ICE', 'resolv',
1324 ('HAVE_ICONV', env['ICONV_LIB']),
1325 ('HAVE_LIBGDI32', 'gdi32'),
1326 ('HAVE_LIBAIKSAURUS', env['AIKSAURUS_LIB']),
1327 ('USE_ASPELL', aspell_lib),
1328 ('USE_ISPELL', 'ispell'),
1329 ('USE_PSPELL', 'pspell'),
1334 system_libs.append(lib[1])
1337 # Build parameters CPPPATH etc
1340 env.AppendUnique(LIBPATH = ['/usr/X11R6/lib'])
1343 # boost: for boost header files
1344 # BUILDDIR/common: for config.h
1345 # TOP_SRCDIR/src: for support/* etc
1347 env['CPPPATH'] += ['$BUILDDIR/common', '$TOP_SRCDIR/src']
1349 # Separating boost directories from CPPPATH stops scons from building
1350 # the dependency tree for boost header files, and effectively reduce
1351 # the null build time of lyx from 29s to 16s. Since lyx may tweak local
1352 # boost headers, this is only done for system boost headers.
1354 env.AppendUnique(CPPPATH = ['$BOOST_INC_PATH'])
1357 env.PrependUnique(CCFLAGS = ['/I$BOOST_INC_PATH'])
1359 env.PrependUnique(CCFLAGS = ['-I$BOOST_INC_PATH'])
1361 # for intl/config.h, intl/libintl.h and intl/libgnuintl.h
1362 if env['nls'] and included_gettext:
1363 env['CPPPATH'].append('$BUILDDIR/intl')
1365 # QT_INC_PATH is not needed for *every* source file
1366 env['CPPPATH'].remove(qt_inc_path)
1369 # A Link script for cygwin see
1370 # http://www.cygwin.com/ml/cygwin/2004-09/msg01101.html
1371 # http://www.cygwin.com/ml/cygwin-apps/2004-09/msg00309.html
1374 if platform_name == 'cygwin':
1375 ld_script_path = '/usr/lib/qt3/mkspecs/cygwin-g++'
1376 ld_script = utils.installCygwinLDScript(ld_script_path)
1377 env.AppendUnique(LINKFLAGS = ['-Wl,--enable-runtime-pseudo-reloc',
1378 '-Wl,--script,%s' % ld_script, '-Wl,-s'])
1383 # fill in the version info
1384 env['VERSION_INFO'] = '''Configuration
1386 Special build flags: %s
1388 C Compiler flags: %s %s
1390 C++ Compiler LyX flags: %s
1391 C++ Compiler flags: %s %s
1393 Linker user flags: %s
1395 Builing directory: %s
1396 Local library directory: %s
1399 Frontend libraries: %s
1400 System libraries: %s
1401 include search path: %s
1407 ''' % (platform_name,
1408 env.subst('$CCFLAGS'), env.subst('$CC'),
1409 env.subst('$CPPFLAGS'), env.subst('$CFLAGS'),
1410 env.subst('$CXX'), env.subst('$CXXFLAGS'),
1411 env.subst('$CPPFLAGS'), env.subst('$CXXFLAGS'),
1412 env.subst('$LINKFLAGS'), env.subst('$LINKFLAGS'),
1413 env.subst('$BUILDDIR'), env.subst('$LOCALLIBPATH'),
1414 str(env['LIBPATH']), str(boost_libraries),
1415 str(frontend_libs), str(system_libs), str(env['CPPPATH']),
1416 frontend, packaging_method,
1417 prefix, env['LYX_DIR'])
1419 if frontend in ['qt2', 'qt3', 'qt4']:
1420 env['VERSION_INFO'] += ''' include dir: %s
1423 ''' % (qt_inc_path, qt_lib_path, env['X11'])
1426 print env['VERSION_INFO']
1429 # Mingw command line may be too short for our link usage,
1430 # Here we use a trick from scons wiki
1431 # http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/LongCmdLinesOnWin32
1433 # I also would like to add logging (commands only) capacity to the
1435 logfile = env.get('logfile', default_log_file)
1436 if logfile != '' or platform_name == 'win32':
1438 utils.setLoggedSpawn(env, logfile, longarg = (platform_name == 'win32'),
1439 info = '''# This is a log of commands used by scons to build lyx
1443 ''' % (time.asctime(), ' '.join(sys.argv),
1444 env['VERSION_INFO'].replace('\n','\n# ')) )
1449 # -h will print out help info
1450 Help(opts.GenerateHelpText(env))
1452 # save environment settings (for fast_start option)
1453 cache_file = open(env_cache_file, 'w')
1454 cPickle.dump(env_cache, cache_file)
1458 #----------------------------------------------------------
1460 #----------------------------------------------------------
1461 # this has been the source of problems on some platforms...
1462 # I find that I need to supply it with full path name
1463 env.SConsignFile(os.path.join(Dir(env['BUILDDIR']).abspath, '.sconsign'))
1464 # this usage needs further investigation.
1465 #env.CacheDir('%s/Cache/%s' % (env['BUILDDIR'], frontend))
1467 print "Building all targets recursively"
1469 if env.has_key('rebuild'):
1470 rebuild_targets = env['rebuild'].split(',')
1471 if 'none' in rebuild_targets or 'no' in rebuild_targets:
1472 rebuild_targets = []
1473 elif 'all' in rebuild_targets or 'yes' in rebuild_targets:
1474 # None: let scons decide which components to build
1475 # Forcing all components to be rebuilt is in theory not necessary
1476 rebuild_targets = None
1478 rebuild_targets = None
1480 def libExists(libname):
1481 ''' Check whether or not lib $LOCALLIBNAME/libname already exists'''
1482 return os.path.isfile(File(env.subst('$LOCALLIBPATH/${LIBPREFIX}%s$LIBSUFFIX'%libname)).abspath)
1484 def appExists(apppath, appname):
1485 ''' Check whether or not application already exists'''
1486 return os.path.isfile(File(env.subst('$BUILDDIR/common/%s/${PROGPREFIX}%s$PROGSUFFIX' % (apppath, appname))).abspath)
1488 targets = BUILD_TARGETS
1489 # msvc need to pass full target name, so I have to look for path/lyx etc
1490 build_lyx = targets == [] or True in ['lyx' in x for x in targets] \
1491 or 'install' in targets or 'all' in targets
1492 build_boost = (included_boost and not libExists('boost_regex')) or 'boost' in targets
1493 build_intl = (included_gettext and not libExists('included_intl')) or 'intl' in targets
1494 build_support = build_lyx or True in [x in targets for x in ['support', 'client', 'tex2lyx']]
1495 build_mathed = build_lyx or 'mathed' in targets
1496 build_insets = build_lyx or 'insets' in targets
1497 build_frontends = build_lyx or 'frontends' in targets
1498 build_graphics = build_lyx or 'graphics' in targets
1499 build_controllers = build_lyx or 'controllers' in targets
1500 build_client = True in ['client' in x for x in targets] \
1501 or 'install' in targets or 'all' in targets
1502 build_tex2lyx = True in ['tex2lyx' in x for x in targets] \
1503 or 'install' in targets or 'all' in targets
1504 build_lyxbase = build_lyx or 'lyxbase' in targets
1505 build_po = 'po' in targets or 'install' in targets or 'all' in targets
1506 build_qt2 = (build_lyx and frontend == 'qt2') or 'qt2' in targets
1507 build_qt3 = (build_lyx and frontend == 'qt3') or 'qt3' in targets
1508 build_qt4 = (build_lyx and frontend == 'qt4') or 'qt4' in targets
1509 build_msvs_projects = use_vc and 'msvs_projects' in targets
1512 # now, if rebuild_targets is specified, do not rebuild some targets
1513 if rebuild_targets is not None:
1515 def ifBuildLib(name, libname, old_value):
1516 # explicitly asked to rebuild
1517 if name in rebuild_targets:
1519 # else if not rebuild, and if the library already exists
1520 elif libExists(libname):
1522 # do not change the original value
1525 build_boost = ifBuildLib('boost', 'included_boost_filesystem', build_boost)
1526 build_intl = ifBuildLib('intl', 'included_intl', build_intl)
1527 build_support = ifBuildLib('support', 'support', build_support)
1528 build_mathed = ifBuildLib('mathed', 'mathed', build_mathed)
1529 build_insets = ifBuildLib('insets', 'insets', build_insets)
1530 build_frontends = ifBuildLib('frontends', 'frontends', build_frontends)
1531 build_graphics = ifBuildLib('graphics', 'graphics', build_graphics)
1532 build_controllers = ifBuildLib('controllers', 'controllers', build_controllers)
1533 build_lyxbase = ifBuildLib('lyxbase', 'lyxbase_pre', build_lyxbase)
1534 build_qt2 = ifBuildLib('qt2', 'qt2', build_qt2)
1535 build_qt3 = ifBuildLib('qt3', 'qt3', build_qt3)
1536 build_qt4 = ifBuildLib('qt4', 'qt4', build_qt4)
1538 def ifBuildApp(name, appname, old_value):
1539 # explicitly asked to rebuild
1540 if name in rebuild_targets:
1542 # else if not rebuild, and if the library already exists
1543 elif appExists(name, appname):
1545 # do not change the original value
1548 build_tex2lyx = ifBuildApp('tex2lyx', 'tex2lyx', build_tex2lyx)
1549 build_client = ifBuildApp('client', 'lyxclient', build_client)
1551 # sync frontend and frontend (maybe build qt4 with frontend=qt3)
1565 env.BuildDir('$BUILDDIR/boost', '$TOP_SRCDIR/boost/libs', duplicate = 0)
1567 boostenv = env.Copy()
1569 # boost use its own config.h
1570 boostenv['CPPPATH'] = ['$TOP_SRCDIR/boost', '$BUILDDIR/boost'] + extra_inc_paths
1571 boostenv.AppendUnique(CCFLAGS = ['-DBOOST_USER_CONFIG="<config.h>"'])
1573 for lib in boost_libs:
1574 print 'Processing files in boost/libs/%s/src...' % lib
1575 boostlib = boostenv.StaticLibrary(
1576 target = '$LOCALLIBPATH/included_boost_%s' % lib,
1577 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/boost/libs/%s/src' % lib),
1578 pattern = '*.cpp', build_dir = '$BUILDDIR/boost/%s/src' % lib)
1580 Alias('boost', boostlib)
1587 intlenv = env.Copy()
1589 print "Processing files in intl..."
1591 env.BuildDir('$BUILDDIR/intl', '$TOP_SRCDIR/intl', duplicate = 0)
1593 # we need the original C compiler for these files
1594 intlenv['CC'] = C_COMPILER
1595 intlenv['CCFLAGS'] = C_CCFLAGS
1597 intlenv.Append(CCFLAGS=['/Dinline#', '/D__attribute__(x)#', '/Duintmax_t=UINT_MAX'])
1598 # intl does not use global config.h
1599 intlenv['CPPPATH'] = ['$BUILDDIR/intl'] + extra_inc_paths
1601 intlenv.Append(CCFLAGS = [
1602 r'-DLOCALEDIR=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1603 r'-DLOCALE_ALIAS_PATH=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1604 r'-DLIBDIR=\"' + env['TOP_SRCDIR'].replace('\\', '\\\\') + r'/lib\"',
1606 '-DENABLE_RELOCATABLE=1',
1608 r'-DINSTALLDIR=\"' + prefix.replace('\\', '\\\\') + r'/lib\"',
1610 '-Dset_relocation_prefix=libintl_set_relocation_prefix',
1611 '-Drelocate=libintl_relocate',
1612 '-DDEPENDS_ON_LIBICONV=1',
1617 intl = intlenv.StaticLibrary(
1618 target = '$LOCALLIBPATH/included_intl',
1620 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/intl'), pattern = '*.c',
1621 exclude = ['vasnprintf.c', 'printf-parse.c', 'printf-args.c', 'os2compat.c'],
1622 build_dir = '$BUILDDIR/intl')
1628 # Now, src code under src/
1630 env.BuildDir('$BUILDDIR/common', '$TOP_SRCDIR/src', duplicate = 0)
1637 print "Processing files in src/support..."
1639 env.substFile('$BUILDDIR/common/support/package.C', '$TOP_SRCDIR/src/support/package.C.in')
1641 support = env.StaticLibrary(
1642 target = '$LOCALLIBPATH/support',
1643 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/support'), pattern = lyx_ext,
1644 exclude = ['os_win32.C', 'os_unix.C', 'os_cygwin.C', 'os_os2.C', 'atexit.c'],
1645 include = ['package.C'], build_dir = '$BUILDDIR/common/support')
1647 Alias('support', support)
1654 print "Processing files in src/mathed..."
1656 mathed = env.StaticLibrary(
1657 target = '$LOCALLIBPATH/mathed',
1658 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/mathed'),
1660 exclude = ['math_xyarrowinset.C', 'math_mboxinset.C', 'formulamacro.C'],
1661 build_dir = '$BUILDDIR/common/mathed')
1663 Alias('mathed', mathed)
1670 print "Processing files in src/insets..."
1672 insets = env.StaticLibrary(
1673 target = '$LOCALLIBPATH/insets',
1674 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/insets'),
1676 exclude = ['insettheorem.C'], build_dir = '$BUILDDIR/common/insets')
1678 Alias('insets', insets)
1685 print "Processing files in src/frontends..."
1687 frontends = env.StaticLibrary(
1688 target = '$LOCALLIBPATH/frontends',
1689 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends'), pattern = lyx_ext,
1690 build_dir = '$BUILDDIR/common/frontends')
1692 Alias('frontends', frontends)
1699 print "Processing files in src/graphics..."
1701 graphics = env.StaticLibrary(
1702 target = '$LOCALLIBPATH/graphics',
1703 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/graphics'), pattern = lyx_ext,
1704 build_dir = '$BUILDDIR/common/graphics')
1706 Alias('graphics', graphics)
1709 if build_controllers:
1711 # src/frontends/controllers
1713 print "Processing files in src/frontends/controllers..."
1715 controllers = env.StaticLibrary(
1716 target = '$LOCALLIBPATH/controllers',
1717 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/controllers'), pattern = lyx_ext,
1718 build_dir = '$BUILDDIR/common/frontends/controllers')
1720 Alias('controllers', controllers)
1724 # src/frontend/qt2/3/4
1726 if build_qt2 or build_qt3 or build_qt4:
1727 env.BuildDir('$BUILDDIR/$frontend', '$TOP_SRCDIR/src/frontend/$frontend', duplicate = 0)
1731 print "Processing files in src/frontends/qt2..."
1734 # disable auto scan to speed up non build time
1735 qt2env['QT_AUTOSCAN'] = 0
1736 qt2env['QT_MOCHPREFIX'] = ''
1741 qt2env.AppendUnique(CPPPATH = [
1743 '$BUILDDIR/common/images',
1744 '$BUILDDIR/common/frontends',
1745 '$BUILDDIR/common/frontends/qt2',
1746 '$BUILDDIR/common/frontends/controllers',
1750 qt2_moc_files = ["$BUILDDIR/common/frontends/qt2/%s" % x for x in Split('''
1753 FileDialog_private.C
1792 QSpellcheckerDialog.C
1794 QTabularCreateDialog.C
1809 # manually moc and uic files for better performance
1810 qt2_moced_files = [qt2env.Moc(x.replace('.C', '_moc.cpp'), x.replace('.C', '.h')) for x in qt2_moc_files]
1812 qt2_uiced_files = [qt2env.Uic('$BUILDDIR/common/frontends/qt2/ui/'+x) for x in \
1813 utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/qt2/ui'), pattern = '*.ui')]
1815 qt2_uiced_cc_files = []
1816 for x in qt2_uiced_files:
1817 qt2_uiced_cc_files.extend(x[1:])
1819 qt2 = qt2env.StaticLibrary(
1820 target = '$LOCALLIBPATH/qt2',
1821 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/qt2/'), pattern = lyx_ext,
1822 build_dir = '$BUILDDIR/common/frontends/qt2') + qt2_moced_files + qt2_uiced_cc_files
1828 print "Processing files in src/frontends/qt3..."
1831 # disable auto scan to speed up non build time
1832 qt3env['QT_AUTOSCAN'] = 0
1833 qt3env['QT_MOCHPREFIX'] = ''
1838 qt3env.AppendUnique(CPPPATH = [
1840 '$BUILDDIR/common/images',
1841 '$BUILDDIR/common/frontends',
1842 '$BUILDDIR/common/frontends/qt3',
1843 '$BUILDDIR/common/frontends/controllers',
1847 qt3_moc_files = ["$BUILDDIR/common/frontends/qt3/%s" % x for x in Split('''
1850 FileDialog_private.C
1890 QSpellcheckerDialog.C
1892 QTabularCreateDialog.C
1907 # manually moc and uic files for better performance
1908 qt3_moced_files = [qt3env.Moc(x.replace('.C', '_moc.cpp'), x.replace('.C', '.h')) for x in qt3_moc_files]
1910 qt3_uiced_files = [qt3env.Uic('$BUILDDIR/common/frontends/qt3/ui/'+x) for x in \
1911 utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/qt3/ui'), pattern = '*.ui')]
1913 qt3_uiced_cc_files = []
1914 for x in qt3_uiced_files:
1915 qt3_uiced_cc_files.extend(x[1:])
1917 qt3 = qt3env.StaticLibrary(
1918 target = '$LOCALLIBPATH/qt3',
1919 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/qt3/'), pattern = lyx_ext,
1920 build_dir = '$BUILDDIR/common/frontends/qt3') + qt3_moced_files + qt3_uiced_cc_files
1926 print "Processing files in src/frontends/qt4..."
1929 qt4env['QT_AUTOSCAN'] = 0
1931 # local qt4 toolset from
1932 # http://www.iua.upf.es/~dgarcia/Codders/sconstools.html
1934 # NOTE: I have to patch qt4.py since it does not automatically
1935 # process .C file!!! (add to cxx_suffixes )
1937 qt4env.Tool('qt4', [scons_dir])
1938 qt4env.EnableQt4Modules(qt_libs, debug = (mode == 'debug'))
1940 qt4env.AppendUnique(CPPPATH = [
1942 '$BUILDDIR/common/images',
1943 '$BUILDDIR/common/frontends',
1944 '$BUILDDIR/common/frontends/qt4',
1945 '$BUILDDIR/common/frontends/controllers',
1950 # FIXME: replace by something from pkg_config
1951 qt4env.Append(CCFLAGS = [
1953 '-DQT_CLEAN_NAMESPACE',
1962 qt4_moc_files = ["$BUILDDIR/common/frontends/qt4/%s" % x for x in Split('''
1965 FileDialog_private.C
2008 QSpellcheckerDialog.C
2010 QTabularCreateDialog.C
2029 resources = [qt4env.Uic4(x.split('.')[0]) for x in \
2030 utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/qt4/ui'), pattern = '*.ui',
2031 build_dir = '$BUILDDIR/common/frontends/qt4/ui')]
2034 # moc qt4_moc_files, the moced files are included in the original files
2036 qt4_moced_files = [qt4env.Moc4(x.replace('.C', '_moc.cpp'), x.replace('.C', '.h')) for x in qt4_moc_files]
2038 qt4 = qt4env.StaticLibrary(
2039 target = '$LOCALLIBPATH/qt4',
2040 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/qt4'), pattern = lyx_ext,
2041 exclude = ['QBrowseBox.C'], build_dir = '$BUILDDIR/common/frontends/qt4')
2050 env.BuildDir('$BUILDDIR/common', '$TOP_SRCDIR/src', duplicate = 0)
2052 print "Processing files in src/client..."
2054 if env['HAVE_FCNTL']:
2055 client = env.Program(
2056 target = '$BUILDDIR/common/client/lyxclient',
2057 LIBS = ['support'] + intl_libs + system_libs +
2058 socket_libs + boost_libraries,
2059 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/client'), pattern = lyx_ext,
2060 build_dir = '$BUILDDIR/common/client')
2062 Alias('client', env.Command(os.path.join('$BUILDDIR', os.path.split(str(client[0]))[1]),
2063 client, [Copy('$TARGET', '$SOURCE')]))
2066 Alias('client', client)
2068 if env['HAVE_FCNTL']:
2069 # define client even if lyxclient is not built with rebuild=no
2070 client = [env.subst('$BUILDDIR/common/client/${PROGPREFIX}lyxclient$PROGSUFFIX')]
2079 print "Processing files in src/tex2lyx..."
2081 tex2lyx_env = env.Copy()
2083 tex2lyx_env.Prepend(CPPPATH = ['$BUILDDIR/common/tex2lyx'])
2084 tex2lyx_env.AppendUnique(LIBPATH = ['#$LOCALLIBPATH'])
2086 for file in ['FloatList.C', 'Floating.C', 'counters.C', 'lyxlayout.h', 'lyxlayout.C',
2087 'lyxtextclass.h', 'lyxtextclass.C', 'lyxlex.C', 'lyxlex_pimpl.C']:
2088 env.Command('$BUILDDIR/common/tex2lyx/'+file, '$TOP_SRCDIR/src/'+file,
2089 [Copy('$TARGET', '$SOURCE')])
2091 tex2lyx = tex2lyx_env.Program(
2092 target = '$BUILDDIR/common/tex2lyx/tex2lyx',
2093 LIBS = ['support'] + boost_libraries + system_libs,
2094 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/tex2lyx'), pattern = lyx_ext,
2095 include = ['FloatList.C', 'Floating.C', 'counters.C', 'lyxlayout.C',
2096 'lyxtextclass.C', 'lyxlex.C', 'lyxlex_pimpl.C'],
2097 build_dir = '$BUILDDIR/common/tex2lyx')
2099 Alias('tex2lyx', env.Command(os.path.join('$BUILDDIR', os.path.split(str(tex2lyx[0]))[1]),
2100 tex2lyx, [Copy('$TARGET', '$SOURCE')]))
2101 Alias('tex2lyx', tex2lyx)
2103 # define tex2lyx even if tex2lyx is not built with rebuild=no
2104 tex2lyx = [env.subst('$BUILDDIR/common/tex2lyx/${PROGPREFIX}tex2lyx$PROGSUFFIX')]
2111 print "Processing files in src..."
2113 env.substFile('$BUILDDIR/common/version.C', '$TOP_SRCDIR/src/version.C.in')
2115 lyx_post_source = Split('''
2124 if env.has_key('USE_ASPELL') and env['USE_ASPELL']:
2125 lyx_post_source.append('aspell.C')
2126 elif env.has_key('USE_PSPELL') and env['USE_PSPELL']:
2127 lyx_post_source.append('pspell.C')
2128 elif env.has_key('USE_ISPELL') and env['USE_ISPELL']:
2129 lyx_post_source.append('ispell.C')
2131 # msvc requires at least one source file with main()
2132 # so I exclude main.C from lyxbase
2133 lyxbase_pre = env.StaticLibrary(
2134 target = '$LOCALLIBPATH/lyxbase_pre',
2135 source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src'), pattern = lyx_ext,
2136 exclude = lyx_post_source + ['main.C', 'aspell.C', 'pspell.C',
2137 'ispell.C', 'Variables.C', 'Sectioning.C'],
2138 include = ['version.C'], build_dir = '$BUILDDIR/common')
2140 lyxbase_post = env.StaticLibrary(
2141 target = '$LOCALLIBPATH/lyxbase_post',
2142 source = ["$BUILDDIR/common/%s" % x for x in lyx_post_source]
2144 Alias('lyxbase', lyxbase_pre)
2145 Alias('lyxbase', lyxbase_post)
2150 # Build lyx with given frontend
2153 target = '$BUILDDIR/$frontend/lyx',
2154 source = ['$BUILDDIR/common/main.C'],
2172 # [/path/to/lyx.ext] => lyx-qt3.ext
2173 target_name = os.path.split(str(lyx[0]))[1].replace('lyx', 'lyx-%s' % frontend)
2174 Alias('lyx', env.Command(os.path.join('$BUILDDIR', target_name), lyx,
2175 [Copy('$TARGET', '$SOURCE')]))
2178 # define lyx even if lyx is not built with rebuild=no
2179 lyx = [env.subst('$BUILDDIR/$frontend/${PROGPREFIX}lyx$PROGSUFFIX')]
2182 if build_msvs_projects:
2183 def build_project(target, dir, full_target = None,
2184 src_pattern = lyx_ext, include = [], resource = None, rebuildTargetOnly = True):
2185 ''' build mavs project files
2186 target: alias (correspond to directory name)
2187 dir: source directory or directories (a list)
2188 full_target: full path/filename of the target
2189 src_pattern: glob pattern
2190 include: files to include into source
2191 resource: directory or directories with resource (.ui) files
2192 rebuildTargetOnly: whether or not only rebuild this target
2194 For non-debug-able targets like static libraries, target (alias) is
2195 enough to build the target. For executable targets, msvs need to know
2196 the full path to start debug them.
2198 if resource is not None:
2199 res = utils.globSource(dir = env.subst('$TOP_SRCDIR/'+resource), pattern = '*.ui',
2200 build_dir = env.subst('$TOP_SRCDIR/'+resource))
2203 if rebuildTargetOnly:
2204 cmds = 'fast_start=yes rebuild='+target
2206 cmds = 'fast_start=yes'
2207 if type(dir) == type([]):
2211 src.extend(utils.globSource(dir = env.subst('$TOP_SRCDIR/' + d),
2212 pattern = src_pattern, include = include,
2213 build_dir = env.subst('$TOP_SRCDIR/' + d) ))
2214 inc.extend(utils.globSource(dir = env.subst('$TOP_SRCDIR/' + d),
2216 build_dir = env.subst('$TOP_SRCDIR/' + d) ))
2218 src = utils.globSource(dir = env.subst('$TOP_SRCDIR/' + dir),
2219 pattern = src_pattern, include = include,
2220 build_dir = env.subst('$TOP_SRCDIR/' + dir) )
2221 inc = utils.globSource(dir = env.subst('$TOP_SRCDIR/' + dir),
2223 build_dir = env.subst('$TOP_SRCDIR/' + dir) )
2224 if full_target is None:
2225 build_target = target
2227 build_target = full_target
2229 proj = env.MSVSProject(
2230 target = target + env['MSVSPROJECTSUFFIX'],
2232 incs = [env.subst('$TOP_SRCDIR/src/config.h')],
2235 buildtarget = build_target,
2239 Alias('msvs_projects', proj)
2241 build_project('boost', ['boost/libs/%s/src' % x for x in boost_libs],
2242 src_pattern = '*.cpp')
2244 build_project('intl', 'intl', src_pattern = '*.c')
2246 build_project('support', 'src/support', include=['package.C.in'])
2248 build_project('mathed', 'src/mathed')
2250 build_project('insets', 'src/insets')
2252 build_project('frontends', 'src/frontends')
2254 build_project('graphics', 'src/graphics')
2256 build_project('controllers', 'src/frontends/controllers')
2258 build_project('qt3', 'src/frontends/qt3', resource = 'src/frontends/qt3/ui')
2260 build_project('qt4', 'src/frontends/qt4', resource = 'src/frontends/qt4/ui')
2262 build_project('client', 'src/client', rebuildTargetOnly = False,
2263 full_target = File(env.subst('$BUILDDIR/common/client/lyxclient$PROGSUFFIX')).abspath)
2265 build_project('tex2lyx', 'src/tex2lyx', rebuildTargetOnly = False,
2266 full_target = File(env.subst('$BUILDDIR/common/tex2lyx/tex2lyx$PROGSUFFIX')).abspath)
2268 build_project('lyxbase', 'src')
2270 if frontend == 'qt3':
2271 build_project('lyx', ['src', 'src/support', 'src/mathed', 'src/insets',
2272 'src/frontends', 'src/graphics', 'src/frontends/controllers',
2273 'src/frontends/qt3'], resource = 'src/frontends/qt3/ui',
2274 rebuildTargetOnly = False,
2275 full_target = File(env.subst('$BUILDDIR/$frontend/lyx$PROGSUFFIX')).abspath)
2277 build_project('lyx', ['src', 'src/support', 'src/mathed', 'src/insets',
2278 'src/frontends', 'src/graphics', 'src/frontends/controllers',
2279 'src/frontends/qt4'], resource = 'src/frontends/qt4/ui',
2280 rebuildTargetOnly = False,
2281 full_target = File(env.subst('$BUILDDIR/$frontend/lyx$PROGSUFFIX')).abspath)
2288 print 'Processing files in po...'
2293 # files to translate
2294 transfiles = glob.glob(os.path.join(env.subst('$TOP_SRCDIR'), 'po', '*.po'))
2295 # possibly *only* handle these languages
2297 if env.has_key('languages'):
2298 languages = env.make_list(env['lanauges'])
2299 # use defulat msgfmt
2300 if not env['MSGFMT']:
2301 print 'msgfmt does not exist. Can not process po files'
2304 env['BUILDERS']['Transfiles'] = Builder(action='$MSGFMT $SOURCE -o $TARGET',suffix='.gmo',src_suffix='.po')
2307 for f in transfiles:
2309 fname = os.path.split(f)[1]
2311 country = fname.split('.')[0]
2313 if not languages or country in languages:
2314 gmo_files.extend(env.Transfiles(f))
2317 if 'install' in targets:
2319 # this part is a bit messy right now. Since scons will provide
2320 # --DESTDIR option soon, at least the dest_dir handling can be
2323 # how to join dest_dir and prefix
2324 def joinPaths(path1, path2):
2325 ''' join path1 and path2, do not use os.path.join because
2326 under window, c:\destdir\d:\program is invalid '''
2328 return os.path.normpath(path2)
2329 # separate drive letter
2330 (drive, path) = os.path.splitdrive(os.path.normpath(path2))
2331 # ignore drive letter, so c:\destdir + c:\program = c:\destdir\program
2332 return os.path.join(os.path.normpath(path1), path[1:])
2334 # install to dest_dir/prefix
2335 dest_dir = env.get('DESTDIR', None)
2336 dest_prefix_dir = joinPaths(dest_dir, env.Dir(prefix).abspath)
2337 # create the directory if needed
2338 if not os.path.isdir(dest_prefix_dir):
2340 os.makedirs(dest_prefix_dir)
2343 if not os.path.isdir(dest_prefix_dir):
2344 print 'Can not create directory', dest_prefix_dir
2347 if env.has_key('exec_prefix'):
2348 bin_dest_dir = joinPaths(dest_dir, Dir(env['exec_prefix']).abspath)
2350 bin_dest_dir = os.path.join(dest_prefix_dir, 'bin')
2352 share_dest_dir = os.path.join(dest_prefix_dir, share_dir + program_suffix)
2354 share_dest_dir = os.path.join(dest_prefix_dir, share_dir)
2355 man_dest_dir = os.path.join(dest_prefix_dir, man_dir)
2356 locale_dest_dir = os.path.join(dest_prefix_dir, locale_dir)
2360 # do not install these files
2361 exclude_list = ['Makefile.am', 'Makefile.in', 'Makefile',
2362 'lyx2lyx_version.py.in']
2364 def install(dest, src):
2365 ''' recusive installation of src to dest '''
2366 # separate file and directory
2367 files = filter(lambda x: os.path.isfile(x) and not os.path.split(x)[1] in exclude_list, src)
2368 dirs = filter(os.path.isdir, src)
2370 env.Install(dest, files)
2374 ins_dir.extend(install(os.path.join(dest, os.path.basename(dir)),
2375 glob.glob(os.path.join(dir, '*'))) )
2378 # install executables (lyxclient may be None)
2381 version_suffix = program_suffix
2386 target_name = os.path.split(str(lyx[0]))[1].replace('lyx', 'lyx%s' % version_suffix)
2387 target = os.path.join(bin_dest_dir, target_name)
2388 env.InstallAs(target, lyx)
2389 Alias('install', target)
2390 # install lyx as lyx-qt3
2391 target_name = os.path.split(str(lyx[0]))[1].replace('lyx', 'lyx-%s%s' % (frontend, version_suffix))
2392 target = os.path.join(bin_dest_dir, target_name)
2393 env.InstallAs(target, lyx)
2394 Alias('install', target)
2397 target_name = os.path.split(str(tex2lyx[0]))[1].replace('tex2lyx', 'tex2lyx%s' % version_suffix)
2398 target = os.path.join(bin_dest_dir, target_name)
2399 env.InstallAs(target, tex2lyx)
2400 Alias('install', target)
2402 # install lyxclient, may not exist
2404 target_name = os.path.split(str(client[0]))[1].replace('client', 'client%s' % version_suffix)
2405 target = os.path.join(bin_dest_dir, target_name)
2406 env.InstallAs(target, client)
2407 Alias('install', target)
2410 dirs = install(share_dest_dir,
2411 [env.subst('$TOP_SRCDIR/lib/') + file for file in ['configure.py', 'encodings',
2412 'chkconfig.ltx', 'CREDITS', 'external_templates', 'symbols', 'languages',
2413 'lyxrc.example', 'syntax.default', 'bind', 'images', 'layouts', 'scripts',
2414 'templates', 'examples', 'kbd', 'lyx2lyx', 'tex', 'clipart', 'doc', 'ui']]
2416 # lyx1.4.x does not have lyx2lyx_version.py.in
2417 if os.path.isfile(env.subst('$TOP_SRCDIR/lib/lyx2lyx/lyx2lyx_version.py.in')):
2418 # subst and install this file
2419 env.substFile(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py',
2420 '$TOP_SRCDIR/lib/lyx2lyx/lyx2lyx_version.py.in')
2421 Alias('install', share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2422 Alias('install', dirs)
2424 env.InstallAs(os.path.join(man_dest_dir, 'lyx' + version_suffix + '.1'),
2425 env.subst('$TOP_SRCDIR/lyx.man'))
2426 env.InstallAs(os.path.join(man_dest_dir, 'tex2lyx' + version_suffix + '.1'),
2427 env.subst('$TOP_SRCDIR/src/tex2lyx/tex2lyx.man'))
2428 env.InstallAs(os.path.join(man_dest_dir, 'lyxclient' + version_suffix + '.1'),
2429 env.subst('$TOP_SRCDIR/src/client/lyxclient.man'))
2430 Alias('install', [os.path.join(man_dest_dir, x + version_suffix + '.1') for
2431 x in ['lyx', 'tex2lyx', 'lyxclient']])
2433 # ru.gmo ==> ru/LC_MESSAGES/lyxSUFFIX.mo
2434 for gmo in gmo_files:
2435 lan = os.path.split(str(gmo))[1].split('.')[0]
2436 dest_file = os.path.join(locale_dest_dir, lan, 'LC_MESSAGES', 'lyx' + version_suffix + '.mo')
2437 env.InstallAs(dest_file, gmo)
2438 Alias('install', dest_file)
2442 Alias('all', ['lyx', 'client', 'tex2lyx'])