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, time
17 # scons_utils.py defines a few utility function
18 sys.path.append('config')
19 import scons_utils as utils
20 # import all file lists
21 from scons_manifest import *
23 #----------------------------------------------------------
24 # Required runtime environment
25 #----------------------------------------------------------
27 # scons asks for 1.5.2, lyx requires 2.3
28 EnsurePythonVersion(2, 3)
29 # Please use at least 0.96.92 (not 0.96.1)
30 EnsureSConsVersion(0, 96)
31 # also check for minor version number for scons 0.96
32 from SCons import __version__
33 version = map(int, __version__.split('.'))
34 if version[0] == 0 and version[1] == 96 and version[2] < 92:
35 print "Scons >= 0.96.92 is required."
38 # determine where I am ...
40 # called as 'cd development/scons; scons'
41 if os.path.isfile('SConstruct'):
44 # called as 'scons -f development/scons/SConstruct'
47 scons_dir = 'development/scons'
50 #----------------------------------------------------------
52 #----------------------------------------------------------
54 # some global settings
56 # get version number from configure.ac so that JMarc does
57 # not have to change SConstruct during lyx release
58 package_version = utils.getVerFromConfigure(top_src_dir)
59 package_cygwin_version = '%s-1' % package_version
60 boost_version = '1_33_1'
63 default_build_mode = 'debug'
66 package_bugreport = 'lyx-devel@lists.lyx.org'
68 package_tarname = 'lyx'
69 package_string = '%s %s' % (package_name, package_version)
71 # various cache/log files
72 default_log_file = 'scons_lyx.log'
73 env_cache_file = 'env.cache'
76 #----------------------------------------------------------
77 # platform dependent settings
78 #----------------------------------------------------------
81 platform_name = 'win32'
82 default_frontend = 'qt4'
83 default_prefix = 'c:/program files/lyx'
84 default_with_x = False
85 default_packaging_method = 'windows'
86 elif os.name == 'posix' and sys.platform != 'cygwin':
87 platform_name = sys.platform
88 default_frontend = 'qt3'
89 default_prefix = '/usr/local'
91 default_packaging_method = 'posix'
92 elif os.name == 'posix' and sys.platform == 'cygwin':
93 platform_name = 'cygwin'
94 default_frontend = 'qt3'
95 default_prefix = '/usr'
97 default_packaging_method = 'posix'
98 elif os.name == 'darwin':
99 platform_name = 'macosx'
100 default_frontend = 'qt3'
101 # FIXME: macOSX default prefix?
103 default_with_x = False
104 default_packaging_method = 'macosx'
105 else: # unsupported system, assume posix behavior
106 platform_name = 'others'
107 default_frontend = 'qt3'
109 default_with_x = True
110 default_packaging_method = 'posix'
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 = ('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, LYX_DATE, 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
396 env['LYX_DATE'] = time.asctime()
398 # determine share_dir etc
399 packaging_method = env.get('packaging')
400 if packaging_method == 'windows':
401 share_dir = 'Resources'
402 man_dir = 'Resources/man/man1'
403 locale_dir = 'Resources/locale'
405 share_dir = 'share/lyx'
406 locale_dir = 'share/locale'
407 if platform_name == 'cygwin':
408 man_dir = 'share/man/man1'
412 # program suffix: can be yes, or a string
413 if env.has_key('version_suffix'):
414 if env['version_suffix'] in true_strings:
415 program_suffix = package_version
416 elif env['version_suffix'] in false_strings:
419 program_suffix = env['version_suffix']
422 # used by package.C.in
423 env['PROGRAM_SUFFIX'] = program_suffix
425 # whether or not add suffix to file and directory names
426 add_suffix = packaging_method != 'windows'
427 # LYX_DIR are different (used in package.C.in)
429 env['LYX_DIR'] = Dir(os.path.join(prefix, share_dir + program_suffix)).abspath
431 env['LYX_DIR'] = Dir(os.path.join(prefix, share_dir)).abspath
432 # we need absolute path for package.C
433 env['LOCALEDIR'] = Dir(os.path.join(prefix, locale_dir)).abspath
436 #---------------------------------------------------------
437 # Setting building environment (Tools, compiler flags etc)
438 #---------------------------------------------------------
440 # Since Tool('mingw') will reset CCFLAGS etc, this should be
441 # done before getEnvVariable
442 if platform_name == 'win32':
448 env.AppendUnique(CPPPATH = ['#c:/MinGW/include'])
450 # we differentiate between hard-coded options and default options
451 # hard-coded options are required and will always be there
452 # default options can be replaced by enviromental variables or command line options
453 CCFLAGS_required = []
454 LINKFLAGS_required = []
457 # under windows, scons is confused by .C/.c and uses gcc instead of
458 # g++. I am forcing the use of g++ here. This is expected to change
459 # after lyx renames all .C files to .cpp
461 # save the old c compiler and CCFLAGS (used by libintl)
462 C_COMPILER = env.subst('$CC')
463 C_CCFLAGS = env.subst('$CCFLAGS').split()
464 # if we use ms vc, the commands are fine (cl.exe and link.exe)
466 # /TP treat all source code as C++
467 # C4819: The file contains a character that cannot be represented
468 # in the current code page (number)
469 # C4996: foo was decleared deprecated
470 CCFLAGS_required.extend(['/TP', '/EHsc'])
472 CCFLAGS_default.extend(['/wd4819', '/wd4996', '/nologo', '/MDd'])
473 # the flags are also needed in C mode (for intl lib)
474 C_CCFLAGS.extend(['/wd4819', '/wd4996', '/nologo', '/MDd'])
476 CCFLAGS_default.extend(['/wd4819', '/wd4996', '/nologo', '/MD'])
477 C_CCFLAGS.extend(['/wd4819', '/wd4996', '/nologo', '/MD'])
479 if env.has_key('CXX') and env['CXX']:
480 env['CC'] = env.subst('$CXX')
481 env['LINK'] = env.subst('$CXX')
486 # for debug/release mode
487 if env.has_key('optimization') and env['optimization'] is not None:
488 # if user supplies optimization flags, use it anyway
489 CCFLAGS_required.extend(env['optimization'].split())
490 # and do not use default
491 set_default_optimization_flags = False
493 set_default_optimization_flags = True
497 CCFLAGS_required.append('/Zi')
498 LINKFLAGS_required.extend(['/debug', '/map'])
500 CCFLAGS_required.append('-g')
501 CCFLAGS_default.append('-O')
502 elif mode == 'release' and set_default_optimization_flags:
504 CCFLAGS_default.append('/O2')
506 CCFLAGS_default.append('-O2')
508 # msvc uses separate tools for profiling
509 if env.has_key('profiling') and env['profiling']:
511 print 'Visual C++ does not use profiling options'
513 CCFLAGS_required.append('-pg')
514 LINKFLAGS_required.append('-pg')
516 if env.has_key('warnings') and env['warnings']:
518 CCFLAGS_default.append('/W2')
520 # Note: autotools detect gxx version and pass -W for 3.x
521 # and -Wextra for other versions of gcc
522 CCFLAGS_default.append('-Wall')
524 # Now, set the variables as follows:
525 # 1. if command line option exists: replace default
526 # 2. then if s envronment variable exists: replace default
527 # 3. set variable to required + default
528 def setEnvVariable(env, name, required = None, default = None, split = True):
529 ''' env: environment to set variable
531 required: hardcoded options
532 default: default options that can be replaced by command line or
533 environment variables
534 split: whether or not split obtained variable like '-02 -g'
536 # 1. ARGUMENTS is already set to env[name], override default.
537 if ARGUMENTS.has_key(name):
538 # env[name] may be rewritten when building tools are reloaded
539 # if that is the case, commandline option will override it.
540 env[name] = ARGUMENTS[name]
542 # then use environment default
543 elif os.environ.has_key(name):
544 print "Acquiring variable %s from system environment: %s" % (name, os.environ[name])
545 default = os.environ[name]
547 default = default.split()
548 # the real value should be env[name] + default + required
551 if env.has_key(name):
552 value = str(env[name]).split()
553 if required is not None:
555 if default is not None:
559 if env.has_key(name):
560 value = str(env[name])
561 if required is not None:
562 value += " " + required
563 if default is not None:
564 value += " " + default
566 # print name, env[name]
568 setEnvVariable(env, 'DESTDIR', split=False)
569 setEnvVariable(env, 'CC')
570 setEnvVariable(env, 'LINK')
571 setEnvVariable(env, 'CPP')
572 setEnvVariable(env, 'CXX')
573 setEnvVariable(env, 'CXXCPP')
574 setEnvVariable(env, 'CCFLAGS', CCFLAGS_required, CCFLAGS_default)
575 setEnvVariable(env, 'CXXFLAGS')
576 setEnvVariable(env, 'CPPFLAGS')
577 setEnvVariable(env, 'LINKFLAGS', LINKFLAGS_required)
579 # if DESTDIR is not set...
580 if env.has_key('dest_dir'):
581 print "This option is obsolete. Please use DESTDIR instead."
582 env['DESTDIR'] = env['dest_dir']
585 #---------------------------------------------------------
586 # Frontend related variables (QTDIR etc)
587 #---------------------------------------------------------
589 if env.has_key('qt_dir') and env['qt_dir']:
590 env['QTDIR'] = env['qt_dir']
591 elif os.path.isdir(os.environ.get('QTDIR', '/usr/lib/qt-3.3')):
592 env['QTDIR'] = os.environ.get('QTDIR', '/usr/lib/qt-3.3')
594 # if there is a valid QTDIR, set path for lib and bin directories
595 if env.has_key('QTDIR'):
596 # add path to the qt tools
597 if os.path.isdir(os.path.join(env['QTDIR'], 'lib')):
598 env.AppendUnique(LIBPATH = [os.path.join(env['QTDIR'], 'lib')])
599 # set environment so that moc etc can be found even if its path is not set properly
600 if os.path.isdir(os.path.join(env['QTDIR'], 'bin')):
601 os.environ['PATH'] += os.pathsep + os.path.join(env['QTDIR'], 'bin')
602 env.PrependENVPath('PATH', os.path.join(env['QTDIR'], 'bin'))
604 if env.has_key('qt_lib_path') and env['qt_lib_path']:
605 qt_lib_path = env.subst('$qt_lib_path')
606 elif env.has_key('QTDIR') and os.path.isdir(os.path.join(env.subst('$QTDIR'), 'lib')):
607 qt_lib_path = env.subst('$QTDIR/lib')
608 # this is the path for cygwin.
609 elif os.path.isdir(os.path.join('/usr/lib/', frontend, 'lib')):
610 qt_lib_path = '/usr/lib/%s/lib' % frontend
612 print "Qt library directory is not found. Please specify it using qt_lib_path"
614 env.AppendUnique(LIBPATH = [qt_lib_path])
615 # qt4 seems to be using pkg_config
616 env.PrependENVPath('PKG_CONFIG_PATH', qt_lib_path)
618 if env.has_key('qt_inc_path') and env['qt_inc_path']:
619 qt_inc_path = env['qt_inc_path']
620 elif env.has_key('QTDIR') and os.path.isdir(os.path.join(env.subst('$QTDIR'), 'include')):
621 qt_inc_path = '$QTDIR/include'
622 # this is the path for cygwin.
623 elif os.path.isdir('/usr/include/' + frontend):
624 qt_inc_path = '/usr/include/' + frontend
626 print "Qt include directory not found. Please specify it using qt_inc_path"
628 # Note that this CPPPATH is for testing only
629 # it will be removed before calling SConscript
630 env['CPPPATH'] = [qt_inc_path]
633 # extra_inc_path and extra_lib_path
636 if env.has_key('extra_inc_path') and env['extra_inc_path']:
637 extra_inc_paths.append(env['extra_inc_path'])
638 if env.has_key('extra_lib_path') and env['extra_lib_path']:
639 env.AppendUnique(LIBPATH = [env['extra_lib_path']])
640 if env.has_key('extra_inc_path1') and env['extra_inc_path1']:
641 extra_inc_paths.append(env['extra_inc_path1'])
642 if env.has_key('extra_lib_path1') and env['extra_lib_path1']:
643 env.AppendUnique(LIBPATH = [env['extra_lib_path1']])
644 if env.has_key('extra_bin_path') and env['extra_bin_path']:
645 # only the first one is needed (a scons bug?)
646 os.environ['PATH'] += os.pathsep + env['extra_bin_path']
647 env.PrependENVPath('PATH', env['extra_bin_path'])
648 # extra_inc_paths will be used later by intlenv etc
649 env.AppendUnique(CPPPATH = extra_inc_paths)
652 #----------------------------------------------------------
654 #----------------------------------------------------------
656 conf = Configure(env,
658 'CheckPkgConfig' : utils.checkPkgConfig,
659 'CheckPackage' : utils.checkPackage,
660 'CheckMkdirOneArg' : utils.checkMkdirOneArg,
661 'CheckSelectArgType' : utils.checkSelectArgType,
662 'CheckBoostLibraries' : utils.checkBoostLibraries,
663 'CheckCommand' : utils.checkCommand,
664 'CheckCXXGlobalCstd' : utils.checkCXXGlobalCstd,
665 'CheckLC_MESSAGES' : utils.checkLC_MESSAGES,
666 'CheckIconvConst' : utils.checkIconvConst,
667 'CheckSizeOfWChar' : utils.checkSizeOfWChar,
671 # pkg-config? (if not, we use hard-coded options)
673 if conf.CheckPkgConfig('0.15.0'):
674 env['HAS_PKG_CONFIG'] = True
676 print 'pkg-config >= 0.1.50 is not found'
677 env['HAS_PKG_CONFIG'] = False
678 env_cache['HAS_PKG_CONFIG'] = env['HAS_PKG_CONFIG']
680 env['HAS_PKG_CONFIG'] = env_cache['HAS_PKG_CONFIG']
682 # zlib? This is required. (fast_start assumes the existance of zlib)
684 if (not use_vc and not conf.CheckLibWithHeader('z', 'zlib.h', 'C')) \
685 or (use_vc and not conf.CheckLibWithHeader('zdll', 'zlib.h', 'C')):
686 print 'Did not find zdll.lib or zlib.h, exiting!'
688 if conf.CheckLib('iconv'):
689 env['ICONV_LIB'] = 'iconv'
690 elif conf.CheckLib('libiconv'):
691 env['ICONV_LIB'] = 'libiconv'
692 elif conf.CheckFunc('iconv_open'):
693 env['ICONV_LIB'] = None
695 print 'Did not find iconv or libiconv, exiting!'
697 env_cache['ICONV_LIB'] = env['ICONV_LIB']
699 env['ICONV_LIB'] = env_cache['ICONV_LIB']
704 # qt3 does not use pkg_config
705 if frontend == 'qt3':
706 # windows lib name is qt-mt3
707 if not conf.CheckLibWithHeader('qt-mt', 'qapp.h', 'c++', 'QApplication qapp();') \
708 and not conf.CheckLibWithHeader('qt-mt3', 'qapp.h', 'c++', 'QApplication qapp();'):
709 print 'Did not find qt libraries, exiting!'
711 elif frontend == 'qt4':
713 # first: try pkg_config
714 if env['HAS_PKG_CONFIG']:
715 succ = conf.CheckPackage('QtCore') or conf.CheckPackage('QtCore4')
716 # FIXME: use pkg_config information?
717 #env['QT4_PKG_CONFIG'] = succ
718 # second: try to link to it
720 # Under linux, I can test the following perfectly
721 # Under windows, lib names need to passed as libXXX4.a ...
722 succ = conf.CheckLibWithHeader('QtCore', 'QtGui/QApplication', 'c++', 'QApplication qapp();') or \
723 conf.CheckLibWithHeader('QtCore4', 'QtGui/QApplication', 'c++', 'QApplication qapp();')
724 # third: try to look up the path
727 for lib in ['QtCore', 'QtGui']:
728 # windows version has something like QtGui4 ...
729 if not (os.path.isfile(os.path.join(qt_lib_path, 'lib%s.a' % lib)) or \
730 os.path.isfile(os.path.join(qt_lib_path, 'lib%s4.a' % lib))):
733 # still can not find it
735 print "Qt4 libraries are found."
737 print 'Did not find qt libraries, exiting!'
740 # now, if msvc2005 is used, we will need that QT_LIB_PATH/QT_LIB.manifest file
742 if frontend == 'qt3':
743 manifest = os.path.join(qt_lib_path, 'qt-mt3.dll.manifest')
744 elif frontend == 'qt4':
746 manifest = os.path.join(qt_lib_path, 'QtGuid4.dll.manifest')
748 manifest = os.path.join(qt_lib_path, 'QtGui4.dll.manifest')
749 if os.path.isfile(manifest):
750 env['LINKCOM'] = [env['LINKCOM'], 'mt.exe /MANIFEST %s /outputresource:$TARGET;1' % manifest]
755 if conf.CheckLib('socket'):
756 socket_libs.append('socket')
757 # nsl is the network services library and provides a
758 # transport-level interface to networking services.
759 if conf.CheckLib('nsl'):
760 socket_libs.append('nsl')
761 env_cache['SOCKET_LIBS'] = socket_libs
763 socket_libs = env_cache['SOCKET_LIBS']
765 # check available boost libs (since lyx1.4 does not use iostream)
767 for lib in ['signals', 'regex', 'filesystem', 'iostreams']:
768 if os.path.isdir(os.path.join(top_src_dir, 'boost', 'libs', lib)):
769 boost_libs.append(lib)
772 # check boost libraries
773 boost_opt = ARGUMENTS.get('boost', 'auto')
774 # check for system boost
775 lib_paths = env['LIBPATH'] + ['/usr/lib', '/usr/local/lib']
776 inc_paths = env['CPPPATH'] + ['/usr/include', '/usr/local/include']
777 # default to $BUILDDIR/libs (use None since this path will be added anyway)
779 # here I assume that all libraries are in the same directory
780 if boost_opt == 'included':
781 boost_libraries = ['included_boost_%s' % x for x in boost_libs]
782 included_boost = True
783 env['BOOST_INC_PATH'] = '$TOP_SRCDIR/boost'
784 elif boost_opt == 'auto':
785 res = conf.CheckBoostLibraries(boost_libs, lib_paths, inc_paths, boost_version, mode == 'debug')
786 # if not found, use local boost
788 boost_libraries = ['included_boost_%s' % x for x in boost_libs]
789 included_boost = True
790 env['BOOST_INC_PATH'] = '$TOP_SRCDIR/boost'
792 included_boost = False
793 (boost_libraries, boost_libpath, env['BOOST_INC_PATH']) = res
794 elif boost_opt == 'system':
795 res = conf.CheckBoostLibraries(boost_libs, lib_paths, inc_paths, boost_version, mode == 'debug')
797 print "Can not find system boost libraries with version %s " % boost_version
798 print "Please supply a path through extra_lib_path and try again."
799 print "Or use boost=included to use included boost libraries."
802 included_boost = False
803 (boost_libraries, boost_libpath, env['BOOST_INC_PATH']) = res
804 env_cache['BOOST_LIBRARIES'] = boost_libraries
805 env_cache['INCLUDED_BOOST'] = included_boost
806 env_cache['BOOST_INC_PATH'] = env['BOOST_INC_PATH']
807 env_cache['BOOST_LIBPATH'] = boost_libpath
809 boost_libraries = env_cache['BOOST_LIBRARIES']
810 included_boost = env_cache['INCLUDED_BOOST']
811 env['BOOST_INC_PATH'] = env_cache['BOOST_INC_PATH']
812 boost_libpath = env_cache['BOOST_LIBPATH']
814 if boost_libpath is not None:
815 env.AppendUnique(LIBPATH = [boost_libpath])
818 env['ENABLE_NLS'] = env['nls']
821 if not env['ENABLE_NLS']:
823 included_gettext = False
825 # check gettext libraries
826 gettext_opt = ARGUMENTS.get('gettext', 'auto')
827 # check for system gettext
829 if gettext_opt in ['auto', 'system']:
830 if conf.CheckLib('intl'):
831 included_gettext = False
835 if gettext_opt == 'system':
836 print "Can not find system gettext library"
837 print "Please supply a path through extra_lib_path and try again."
838 print "Or use gettext=included to use included gettext libraries."
840 # now, auto and succ = false, or gettext=included
842 # we do not need to set LIBPATH now.
843 included_gettext = True
844 intl_libs = ['included_intl']
845 env_cache['INCLUDED_GETTEXT'] = included_gettext
846 env_cache['INTL_LIBS'] = intl_libs
848 included_gettext = env_cache['INCLUDED_GETTEXT']
849 intl_libs = env_cache['INTL_LIBS']
852 # check for msgfmt command
854 env['MSGFMT'] = conf.CheckCommand('msgfmt')
855 env_cache['MSGFMT'] = env['MSGFMT']
857 env['MSGFMT'] = env_cache['MSGFMT']
859 # cygwin packaging requires the binaries to be stripped
860 if platform_name == 'cygwin':
862 env['STRIP'] = conf.CheckCommand('strip')
863 env_cache['STRIP'] = env['STRIP']
865 env['STRIP'] = env_cache['STRIP']
867 # check uic and moc commands for qt frontends
869 if frontend[:2] == 'qt' and (conf.CheckCommand('uic') == None \
870 or conf.CheckCommand('moc') == None):
871 print 'uic or moc command is not found for frontend', frontend
875 # Customized builders
877 # install customized builders
878 env['BUILDERS']['substFile'] = Builder(action = utils.env_subst)
881 #----------------------------------------------------------
882 # Generating config.h
883 #----------------------------------------------------------
884 aspell_lib = 'aspell'
885 # assume that we use aspell, aspelld compiled for msvc
886 if platform_name == 'win32' and mode == 'debug' and use_vc:
887 aspell_lib = 'aspelld'
889 # check the existence of config.h
890 config_h = os.path.join(env.Dir('$BUILDDIR/common').path, 'config.h')
891 boost_config_h = os.path.join(env.Dir('$BUILDDIR/boost').path, 'config.h')
892 if not fast_start or not os.path.isfile(boost_config_h) \
893 or not os.path.isfile(config_h):
895 print "Creating %s..." % boost_config_h
897 utils.createConfigFile(conf,
898 config_file = boost_config_h,
899 config_pre = '''/* boost/config.h. Generated by SCons. */
904 * This file is part of LyX, the document processor.
905 * Licence details can be found in the file COPYING.
907 * This is the compilation configuration file for LyX.
908 * It was generated by scon.
909 * You might want to change some of the defaults if something goes wrong
910 * during the compilation.
913 #ifndef _BOOST_CONFIG_H
914 #define _BOOST_CONFIG_H
917 ('ostream', 'HAVE_OSTREAM', 'cxx'),
918 ('locale', 'HAVE_LOCALE', 'cxx'),
919 ('sstream', 'HAVE_SSTREAM', 'cxx'),
920 #('newapis.h', 'HAVE_NEWAPIS_H', 'c'),
923 (env.has_key('assertions') and env['assertions'],
925 'Define if you want assertions to be enabled in the code'
929 ('wchar_t', 'HAVE_WCHAR_T', None),
933 #if defined(HAVE_OSTREAM) && defined(HAVE_LOCALE) && defined(HAVE_SSTREAM)
934 # define USE_BOOST_FORMAT 1
936 # define USE_BOOST_FORMAT 0
939 #if !defined(ENABLE_ASSERTIONS)
940 # define BOOST_DISABLE_ASSERTS 1
942 #define BOOST_ENABLE_ASSERT_HANDLER 1
944 #define BOOST_DISABLE_THREADS 1
945 #define BOOST_NO_WSTRING 1
948 # define BOOST_POSIX 1
949 # define BOOST_POSIX_API 1
950 # define BOOST_POSIX_PATH 1
953 #define BOOST_ALL_NO_LIB 1
955 #if defined(HAVE_NEWAPIS_H)
956 # define WANT_GETFILEATTRIBUTESEX_WRAPPER 1
963 print "\nGenerating %s..." % config_h
965 # AIKSAURUS_H_LOCATION
966 if (conf.CheckCXXHeader("Aiksaurus.h")):
967 aik_location = '<Aiksaurus.h>'
968 elif (conf.CheckCXXHeader("Aiksaurus/Aiksaurus.h")):
969 aik_location = '<Aiksaurus/Aiksaurus.h>'
973 # determine headers to use
974 spell_opt = ARGUMENTS.get('spell', 'auto')
975 env['USE_ASPELL'] = False
976 env['USE_PSPELL'] = False
977 env['USE_ISPELL'] = False
978 if spell_opt in ['auto', 'aspell'] and conf.CheckLib(aspell_lib):
979 spell_engine = 'USE_ASPELL'
980 elif spell_opt in ['auto', 'pspell'] and conf.CheckLib('pspell'):
981 spell_engine = 'USE_PSPELL'
982 elif spell_opt in ['auto', 'ispell'] and conf.CheckLib('ispell'):
983 spell_engine = 'USE_ISPELL'
987 if spell_engine is not None:
988 env[spell_engine] = True
990 if spell_opt == 'auto':
991 print "Warning: Can not locate any spell checker"
992 elif spell_opt != 'no':
993 print "Warning: Can not locate specified spell checker:", spell_opt
996 # check arg types of select function
997 (select_arg1, select_arg234, select_arg5) = conf.CheckSelectArgType()
999 # check the size of wchar_t
1000 sizeof_wchar_t = conf.CheckSizeOfWChar()
1002 if sizeof_wchar_t == 0:
1003 print 'Error: Can not determine the size of wchar_t.'
1008 result = utils.createConfigFile(conf,
1009 config_file = config_h,
1010 config_pre = '''/* config.h. Generated by SCons. */
1015 * This file is part of LyX, the document processor.
1016 * Licence details can be found in the file COPYING.
1018 * This is the compilation configuration file for LyX.
1019 * It was generated by scon.
1020 * You might want to change some of the defaults if something goes wrong
1021 * during the compilation.
1028 ('io.h', 'HAVE_IO_H', 'c'),
1029 ('limits.h', 'HAVE_LIMITS_H', 'c'),
1030 ('locale.h', 'HAVE_LOCALE_H', 'c'),
1031 ('process.h', 'HAVE_PROCESS_H', 'c'),
1032 ('stdlib.h', 'HAVE_STDLIB_H', 'c'),
1033 ('sys/stat.h', 'HAVE_SYS_STAT_H', 'c'),
1034 ('sys/time.h', 'HAVE_SYS_TIME_H', 'c'),
1035 ('sys/types.h', 'HAVE_SYS_TYPES_H', 'c'),
1036 ('sys/utime.h', 'HAVE_SYS_UTIME_H', 'c'),
1037 ('sys/socket.h', 'HAVE_SYS_SOCKET_H', 'c'),
1038 ('unistd.h', 'HAVE_UNISTD_H', 'c'),
1039 ('utime.h', 'HAVE_UTIME_H', 'c'),
1040 ('direct.h', 'HAVE_DIRECT_H', 'c'),
1041 ('istream', 'HAVE_ISTREAM', 'cxx'),
1042 ('ios', 'HAVE_IOS', 'cxx'),
1045 ('open', 'HAVE_OPEN', None),
1046 ('close', 'HAVE_CLOSE', None),
1047 ('popen', 'HAVE_POPEN', None),
1048 ('pclose', 'HAVE_PCLOSE', None),
1049 ('_open', 'HAVE__OPEN', None),
1050 ('_close', 'HAVE__CLOSE', None),
1051 ('_popen', 'HAVE__POPEN', None),
1052 ('_pclose', 'HAVE__PCLOSE', None),
1053 ('getpid', 'HAVE_GETPID', None),
1054 ('_getpid', 'HAVE__GETPID', None),
1055 ('mkdir', 'HAVE_MKDIR', None),
1056 ('_mkdir', 'HAVE__MKDIR', None),
1057 ('mktemp', 'HAVE_MKTEMP', None),
1058 ('mkstemp', 'HAVE_MKSTEMP', None),
1059 ('strerror', 'HAVE_STRERROR', None),
1060 ('count', 'HAVE_STD_COUNT', '''
1061 #include <algorithm>
1065 return std::count(a, a+5, 'l');
1068 ('getcwd', 'HAVE_GETCWD', None),
1069 ('setenv', 'HAVE_SETENV', None),
1070 ('putenv', 'HAVE_PUTENV', None),
1071 ('fcntl', 'HAVE_FCNTL', None),
1074 ('std::istreambuf_iterator<std::istream>', 'HAVE_DECL_ISTREAMBUF_ITERATOR',
1075 '#include <streambuf>\n#include <istream>'),
1076 ('wchar_t', 'HAVE_WCHAR_T', None),
1079 ('gdi32', 'HAVE_LIBGDI32'),
1080 (('Aiksaurus', 'libAiksaurus'), 'HAVE_LIBAIKSAURUS', 'AIKSAURUS_LIB'),
1083 (conf.CheckType('pid_t', includes='#include <sys/types.h>'),
1085 'Define is sys/types.h does not have pid_t',
1087 '#define pid_t int',
1089 (conf.CheckCXXGlobalCstd(),
1091 'Define if your C++ compiler puts C library functions in the global namespace'
1093 (conf.CheckMkdirOneArg(),
1094 'MKDIR_TAKES_ONE_ARG',
1095 'Define if mkdir takes only one argument.'
1097 (conf.CheckIconvConst(),
1099 'Define as const if the declaration of iconv() needs const.',
1100 '#define ICONV_CONST const',
1101 '#define ICONV_CONST',
1103 (conf.CheckLC_MESSAGES(),
1105 'Define if your <locale.h> file defines LC_MESSAGES.'
1107 (devel_version, 'DEVEL_VERSION', 'Whether or not a development version'),
1110 "Define to 1 if translation of program messages to the user's native anguage is requested.",
1112 (env['nls'] and not included_gettext,
1114 'Define to 1 if using system gettext library'
1116 (env.has_key('warnings') and env['warnings'],
1118 'Define this if you want to see the warning directives put here and there by the developpers to get attention'
1120 (env.has_key('concept_checks') and env['concept_checks'],
1121 '_GLIBCXX_CONCEPT_CHECKS',
1122 'libstdc++ concept checking'
1124 (env.has_key('stdlib_debug') and env['stdlib_debug'],
1126 'libstdc++ debug mode'
1128 (env.has_key('stdlib_debug') and env['stdlib_debug'],
1129 '_GLIBCXX_DEBUG_PEDANTIC',
1130 'libstdc++ pedantic debug mode'
1132 (os.name != 'nt', 'BOOST_POSIX',
1133 'Indicates to boost < 1.34 which API to use (posix or windows).'
1135 (os.name != 'nt', 'BOOST_POSIX_API',
1136 'Indicates to boost 1.34 which API to use (posix or windows).'
1138 (os.name != 'nt', 'BOOST_POSIX_PATH',
1139 'Indicates to boost 1.34 which path style to use (posix or windows).'
1141 (spell_engine is not None, spell_engine,
1142 'Spell engine to use'
1144 # we need to know the byte order for unicode conversions
1145 (sys.byteorder == 'big', 'WORDS_BIGENDIAN',
1146 'Define to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX).'
1150 ('#define PACKAGE "%s%s"' % (package, program_suffix),
1152 ('#define PACKAGE_BUGREPORT "%s"' % package_bugreport,
1153 'Define to the address where bug reports for this package should be sent.'),
1154 ('#define PACKAGE_NAME "%s"' % package_name,
1155 'Define to the full name of this package.'),
1156 ('#define PACKAGE_STRING "%s"' % package_string,
1157 'Define to the full name and version of this package.'),
1158 ('#define PACKAGE_TARNAME "%s"' % package_tarname,
1159 'Define to the one symbol short name of this package.'),
1160 ('#define PACKAGE_VERSION "%s"' % package_version,
1161 'Define to the version of this package.'),
1162 ('#define BOOST_ALL_NO_LIB 1',
1163 'disable automatic linking of boost libraries.'),
1164 ('#define USE_%s_PACKAGING 1' % packaging_method.upper(),
1165 'Packaging method'),
1166 ('#define AIKSAURUS_H_LOCATION ' + aik_location,
1167 'Aiksaurus include file'),
1168 ('#define SELECT_TYPE_ARG1 %s' % select_arg1,
1169 "Define to the type of arg 1 for `select'."),
1170 ('#define SELECT_TYPE_ARG234 %s' % select_arg234,
1171 "Define to the type of arg 2, 3, 4 for `select'."),
1172 ('#define SELECT_TYPE_ARG5 %s' % select_arg5,
1173 "Define to the type of arg 5 for `select'."),
1174 ('#define SIZEOF_WCHAR_T %d' % sizeof_wchar_t,
1175 'Define to be the size of type wchar_t'),
1177 config_post = '''/************************************************************
1178 ** You should not need to change anything beyond this point */
1180 #ifndef HAVE_STRERROR
1181 #if defined(__cplusplus)
1184 char * strerror(int n);
1188 #ifndef HAVE_DECL_MKSTEMP
1189 #if defined(__cplusplus)
1196 #include <../boost/config.h>
1202 # these keys are needed in env
1203 for key in ['USE_ASPELL', 'USE_PSPELL', 'USE_ISPELL', 'HAVE_FCNTL',\
1204 'HAVE_LIBGDI32', 'HAVE_LIBAIKSAURUS', 'AIKSAURUS_LIB']:
1205 # USE_ASPELL etc does not go through result
1206 if result.has_key(key):
1207 env[key] = result[key]
1208 env_cache[key] = env[key]
1211 # if nls=yes and gettext=included, create intl/config.h
1212 # intl/libintl.h etc
1214 intl_config_h = os.path.join(env.Dir('$BUILDDIR/intl').path, 'config.h')
1215 if env['nls'] and included_gettext:
1217 print "Creating %s..." % intl_config_h
1219 # create intl/config.h
1220 result = utils.createConfigFile(conf,
1221 config_file = intl_config_h,
1222 config_pre = '''/* intl/config.h. Generated by SCons. */
1227 * This file is part of LyX, the document processor.
1228 * Licence details can be found in the file COPYING.
1230 * This is the compilation configuration file for LyX.
1231 * It was generated by scon.
1232 * You might want to change some of the defaults if something goes wrong
1233 * during the compilation.
1240 ('unistd.h', 'HAVE_UNISTD_H', 'c'),
1241 ('inttypes.h', 'HAVE_INTTYPES_H', 'c'),
1242 ('string.h', 'HAVE_STRING_H', 'c'),
1243 ('strings.h', 'HAVE_STRINGS_H', 'c'),
1244 ('argz.h', 'HAVE_ARGZ_H', 'c'),
1245 ('limits.h', 'HAVE_LIMITS_H', 'c'),
1246 ('alloca.h', 'HAVE_ALLOCA_H', 'c'),
1247 ('stddef.h', 'HAVE_STDDEF_H', 'c'),
1248 ('stdint.h', 'HAVE_STDINT_H', 'c'),
1249 ('sys/param.h', 'HAVE_SYS_PARAM_H', 'c'),
1252 ('getcwd', 'HAVE_GETCWD', None),
1253 ('stpcpy', 'HAVE_STPCPY', None),
1254 ('strcasecmp', 'HAVE_STRCASECMP', None),
1255 ('strdup', 'HAVE_STRDUP', None),
1256 ('strtoul', 'HAVE_STRTOUL', None),
1257 ('alloca', 'HAVE_ALLOCA', None),
1258 ('__fsetlocking', 'HAVE___FSETLOCKING', None),
1259 ('mempcpy', 'HAVE_MEMPCPY', None),
1260 ('__argz_count', 'HAVE___ARGZ_COUNT', None),
1261 ('__argz_next', 'HAVE___ARGZ_NEXT', None),
1262 ('__argz_stringify', 'HAVE___ARGZ_STRINGIFY', None),
1263 ('setlocale', 'HAVE_SETLOCALE', None),
1264 ('tsearch', 'HAVE_TSEARCH', None),
1265 ('getegid', 'HAVE_GETEGID', None),
1266 ('getgid', 'HAVE_GETGID', None),
1267 ('getuid', 'HAVE_GETUID', None),
1268 ('wcslen', 'HAVE_WCSLEN', None),
1269 ('asprintf', 'HAVE_ASPRINTF', None),
1270 ('wprintf', 'HAVE_WPRINTF', None),
1271 ('snprintf', 'HAVE_SNPRINTF', None),
1272 ('printf', 'HAVE_POSIX_PRINTF', None),
1273 ('fcntl', 'HAVE_FCNTL', None),
1276 ('intmax_t', 'HAVE_INTMAX_T', None),
1277 ('long double', 'HAVE_LONG_DOUBLE', None),
1278 ('long long', 'HAVE_LONG_LONG', None),
1279 ('wchar_t', 'HAVE_WCHAR_T', None),
1280 ('wint_t', 'HAVE_WINT_T', None),
1281 ('uintmax_t', 'HAVE_INTTYPES_H_WITH_UINTMAX', '#include <inttypes.h>'),
1282 ('uintmax_t', 'HAVE_STDINT_H_WITH_UINTMAX', '#include <stdint.h>'),
1288 (conf.CheckLC_MESSAGES(),
1290 'Define if your <locale.h> file defines LC_MESSAGES.'
1292 (conf.CheckIconvConst(),
1294 'Define as const if the declaration of iconv() needs const.',
1295 '#define ICONV_CONST const',
1296 '#define ICONV_CONST',
1298 (conf.CheckType('intmax_t', includes='#include <stdint.h>') or \
1299 conf.CheckType('intmax_t', includes='#include <inttypes.h>'),
1301 "Define to 1 if you have the `intmax_t' type."
1303 (env.has_key('nls') and env['nls'],
1305 "Define to 1 if translation of program messages to the user's native anguage is requested.",
1309 ('#define HAVE_ICONV 1', 'Define if iconv or libiconv is found'),
1310 ('#define SIZEOF_WCHAR_T %d' % sizeof_wchar_t,
1311 'Define to be the size of type wchar_t'),
1313 config_post = '#endif'
1316 # these keys are needed in env
1317 for key in ['HAVE_ASPRINTF', 'HAVE_WPRINTF', 'HAVE_SNPRINTF', \
1318 'HAVE_POSIX_PRINTF', 'HAVE_LIBC']:
1319 # USE_ASPELL etc does not go through result
1320 if result.has_key(key):
1321 env[key] = result[key]
1322 env_cache[key] = env[key]
1326 # this comes as a big surprise, without this line
1327 # (doing nothing obvious), adding fast_start=yes
1328 # to a build with fast_start=no will result in a rebuild
1329 # Note that the exact header file to check does not matter
1330 conf.CheckCHeader('io.h')
1331 # only a few variables need to be rescanned
1332 for key in ['USE_ASPELL', 'USE_PSPELL', 'USE_ISPELL', 'HAVE_FCNTL',\
1333 'HAVE_LIBGDI32', 'HAVE_LIBAIKSAURUS', 'AIKSAURUS_LIB']:
1334 env[key] = env_cache[key]
1337 if env['nls'] and included_gettext:
1338 # only a few variables need to be rescanned
1339 for key in ['HAVE_ASPRINTF', 'HAVE_WPRINTF', 'HAVE_SNPRINTF', \
1340 'HAVE_POSIX_PRINTF', 'HAVE_LIBC']:
1341 env[key] = env_cache[key]
1343 # this looks misplaced, but intl/libintl.h is needed by src/message.C
1344 if env['nls'] and included_gettext:
1345 # libgnuintl.h.in => libintl.h
1346 env.Depends('$TOP_SRCDIR/intl/libintl.h', '$BUILDDIR/intl/config.h')
1347 env.substFile('$BUILDDIR/intl/libintl.h', '$TOP_SRCDIR/intl/libgnuintl.h.in')
1348 env.Command('$BUILDDIR/intl/libgnuintl.h', '$BUILDDIR/intl/libintl.h',
1349 [Copy('$TARGET', '$SOURCE')])
1352 # Finish auto-configuration
1355 #----------------------------------------------------------
1356 # Now set up our build process accordingly
1357 #----------------------------------------------------------
1362 # NOTE: Tool('qt') or Tool('qt4') will be loaded later
1363 # in their respective directory and specialized env.
1364 if frontend == 'qt3':
1365 # note: env.Tool('qt') my set QT_LIB to qt
1366 if platform_name == 'win32':
1367 qt_libs = ['qt-mt3']
1370 frontend_libs = qt_libs
1371 elif frontend == 'qt4':
1372 qt_libs = ['QtCore', 'QtGui']
1373 # set the right lib names
1374 if platform_name == 'win32':
1375 if mode == 'debug' and use_vc:
1376 qt_lib_suffix = 'd4'
1381 qt_lib_suffix = '_debug'
1384 frontend_libs = [x + qt_lib_suffix for x in qt_libs]
1387 if env['ICONV_LIB'] is None:
1390 system_libs = [env['ICONV_LIB']]
1391 if platform_name in ['win32', 'cygwin']:
1392 # the final link step needs stdc++ to succeed under mingw
1393 # FIXME: shouldn't g++ automatically link to stdc++?
1395 system_libs += ['ole32', 'shlwapi', 'shell32', 'advapi32', 'zdll']
1397 system_libs += ['shlwapi', 'stdc++', 'z']
1398 elif platform_name == 'cygwin' and env['X11']:
1399 system_libs += ['GL', 'Xmu', 'Xi', 'Xrender', 'Xrandr',
1400 'Xcursor', 'Xft', 'freetype', 'fontconfig', 'Xext', 'X11', 'SM', 'ICE',
1401 'resolv', 'pthread', 'z']
1403 system_libs += ['z']
1406 ('HAVE_LIBGDI32', 'gdi32'),
1407 ('HAVE_LIBAIKSAURUS', env['AIKSAURUS_LIB']),
1408 ('USE_ASPELL', aspell_lib),
1409 ('USE_ISPELL', 'ispell'),
1410 ('USE_PSPELL', 'pspell'),
1415 system_libs.append(lib[1])
1418 # Build parameters CPPPATH etc
1421 env.AppendUnique(LIBPATH = ['/usr/X11R6/lib'])
1424 # boost: for boost header files
1425 # BUILDDIR/common: for config.h
1426 # TOP_SRCDIR/src: for support/* etc
1428 env['CPPPATH'] += ['$BUILDDIR/common', '$TOP_SRCDIR/src']
1430 # Separating boost directories from CPPPATH stops scons from building
1431 # the dependency tree for boost header files, and effectively reduce
1432 # the null build time of lyx from 29s to 16s. Since lyx may tweak local
1433 # boost headers, this is only done for system boost headers.
1435 env.AppendUnique(CPPPATH = ['$BOOST_INC_PATH'])
1438 env.PrependUnique(CCFLAGS = ['/I$BOOST_INC_PATH'])
1440 env.PrependUnique(CCFLAGS = ['-I$BOOST_INC_PATH'])
1442 # for intl/config.h, intl/libintl.h and intl/libgnuintl.h
1443 if env['nls'] and included_gettext:
1444 env['CPPPATH'].append('$BUILDDIR/intl')
1446 # QT_INC_PATH is not needed for *every* source file
1447 env['CPPPATH'].remove(qt_inc_path)
1450 # A Link script for cygwin see
1451 # http://www.cygwin.com/ml/cygwin/2004-09/msg01101.html
1452 # http://www.cygwin.com/ml/cygwin-apps/2004-09/msg00309.html
1455 if platform_name == 'cygwin':
1456 ld_script_path = '/tmp'
1457 ld_script = utils.installCygwinLDScript(ld_script_path)
1458 env.AppendUnique(LINKFLAGS = ['-Wl,--enable-runtime-pseudo-reloc',
1459 '-Wl,--script,%s' % ld_script, '-Wl,-s'])
1464 # fill in the version info
1465 env['VERSION_INFO'] = '''Configuration
1467 Special build flags: %s
1469 C Compiler flags: %s %s
1471 C++ Compiler LyX flags: %s
1472 C++ Compiler flags: %s %s
1474 Linker user flags: %s
1476 Builing directory: %s
1477 Local library directory: %s
1480 Frontend libraries: %s
1481 System libraries: %s
1482 include search path: %s
1488 ''' % (platform_name,
1489 env.subst('$CCFLAGS'), env.subst('$CC'),
1490 env.subst('$CPPFLAGS'), env.subst('$CFLAGS'),
1491 env.subst('$CXX'), env.subst('$CXXFLAGS'),
1492 env.subst('$CPPFLAGS'), env.subst('$CXXFLAGS'),
1493 env.subst('$LINKFLAGS'), env.subst('$LINKFLAGS'),
1494 env.subst('$BUILDDIR'), env.subst('$LOCALLIBPATH'),
1495 str(env['LIBPATH']), str(boost_libraries),
1496 str(frontend_libs), str(system_libs), str(env['CPPPATH']),
1497 frontend, packaging_method,
1498 prefix, env['LYX_DIR'])
1500 if frontend in ['qt3', 'qt4']:
1501 env['VERSION_INFO'] += ''' include dir: %s
1504 ''' % (qt_inc_path, qt_lib_path, env['X11'])
1507 print env['VERSION_INFO']
1510 # Mingw command line may be too short for our link usage,
1511 # Here we use a trick from scons wiki
1512 # http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/LongCmdLinesOnWin32
1514 # I also would like to add logging (commands only) capacity to the
1516 logfile = env.get('logfile', default_log_file)
1517 if logfile != '' or platform_name == 'win32':
1519 utils.setLoggedSpawn(env, logfile, longarg = (platform_name == 'win32'),
1520 info = '''# This is a log of commands used by scons to build lyx
1524 ''' % (time.asctime(), ' '.join(sys.argv),
1525 env['VERSION_INFO'].replace('\n','\n# ')) )
1530 # -h will print out help info
1531 Help(opts.GenerateHelpText(env))
1533 # save environment settings (for fast_start option)
1534 cache_file = open(env_cache_file, 'w')
1535 cPickle.dump(env_cache, cache_file)
1539 #----------------------------------------------------------
1541 #----------------------------------------------------------
1542 # this has been the source of problems on some platforms...
1543 # I find that I need to supply it with full path name
1544 env.SConsignFile(os.path.join(Dir(env['BUILDDIR']).abspath, '.sconsign'))
1545 # this usage needs further investigation.
1546 #env.CacheDir('%s/Cache/%s' % (env['BUILDDIR'], frontend))
1548 print "Building all targets recursively"
1550 if env.has_key('rebuild'):
1551 rebuild_targets = env['rebuild'].split(',')
1552 if 'none' in rebuild_targets or 'no' in rebuild_targets:
1553 rebuild_targets = []
1554 elif 'all' in rebuild_targets or 'yes' in rebuild_targets:
1555 # None: let scons decide which components to build
1556 # Forcing all components to be rebuilt is in theory not necessary
1557 rebuild_targets = None
1559 rebuild_targets = None
1561 def libExists(libname):
1562 ''' Check whether or not lib $LOCALLIBNAME/libname already exists'''
1563 return os.path.isfile(File(env.subst('$LOCALLIBPATH/${LIBPREFIX}%s$LIBSUFFIX'%libname)).abspath)
1565 def appExists(apppath, appname):
1566 ''' Check whether or not application already exists'''
1567 return os.path.isfile(File(env.subst('$BUILDDIR/common/%s/${PROGPREFIX}%s$PROGSUFFIX' % (apppath, appname))).abspath)
1569 targets = BUILD_TARGETS
1570 # msvc need to pass full target name, so I have to look for path/lyx etc
1571 build_lyx = targets == [] or True in ['lyx' in x for x in targets] \
1572 or 'install' in targets or 'all' in targets
1573 build_boost = (included_boost and not libExists('boost_regex')) or 'boost' in targets
1574 build_intl = (included_gettext and not libExists('included_intl')) or 'intl' in targets
1575 build_support = build_lyx or True in [x in targets for x in ['support', 'client', 'tex2lyx']]
1576 build_mathed = build_lyx or 'mathed' in targets
1577 build_insets = build_lyx or 'insets' in targets
1578 build_frontends = build_lyx or 'frontends' in targets
1579 build_graphics = build_lyx or 'graphics' in targets
1580 build_controllers = build_lyx or 'controllers' in targets
1581 build_client = True in ['client' in x for x in targets] \
1582 or 'install' in targets or 'all' in targets
1583 build_tex2lyx = True in ['tex2lyx' in x for x in targets] \
1584 or 'install' in targets or 'all' in targets
1585 build_lyxbase = build_lyx or 'lyxbase' in targets
1586 build_po = 'po' in targets or 'install' in targets or 'all' in targets
1587 build_qt3 = (build_lyx and frontend == 'qt3') or 'qt3' in targets
1588 build_qt4 = (build_lyx and frontend == 'qt4') or 'qt4' in targets
1589 build_msvs_projects = use_vc and 'msvs_projects' in targets
1592 # now, if rebuild_targets is specified, do not rebuild some targets
1593 if rebuild_targets is not None:
1595 def ifBuildLib(name, libname, old_value):
1596 # explicitly asked to rebuild
1597 if name in rebuild_targets:
1599 # else if not rebuild, and if the library already exists
1600 elif libExists(libname):
1602 # do not change the original value
1605 build_boost = ifBuildLib('boost', 'included_boost_filesystem', build_boost)
1606 build_intl = ifBuildLib('intl', 'included_intl', build_intl)
1607 build_support = ifBuildLib('support', 'support', build_support)
1608 build_mathed = ifBuildLib('mathed', 'mathed', build_mathed)
1609 build_insets = ifBuildLib('insets', 'insets', build_insets)
1610 build_frontends = ifBuildLib('frontends', 'frontends', build_frontends)
1611 build_graphics = ifBuildLib('graphics', 'graphics', build_graphics)
1612 build_controllers = ifBuildLib('controllers', 'controllers', build_controllers)
1613 build_lyxbase = ifBuildLib('lyxbase', 'lyxbase_pre', build_lyxbase)
1614 build_qt3 = ifBuildLib('qt3', 'qt3', build_qt3)
1615 build_qt4 = ifBuildLib('qt4', 'qt4', build_qt4)
1617 def ifBuildApp(name, appname, old_value):
1618 # explicitly asked to rebuild
1619 if name in rebuild_targets:
1621 # else if not rebuild, and if the library already exists
1622 elif appExists(name, appname):
1624 # do not change the original value
1627 build_tex2lyx = ifBuildApp('tex2lyx', 'tex2lyx', build_tex2lyx)
1628 build_client = ifBuildApp('client', 'lyxclient', build_client)
1630 # sync frontend and frontend (maybe build qt4 with frontend=qt3)
1642 env.BuildDir('$BUILDDIR/boost', '$TOP_SRCDIR/boost/libs', duplicate = 0)
1644 boostenv = env.Copy()
1646 # boost use its own config.h
1647 boostenv['CPPPATH'] = ['$TOP_SRCDIR/boost', '$BUILDDIR/boost'] + extra_inc_paths
1648 boostenv.AppendUnique(CCFLAGS = ['-DBOOST_USER_CONFIG="<config.h>"'])
1650 for lib in boost_libs:
1651 print 'Processing files in boost/libs/%s/src...' % lib
1652 boostlib = boostenv.StaticLibrary(
1653 target = '$LOCALLIBPATH/included_boost_%s' % lib,
1654 source = ['$BUILDDIR/boost/%s/src/%s' % (lib, x) for x in eval('boost_libs_%s_src_files' % lib)]
1656 Alias('boost', boostlib)
1663 intlenv = env.Copy()
1665 print "Processing files in intl..."
1667 env.BuildDir('$BUILDDIR/intl', '$TOP_SRCDIR/intl', duplicate = 0)
1669 # we need the original C compiler for these files
1670 intlenv['CC'] = C_COMPILER
1671 intlenv['CCFLAGS'] = C_CCFLAGS
1673 intlenv.Append(CCFLAGS=['/Dinline#', '/D__attribute__(x)#', '/Duintmax_t=UINT_MAX'])
1674 # intl does not use global config.h
1675 intlenv['CPPPATH'] = ['$BUILDDIR/intl'] + extra_inc_paths
1677 intlenv.Append(CCFLAGS = [
1678 r'-DLOCALEDIR=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1679 r'-DLOCALE_ALIAS_PATH=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1680 r'-DLIBDIR=\"' + env['TOP_SRCDIR'].replace('\\', '\\\\') + r'/lib\"',
1682 '-DENABLE_RELOCATABLE=1',
1684 r'-DINSTALLDIR=\"' + prefix.replace('\\', '\\\\') + r'/lib\"',
1686 '-Dset_relocation_prefix=libintl_set_relocation_prefix',
1687 '-Drelocate=libintl_relocate',
1688 '-DDEPENDS_ON_LIBICONV=1',
1693 intl = intlenv.StaticLibrary(
1694 target = '$LOCALLIBPATH/included_intl',
1696 source = ['$BUILDDIR/intl/%s' % x for x in intl_files]
1702 # Now, src code under src/
1704 env.BuildDir('$BUILDDIR/common', '$TOP_SRCDIR/src', duplicate = 0)
1711 print "Processing files in src/support..."
1713 env.Depends('$BUILDDIR/common/support/package.C', '$BUILDDIR/common/config.h')
1714 env.substFile('$BUILDDIR/common/support/package.C', '$TOP_SRCDIR/src/support/package.C.in')
1716 support = env.StaticLibrary(
1717 target = '$LOCALLIBPATH/support',
1718 source = ['$BUILDDIR/common/support/%s' % x for x in src_support_files]
1720 Alias('support', support)
1727 print "Processing files in src/mathed..."
1729 mathed = env.StaticLibrary(
1730 target = '$LOCALLIBPATH/mathed',
1731 source = ['$BUILDDIR/common/mathed/%s' % x for x in src_mathed_files]
1733 Alias('mathed', mathed)
1740 print "Processing files in src/insets..."
1742 insets = env.StaticLibrary(
1743 target = '$LOCALLIBPATH/insets',
1744 source = ['$BUILDDIR/common/insets/%s' % x for x in src_insets_files]
1746 Alias('insets', insets)
1753 print "Processing files in src/frontends..."
1755 frontends = env.StaticLibrary(
1756 target = '$LOCALLIBPATH/frontends',
1757 source = ['$BUILDDIR/common/frontends/%s' % x for x in src_frontends_files]
1759 Alias('frontends', frontends)
1766 print "Processing files in src/graphics..."
1768 graphics = env.StaticLibrary(
1769 target = '$LOCALLIBPATH/graphics',
1770 source = ['$BUILDDIR/common/graphics/%s' % x for x in src_graphics_files]
1772 Alias('graphics', graphics)
1775 if build_controllers:
1777 # src/frontends/controllers
1779 print "Processing files in src/frontends/controllers..."
1781 controllers = env.StaticLibrary(
1782 target = '$LOCALLIBPATH/controllers',
1783 source = ['$BUILDDIR/common/frontends/controllers/%s' % x for x in src_frontends_controllers_files]
1785 Alias('controllers', controllers)
1789 # src/frontend/qt3/4
1791 if build_qt3 or build_qt4:
1792 env.BuildDir('$BUILDDIR/$frontend', '$TOP_SRCDIR/src/frontend/$frontend', duplicate = 0)
1795 print "Processing files in src/frontends/qt3..."
1798 # disable auto scan to speed up non build time
1799 qt3env['QT_AUTOSCAN'] = 0
1800 qt3env['QT_MOCHPREFIX'] = ''
1805 qt3env.AppendUnique(CPPPATH = [
1807 '$BUILDDIR/common/images',
1808 '$BUILDDIR/common/frontends',
1809 '$BUILDDIR/common/frontends/qt3',
1810 '$BUILDDIR/common/frontends/controllers',
1814 qt3_moc_files = ["$BUILDDIR/common/frontends/qt3/%s" % x for x in src_frontends_qt3_moc_files]
1816 # manually moc and uic files for better performance
1817 qt3_moced_files = [qt3env.Moc(x.replace('.C', '_moc.cpp'), x.replace('.C', '.h')) for x in qt3_moc_files]
1819 qt3_uiced_files = [qt3env.Uic('$BUILDDIR/common/frontends/qt3/ui/'+x) for x in \
1820 src_frontends_qt3_ui_files]
1822 qt3_uiced_cc_files = []
1823 for x in qt3_uiced_files:
1824 qt3_uiced_cc_files.extend(x[1:])
1826 qt3 = qt3env.StaticLibrary(
1827 target = '$LOCALLIBPATH/qt3',
1828 source = ['$BUILDDIR/common/frontends/qt3/%s' % x for x in src_frontends_qt3_files] \
1829 + qt3_uiced_cc_files
1835 print "Processing files in src/frontends/qt4..."
1838 qt4env['QT_AUTOSCAN'] = 0
1840 # local qt4 toolset from
1841 # http://www.iua.upf.es/~dgarcia/Codders/sconstools.html
1843 # NOTE: I have to patch qt4.py since it does not automatically
1844 # process .C file!!! (add to cxx_suffixes )
1846 qt4env.Tool('qt4', [scons_dir])
1847 qt4env.EnableQt4Modules(qt_libs, debug = (mode == 'debug'))
1849 qt4env.AppendUnique(CPPPATH = [
1851 '$BUILDDIR/common/images',
1852 '$BUILDDIR/common/frontends',
1853 '$BUILDDIR/common/frontends/qt4',
1854 '$BUILDDIR/common/frontends/controllers',
1859 # FIXME: replace by something from pkg_config
1860 qt4env.Append(CCFLAGS = [
1862 '-DQT_CLEAN_NAMESPACE',
1870 qt4_moc_files = ["$BUILDDIR/common/frontends/qt4/%s" % x for x in src_frontends_qt4_moc_files]
1875 resources = [qt4env.Uic4(x.split('.')[0]) for x in \
1876 ["$BUILDDIR/common/frontends/qt4/ui/%s" % x for x in src_frontends_qt4_ui_files]]
1879 # moc qt4_moc_files, the moced files are included in the original files
1881 qt4_moced_files = [qt4env.Moc4(x.replace('.C', '_moc.cpp'), x.replace('.C', '.h')) for x in qt4_moc_files]
1883 qt4 = qt4env.StaticLibrary(
1884 target = '$LOCALLIBPATH/qt4',
1885 source = ['$BUILDDIR/common/frontends/qt4/%s' % x for x in src_frontends_qt4_files]
1894 env.BuildDir('$BUILDDIR/common', '$TOP_SRCDIR/src', duplicate = 0)
1896 print "Processing files in src/client..."
1898 if env['HAVE_FCNTL']:
1899 client = env.Program(
1900 target = '$BUILDDIR/common/client/lyxclient',
1901 LIBS = ['support'] + intl_libs + system_libs +
1902 socket_libs + boost_libraries,
1903 source = ['$BUILDDIR/common/client/%s' % x for x in src_client_files]
1905 Alias('client', env.Command(os.path.join('$BUILDDIR', os.path.split(str(client[0]))[1]),
1906 client, [Copy('$TARGET', '$SOURCE')]))
1909 Alias('client', client)
1911 if env['HAVE_FCNTL']:
1912 # define client even if lyxclient is not built with rebuild=no
1913 client = [env.subst('$BUILDDIR/common/client/${PROGPREFIX}lyxclient$PROGSUFFIX')]
1922 print "Processing files in src/tex2lyx..."
1924 tex2lyx_env = env.Copy()
1926 tex2lyx_env.Prepend(CPPPATH = ['$BUILDDIR/common/tex2lyx'])
1927 tex2lyx_env.AppendUnique(LIBPATH = ['#$LOCALLIBPATH'])
1929 for file in ['FloatList.C', 'Floating.C', 'counters.C', 'lyxlayout.h', 'lyxlayout.C',
1930 'lyxtextclass.h', 'lyxtextclass.C', 'lyxlex.C', 'lyxlex_pimpl.C']:
1931 env.Command('$BUILDDIR/common/tex2lyx/'+file, '$TOP_SRCDIR/src/'+file,
1932 [Copy('$TARGET', '$SOURCE')])
1934 tex2lyx = tex2lyx_env.Program(
1935 target = '$BUILDDIR/common/tex2lyx/tex2lyx',
1936 LIBS = ['support'] + boost_libraries + system_libs,
1937 source = ['$BUILDDIR/common/tex2lyx/%s' % x for x in src_tex2lyx_files]
1939 Alias('tex2lyx', env.Command(os.path.join('$BUILDDIR', os.path.split(str(tex2lyx[0]))[1]),
1940 tex2lyx, [Copy('$TARGET', '$SOURCE')]))
1941 Alias('tex2lyx', tex2lyx)
1943 # define tex2lyx even if tex2lyx is not built with rebuild=no
1944 tex2lyx = [env.subst('$BUILDDIR/common/tex2lyx/${PROGPREFIX}tex2lyx$PROGSUFFIX')]
1951 print "Processing files in src..."
1953 env.Depends('$BUILDDIR/common/version.C', '$BUILDDIR/common/config.h')
1954 env.substFile('$BUILDDIR/common/version.C', '$TOP_SRCDIR/src/version.C.in')
1956 if env.has_key('USE_ASPELL') and env['USE_ASPELL']:
1957 src_post_files.append('aspell.C')
1958 elif env.has_key('USE_PSPELL') and env['USE_PSPELL']:
1959 src_post_files.append('pspell.C')
1960 elif env.has_key('USE_ISPELL') and env['USE_ISPELL']:
1961 src_post_files.append('ispell.C')
1963 # msvc requires at least one source file with main()
1964 # so I exclude main.C from lyxbase
1965 lyxbase_pre = env.StaticLibrary(
1966 target = '$LOCALLIBPATH/lyxbase_pre',
1967 source = ['$BUILDDIR/common/%s' % x for x in src_pre_files]
1969 lyxbase_post = env.StaticLibrary(
1970 target = '$LOCALLIBPATH/lyxbase_post',
1971 source = ["$BUILDDIR/common/%s" % x for x in src_post_files]
1973 Alias('lyxbase', lyxbase_pre)
1974 Alias('lyxbase', lyxbase_post)
1979 # Build lyx with given frontend
1982 target = '$BUILDDIR/$frontend/lyx',
1983 source = ['$BUILDDIR/common/main.C'],
2001 # [/path/to/lyx.ext] => lyx-qt3.ext
2002 target_name = os.path.split(str(lyx[0]))[1].replace('lyx', 'lyx-%s' % frontend)
2003 Alias('lyx', env.Command(os.path.join('$BUILDDIR', target_name), lyx,
2004 [Copy('$TARGET', '$SOURCE')]))
2007 # define lyx even if lyx is not built with rebuild=no
2008 lyx = [env.subst('$BUILDDIR/$frontend/${PROGPREFIX}lyx$PROGSUFFIX')]
2011 if build_msvs_projects:
2012 def build_project(target, full_target = None,
2013 src = [], inc = [], res = [], rebuildTargetOnly = True):
2014 ''' build mavs project files
2015 target: alias (correspond to directory name)
2016 full_target: full path/filename of the target
2020 rebuildTargetOnly: whether or not only rebuild this target
2022 For non-debug-able targets like static libraries, target (alias) is
2023 enough to build the target. For executable targets, msvs need to know
2024 the full path to start debug them.
2026 if rebuildTargetOnly:
2027 cmds = 'fast_start=yes rebuild='+target
2029 cmds = 'fast_start=yes'
2030 if full_target is None:
2031 build_target = target
2033 build_target = full_target
2035 proj = env.MSVSProject(
2036 target = target + env['MSVSPROJECTSUFFIX'],
2037 # this allows easy access to header files (along with source)
2038 srcs = [env.subst(x) for x in src + inc],
2039 incs = [env.subst('$TOP_SRCDIR/src/config.h')],
2040 localincs = [env.subst(x) for x in inc],
2041 resources = [env.subst(x) for x in res],
2042 buildtarget = build_target,
2046 Alias('msvs_projects', proj)
2049 for lib in boost_libs:
2050 boost_src += ['$TOP_SRCDIR/boost/libs/%s/src/%s' % (lib, x) for x in eval('boost_libs_%s_src_files' % lib)]
2051 build_project('boost', src = boost_src)
2053 build_project('intl', src = ['$TOP_SRCDIR/intl/%s' % x for x in intl_files],
2054 inc = ['$TOP_SRCDIR/intl/%s' % x for x in intl_header_files])
2056 build_project('support', src = ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_files],
2057 inc = ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files])
2059 build_project('mathed', src = ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_files],
2060 inc = ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files])
2062 build_project('insets', src = ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_files],
2063 inc = ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files])
2065 build_project('frontends', src = ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_files],
2066 inc = ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files])
2068 build_project('graphics', src = ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_files],
2069 inc = ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files])
2071 build_project('controllers', src = ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files],
2072 inc = ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files])
2074 build_project('qt3', src = ['$TOP_SRCDIR/src/frontends/qt3/%s' % x for x in src_frontends_qt3_files + src_frontends_qt3_moc_files],
2075 inc = ['$TOP_SRCDIR/src/frontends/qt3/%s' % x for x in src_frontends_qt3_header_files],
2076 res = ['$TOP_SRCDIR/src/frontends/qt3/ui/%s' % x for x in src_frontends_qt3_ui_files])
2078 build_project('qt4', src = ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_files + src_frontends_qt4_moc_files],
2079 inc = ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_header_files],
2080 res = ['$TOP_SRCDIR/src/frontends/qt4/ui/%s' % x for x in src_frontends_qt4_ui_files])
2082 build_project('client', src = ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_files],
2083 inc = ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_header_files],
2084 rebuildTargetOnly = False,
2085 full_target = File(env.subst('$BUILDDIR/common/client/lyxclient$PROGSUFFIX')).abspath)
2087 build_project('tex2lyx', src = ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_files],
2088 inc = ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_header_files],
2089 rebuildTargetOnly = False,
2090 full_target = File(env.subst('$BUILDDIR/common/tex2lyx/tex2lyx$PROGSUFFIX')).abspath)
2092 build_project('lyxbase', src = ['$TOP_SRCDIR/src/%s' % x for x in src_pre_files + src_post_files],
2093 inc = ['$TOP_SRCDIR/src/%s' % x for x in src_header_files])
2095 if frontend == 'qt3':
2096 build_project('lyx',
2097 src = ['$TOP_SRCDIR/src/%s' % x for x in src_pre_files + src_post_files] + \
2098 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_files] + \
2099 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_files] + \
2100 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_files] + \
2101 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_files] + \
2102 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_files] + \
2103 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files] + \
2104 ['$TOP_SRCDIR/src/frontends/qt3/%s' % x for x in src_frontends_qt3_files + src_frontends_qt3_moc_files],
2105 inc = ['$TOP_SRCDIR/src/%s' % x for x in src_header_files] + \
2106 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files] + \
2107 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_header_files] + \
2108 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files] + \
2109 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files] + \
2110 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files] + \
2111 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files] + \
2112 ['$TOP_SRCDIR/src/frontends/qt3/%s' % x for x in src_frontends_qt3_header_files],
2113 res = ['$TOP_SRCDIR/src/frontends/qt3/ui/%s' % x for x in src_frontends_qt3_ui_files],
2114 rebuildTargetOnly = False,
2115 full_target = File(env.subst('$BUILDDIR/$frontend/lyx$PROGSUFFIX')).abspath)
2117 build_project('lyx',
2118 src = ['$TOP_SRCDIR/src/%s' % x for x in src_pre_files + src_post_files] + \
2119 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_files] + \
2120 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_files] + \
2121 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_files] + \
2122 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_files] + \
2123 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_files] + \
2124 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files] + \
2125 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_files + src_frontends_qt4_moc_files],
2126 inc = ['$TOP_SRCDIR/src/%s' % x for x in src_header_files] + \
2127 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files] + \
2128 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_header_files] + \
2129 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files] + \
2130 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files] + \
2131 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files] + \
2132 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files] + \
2133 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_header_files],
2134 res = ['$TOP_SRCDIR/src/frontends/qt4/ui/%s' % x for x in src_frontends_qt4_ui_files],
2135 rebuildTargetOnly = False,
2136 full_target = File(env.subst('$BUILDDIR/$frontend/lyx$PROGSUFFIX')).abspath)
2143 print 'Processing files in po...'
2148 # files to translate
2149 transfiles = glob.glob(os.path.join(env.subst('$TOP_SRCDIR'), 'po', '*.po'))
2150 # possibly *only* handle these languages
2152 if env.has_key('languages'):
2153 languages = env.make_list(env['lanauges'])
2154 # use defulat msgfmt
2156 if not env['MSGFMT']:
2157 print 'msgfmt does not exist. Can not process po files'
2160 env['BUILDERS']['Transfiles'] = Builder(action='$MSGFMT $SOURCE -o $TARGET',suffix='.gmo',src_suffix='.po')
2162 for f in transfiles:
2164 fname = os.path.split(f)[1]
2166 country = fname.split('.')[0]
2168 if not languages or country in languages:
2169 gmo_files.extend(env.Transfiles(f))
2172 if 'install' in targets:
2174 # this part is a bit messy right now. Since scons will provide
2175 # --DESTDIR option soon, at least the dest_dir handling can be
2178 # how to join dest_dir and prefix
2179 def joinPaths(path1, path2):
2180 ''' join path1 and path2, do not use os.path.join because
2181 under window, c:\destdir\d:\program is invalid '''
2183 return os.path.normpath(path2)
2184 # separate drive letter
2185 (drive, path) = os.path.splitdrive(os.path.normpath(path2))
2186 # ignore drive letter, so c:\destdir + c:\program = c:\destdir\program
2187 return os.path.join(os.path.normpath(path1), path[1:])
2189 # install to dest_dir/prefix
2190 dest_dir = env.get('DESTDIR', None)
2191 dest_prefix_dir = joinPaths(dest_dir, env.Dir(prefix).abspath)
2192 # create the directory if needed
2193 if not os.path.isdir(dest_prefix_dir):
2195 os.makedirs(dest_prefix_dir)
2198 if not os.path.isdir(dest_prefix_dir):
2199 print 'Can not create directory', dest_prefix_dir
2202 if env.has_key('exec_prefix'):
2203 bin_dest_dir = joinPaths(dest_dir, Dir(env['exec_prefix']).abspath)
2205 bin_dest_dir = os.path.join(dest_prefix_dir, 'bin')
2207 share_dest_dir = os.path.join(dest_prefix_dir, share_dir + program_suffix)
2209 share_dest_dir = os.path.join(dest_prefix_dir, share_dir)
2210 man_dest_dir = os.path.join(dest_prefix_dir, man_dir)
2211 locale_dest_dir = os.path.join(dest_prefix_dir, locale_dir)
2215 # install executables (lyxclient may be None)
2218 version_suffix = program_suffix
2222 # install lyx, if in release mode, try to strip the binary
2223 if env.has_key('STRIP') and env['STRIP'] is not None and mode != 'debug':
2224 # create a builder to strip and install
2225 env['BUILDERS']['StripInstallAs'] = Builder(action='$STRIP $SOURCE -o $TARGET')
2227 # install executables
2228 for (name, obj) in (('lyx', lyx), ('tex2lyx', tex2lyx), ('client', client)):
2231 target_name = os.path.split(str(obj[0]))[1].replace(name, '%s%s' % (name, version_suffix))
2232 target = os.path.join(bin_dest_dir, target_name)
2233 if env['BUILDERS'].has_key('StripInstallAs'):
2234 env.StripInstallAs(target, obj)
2236 env.InstallAs(target, obj)
2237 Alias('install', target)
2241 for (dir,files) in [
2243 ('clipart', lib_clipart_files),
2244 ('examples', lib_examples_files),
2245 ('images', lib_images_files),
2246 ('images/math', lib_images_math_files),
2247 ('bind', lib_bind_files),
2248 ('kbd', lib_kbd_files),
2249 ('layouts', lib_layouts_files),
2250 ('scripts', lib_scripts_files),
2251 ('templates', lib_templates_files),
2252 ('tex', lib_tex_files),
2253 ('ui', lib_ui_files),
2254 ('doc', lib_doc_files),
2255 ('lyx2lyx', lib_lyx2lyx_files)]:
2256 dirs.append(env.Install(os.path.join(share_dest_dir, dir),
2257 [env.subst('$TOP_SRCDIR/lib/%s/%s' % (dir, file)) for file in files]))
2258 Alias('install', dirs)
2260 if platform_name == 'cygwin':
2261 # cygwin packaging requires a file /usr/share/doc/Cygwin/foot-vendor-suffix.README
2262 Cygwin_README = os.path.join(dest_prefix_dir, 'share', 'doc', 'Cygwin',
2263 '%s-%s.README' % (package, package_cygwin_version))
2264 env.InstallAs(Cygwin_README,
2265 os.path.join(env.subst('$TOP_SRCDIR'), 'README.cygwin'))
2266 Alias('install', Cygwin_README)
2267 # also a directory /usr/share/doc/lyx for README etc
2268 Cygwin_Doc = os.path.join(dest_prefix_dir, 'share', 'doc', package)
2269 env.Install(Cygwin_Doc, [os.path.join(env.subst('$TOP_SRCDIR'), x) for x in \
2270 ['INSTALL', 'README', 'README.Cygwin', 'RELEASE-NOTES', 'COPYING', 'ANNOUNCE']])
2271 Alias('install', Cygwin_Doc)
2272 # cygwin fonts also need to be installed
2273 Cygwin_fonts = os.path.join(share_dest_dir, 'fonts')
2274 env.Install(Cygwin_fonts,
2275 [env.subst('$TOP_SRCDIR/development/Win32/packaging/bakoma/%s' % file) \
2276 for file in win32_bakoma_fonts])
2277 Alias('install', Cygwin_fonts)
2278 # we also need a post installation script
2279 tmp_script = utils.installCygwinPostinstallScript('/tmp')
2280 postinstall_script = os.path.join(dest_dir, 'etc', 'postinstall', 'lyx.sh')
2281 env.Install(postinstall_script, tmp_script)
2282 Alias('install', postinstall_script)
2284 # subst and install lyx2lyx_version.py which is not in scons_manifest.py
2285 env.Depends(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py', '$BUILDDIR/common/config.h')
2286 env.substFile(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py',
2287 '$TOP_SRCDIR/lib/lyx2lyx/lyx2lyx_version.py.in')
2288 Alias('install', share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2291 env.InstallAs(os.path.join(man_dest_dir, 'lyx' + version_suffix + '.1'),
2292 env.subst('$TOP_SRCDIR/lyx.man'))
2293 env.InstallAs(os.path.join(man_dest_dir, 'tex2lyx' + version_suffix + '.1'),
2294 env.subst('$TOP_SRCDIR/src/tex2lyx/tex2lyx.man'))
2295 env.InstallAs(os.path.join(man_dest_dir, 'lyxclient' + version_suffix + '.1'),
2296 env.subst('$TOP_SRCDIR/src/client/lyxclient.man'))
2297 Alias('install', [os.path.join(man_dest_dir, x + version_suffix + '.1') for
2298 x in ['lyx', 'tex2lyx', 'lyxclient']])
2300 # ru.gmo ==> ru/LC_MESSAGES/lyxSUFFIX.mo
2301 for gmo in gmo_files:
2302 lan = os.path.split(str(gmo))[1].split('.')[0]
2303 dest_file = os.path.join(locale_dest_dir, lan, 'LC_MESSAGES', 'lyx' + program_suffix + '.mo')
2304 env.InstallAs(dest_file, gmo)
2305 Alias('install', dest_file)
2309 Alias('all', ['lyx', 'client', 'tex2lyx'])