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 # determine where I am ...
19 from SCons.Node.FS import default_fs
20 # default_fs.SConstruct_dir is where SConstruct file is located.
21 scons_dir = default_fs.SConstruct_dir.path
22 scons_absdir = default_fs.SConstruct_dir.abspath
24 # if SConstruct is copied to the top source directory
25 if os.path.exists(os.path.join(scons_dir, 'development', 'scons', 'scons_manifest.py')):
26 scons_dir = os.path.join(scons_dir, 'development', 'scons')
27 scons_absdir = os.path.join(scons_absdir, 'development', 'scons')
28 # get the ../.. of scons_dir
29 top_src_dir = os.path.split(os.path.split(scons_absdir)[0])[0]
31 sys.path.extend([scons_absdir, os.path.join(top_src_dir, 'lib', 'doc')])
34 # scons_utils.py defines a few utility function
35 import scons_utils as utils
36 # import all file lists
37 from scons_manifest import *
39 #----------------------------------------------------------
40 # Required runtime environment
41 #----------------------------------------------------------
43 # scons asks for 1.5.2, lyx requires 2.3
44 EnsurePythonVersion(2, 3)
45 # Please use at least 0.96.92 (not 0.96.1)
46 EnsureSConsVersion(0, 96)
47 # also check for minor version number for scons 0.96
48 from SCons import __version__
49 # allow the use of snapshot version of scons
50 __version__ = __version__.split('d')[0]
51 version = map(int, __version__.split('.'))
52 if version[0] == 0 and version[1] == 96 and version[2] < 92:
53 print "Scons >= 0.96.92 is required."
57 #----------------------------------------------------------
59 #----------------------------------------------------------
61 # some global settings
63 # get version number from configure.ac so that JMarc does
64 # not have to change SConstruct during lyx release
65 package_version, lyx_date = utils.getVerFromConfigure(top_src_dir)
66 package_cygwin_version = '%s-1' % package_version
67 boost_version = ['1_34']
69 if 'svn' in package_version:
71 default_build_mode = 'debug'
74 default_build_mode = 'release'
77 package_bugreport = 'lyx-devel@lists.lyx.org'
79 package_tarname = 'lyx'
80 package_string = '%s %s' % (package_name, package_version)
82 # various cache/log files
83 default_log_file = 'scons_lyx.log'
84 opt_cache_file = 'opt.cache'
87 #----------------------------------------------------------
88 # platform dependent settings
89 #----------------------------------------------------------
92 platform_name = 'win32'
93 default_prefix = 'c:/program files/lyx'
94 default_with_x = False
95 default_packaging_method = 'windows'
96 elif os.name == 'posix' and sys.platform != 'cygwin':
97 platform_name = sys.platform
98 default_prefix = '/usr/local'
100 default_packaging_method = 'posix'
101 elif os.name == 'posix' and sys.platform == 'cygwin':
102 platform_name = 'cygwin'
103 default_prefix = '/usr'
104 default_with_x = True
105 default_packaging_method = 'posix'
106 elif os.name == 'darwin':
107 platform_name = 'macosx'
108 # FIXME: macOSX default prefix?
110 default_with_x = False
111 default_packaging_method = 'macosx'
112 else: # unsupported system, assume posix behavior
113 platform_name = 'others'
115 default_with_x = True
116 default_packaging_method = 'posix'
118 #---------------------------------------------------------
120 #----------------------------------------------------------
122 # You can set perminant default values in config.py
123 if os.path.isfile('config.py'):
124 print "Getting options from config.py..."
125 print open('config.py').read()
127 opts = Options(['config.py'])
130 EnumOption('frontend', 'Main GUI', 'qt4',
131 allowed_values = ('qt4',) ),
132 # debug or release build
133 EnumOption('mode', 'Building method', default_build_mode,
134 allowed_values = ('debug', 'release') ),
137 'Use included, system boost library, or try sytem boost first.',
138 'auto', allowed_values = (
139 'auto', # detect boost, if not found, use included
140 'included', # always use included boost
141 'system', # always use system boost, fail if can not find
144 EnumOption('gettext',
145 'Use included, system gettext library, or try sytem gettext first',
146 'auto', allowed_values = (
147 'auto', # detect gettext, if not found, use included
148 'included', # always use included gettext
149 'system', # always use system gettext, fail if can not find
152 EnumOption('spell', 'Choose spell checker to use.', 'auto',
153 allowed_values = ('aspell', 'pspell', 'ispell', 'auto', 'no') ),
155 EnumOption('packaging', 'Packaging method to use.', default_packaging_method,
156 allowed_values = ('windows', 'posix', 'macosx')),
158 BoolOption('fast_start', 'This option is obsolete.', False),
159 # No precompiled header support (too troublesome to make it work for msvc)
160 # BoolOption('pch', 'Whether or not use pch', False),
161 # enable assertion, (config.h has ENABLE_ASSERTIOS
162 BoolOption('assertions', 'Use assertions', True),
163 # config.h define _GLIBCXX_CONCEPT_CHECKS
164 # Note: for earlier version of gcc (3.3) define _GLIBCPP_CONCEPT_CHECKS
165 BoolOption('concept_checks', 'Enable concept checks', True),
167 BoolOption('nls', 'Whether or not use native language support', True),
169 BoolOption('profiling', 'Whether or not enable profiling', False),
170 # config.h define _GLIBCXX_DEBUG and _GLIBCXX_DEBUG_PEDANTIC
171 BoolOption('stdlib_debug', 'Whether or not turn on stdlib debug', False),
173 BoolOption('X11', 'Use x11 windows system', default_with_x),
174 # use MS VC++ to build lyx
175 BoolOption('use_vc', 'Use MS VC++ to build lyx (cl.exe will be probed)', None),
177 PathOption('qt_dir', 'Path to qt directory', None),
179 PathOption('qt_inc_path', 'Path to qt include directory', None),
181 PathOption('qt_lib_path', 'Path to qt library directory', None),
182 # extra include and libpath
183 PathOption('extra_inc_path', 'Extra include path', None),
185 PathOption('extra_lib_path', 'Extra library path', None),
187 PathOption('extra_bin_path', 'A convenient way to add a path to $PATH', None),
189 PathOption('extra_inc_path1', 'Extra include path', None),
191 PathOption('extra_lib_path1', 'Extra library path', None),
192 # rebuild only specifed, comma separated targets
193 ('rebuild', '''rebuild only specifed, comma separated targets.
194 yes or all (default): rebuild everything
195 no or none: rebuild nothing (usually used for installation)
196 comp1,comp2,...: rebuild specified targets''', None),
197 # can be set to a non-existing directory
198 ('prefix', 'install architecture-independent files in PREFIX', default_prefix),
199 # replace the default name and location of the windows installer
200 ('win_installer', 'name or full path to the windows installer', None),
201 # the deps package used to create minimal installer (qt and other libraries)
202 ('deps_dir', 'path to the development depedency packages with zlib, iconv, zlib and qt libraries', None),
203 # whether or not build bundle installer
204 BoolOption('bundle', 'Whether or not build bundle installer', False),
205 # the bundle directory, containing bundled applications
206 PathOption('bundle_dir', 'path to the bundle dependency package with miktex setup.exe etc', None),
207 # build directory, will use $mode if not set
208 ('build_dir', 'Build directory', None),
210 ('version_suffix', 'install lyx as lyx-suffix', None),
211 # how to load options
212 ('load_option', '''load option from previous scons run. option can be
213 yes (default): load all options
214 no: do not load any option
215 opt1,opt2: load specified options
216 -opt1,opt2: load all options other than specified ones''', 'yes'),
218 ('optimization', 'optimization CCFLAGS option.', None),
220 PathOption('exec_prefix', 'install architecture-independent executable files in PREFIX', None),
222 ('logfile', 'save commands (not outputs) to logfile', default_log_file),
223 # provided for backward compatibility
224 ('dest_dir', 'install to DESTDIR. (Provided for backward compatibility only)', None),
225 # environment variable can be set as options.
226 ('DESTDIR', 'install to DESTDIR', None),
227 ('CC', 'replace default $CC', None),
228 ('LINK', 'replace default $LINK', None),
229 ('CPP', 'replace default $CPP', None),
230 ('CXX', 'replace default $CXX', None),
231 ('CXXCPP', 'replace default $CXXCPP', None),
232 ('CCFLAGS', 'replace default $CCFLAGS', None),
233 ('CPPFLAGS', 'replace default $CPPFLAGS', None),
234 ('LINKFLAGS', 'replace default $LINKFLAGS', None),
238 all_options = [x.key for x in opts.options]
240 # copied from SCons/Options/BoolOption.py
241 # We need to use them before a boolean ARGUMENTS option is available
243 true_strings = ('y', 'yes', 'true', 't', '1', 'on' , 'all' )
244 false_strings = ('n', 'no', 'false', 'f', '0', 'off', 'none')
246 if ARGUMENTS.has_key('fast_start'):
247 print 'fast_start option is obsolete'
249 # if load_option=yes (default), load saved comand line options
251 # This option can take value yes/no/opt1,opt2/-opt1,opt2
252 # and tries to be clever in choosing options to load
253 if (not ARGUMENTS.has_key('load_option') or \
254 ARGUMENTS['load_option'] not in false_strings) \
255 and os.path.isfile(opt_cache_file):
256 cache_file = open(opt_cache_file)
257 opt_cache = cPickle.load(cache_file)
259 # import cached options, but we should ignore qt_dir when frontend changes
260 if ARGUMENTS.has_key('frontend') and opt_cache.has_key('frontend') \
261 and ARGUMENTS['frontend'] != opt_cache['frontend'] \
262 and opt_cache.has_key('qt_dir'):
263 opt_cache.pop('qt_dir')
264 # and we do not cache some options (dest_dir is obsolete)
265 for arg in ['load_option', 'dest_dir', 'bundle']:
266 if opt_cache.has_key(arg):
268 # remove obsolete cached keys (well, SConstruct is evolving. :-)
269 for arg in opt_cache.keys():
270 if arg not in all_options:
271 print 'Option %s is obsolete, do not load it' % arg
273 # now, if load_option=opt1,opt2 or -opt1,opt2
274 if ARGUMENTS.has_key('load_option') and \
275 ARGUMENTS['load_option'] not in true_strings + false_strings:
276 # if -opt1,opt2 is specified, do not load these options
277 if ARGUMENTS['load_option'][0] == '-':
278 for arg in ARGUMENTS['load_option'][1:].split(','):
279 if opt_cache.has_key(arg):
281 # if opt1,opt2 is specified, only load specified options
283 args = ARGUMENTS['load_option'].split(',')
284 for arg in opt_cache.keys():
287 # now restore options as if entered from command line
288 for key in opt_cache.keys():
289 if not ARGUMENTS.has_key(key):
290 ARGUMENTS[key] = opt_cache[key]
291 print "Restoring cached option %s=%s" % (key, ARGUMENTS[key])
294 # check if there is unused (or misspelled) argument
295 for arg in ARGUMENTS.keys():
296 if arg not in all_options:
298 print "Unknown option '%s'... exiting." % arg
300 print "Available options are (check 'scons -help' for details):"
301 print ' ' + '\n '.join(textwrap.wrap(', '.join(all_options)))
305 cache_file = open(opt_cache_file, 'w')
306 cPickle.dump(ARGUMENTS, cache_file)
309 #---------------------------------------------------------
310 # Setting up environment
311 #---------------------------------------------------------
313 # I do not really like ENV=os.environ, but you may add it
314 # here if you experience some environment related problem
315 env = Environment(options = opts)
317 # set individual variables since I do not really like ENV = os.environ
318 env['ENV']['PATH'] = os.environ.get('PATH')
319 env['ENV']['HOME'] = os.environ.get('HOME')
320 # these are defined for MSVC
321 env['ENV']['LIB'] = os.environ.get('LIB')
322 env['ENV']['INCLUDE'] = os.environ.get('INCLUDE')
324 # for simplicity, use var instead of env[var]
325 frontend = env['frontend']
326 prefix = env['prefix']
329 if platform_name == 'win32':
330 if env.has_key('use_vc'):
331 use_vc = env['use_vc']
332 if WhereIs('cl.exe') is None:
333 print "cl.exe is not found. Are you using the MSVC environment?"
335 elif WhereIs('cl.exe') is not None:
342 # lyx will be built to $build/build_dir so it is possible
343 # to build multiple build_dirs using the same source
344 # $mode can be debug or release
345 if env.has_key('build_dir') and env['build_dir'] is not None:
346 # create the directory if needed
347 if not os.path.isdir(env['build_dir']):
349 os.makedirs(env['build_dir'])
352 if not os.path.isdir(env['build_dir']):
353 print 'Can not create directory', env['build_dir']
355 env['BUILDDIR'] = env['build_dir']
357 # Determine the name of the build $mode
358 env['BUILDDIR'] = '#' + mode
360 # all built libraries will go to build_dir/libs
361 # (This is different from the make file approach)
362 env['LOCALLIBPATH'] = '$BUILDDIR/libs'
363 env.AppendUnique(LIBPATH = ['$LOCALLIBPATH'])
366 # Here is a summary of variables defined in env
368 # 2. undefined options with a non-None default value
369 # 3. compiler commands and flags like CCFLAGS.
370 # MSGFMT used to process po files
371 # 4. Variables that will be used to replace variables in some_file.in
372 # src/support/Package.cpp.in:
373 # TOP_SRCDIR, LOCALEDIR, LYX_DIR, PROGRAM_SUFFIX
374 # lib/lyx2lyx/lyx2lyx_version.py.in
377 # full path name is used to build msvs project files
378 # and to replace TOP_SRCDIR in package.C
379 env['TOP_SRCDIR'] = Dir(top_src_dir).abspath
381 # determine share_dir etc
382 packaging_method = env.get('packaging')
383 if packaging_method == 'windows':
384 share_dir = 'Resources'
385 man_dir = 'Resources/man/man1'
386 locale_dir = 'Resources/locale'
388 share_dir = 'share/lyx'
389 locale_dir = 'share/locale'
390 if platform_name == 'cygwin':
391 man_dir = 'share/man/man1'
395 # program suffix: can be yes, or a string
396 if env.has_key('version_suffix'):
397 if env['version_suffix'] in true_strings:
398 program_suffix = package_version
399 elif env['version_suffix'] in false_strings:
402 program_suffix = env['version_suffix']
405 # used by Package.cpp.in
406 env['PROGRAM_SUFFIX'] = program_suffix
408 # whether or not add suffix to file and directory names
409 add_suffix = packaging_method != 'windows'
410 # LYX_DIR are different (used in Package.cpp.in)
412 env['LYX_DIR'] = Dir(os.path.join(prefix, share_dir + program_suffix)).abspath
414 env['LYX_DIR'] = Dir(os.path.join(prefix, share_dir)).abspath
415 # we need absolute path for package.C
416 env['LOCALEDIR'] = Dir(os.path.join(prefix, locale_dir)).abspath
419 #---------------------------------------------------------
420 # Setting building environment (Tools, compiler flags etc)
421 #---------------------------------------------------------
423 # Since Tool('mingw') will reset CCFLAGS etc, this should be
424 # done before getEnvVariable
425 if platform_name == 'win32':
431 env.AppendUnique(CPPPATH = ['#c:/MinGW/include'])
432 # fix a scons winres bug (there is a missing space between ${RCINCPREFIX} and ${SOURCE.dir}
434 env['RCCOM'] = '$RC $_CPPDEFFLAGS $RCINCFLAGS ${RCINCPREFIX} ${SOURCE.dir} $RCFLAGS -i $SOURCE -o $TARGET'
437 # we differentiate between hard-coded options and default options
438 # hard-coded options are required and will always be there
439 # default options can be replaced by enviromental variables or command line options
440 CCFLAGS_required = []
441 LINKFLAGS_required = []
444 # under windows, scons is confused by .C/.c and uses gcc instead of
445 # g++. I am forcing the use of g++ here. This is expected to change
446 # after lyx renames all .C files to .cpp
448 # save the old c compiler and CCFLAGS (used by libintl)
449 C_COMPILER = env.subst('$CC')
450 C_CCFLAGS = env.subst('$CCFLAGS').split()
451 # if we use ms vc, the commands are fine (cl.exe and link.exe)
453 # C4819: The file contains a character that cannot be represented
454 # in the current code page (number)
455 # C4996: foo was decleared deprecated
456 CCFLAGS_required.append('/EHsc')
458 CCFLAGS_default.extend(['/wd4819', '/wd4996', '/nologo', '/MDd'])
459 # the flags are also needed in C mode (for intl lib)
460 C_CCFLAGS.extend(['/wd4819', '/wd4996', '/nologo', '/MDd'])
462 CCFLAGS_default.extend(['/wd4819', '/wd4996', '/nologo', '/MD'])
463 C_CCFLAGS.extend(['/wd4819', '/wd4996', '/nologo', '/MD'])
465 if env.has_key('CXX') and env['CXX']:
466 env['CC'] = env.subst('$CXX')
467 env['LINK'] = env.subst('$CXX')
472 # for debug/release mode
473 if env.has_key('optimization') and env['optimization'] is not None:
474 # if user supplies optimization flags, use it anyway
475 CCFLAGS_required.extend(env['optimization'].split())
476 # and do not use default
477 set_default_optimization_flags = False
479 set_default_optimization_flags = True
483 CCFLAGS_required.append('/Zi')
484 LINKFLAGS_required.extend(['/debug', '/map'])
486 CCFLAGS_required.append('-g')
487 CCFLAGS_default.append('-O')
488 elif mode == 'release' and set_default_optimization_flags:
490 CCFLAGS_default.append('/O2')
492 CCFLAGS_default.append('-O2')
494 # msvc uses separate tools for profiling
495 if env.has_key('profiling') and env['profiling']:
497 print 'Visual C++ does not use profiling options'
499 CCFLAGS_required.append('-pg')
500 LINKFLAGS_required.append('-pg')
502 if env.has_key('warnings') and env['warnings']:
504 CCFLAGS_default.append('/W2')
506 # Note: autotools detect gxx version and pass -W for 3.x
507 # and -Wextra for other versions of gcc
508 CCFLAGS_default.append('-Wall')
510 # Now, set the variables as follows:
511 # 1. if command line option exists: replace default
512 # 2. then if s envronment variable exists: replace default
513 # 3. set variable to required + default
514 def setEnvVariable(env, name, required = None, default = None, split = True):
515 ''' env: environment to set variable
517 required: hardcoded options
518 default: default options that can be replaced by command line or
519 environment variables
520 split: whether or not split obtained variable like '-02 -g'
522 # 1. ARGUMENTS is already set to env[name], override default.
523 if ARGUMENTS.has_key(name):
524 # env[name] may be rewritten when building tools are reloaded
525 # if that is the case, commandline option will override it.
526 env[name] = ARGUMENTS[name]
528 # then use environment default
529 elif os.environ.has_key(name):
530 print "Acquiring variable %s from system environment: %s" % (name, os.environ[name])
531 default = os.environ[name]
533 default = default.split()
534 # the real value should be env[name] + default + required
537 if env.has_key(name):
538 value = str(env[name]).split()
539 if required is not None:
541 if default is not None:
545 if env.has_key(name):
546 value = str(env[name])
547 if required is not None:
548 value += " " + required
549 if default is not None:
550 value += " " + default
552 # print name, env[name]
554 setEnvVariable(env, 'DESTDIR', split=False)
555 setEnvVariable(env, 'CC')
556 setEnvVariable(env, 'LINK')
557 setEnvVariable(env, 'CPP')
558 setEnvVariable(env, 'CXX')
559 setEnvVariable(env, 'CXXCPP')
560 setEnvVariable(env, 'CCFLAGS', CCFLAGS_required, CCFLAGS_default)
561 setEnvVariable(env, 'CXXFLAGS')
562 setEnvVariable(env, 'CPPFLAGS')
563 setEnvVariable(env, 'LINKFLAGS', LINKFLAGS_required)
565 # if DESTDIR is not set...
566 if env.has_key('dest_dir'):
567 print "This option is obsolete. Please use DESTDIR instead."
568 env['DESTDIR'] = env['dest_dir']
571 # extra_inc_path and extra_lib_path
574 if env.has_key('extra_inc_path') and env['extra_inc_path']:
575 extra_inc_paths.append(env['extra_inc_path'])
576 if env.has_key('extra_lib_path') and env['extra_lib_path']:
577 env.AppendUnique(LIBPATH = [env['extra_lib_path']])
578 if env.has_key('extra_inc_path1') and env['extra_inc_path1']:
579 extra_inc_paths.append(env['extra_inc_path1'])
580 if env.has_key('extra_lib_path1') and env['extra_lib_path1']:
581 env.AppendUnique(LIBPATH = [env['extra_lib_path1']])
582 if env.has_key('extra_bin_path') and env['extra_bin_path']:
583 # only the first one is needed (a scons bug?)
584 os.environ['PATH'] += os.pathsep + env['extra_bin_path']
585 env.PrependENVPath('PATH', env['extra_bin_path'])
586 # extra_inc_paths will be used later by intlenv etc
587 env.AppendUnique(CPPPATH = extra_inc_paths)
590 #----------------------------------------------------------
592 #----------------------------------------------------------
594 conf = Configure(env,
596 'CheckPkgConfig' : utils.checkPkgConfig,
597 'CheckPackage' : utils.checkPackage,
598 'CheckMkdirOneArg' : utils.checkMkdirOneArg,
599 'CheckSelectArgType' : utils.checkSelectArgType,
600 'CheckBoostLibraries' : utils.checkBoostLibraries,
601 'CheckCommand' : utils.checkCommand,
602 'CheckNSIS' : utils.checkNSIS,
603 'CheckCXXGlobalCstd' : utils.checkCXXGlobalCstd,
604 'CheckLC_MESSAGES' : utils.checkLC_MESSAGES,
605 'CheckIconvConst' : utils.checkIconvConst,
606 'CheckSizeOfWChar' : utils.checkSizeOfWChar,
607 'CheckDeclaration' : utils.checkDeclaration,
611 # When using msvc, windows.h is required
612 if use_vc and not conf.CheckCHeader('windows.h'):
613 print 'Windows.h is not found. Please install Windows Platform SDK.'
614 print 'Please check config.log for more information.'
617 # pkg-config? (if not, we use hard-coded options)
618 if conf.CheckPkgConfig('0.15.0'):
619 env['HAS_PKG_CONFIG'] = True
621 print 'pkg-config >= 0.1.50 is not found'
622 env['HAS_PKG_CONFIG'] = False
624 # zlib? This is required.
625 if (not use_vc and not conf.CheckLibWithHeader('z', 'zlib.h', 'C')) \
626 or (use_vc and not conf.CheckLibWithHeader('zdll', 'zlib.h', 'C')):
627 print 'Did not find zdll.lib or zlib.h, exiting!'
628 print 'Please check config.log for more information.'
630 if conf.CheckLib('iconv'):
631 env['ICONV_LIB'] = 'iconv'
632 elif conf.CheckLib('libiconv'):
633 env['ICONV_LIB'] = 'libiconv'
634 elif conf.CheckFunc('iconv_open'):
635 env['ICONV_LIB'] = None
637 print 'Did not find iconv or libiconv, exiting!'
638 print 'Please check config.log for more information.'
643 if conf.CheckLib('socket'):
644 socket_libs.append('socket')
645 # nsl is the network services library and provides a
646 # transport-level interface to networking services.
647 if conf.CheckLib('nsl'):
648 socket_libs.append('nsl')
650 # check available boost libs (since lyx1.4 does not use iostream)
652 for lib in ['signals', 'regex', 'filesystem', 'iostreams']:
653 if os.path.isdir(os.path.join(top_src_dir, 'boost', 'libs', lib)):
654 boost_libs.append(lib)
656 # check boost libraries
657 boost_opt = ARGUMENTS.get('boost', 'auto')
658 # check for system boost
659 lib_paths = env['LIBPATH'] + ['/usr/lib', '/usr/local/lib']
660 inc_paths = env['CPPPATH'] + ['/usr/include', '/usr/local/include']
661 # default to $BUILDDIR/libs (use None since this path will be added anyway)
663 # here I assume that all libraries are in the same directory
664 if boost_opt == 'included':
665 boost_libraries = ['included_boost_%s' % x for x in boost_libs]
666 included_boost = True
667 env['BOOST_INC_PATH'] = '$TOP_SRCDIR/boost'
668 elif boost_opt == 'auto':
669 res = conf.CheckBoostLibraries(boost_libs, lib_paths, inc_paths, boost_version, mode == 'debug')
670 # if not found, use local boost
672 boost_libraries = ['included_boost_%s' % x for x in boost_libs]
673 included_boost = True
674 env['BOOST_INC_PATH'] = '$TOP_SRCDIR/boost'
676 included_boost = False
677 (boost_libraries, boost_libpath, env['BOOST_INC_PATH']) = res
678 elif boost_opt == 'system':
679 res = conf.CheckBoostLibraries(boost_libs, lib_paths, inc_paths, boost_version, mode == 'debug')
681 print "Can not find system boost libraries with version %s " % boost_version
682 print "Please supply a path through extra_lib_path and try again."
683 print "Or use boost=included to use included boost libraries."
686 included_boost = False
687 (boost_libraries, boost_libpath, env['BOOST_INC_PATH']) = res
690 if boost_libpath is not None:
691 env.AppendUnique(LIBPATH = [boost_libpath])
694 env['ENABLE_NLS'] = env['nls']
696 if not env['ENABLE_NLS']:
698 included_gettext = False
700 # check gettext libraries
701 gettext_opt = ARGUMENTS.get('gettext', 'auto')
702 # check for system gettext
704 if gettext_opt in ['auto', 'system']:
705 if conf.CheckFunc('gettext'):
706 included_gettext = False
709 elif conf.CheckLib('intl'):
710 included_gettext = False
714 if gettext_opt == 'system':
715 print "Can not find system gettext library"
716 print "Please supply a path through extra_lib_path and try again."
717 print "Or use gettext=included to use included gettext libraries."
719 # now, auto and succ = false, or gettext=included
721 # we do not need to set LIBPATH now.
722 included_gettext = True
723 intl_libs = ['included_intl']
727 # check for msgfmt command
728 env['MSGFMT'] = conf.CheckCommand('msgfmt')
729 env['MSGMERGE'] = conf.CheckCommand('msgmerge')
730 env['XGETTEXT'] = conf.CheckCommand('xgettext')
731 env['MSGUNIQ'] = conf.CheckCommand('msguniq')
733 # if under windows, check the nsis compiler
734 if platform_name == 'win32':
735 env['NSIS'] = conf.CheckNSIS()
737 # cygwin packaging requires the binaries to be stripped
738 if platform_name == 'cygwin':
739 env['STRIP'] = conf.CheckCommand('strip')
742 # Customized builders
744 # install customized builders
745 env['BUILDERS']['substFile'] = Builder(action = utils.env_subst)
746 env['BUILDERS']['installTOC'] = Builder(action = utils.env_toc)
747 env['BUILDERS']['potfiles'] = Builder(action = utils.env_potfiles)
750 #----------------------------------------------------------
751 # Generating config.h
752 #----------------------------------------------------------
753 aspell_lib = 'aspell'
754 # assume that we use aspell, aspelld compiled for msvc
755 if platform_name == 'win32' and mode == 'debug' and use_vc:
756 aspell_lib = 'aspelld'
758 # check the existence of config.h
759 config_h = os.path.join(env.Dir('$BUILDDIR/src').path, 'config.h')
760 boost_config_h = os.path.join(env.Dir('$BUILDDIR/boost').path, 'config.h')
762 print "Creating %s..." % boost_config_h
764 utils.createConfigFile(conf,
765 config_file = boost_config_h,
766 config_pre = '''/* boost/config.h. Generated by SCons. */
771 * This file is part of LyX, the document processor.
772 * Licence details can be found in the file COPYING.
774 * This is the compilation configuration file for LyX.
775 * It was generated by scon.
776 * You might want to change some of the defaults if something goes wrong
777 * during the compilation.
780 #ifndef _BOOST_CONFIG_H
781 #define _BOOST_CONFIG_H
784 ('ostream', 'HAVE_OSTREAM', 'cxx'),
785 ('locale', 'HAVE_LOCALE', 'cxx'),
786 ('sstream', 'HAVE_SSTREAM', 'cxx'),
787 #('newapis.h', 'HAVE_NEWAPIS_H', 'c'),
790 (env.has_key('assertions') and env['assertions'],
792 'Define if you want assertions to be enabled in the code'
796 ('wchar_t', 'HAVE_WCHAR_T', None),
800 #if defined(HAVE_OSTREAM) && defined(HAVE_LOCALE) && defined(HAVE_SSTREAM)
801 # define USE_BOOST_FORMAT 1
803 # define USE_BOOST_FORMAT 0
806 #if !defined(ENABLE_ASSERTIONS)
807 # define BOOST_DISABLE_ASSERTS 1
809 #define BOOST_ENABLE_ASSERT_HANDLER 1
811 #define BOOST_DISABLE_THREADS 1
812 #define BOOST_NO_WSTRING 1
815 # define BOOST_POSIX 1
816 # define BOOST_POSIX_API 1
817 # define BOOST_POSIX_PATH 1
820 #define BOOST_ALL_NO_LIB 1
822 #if defined(HAVE_NEWAPIS_H)
823 # define WANT_GETFILEATTRIBUTESEX_WRAPPER 1
827 * the FreeBSD libc uses UCS4, but libstdc++ has no proper wchar_t
828 * support compiled in:
829 * http://gcc.gnu.org/onlinedocs/libstdc++/faq/index.html#3_9
830 * And we are not interested at all what libc
831 * does: What we need is a 32bit wide wchar_t, and a libstdc++ that
832 * has the needed wchar_t support and uses UCS4. Whether it
833 * implements this with the help of libc, or whether it has own code
834 * does not matter for us, because we don't use libc directly (Georg)
836 #if defined(HAVE_WCHAR_T) && SIZEOF_WCHAR_T == 4 && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
844 print "\nGenerating %s..." % config_h
846 # AIKSAURUS_H_LOCATION
847 if (conf.CheckCXXHeader("Aiksaurus.h")):
848 aik_location = '<Aiksaurus.h>'
849 elif (conf.CheckCXXHeader("Aiksaurus/Aiksaurus.h")):
850 aik_location = '<Aiksaurus/Aiksaurus.h>'
854 # determine headers to use
855 spell_opt = ARGUMENTS.get('spell', 'auto')
856 env['USE_ASPELL'] = False
857 env['USE_PSPELL'] = False
858 env['USE_ISPELL'] = False
859 if spell_opt in ['auto', 'aspell'] and conf.CheckLib(aspell_lib):
860 spell_engine = 'USE_ASPELL'
861 elif spell_opt in ['auto', 'pspell'] and conf.CheckLib('pspell'):
862 spell_engine = 'USE_PSPELL'
863 elif spell_opt in ['auto', 'ispell'] and conf.CheckLib('ispell'):
864 spell_engine = 'USE_ISPELL'
868 if spell_engine is not None:
869 env[spell_engine] = True
871 if spell_opt == 'auto':
872 print "Warning: Can not locate any spell checker"
873 elif spell_opt != 'no':
874 print "Warning: Can not locate specified spell checker:", spell_opt
875 print 'Please check config.log for more information.'
878 # check arg types of select function
879 (select_arg1, select_arg234, select_arg5) = conf.CheckSelectArgType()
881 # check the size of wchar_t
882 sizeof_wchar_t = conf.CheckSizeOfWChar()
884 if sizeof_wchar_t == 0:
885 print 'Error: Can not determine the size of wchar_t.'
886 print 'Please check config.log for more information.'
890 # fill in the version info
891 env['VERSION_INFO'] = '''Configuration
893 Special build flags: %s
895 C Compiler flags: %s %s
897 C++ Compiler LyX flags: %s
898 C++ Compiler flags: %s %s
900 Linker user flags: %s
902 Builing directory: %s
903 Local library directory: %s
906 include search path: %s
912 ''' % (platform_name,
913 env.subst('$CCFLAGS'), env.subst('$CC'),
914 env.subst('$CPPFLAGS'), env.subst('$CFLAGS'),
915 env.subst('$CXX'), env.subst('$CXXFLAGS'),
916 env.subst('$CPPFLAGS'), env.subst('$CXXFLAGS'),
917 env.subst('$LINKFLAGS'), env.subst('$LINKFLAGS'),
918 env.subst('$BUILDDIR'), env.subst('$LOCALLIBPATH'),
919 str(env['LIBPATH']), str(boost_libraries),
921 frontend, packaging_method,
922 prefix, env['LYX_DIR'])
926 result = utils.createConfigFile(conf,
927 config_file = config_h,
928 config_pre = '''/* config.h. Generated by SCons. */
933 * This file is part of LyX, the document processor.
934 * Licence details can be found in the file COPYING.
936 * This is the compilation configuration file for LyX.
937 * It was generated by scon.
938 * You might want to change some of the defaults if something goes wrong
939 * during the compilation.
946 ('io.h', 'HAVE_IO_H', 'c'),
947 ('limits.h', 'HAVE_LIMITS_H', 'c'),
948 ('locale.h', 'HAVE_LOCALE_H', 'c'),
949 ('process.h', 'HAVE_PROCESS_H', 'c'),
950 ('stdlib.h', 'HAVE_STDLIB_H', 'c'),
951 ('sys/stat.h', 'HAVE_SYS_STAT_H', 'c'),
952 ('sys/time.h', 'HAVE_SYS_TIME_H', 'c'),
953 ('sys/types.h', 'HAVE_SYS_TYPES_H', 'c'),
954 ('sys/utime.h', 'HAVE_SYS_UTIME_H', 'c'),
955 ('sys/socket.h', 'HAVE_SYS_SOCKET_H', 'c'),
956 ('unistd.h', 'HAVE_UNISTD_H', 'c'),
957 ('utime.h', 'HAVE_UTIME_H', 'c'),
958 ('direct.h', 'HAVE_DIRECT_H', 'c'),
959 ('istream', 'HAVE_ISTREAM', 'cxx'),
960 ('ios', 'HAVE_IOS', 'cxx'),
963 ('open', 'HAVE_OPEN', None),
964 ('chmod', 'HAVE_CHMOD', None),
965 ('close', 'HAVE_CLOSE', None),
966 ('popen', 'HAVE_POPEN', None),
967 ('pclose', 'HAVE_PCLOSE', None),
968 ('_open', 'HAVE__OPEN', None),
969 ('_close', 'HAVE__CLOSE', None),
970 ('_popen', 'HAVE__POPEN', None),
971 ('_pclose', 'HAVE__PCLOSE', None),
972 ('getpid', 'HAVE_GETPID', None),
973 ('_getpid', 'HAVE__GETPID', None),
974 ('mkdir', 'HAVE_MKDIR', None),
975 ('_mkdir', 'HAVE__MKDIR', None),
976 ('mktemp', 'HAVE_MKTEMP', None),
977 ('mkstemp', 'HAVE_MKSTEMP', None),
978 ('strerror', 'HAVE_STRERROR', None),
979 ('getcwd', 'HAVE_GETCWD', None),
980 ('setenv', 'HAVE_SETENV', None),
981 ('putenv', 'HAVE_PUTENV', None),
982 ('fcntl', 'HAVE_FCNTL', None),
983 ('mkfifo', 'HAVE_MKFIFO', None),
986 ('mkstemp', 'HAVE_DECL_MKSTEMP', ['unistd.h', 'stdlib.h']),
989 ('std::istreambuf_iterator<std::istream>', 'HAVE_DECL_ISTREAMBUF_ITERATOR',
990 '#include <streambuf>\n#include <istream>'),
991 ('wchar_t', 'HAVE_WCHAR_T', None),
992 ('mode_t', 'HAVE_MODE_T', "#include <sys/types.h>"),
995 ('gdi32', 'HAVE_LIBGDI32'),
996 (('Aiksaurus', 'libAiksaurus'), 'HAVE_LIBAIKSAURUS', 'AIKSAURUS_LIB'),
999 (conf.CheckType('pid_t', includes='#include <sys/types.h>'),
1001 'Define is sys/types.h does not have pid_t',
1003 '#define pid_t int',
1005 (conf.CheckCXXGlobalCstd(),
1007 'Define if your C++ compiler puts C library functions in the global namespace'
1009 (conf.CheckMkdirOneArg(),
1010 'MKDIR_TAKES_ONE_ARG',
1011 'Define if mkdir takes only one argument.'
1013 (conf.CheckIconvConst(),
1015 'Define as const if the declaration of iconv() needs const.',
1016 '#define ICONV_CONST const',
1017 '#define ICONV_CONST',
1019 (conf.CheckLC_MESSAGES(),
1021 'Define if your <locale.h> file defines LC_MESSAGES.'
1023 (devel_version, 'DEVEL_VERSION', 'Whether or not a development version'),
1026 "Define to 1 if translation of program messages to the user's native anguage is requested.",
1028 (env['nls'] and not included_gettext,
1030 'Define to 1 if using system gettext library'
1032 (env.has_key('concept_checks') and env['concept_checks'],
1033 '_GLIBCXX_CONCEPT_CHECKS',
1034 'libstdc++ concept checking'
1036 (env.has_key('stdlib_debug') and env['stdlib_debug'],
1038 'libstdc++ debug mode'
1040 (env.has_key('stdlib_debug') and env['stdlib_debug'],
1041 '_GLIBCXX_DEBUG_PEDANTIC',
1042 'libstdc++ pedantic debug mode'
1044 (os.name != 'nt', 'BOOST_POSIX',
1045 'Indicates to boost < 1.34 which API to use (posix or windows).'
1047 (os.name != 'nt', 'BOOST_POSIX_API',
1048 'Indicates to boost 1.34 which API to use (posix or windows).'
1050 (os.name != 'nt', 'BOOST_POSIX_PATH',
1051 'Indicates to boost 1.34 which path style to use (posix or windows).'
1053 (spell_engine is not None, spell_engine,
1054 'Spell engine to use'
1056 # we need to know the byte order for unicode conversions
1057 (sys.byteorder == 'big', 'WORDS_BIGENDIAN',
1058 'Define to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX).'
1062 ('#define PACKAGE "%s%s"' % (package, program_suffix),
1064 ('#define PACKAGE_BUGREPORT "%s"' % package_bugreport,
1065 'Define to the address where bug reports for this package should be sent.'),
1066 ('#define PACKAGE_NAME "%s"' % package_name,
1067 'Define to the full name of this package.'),
1068 ('#define PACKAGE_STRING "%s"' % package_string,
1069 'Define to the full name and version of this package.'),
1070 ('#define PACKAGE_TARNAME "%s"' % package_tarname,
1071 'Define to the one symbol short name of this package.'),
1072 ('#define PACKAGE_VERSION "%s"' % package_version,
1073 'Define to the version of this package.'),
1074 ('#define VERSION_INFO "%s"' % env['VERSION_INFO'].replace('\n', '\\n'),
1075 'Full version info'),
1076 ('#define LYX_DATE "%s"' % lyx_date,
1078 ('#define BOOST_ALL_NO_LIB 1',
1079 'disable automatic linking of boost libraries.'),
1080 ('#define USE_%s_PACKAGING 1' % packaging_method.upper(),
1081 'Packaging method'),
1082 ('#define AIKSAURUS_H_LOCATION ' + aik_location,
1083 'Aiksaurus include file'),
1084 ('#define SELECT_TYPE_ARG1 %s' % select_arg1,
1085 "Define to the type of arg 1 for `select'."),
1086 ('#define SELECT_TYPE_ARG234 %s' % select_arg234,
1087 "Define to the type of arg 2, 3, 4 for `select'."),
1088 ('#define SELECT_TYPE_ARG5 %s' % select_arg5,
1089 "Define to the type of arg 5 for `select'."),
1090 ('#define SIZEOF_WCHAR_T %d' % sizeof_wchar_t,
1091 'Define to be the size of type wchar_t'),
1093 config_post = '''/************************************************************
1094 ** You should not need to change anything beyond this point */
1096 #ifndef HAVE_STRERROR
1097 #if defined(__cplusplus)
1100 char * strerror(int n);
1103 #include <../boost/config.h>
1109 # these keys are needed in env
1110 for key in ['USE_ASPELL', 'USE_PSPELL', 'USE_ISPELL', 'HAVE_FCNTL',\
1111 'HAVE_LIBGDI32', 'HAVE_LIBAIKSAURUS', 'AIKSAURUS_LIB']:
1112 # USE_ASPELL etc does not go through result
1113 if result.has_key(key):
1114 env[key] = result[key]
1117 # if nls=yes and gettext=included, create intl/config.h
1118 # intl/libintl.h etc
1120 intl_config_h = os.path.join(env.Dir('$BUILDDIR/intl').path, 'config.h')
1121 if env['nls'] and included_gettext:
1123 print "Creating %s..." % intl_config_h
1125 # create intl/config.h
1126 result = utils.createConfigFile(conf,
1127 config_file = intl_config_h,
1128 config_pre = '''/* intl/config.h. Generated by SCons. */
1133 * This file is part of LyX, the document processor.
1134 * Licence details can be found in the file COPYING.
1136 * This is the compilation configuration file for LyX.
1137 * It was generated by scon.
1138 * You might want to change some of the defaults if something goes wrong
1139 * during the compilation.
1146 ('unistd.h', 'HAVE_UNISTD_H', 'c'),
1147 ('inttypes.h', 'HAVE_INTTYPES_H', 'c'),
1148 ('string.h', 'HAVE_STRING_H', 'c'),
1149 ('strings.h', 'HAVE_STRINGS_H', 'c'),
1150 ('argz.h', 'HAVE_ARGZ_H', 'c'),
1151 ('limits.h', 'HAVE_LIMITS_H', 'c'),
1152 ('alloca.h', 'HAVE_ALLOCA_H', 'c'),
1153 ('stddef.h', 'HAVE_STDDEF_H', 'c'),
1154 ('stdint.h', 'HAVE_STDINT_H', 'c'),
1155 ('sys/param.h', 'HAVE_SYS_PARAM_H', 'c'),
1158 ('getcwd', 'HAVE_GETCWD', None),
1159 ('stpcpy', 'HAVE_STPCPY', None),
1160 ('strcasecmp', 'HAVE_STRCASECMP', None),
1161 ('strdup', 'HAVE_STRDUP', None),
1162 ('strtoul', 'HAVE_STRTOUL', None),
1163 ('alloca', 'HAVE_ALLOCA', None),
1164 ('__fsetlocking', 'HAVE___FSETLOCKING', None),
1165 ('mempcpy', 'HAVE_MEMPCPY', None),
1166 ('__argz_count', 'HAVE___ARGZ_COUNT', None),
1167 ('__argz_next', 'HAVE___ARGZ_NEXT', None),
1168 ('__argz_stringify', 'HAVE___ARGZ_STRINGIFY', None),
1169 ('setlocale', 'HAVE_SETLOCALE', None),
1170 ('tsearch', 'HAVE_TSEARCH', None),
1171 ('getegid', 'HAVE_GETEGID', None),
1172 ('getgid', 'HAVE_GETGID', None),
1173 ('getuid', 'HAVE_GETUID', None),
1174 ('wcslen', 'HAVE_WCSLEN', None),
1175 ('asprintf', 'HAVE_ASPRINTF', None),
1176 ('wprintf', 'HAVE_WPRINTF', None),
1177 ('snprintf', 'HAVE_SNPRINTF', None),
1178 ('printf', 'HAVE_POSIX_PRINTF', None),
1179 ('fcntl', 'HAVE_FCNTL', None),
1182 ('intmax_t', 'HAVE_INTMAX_T', None),
1183 ('long double', 'HAVE_LONG_DOUBLE', None),
1184 ('long long', 'HAVE_LONG_LONG', None),
1185 ('wchar_t', 'HAVE_WCHAR_T', None),
1186 ('wint_t', 'HAVE_WINT_T', None),
1187 ('uintmax_t', 'HAVE_INTTYPES_H_WITH_UINTMAX', '#include <inttypes.h>'),
1188 ('uintmax_t', 'HAVE_STDINT_H_WITH_UINTMAX', '#include <stdint.h>'),
1194 (conf.CheckLC_MESSAGES(),
1196 'Define if your <locale.h> file defines LC_MESSAGES.'
1198 (conf.CheckIconvConst(),
1200 'Define as const if the declaration of iconv() needs const.',
1201 '#define ICONV_CONST const',
1202 '#define ICONV_CONST',
1204 (conf.CheckType('intmax_t', includes='#include <stdint.h>') or \
1205 conf.CheckType('intmax_t', includes='#include <inttypes.h>'),
1207 "Define to 1 if you have the `intmax_t' type."
1209 (env.has_key('nls') and env['nls'],
1211 "Define to 1 if translation of program messages to the user's native anguage is requested.",
1215 ('#define HAVE_ICONV 1', 'Define if iconv or libiconv is found'),
1216 ('#define SIZEOF_WCHAR_T %d' % sizeof_wchar_t,
1217 'Define to be the size of type wchar_t'),
1219 config_post = '#endif'
1222 # these keys are needed in env
1223 for key in ['HAVE_ASPRINTF', 'HAVE_WPRINTF', 'HAVE_SNPRINTF', \
1224 'HAVE_POSIX_PRINTF', 'HAVE_LIBC']:
1225 # USE_ASPELL etc does not go through result
1226 if result.has_key(key):
1227 env[key] = result[key]
1230 # this looks misplaced, but intl/libintl.h is needed by src/message.C
1231 if env['nls'] and included_gettext:
1232 # libgnuintl.h.in => libintl.h
1233 env.Depends('$TOP_SRCDIR/intl/libintl.h', '$BUILDDIR/intl/config.h')
1234 env.substFile('$BUILDDIR/intl/libintl.h', '$TOP_SRCDIR/intl/libgnuintl.h.in')
1235 env.Command('$BUILDDIR/intl/libgnuintl.h', '$BUILDDIR/intl/libintl.h',
1236 [Copy('$TARGET', '$SOURCE')])
1239 # Finish auto-configuration
1242 #----------------------------------------------------------
1243 # Now set up our build process accordingly
1244 #----------------------------------------------------------
1246 if env['ICONV_LIB'] is None:
1249 system_libs = [env['ICONV_LIB']]
1250 if platform_name in ['win32', 'cygwin']:
1251 # the final link step needs stdc++ to succeed under mingw
1252 # FIXME: shouldn't g++ automatically link to stdc++?
1254 system_libs += ['ole32', 'shlwapi', 'shell32', 'advapi32', 'zdll']
1256 system_libs += ['shlwapi', 'stdc++', 'z']
1257 elif platform_name == 'cygwin' and env['X11']:
1258 system_libs += ['GL', 'Xmu', 'Xi', 'Xrender', 'Xrandr',
1259 'Xcursor', 'Xft', 'freetype', 'fontconfig', 'Xext', 'X11', 'SM', 'ICE',
1260 'resolv', 'pthread', 'z']
1262 system_libs += ['z']
1265 ('HAVE_LIBGDI32', 'gdi32'),
1266 ('HAVE_LIBAIKSAURUS', env['AIKSAURUS_LIB']),
1267 ('USE_ASPELL', aspell_lib),
1268 ('USE_ISPELL', 'ispell'),
1269 ('USE_PSPELL', 'pspell'),
1274 system_libs.append(lib[1])
1277 # Build parameters CPPPATH etc
1280 env.AppendUnique(LIBPATH = ['/usr/X11R6/lib'])
1283 # boost: for boost header files
1284 # BUILDDIR/src: for config.h
1285 # TOP_SRCDIR/src: for support/* etc
1287 env['CPPPATH'] += ['$BUILDDIR/src', '$TOP_SRCDIR/src']
1289 # Separating boost directories from CPPPATH stops scons from building
1290 # the dependency tree for boost header files, and effectively reduce
1291 # the null build time of lyx from 29s to 16s. Since lyx may tweak local
1292 # boost headers, the following is not 100% safe.
1293 # env.AppendUnique(CPPPATH = ['$BOOST_INC_PATH'])
1294 env.PrependUnique(CCFLAGS = ['$INCPREFIX$BOOST_INC_PATH'])
1296 # for intl/config.h, intl/libintl.h and intl/libgnuintl.h
1297 if env['nls'] and included_gettext:
1298 env['CPPPATH'].append('$BUILDDIR/intl')
1302 # A Link script for cygwin see
1303 # http://www.cygwin.com/ml/cygwin/2004-09/msg01101.html
1304 # http://www.cygwin.com/ml/cygwin-apps/2004-09/msg00309.html
1307 if platform_name == 'cygwin':
1308 ld_script_path = '/tmp'
1309 ld_script = utils.installCygwinLDScript(ld_script_path)
1310 env.AppendUnique(LINKFLAGS = ['-Wl,--enable-runtime-pseudo-reloc',
1311 '-Wl,--script,%s' % ld_script, '-Wl,-s'])
1314 #---------------------------------------------------------
1315 # Frontend related variables (QTDIR etc)
1316 #---------------------------------------------------------
1319 # create a separate environment so that other files do not have
1320 # to be built with all the include directories etc
1322 if frontend == 'qt4':
1323 frontend_env = env.Copy()
1325 # handle qt related user specified paths
1326 # set environment so that moc etc can be found even if its path is not set properly
1327 if frontend_env.has_key('qt_dir') and frontend_env['qt_dir']:
1328 frontend_env['QTDIR'] = frontend_env['qt_dir']
1329 if os.path.isdir(os.path.join(frontend_env['qt_dir'], 'bin')):
1330 os.environ['PATH'] += os.pathsep + os.path.join(frontend_env['qt_dir'], 'bin')
1331 frontend_env.PrependENVPath('PATH', os.path.join(frontend_env['qt_dir'], 'bin'))
1332 if os.path.isdir(os.path.join(frontend_env['qt_dir'], 'lib')):
1333 frontend_env.PrependENVPath('PKG_CONFIG_PATH', os.path.join(frontend_env['qt_dir'], 'lib'))
1335 # if separate qt_lib_path is given
1336 if frontend_env.has_key('qt_lib_path') and frontend_env['qt_lib_path']:
1337 qt_lib_path = frontend_env.subst('$qt_lib_path')
1338 frontend_env.AppendUnique(LIBPATH = [qt_lib_path])
1339 frontend_env.PrependENVPath('PKG_CONFIG_PATH', qt_lib_path)
1343 # if separate qt_inc_path is given
1344 if frontend_env.has_key('qt_inc_path') and frontend_env['qt_inc_path']:
1345 qt_inc_path = frontend_env['qt_inc_path']
1349 # local qt4 toolset from
1350 # http://www.iua.upf.es/~dgarcia/Codders/sconstools.html
1352 # NOTE: I have to patch qt4.py since it does not automatically
1353 # process .C file!!! (add to cxx_suffixes )
1355 frontend_env.Tool('qt4', [scons_dir])
1356 frontend_env['QT_AUTOSCAN'] = 0
1357 frontend_env['QT4_AUTOSCAN'] = 0
1358 frontend_env['QT4_UICDECLFLAGS'] = '-tr lyx::qt_'
1360 if qt_lib_path is None:
1361 qt_lib_path = os.path.join(frontend_env.subst('$QTDIR'), 'lib')
1362 if qt_inc_path is None:
1363 qt_inc_path = os.path.join(frontend_env.subst('$QTDIR'), 'include')
1366 conf = Configure(frontend_env,
1368 'CheckPackage' : utils.checkPackage,
1369 'CheckCommand' : utils.checkCommand,
1374 # first: try pkg_config
1375 if frontend_env['HAS_PKG_CONFIG']:
1376 succ = conf.CheckPackage('QtCore') or conf.CheckPackage('QtCore4')
1377 # FIXME: use pkg_config information?
1378 #frontend_env['QT4_PKG_CONFIG'] = succ
1379 # second: try to link to it
1381 # Under linux, I can test the following perfectly
1382 # Under windows, lib names need to passed as libXXX4.a ...
1383 if platform_name == 'win32':
1384 succ = conf.CheckLibWithHeader('QtCore4', 'QtGui/QApplication', 'c++', 'QApplication qapp();')
1386 succ = conf.CheckLibWithHeader('QtCore', 'QtGui/QApplication', 'c++', 'QApplication qapp();')
1387 # still can not find it
1389 print 'Did not find qt libraries, exiting!'
1390 print 'Please check config.log for more information.'
1393 # Now, determine the correct suffix:
1394 qt_libs = ['QtCore', 'QtGui']
1395 if platform_name == 'win32':
1396 if mode == 'debug' and use_vc and \
1397 conf.CheckLibWithHeader('QtCored4', 'QtGui/QApplication', 'c++', 'QApplication qapp();'):
1398 qt_lib_suffix = 'd4'
1399 use_qt_debug_libs = True
1402 use_qt_debug_libs = False
1404 if mode == 'debug' and conf.CheckLibWithHeader('QtCore_debug', 'QtGui/QApplication', 'c++', 'QApplication qapp();'):
1405 qt_lib_suffix = '_debug'
1406 use_qt_debug_libs = True
1409 use_qt_debug_libs = False
1410 frontend_env.EnableQt4Modules(qt_libs, debug = (mode == 'debug' and use_qt_debug_libs))
1411 frontend_libs = [x + qt_lib_suffix for x in qt_libs]
1412 qtcore_lib = ['QtCore' + qt_lib_suffix]
1414 # check uic and moc commands for qt frontends
1415 if conf.CheckCommand('uic') == None or conf.CheckCommand('moc') == None:
1416 print 'uic or moc command is not found for frontend', frontend
1419 # now, if msvc2005 is used, we will need to embed lyx.exe.manifest to lyx.exe
1420 # NOTE: previously, lyx.exe had to be linked to some qt manifest to work.
1421 # For some unknown changes in msvc or qt, this is no longer needed.
1423 frontend_env['LINKCOM'] = [frontend_env['LINKCOM'], \
1424 'mt.exe /MANIFEST %s /outputresource:$TARGET;1' % \
1425 env.File('$BUILDDIR/lyx.exe.manifest').path]
1427 frontend_env = conf.Finish()
1434 print env['VERSION_INFO']
1437 # Mingw command line may be too short for our link usage,
1438 # Here we use a trick from scons wiki
1439 # http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/LongCmdLinesOnWin32
1441 # I also would like to add logging (commands only) capacity to the
1443 logfile = env.get('logfile', default_log_file)
1444 if logfile != '' or platform_name == 'win32':
1446 utils.setLoggedSpawn(env, logfile, longarg = (platform_name == 'win32'),
1447 info = '''# This is a log of commands used by scons to build lyx
1451 ''' % (time.asctime(), ' '.join(sys.argv),
1452 env['VERSION_INFO'].replace('\n','\n# ')) )
1457 # -h will print out help info
1458 Help(opts.GenerateHelpText(env))
1462 #----------------------------------------------------------
1464 #----------------------------------------------------------
1465 # this has been the source of problems on some platforms...
1466 # I find that I need to supply it with full path name
1467 env.SConsignFile(os.path.join(Dir(env['BUILDDIR']).abspath, '.sconsign'))
1468 # this usage needs further investigation.
1469 #env.CacheDir('%s/Cache/%s' % (env['BUILDDIR'], frontend))
1470 env.BuildDir('$BUILDDIR/boost', '$TOP_SRCDIR/boost/libs', duplicate = 0)
1471 env.BuildDir('$BUILDDIR/src', '$TOP_SRCDIR/src', duplicate = 0)
1472 frontend_env.BuildDir('$BUILDDIR/src', '$TOP_SRCDIR/src', duplicate = 0)
1474 print "Building all targets recursively"
1476 if env.has_key('rebuild'):
1477 rebuild_targets = env['rebuild'].split(',')
1478 if 'none' in rebuild_targets or 'no' in rebuild_targets:
1479 rebuild_targets = []
1480 elif 'all' in rebuild_targets or 'yes' in rebuild_targets:
1481 # None: let scons decide which components to build
1482 # Forcing all components to be rebuilt is in theory not necessary
1483 rebuild_targets = None
1485 rebuild_targets = None
1487 def libExists(libname):
1488 ''' Check whether or not lib $LOCALLIBNAME/libname already exists'''
1489 return os.path.isfile(File(env.subst('$LOCALLIBPATH/${LIBPREFIX}%s$LIBSUFFIX'%libname)).abspath)
1491 def appExists(apppath, appname):
1492 ''' Check whether or not application already exists'''
1493 return os.path.isfile(File(env.subst('$BUILDDIR/src/%s/${PROGPREFIX}%s$PROGSUFFIX' % (apppath, appname))).abspath)
1495 targets = BUILD_TARGETS
1496 build_install = 'install' in targets or 'installer' in targets
1497 build_installer = 'installer' in targets
1498 # msvc need to pass full target name, so I have to look for path/lyx etc
1499 build_lyx = build_installer or targets == [] or True in ['lyx' in x for x in targets] \
1500 or build_install or 'all' in targets
1501 build_boost = (included_boost and not libExists('boost_regex')) or 'boost' in targets
1502 build_intl = (included_gettext and not libExists('included_intl')) or 'intl' in targets
1503 build_support = build_lyx or True in [x in targets for x in ['support', 'client', 'tex2lyx']]
1504 build_mathed = build_lyx or 'mathed' in targets
1505 build_insets = build_lyx or 'insets' in targets
1506 build_frontends = build_lyx or 'frontends' in targets
1507 build_graphics = build_lyx or 'graphics' in targets
1508 build_controllers = build_lyx or 'controllers' in targets
1509 build_client = True in ['client' in x for x in targets] \
1510 or build_install or 'all' in targets or build_installer
1511 build_tex2lyx = True in ['tex2lyx' in x for x in targets] \
1512 or build_install or 'all' in targets or build_installer
1513 build_lyxbase = build_lyx or 'lyxbase' in targets
1514 update_po = 'update_po' in targets
1515 update_manifest = 'update_manifest' in targets
1516 build_po = 'po' in targets or build_install or 'all' in targets
1517 build_qt4 = (build_lyx and frontend == 'qt4') or 'qt4' in targets
1518 build_msvs_projects = use_vc and 'msvs_projects' in targets
1521 # now, if rebuild_targets is specified, do not rebuild some targets
1522 if rebuild_targets is not None:
1524 def ifBuildLib(name, libname, old_value):
1525 # explicitly asked to rebuild
1526 if name in rebuild_targets:
1528 # else if not rebuild, and if the library already exists
1529 elif libExists(libname):
1531 # do not change the original value
1534 build_boost = ifBuildLib('boost', 'included_boost_filesystem', build_boost)
1535 build_intl = ifBuildLib('intl', 'included_intl', build_intl)
1536 build_support = ifBuildLib('support', 'support', build_support)
1537 build_mathed = ifBuildLib('mathed', 'mathed', build_mathed)
1538 build_insets = ifBuildLib('insets', 'insets', build_insets)
1539 build_frontends = ifBuildLib('frontends', 'frontends', build_frontends)
1540 build_graphics = ifBuildLib('graphics', 'graphics', build_graphics)
1541 build_controllers = ifBuildLib('controllers', 'controllers', build_controllers)
1542 build_lyxbase = ifBuildLib('lyxbase', 'lyxbase_pre', build_lyxbase)
1543 build_qt4 = ifBuildLib('qt4', 'qt4', build_qt4)
1545 def ifBuildApp(name, appname, old_value):
1546 # explicitly asked to rebuild
1547 if name in rebuild_targets:
1549 # else if not rebuild, and if the library already exists
1550 elif appExists(name, appname):
1552 # do not change the original value
1555 build_tex2lyx = ifBuildApp('tex2lyx', 'tex2lyx', build_tex2lyx)
1556 build_client = ifBuildApp('client', 'lyxclient', build_client)
1558 # sync frontend and frontend (?)
1569 boostenv = env.Copy()
1571 # boost use its own config.h
1572 boostenv['CPPPATH'] = ['$BUILDDIR/boost'] + extra_inc_paths
1573 boostenv['CCFLAGS'] = ['$INCPREFIX$TOP_SRCDIR/boost']
1574 boostenv.AppendUnique(CCFLAGS = ['-DBOOST_USER_CONFIG="<config.h>"'])
1576 for lib in boost_libs:
1577 print 'Processing files in boost/libs/%s/src...' % lib
1578 boostlib = boostenv.StaticLibrary(
1579 target = '$LOCALLIBPATH/included_boost_%s' % lib,
1580 source = ['$BUILDDIR/boost/%s/src/%s' % (lib, x) for x in eval('boost_libs_%s_src_files' % lib)]
1582 Alias('boost', boostlib)
1589 intlenv = env.Copy()
1591 print "Processing files in intl..."
1594 # we need the original C compiler for these files
1595 intlenv['CC'] = C_COMPILER
1596 intlenv['CCFLAGS'] = C_CCFLAGS
1598 intlenv.Append(CCFLAGS=['/Dinline#', '/D__attribute__(x)#', '/Duintmax_t=UINT_MAX'])
1599 # intl does not use global config.h
1600 intlenv['CPPPATH'] = ['$BUILDDIR/intl'] + extra_inc_paths
1602 intlenv.Append(CCFLAGS = [
1603 r'-DLOCALEDIR=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1604 r'-DLOCALE_ALIAS_PATH=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1605 r'-DLIBDIR=\"' + env['TOP_SRCDIR'].replace('\\', '\\\\') + r'/lib\"',
1607 '-DENABLE_RELOCATABLE=1',
1609 r'-DINSTALLDIR=\"' + prefix.replace('\\', '\\\\') + r'/lib\"',
1611 '-Dset_relocation_prefix=libintl_set_relocation_prefix',
1612 '-Drelocate=libintl_relocate',
1613 '-DDEPENDS_ON_LIBICONV=1',
1618 intl = intlenv.StaticLibrary(
1619 target = '$LOCALLIBPATH/included_intl',
1621 source = ['$BUILDDIR/intl/%s' % x for x in intl_files]
1627 # Now, src code under src/
1635 print "Processing files in src/support..."
1637 frontend_env.Depends('$BUILDDIR/src/support/Package.cpp', '$BUILDDIR/src/config.h')
1638 Package_cpp = env.substFile('$BUILDDIR/src/support/Package.cpp', '$TOP_SRCDIR/src/support/Package.cpp.in')
1640 support = frontend_env.StaticLibrary(
1641 target = '$LOCALLIBPATH/support',
1642 source = ['$BUILDDIR/src/support/%s' % x for x in src_support_files] + Package_cpp + \
1643 ['$BUILDDIR/src/support/minizip/%s' % x for x in src_support_minizip_files] + \
1644 ['$BUILDDIR/src/support/minizip/%s' % x for x in src_support_minizip_windows_files if platform_name == 'win32'],
1648 '-DQT_CLEAN_NAMESPACE',
1653 CPPPATH = ['$CPPPATH', '$TOP_SRCDIR/src/support/minizip']
1655 Alias('support', support)
1662 print "Processing files in src/mathed..."
1664 mathed = env.StaticLibrary(
1665 target = '$LOCALLIBPATH/mathed',
1666 source = ['$BUILDDIR/src/mathed/%s' % x for x in src_mathed_files]
1668 Alias('mathed', mathed)
1675 print "Processing files in src/insets..."
1677 insets = env.StaticLibrary(
1678 target = '$LOCALLIBPATH/insets',
1679 source = ['$BUILDDIR/src/insets/%s' % x for x in src_insets_files]
1681 Alias('insets', insets)
1688 print "Processing files in src/frontends..."
1690 frontends = env.StaticLibrary(
1691 target = '$LOCALLIBPATH/frontends',
1692 source = ['$BUILDDIR/src/frontends/%s' % x for x in src_frontends_files]
1694 Alias('frontends', frontends)
1701 print "Processing files in src/graphics..."
1703 graphics = env.StaticLibrary(
1704 target = '$LOCALLIBPATH/graphics',
1705 source = ['$BUILDDIR/src/graphics/%s' % x for x in src_graphics_files]
1707 Alias('graphics', graphics)
1710 if build_controllers:
1712 # src/frontends/controllers
1714 print "Processing files in src/frontends/controllers..."
1716 controllers = env.StaticLibrary(
1717 target = '$LOCALLIBPATH/controllers',
1718 source = ['$BUILDDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files]
1720 Alias('controllers', controllers)
1727 print "Processing files in src/frontends/qt4..."
1728 frontend_env['QT4_MOCHPREFIX'] = ''
1729 frontend_env['QT4_MOCHSUFFIX'] = '_moc.cpp'
1731 # tells scons how to get these moced files, although not all moced files are needed
1732 # (or are actually generated).
1733 qt4_moced_files = [frontend_env.Moc4('$BUILDDIR/src/frontends/qt4/%s' % x)
1734 for x in src_frontends_qt4_header_files ]
1735 resources = [frontend_env.Uic4('$BUILDDIR/src/frontends/qt4/ui/%s' % x.split('.')[0])
1736 for x in src_frontends_qt4_ui_files]
1739 # moc qt4_moc_files, the moced files are included in the original files
1741 qt4 = frontend_env.StaticLibrary(
1742 target = '$LOCALLIBPATH/qt4',
1743 source = ['$BUILDDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_files],
1747 '$BUILDDIR/src/images',
1748 '$BUILDDIR/src/frontends',
1749 '$BUILDDIR/src/frontends/qt4',
1750 '$BUILDDIR/src/frontends/qt4/ui',
1751 '$BUILDDIR/src/frontends/controllers'
1756 '-DQT_CLEAN_NAMESPACE',
1770 print "Processing files in src/client..."
1772 if env['HAVE_FCNTL']:
1773 client = frontend_env.Program(
1774 target = '$BUILDDIR/src/client/lyxclient',
1775 LIBS = ['support'] + intl_libs + system_libs +
1776 socket_libs + boost_libraries + qtcore_lib,
1777 source = ['$BUILDDIR/src/client/%s' % x for x in src_client_files] + \
1778 utils.createResFromIcon(frontend_env, 'lyx_32x32.ico', '$LOCALLIBPATH/client.rc')
1780 Alias('client', frontend_env.Command(os.path.join('$BUILDDIR', os.path.split(str(client[0]))[1]),
1781 client, [Copy('$TARGET', '$SOURCE')]))
1784 Alias('client', client)
1786 if env['HAVE_FCNTL']:
1787 # define client even if lyxclient is not built with rebuild=no
1788 client = [env.subst('$BUILDDIR/src/client/${PROGPREFIX}lyxclient$PROGSUFFIX')]
1797 print "Processing files in src/tex2lyx..."
1800 for file in src_tex2lyx_copied_files + src_tex2lyx_copied_header_files:
1801 frontend_env.Command('$BUILDDIR/src/tex2lyx/'+file, '$TOP_SRCDIR/src/'+file,
1802 [Copy('$TARGET', '$SOURCE')])
1804 tex2lyx = frontend_env.Program(
1805 target = '$BUILDDIR/src/tex2lyx/tex2lyx',
1806 LIBS = ['support'] + boost_libraries + intl_libs + system_libs + qtcore_lib,
1807 source = ['$BUILDDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_files + src_tex2lyx_copied_files] + \
1808 utils.createResFromIcon(frontend_env, 'lyx_32x32.ico', '$LOCALLIBPATH/tex2lyx.rc'),
1809 CPPPATH = ['$BUILDDIR/src/tex2lyx', '$CPPPATH'],
1810 LIBPATH = ['#$LOCALLIBPATH', '$LIBPATH'],
1812 Alias('tex2lyx', frontend_env.Command(os.path.join('$BUILDDIR', os.path.split(str(tex2lyx[0]))[1]),
1813 tex2lyx, [Copy('$TARGET', '$SOURCE')]))
1814 Alias('tex2lyx', tex2lyx)
1816 # define tex2lyx even if tex2lyx is not built with rebuild=no
1817 tex2lyx = [frontend_env.subst('$BUILDDIR/src/tex2lyx/${PROGPREFIX}tex2lyx$PROGSUFFIX')]
1824 print "Processing files in src..."
1826 if env.has_key('USE_ASPELL') and env['USE_ASPELL']:
1827 src_post_files.append('ASpell.cpp')
1828 elif env.has_key('USE_PSPELL') and env['USE_PSPELL']:
1829 src_post_files.append('PSpell.cpp')
1830 elif env.has_key('USE_ISPELL') and env['USE_ISPELL']:
1831 src_post_files.append('ISpell.cpp')
1833 # msvc requires at least one source file with main()
1834 # so I exclude main.cpp from lyxbase
1835 lyxbase_pre = env.StaticLibrary(
1836 target = '$LOCALLIBPATH/lyxbase_pre',
1837 source = ['$BUILDDIR/src/%s' % x for x in src_pre_files]
1839 lyxbase_post = env.StaticLibrary(
1840 target = '$LOCALLIBPATH/lyxbase_post',
1841 source = ["$BUILDDIR/src/%s" % x for x in src_post_files]
1843 Alias('lyxbase', lyxbase_pre)
1844 Alias('lyxbase', lyxbase_post)
1849 # Build lyx with given frontend
1851 lyx = frontend_env.Program(
1852 target = '$BUILDDIR/lyx',
1853 source = ['$BUILDDIR/src/main.cpp'] + \
1854 utils.createResFromIcon(frontend_env, 'lyx_32x32.ico', '$LOCALLIBPATH/lyx.rc'),
1874 # define lyx even if lyx is not built with rebuild=no
1875 lyx = [frontend_env.subst('$BUILDDIR/${PROGPREFIX}lyx$PROGSUFFIX')]
1878 if build_msvs_projects:
1879 def build_project(target, full_target = None,
1880 src = [], inc = [], res = [], rebuildTargetOnly = True):
1881 ''' build mavs project files
1882 target: alias (correspond to directory name)
1883 full_target: full path/filename of the target
1887 rebuildTargetOnly: whether or not only rebuild this target
1889 For non-debug-able targets like static libraries, target (alias) is
1890 enough to build the target. For executable targets, msvs need to know
1891 the full path to start debug them.
1893 if rebuildTargetOnly:
1894 cmds = 'rebuild='+target
1897 if full_target is None:
1898 build_target = target
1900 build_target = full_target
1902 proj = env.MSVSProject(
1903 target = target + env['MSVSPROJECTSUFFIX'],
1904 # this allows easy access to header files (along with source)
1905 srcs = [env.subst(x) for x in src + inc],
1906 incs = [env.subst('$TOP_SRCDIR/src/config.h')],
1907 localincs = [env.subst(x) for x in inc],
1908 resources = [env.subst(x) for x in res],
1909 buildtarget = build_target,
1913 Alias('msvs_projects', proj)
1915 build_project('client', src = ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_files],
1916 inc = ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_header_files],
1917 rebuildTargetOnly = False,
1918 full_target = File(env.subst('$BUILDDIR/src/client/lyxclient$PROGSUFFIX')).abspath)
1920 build_project('tex2lyx', src = ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_files],
1921 inc = ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_header_files],
1922 rebuildTargetOnly = False,
1923 full_target = File(env.subst('$BUILDDIR/src/tex2lyx/tex2lyx$PROGSUFFIX')).abspath)
1925 build_project('lyx',
1926 src = ['$TOP_SRCDIR/src/%s' % x for x in src_pre_files + src_post_files + ['version.cpp']] + \
1927 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_files + ['Package.cpp'] ] + \
1928 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_files] + \
1929 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_files] + \
1930 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_files] + \
1931 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_files] + \
1932 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files] + \
1933 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_files + src_frontends_qt4_moc_files],
1934 inc = ['$TOP_SRCDIR/src/%s' % x for x in src_header_files] + \
1935 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files] + \
1936 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_header_files] + \
1937 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files] + \
1938 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files] + \
1939 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files] + \
1940 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files] + \
1941 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_header_files],
1942 res = ['$TOP_SRCDIR/src/frontends/qt4/ui/%s' % x for x in src_frontends_qt4_ui_files],
1943 rebuildTargetOnly = False,
1944 full_target = File(env.subst('$BUILDDIR/lyx$PROGSUFFIX')).abspath)
1949 # update scons_manifest.py
1951 # When you run 'scons update_manifest', it tells you which files are missing
1952 # and which files are not in the source tree. It also generates a
1953 # scons_manifest.py.new file with all the missing files added to
1954 # XXX_extra_files. It will *not* change other sections of existing
1957 print 'Validating development/scons/scons_manifest.py...'
1959 manifest = open(env.File('$TOP_SRCDIR/development/scons/scons_manifest.py.new').abspath, 'w')
1960 print >> manifest, 'from SCons.Util import Split\n'
1962 ignore_dirs = ['boost/boost', 'm4', 'development',
1963 utils.relativePath(env.Dir('$BUILDDIR').abspath, env.Dir('$TOP_SRCDIR').abspath)]
1964 ignore_types = ['.svn', '.deps', '.cache', '.tmp', '.bak', '.gmo', '.pot',
1965 '.pyc', '.pyo', '.o', '_moc.cpp', 'Makefile.in', 'config.h.in',
1966 'LaTeXConfig.lyx', 'version.cpp', 'Package.cpp']
1967 ext_types = ['_header_files', '_files', '_pre_files', '_post_files', '_moc_files', '_inc_files',
1968 '_copied_files', '_copied_header_files', '_extra_header_files', '_extra_src_files', '_extra_files']
1969 for root,path,files in os.walk(env.Dir('$TOP_SRCDIR').abspath):
1970 if os.path.split(root)[-1][0] == '.' \
1971 or True in [x in root for x in ignore_types] \
1972 or True in [utils.isSubDir(root, x) for x in ignore_dirs]:
1974 dirname = utils.relativePath(root, env.subst('$TOP_SRCDIR')).replace(os.sep, '_')
1977 # files in the current manifest.py
1979 for ext in ext_types:
1980 if 'copied' not in ext and dirname + ext in locals():
1981 cur_files.extend(eval(dirname + ext))
1983 # compare files with cur_files
1984 files = [x for x in files if x[0] != '.' and True not in [len(x) >= len(y) and x[-len(y):] == y for y in ignore_types]]
1986 if cur_files != files:
1989 if f not in cur_files:
1995 if len(missing) > 0:
1996 print 'Missing: %s in %s' % (', '.join(missing), root)
1997 if dirname + '_extra_files' in locals():
1998 exec('%s_extra_files.extend(missing)' % dirname)
2000 exec('%s_extra_files = missing' % dirname)
2002 print 'Extra: %s in %s' % (', '.join(extra), root)
2003 # write to a new manifest file
2004 for ext in ext_types:
2005 if dirname + ext in locals():
2006 exec('%s%s.sort()' % (dirname, ext))
2007 print >> manifest, "%s%s = Split('''\n " % (dirname, ext),
2008 print >> manifest, eval(r"'\n '.join(%s%s)" % (dirname, ext))
2009 print >> manifest, "''')\n\n"
2011 Alias('update_manifest', None)
2018 print 'Updating po/*.po files...'
2020 # whether or not update po files
2021 if not env['XGETTEXT'] or not env['MSGMERGE'] or not env['MSGUNIQ']:
2022 print 'xgettext or msgmerge does not exist. Cannot merge po files'
2024 # rebuild POTFILES.in
2025 POTFILES_in = env.potfiles('$TOP_SRCDIR/po/POTFILES.in',
2026 ['$TOP_SRCDIR/src/%s' % x for x in src_header_files + src_pre_files + src_post_files + \
2027 src_extra_src_files] + \
2028 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files + src_support_files + \
2029 src_support_extra_header_files + src_support_extra_src_files] + \
2030 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_header_files + src_mathed_files] + \
2031 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files + src_insets_files] + \
2032 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files + src_frontends_files] + \
2033 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files + src_graphics_files] + \
2034 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files + src_frontends_controllers_files] + \
2035 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_header_files + src_frontends_qt4_files + src_frontends_qt4_moc_files] + \
2036 ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_header_files + src_client_files ] + \
2037 ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_header_files + src_tex2lyx_files ]
2039 Alias('update_po', POTFILES_in)
2040 # build language_l10n.pot, ui_l10n.pot, layouts_l10n.pot, qt4_l10n.pot, external_l10n
2041 # and combine them to lyx.po
2042 env['LYX_POT'] = 'python $TOP_SRCDIR/po/lyx_pot.py'
2043 lyx_po = env.Command('$BUILDDIR/po/lyx.po',
2044 env.Command('$BUILDDIR/po/all.po',
2045 [env.Command('$BUILDDIR/po/qt4_l10n.pot',
2046 ['$TOP_SRCDIR/src/frontends/qt4/ui/%s' % x for x in src_frontends_qt4_ui_files],
2047 '$LYX_POT -b $TOP_SRCDIR -t qt4 -o $TARGET $SOURCES'),
2048 env.Command('$BUILDDIR/po/layouts_l10n.pot',
2049 ['$TOP_SRCDIR/lib/layouts/%s' % x for x in lib_layouts_files + lib_layouts_inc_files],
2050 '$LYX_POT -b $TOP_SRCDIR -t layouts -o $TARGET $SOURCES'),
2051 env.Command('$BUILDDIR/po/languages_l10n.pot', '$TOP_SRCDIR/lib/languages',
2052 '$LYX_POT -b $TOP_SRCDIR -t languages -o $TARGET $SOURCES'),
2053 env.Command('$BUILDDIR/po/ui_l10n.pot',
2054 ['$TOP_SRCDIR/lib/ui/%s' % x for x in lib_ui_files],
2055 '$LYX_POT -b $TOP_SRCDIR -t ui -o $TARGET $SOURCES'),
2056 env.Command('$BUILDDIR/po/external_l10n.pot', '$TOP_SRCDIR/lib/external_templates',
2057 '$LYX_POT -b $TOP_SRCDIR -t external -o $TARGET $SOURCES'),
2059 ['$MSGUNIQ -o $TARGET $SOURCE',
2060 '''$XGETTEXT --default-domain=${TARGET.base} \
2061 --directory=$TOP_SRCDIR --add-comments=TRANSLATORS: \
2062 --language=C++ --join-existing \
2063 --keyword=_ --keyword=N_ --keyword=B_ --keyword=qt_ \
2064 --files-from=$TOP_SRCDIR/po/POTFILES.in \
2065 --copyright-holder="LyX Developers" \
2066 --msgid-bugs-address="lyx-devel@lists.lyx.org" ''']
2068 env.Depends(lyx_po, POTFILES_in)
2069 # copy lyx.po to lyx.pot
2070 lyx_pot = env.Command('$BUILDDIR/po/lyx.pot', lyx_po,
2071 Copy('$TARGET', '$SOURCE'))
2074 # files to translate
2075 transfiles = glob.glob(os.path.join(env.Dir('$TOP_SRCDIR/po').abspath, '*.po'))
2076 # possibly *only* handle these languages
2078 if env.has_key('languages'):
2079 languages = env.make_list(env['languages'])
2080 # merge. if I use lan.po as $TARGET, it will be removed
2081 # before it is merged. In this builder,
2082 # $BUILDDIR/po/lang.po is merged from po/lang.po and $BUILDDIR/po/lyx.pot
2083 # and is copied to po/lang.po
2084 env['BUILDERS']['msgmerge'] = Builder(action=[
2085 '$MSGMERGE $TOP_SRCDIR/po/${TARGET.filebase}.po $SOURCE -o $TARGET',
2086 Copy('$TOP_SRCDIR/po/${TARGET.filebase}.po', '$TARGET')]
2088 # for each po file, generate pot
2089 for po_file in transfiles:
2091 fname = os.path.split(po_file)[1]
2093 country = fname.split('.')[0]
2095 if not languages or country in languages:
2096 # merge po files, the generated lan.po_new file is copied to lan.po file.
2097 po = env.msgmerge('$BUILDDIR/po/%s.po' % country, lyx_pot)
2098 env.Depends(po, POTFILES_in)
2099 Alias('update_po', po)
2106 print 'Processing files in po...'
2111 # files to translate
2112 transfiles = glob.glob(os.path.join(env.subst('$TOP_SRCDIR'), 'po', '*.po'))
2113 # possibly *only* handle these languages
2115 if env.has_key('languages'):
2116 languages = env.make_list(env['lanauges'])
2117 # use defulat msgfmt
2119 if not env['MSGFMT']:
2120 print 'msgfmt does not exist. Can not process po files'
2123 env['BUILDERS']['Transfiles'] = Builder(action='$MSGFMT $SOURCE -c --statistics -o $TARGET',suffix='.gmo',src_suffix='.po')
2125 for f in transfiles:
2127 fname = os.path.split(f)[1]
2129 country = fname.split('.')[0]
2131 if not languages or country in languages:
2132 gmo_files.extend(env.Transfiles(f))
2137 # this part is a bit messy right now. Since scons will provide
2138 # --DESTDIR option soon, at least the dest_dir handling can be
2141 # how to join dest_dir and prefix
2142 def joinPaths(path1, path2):
2143 ''' join path1 and path2, do not use os.path.join because
2144 under window, c:\destdir\d:\program is invalid '''
2146 return os.path.normpath(path2)
2147 # separate drive letter
2148 (drive, path) = os.path.splitdrive(os.path.normpath(path2))
2149 # ignore drive letter, so c:\destdir + c:\program = c:\destdir\program
2150 return os.path.join(os.path.normpath(path1), path[1:])
2152 # install to dest_dir/prefix
2153 dest_dir = env.get('DESTDIR', '')
2154 dest_prefix_dir = joinPaths(dest_dir, env.Dir(prefix).abspath)
2155 # create the directory if needed
2156 if not os.path.isdir(dest_prefix_dir):
2158 os.makedirs(dest_prefix_dir)
2161 if not os.path.isdir(dest_prefix_dir):
2162 print 'Can not create directory', dest_prefix_dir
2165 if env.has_key('exec_prefix'):
2166 bin_dest_dir = joinPaths(dest_dir, Dir(env['exec_prefix']).abspath)
2168 bin_dest_dir = os.path.join(dest_prefix_dir, 'bin')
2170 share_dest_dir = os.path.join(dest_prefix_dir, share_dir + program_suffix)
2172 share_dest_dir = os.path.join(dest_prefix_dir, share_dir)
2173 man_dest_dir = os.path.join(dest_prefix_dir, man_dir)
2174 locale_dest_dir = os.path.join(dest_prefix_dir, locale_dir)
2175 env['LYX2LYX_DEST'] = os.path.join(share_dest_dir, 'lyx2lyx')
2179 # install executables (lyxclient may be None)
2182 version_suffix = program_suffix
2186 # install lyx, if in release mode, try to strip the binary
2187 if env.has_key('STRIP') and env['STRIP'] is not None and mode != 'debug':
2188 # create a builder to strip and install
2189 env['BUILDERS']['StripInstallAs'] = Builder(action='$STRIP $SOURCE -o $TARGET')
2191 # install executables
2192 for (name, obj) in (('lyx', lyx), ('tex2lyx', tex2lyx), ('client', client)):
2195 target_name = os.path.split(str(obj[0]))[1].replace(name, '%s%s' % (name, version_suffix))
2196 target = os.path.join(bin_dest_dir, target_name)
2197 if env['BUILDERS'].has_key('StripInstallAs'):
2198 env.StripInstallAs(target, obj)
2200 env.InstallAs(target, obj)
2201 Alias('install', target)
2205 for (dir,files) in [
2207 ('bind', lib_bind_files),
2208 ('bind/de', lib_bind_de_files),
2209 ('bind/fi', lib_bind_fi_files),
2210 ('bind/pt', lib_bind_pt_files),
2211 ('bind/sv', lib_bind_sv_files),
2212 ('doc', lib_doc_files),
2213 ('doc/biblio', lib_doc_biblio_files),
2214 ('doc/clipart', lib_doc_clipart_files),
2215 ('doc/cs', lib_doc_cs_files),
2216 ('doc/da', lib_doc_da_files),
2217 ('doc/de', lib_doc_de_files),
2218 ('doc/de/clipart', lib_doc_de_clipart_files),
2219 ('doc/es', lib_doc_es_files),
2220 ('doc/es/clipart', lib_doc_es_clipart_files),
2221 ('doc/eu', lib_doc_eu_files),
2222 ('doc/fr', lib_doc_fr_files),
2223 ('doc/he', lib_doc_he_files),
2224 ('doc/hu', lib_doc_hu_files),
2225 ('doc/it', lib_doc_it_files),
2226 ('doc/nl', lib_doc_nl_files),
2227 ('doc/nb', lib_doc_nb_files),
2228 ('doc/pl', lib_doc_pl_files),
2229 ('doc/pt', lib_doc_pt_files),
2230 ('doc/ro', lib_doc_ro_files),
2231 ('doc/ru', lib_doc_ru_files),
2232 ('doc/sk', lib_doc_sk_files),
2233 ('doc/sl', lib_doc_sl_files),
2234 ('doc/sv', lib_doc_sv_files),
2235 ('examples', lib_examples_files),
2236 ('examples/ca', lib_examples_ca_files),
2237 ('examples/cs', lib_examples_cs_files),
2238 ('examples/da', lib_examples_da_files),
2239 ('examples/de', lib_examples_de_files),
2240 ('examples/es', lib_examples_es_files),
2241 ('examples/eu', lib_examples_eu_files),
2242 ('examples/fa', lib_examples_fa_files),
2243 ('examples/fr', lib_examples_fr_files),
2244 ('examples/he', lib_examples_he_files),
2245 ('examples/hu', lib_examples_hu_files),
2246 ('examples/it', lib_examples_it_files),
2247 ('examples/nl', lib_examples_nl_files),
2248 ('examples/pl', lib_examples_pl_files),
2249 ('examples/pt', lib_examples_pt_files),
2250 ('examples/ru', lib_examples_ru_files),
2251 ('examples/sl', lib_examples_sl_files),
2252 ('examples/ro', lib_examples_ro_files),
2253 ('fonts', lib_fonts_files),
2254 ('images', lib_images_files),
2255 ('images/math', lib_images_math_files),
2256 ('kbd', lib_kbd_files),
2257 ('layouts', lib_layouts_files + lib_layouts_inc_files),
2258 ('lyx2lyx', lib_lyx2lyx_files),
2259 ('scripts', lib_scripts_files),
2260 ('templates', lib_templates_files),
2261 ('tex', lib_tex_files),
2262 ('ui', lib_ui_files)]:
2263 dirs.append(env.Install(os.path.join(share_dest_dir, dir),
2264 [env.subst('$TOP_SRCDIR/lib/%s/%s' % (dir, file)) for file in files]))
2265 Alias('install', dirs)
2267 # subst and install lyx2lyx_version.py which is not in scons_manifest.py
2268 env.Depends(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py', '$BUILDDIR/src/config.h')
2269 env.substFile(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py',
2270 '$TOP_SRCDIR/lib/lyx2lyx/lyx2lyx_version.py.in')
2271 Alias('install', share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2272 sys.path.append(share_dest_dir + '/lyx2lyx')
2274 # generate TOC files for each doc
2275 languages = depend.all_documents(env.Dir('$TOP_SRCDIR/lib/doc').abspath)
2277 for lang in languages.keys():
2278 if os.path.isdir(os.path.join(env.Dir('$TOP_SRCDIR/lib/doc').abspath, lang)):
2279 toc = env.installTOC(os.path.join(share_dest_dir, 'doc', lang, 'TOC.lyx'),
2282 # doc_toc.build_toc needs a installed version of lyx2lyx to execute
2283 env.Depends(toc, share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2285 # this is for English
2286 toc = env.installTOC(os.path.join(share_dest_dir, 'doc', 'TOC.lyx'),
2289 env.Depends(toc, share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2290 Alias('install', tocs)
2292 if platform_name == 'cygwin':
2293 # cygwin packaging requires a file /usr/share/doc/Cygwin/foot-vendor-suffix.README
2294 Cygwin_README = os.path.join(dest_prefix_dir, 'share', 'doc', 'Cygwin',
2295 '%s-%s.README' % (package, package_cygwin_version))
2296 env.InstallAs(Cygwin_README,
2297 os.path.join(env.subst('$TOP_SRCDIR'), 'README.cygwin'))
2298 Alias('install', Cygwin_README)
2299 # also a directory /usr/share/doc/lyx for README etc
2300 Cygwin_Doc = os.path.join(dest_prefix_dir, 'share', 'doc', package)
2301 env.Install(Cygwin_Doc, [os.path.join(env.subst('$TOP_SRCDIR'), x) for x in \
2302 ['INSTALL', 'README', 'README.Cygwin', 'RELEASE-NOTES', 'COPYING', 'ANNOUNCE']])
2303 Alias('install', Cygwin_Doc)
2304 # cygwin fonts also need to be installed
2305 Cygwin_fonts = os.path.join(share_dest_dir, 'fonts')
2306 env.Install(Cygwin_fonts,
2307 [env.subst('$TOP_SRCDIR/development/Win32/packaging/bakoma/%s' % file) \
2308 for file in win32_bakoma_fonts])
2309 Alias('install', Cygwin_fonts)
2310 # we also need a post installation script
2311 tmp_script = utils.installCygwinPostinstallScript('/tmp')
2312 postinstall_path = os.path.join(dest_dir, 'etc', 'postinstall')
2313 env.Install(postinstall_path, tmp_script)
2314 Alias('install', postinstall_path)
2318 env.InstallAs(os.path.join(man_dest_dir, 'lyx' + version_suffix + '.1'),
2319 env.subst('$TOP_SRCDIR/lyx.man'))
2320 env.InstallAs(os.path.join(man_dest_dir, 'tex2lyx' + version_suffix + '.1'),
2321 env.subst('$TOP_SRCDIR/src/tex2lyx/tex2lyx.man'))
2322 env.InstallAs(os.path.join(man_dest_dir, 'lyxclient' + version_suffix + '.1'),
2323 env.subst('$TOP_SRCDIR/src/client/lyxclient.man'))
2324 Alias('install', [os.path.join(man_dest_dir, x + version_suffix + '.1') for
2325 x in ['lyx', 'tex2lyx', 'lyxclient']])
2327 # ru.gmo ==> ru/LC_MESSAGES/lyxSUFFIX.mo
2328 for gmo in gmo_files:
2329 lan = os.path.split(str(gmo))[1].split('.')[0]
2330 dest_file = os.path.join(locale_dest_dir, lan, 'LC_MESSAGES', 'lyx' + program_suffix + '.mo')
2331 env.InstallAs(dest_file, gmo)
2332 Alias('install', dest_file)
2337 # build windows installer using NSIS
2340 # There is a nsis builder on scons wiki but it does not work with
2341 # our lyx.nsi because it does not dig through all the include directives
2342 # and find the dependencies automatically. Also, it can not parse
2343 # OutFile in lyx.nsi since it is defined as SETUP_EXE which is in turn
2344 # something rely on date.
2345 # Because of this, I am doing a simple nsis builder here.
2346 if platform_name != 'win32':
2347 print 'installer target is only available for windows platform'
2349 if mode != 'release':
2350 print 'installer has to be built in release mode (use option mode=release)'
2352 installer_files = ['$TOP_SRCDIR/development/Win32/packaging/installer/%s' \
2353 % x for x in development_Win32_packaging_installer] + \
2354 ['$TOP_SRCDIR/development/Win32/packaging/installer/components/%s' \
2355 % x for x in development_Win32_packaging_installer_components] + \
2356 ['$TOP_SRCDIR/development/Win32/packaging/installer/dialogs/%s' \
2357 % x for x in development_Win32_packaging_installer_dialogs] + \
2358 ['$TOP_SRCDIR/development/Win32/packaging/installer/graphics/%s' \
2359 % x for x in development_Win32_packaging_installer_graphics] + \
2360 ['$TOP_SRCDIR/development/Win32/packaging/installer/include/%s' \
2361 % x for x in development_Win32_packaging_installer_include] + \
2362 ['$TOP_SRCDIR/development/Win32/packaging/installer/lang/%s' \
2363 % x for x in development_Win32_packaging_installer_lang]
2364 if env.has_key('NSIS') and env['NSIS'] is not None:
2365 # create a builder to strip and install
2366 env['BUILDERS']['installer'] = Builder(generator=utils.env_nsis)
2368 print 'No nsis compiler is found. Existing...'
2370 if not env.has_key('win_installer') or env['win_installer'] is None:
2372 env['win_installer'] = '%s-%s-%s-Installer.exe' % (package_name, package_version, time.strftime('%Y-%m-%d'))
2374 env['win_installer'] = '%s-%s-Installer.exe' % (package_name, package_version)
2375 # provide default setting
2376 if not env.has_key('deps_dir') or env['deps_dir'] is None:
2377 env['deps_dir'] = os.path.join(env.Dir('$TOP_SRCDIR').abspath, 'lyx-windows-deps-msvc-qt4')
2378 if not os.path.isdir(env.Dir('$deps_dir').abspath):
2379 print 'Development dependency package is not found.'
2382 env['deps_dir'] = env.Dir('$deps_dir').abspath
2384 if env.has_key('bundle_dir') and os.path.isdir(env.Dir('$bundle_dir').abspath):
2385 env['bundle_dir'] = env.Dir('$bundle_dir').abspath
2386 elif os.path.isdir(os.path.join(env.Dir('$TOP_SRCDIR').abspath, 'lyx-windows-bundle-deps')):
2387 env['bundle_dir'] = os.path.join(env.Dir('$TOP_SRCDIR').abspath, 'lyx-windows-bundle-deps')
2389 env['bundle_dir'] = None
2390 # if absolute path is given, use it, otherwise, write to current directory
2391 if not (':' in env['win_installer'] or '/' in env['win_installer'] or '\\' in env['win_installer']):
2392 env['win_installer'] = os.path.join(env.Dir('$BUILDDIR').abspath, env['win_installer'])
2393 env.Append(NSISDEFINES={
2394 'ExeFile':env['win_installer'],
2395 'BundleExeFile':env['win_installer'].replace('.exe', '-bundle.exe'),
2396 'FilesLyx':env.Dir(dest_prefix_dir).abspath,
2397 'FilesDeps':env['deps_dir'],
2398 'FilesBundle':env['bundle_dir'],
2400 installer = env.installer(env['win_installer'],
2401 '$TOP_SRCDIR/development/Win32/packaging/installer/lyx.nsi')
2402 # since I can not use a scanner, explicit dependent is required
2403 env.Depends(installer, 'install')
2404 env.Depends(installer, installer_files)
2405 env.Alias('installer', installer)
2406 # also generate bundle?
2407 if env.has_key('bundle') and env['bundle']:
2408 if env['bundle_dir'] is None or not os.path.isdir(env['bundle_dir']):
2409 print 'Bundle directory does not exist (default to %s\lyx-windows-bundle-deps.' % env.Dir('$TOP_SRCDIR').abspath
2410 print 'Use bundle_dir option to specify'
2412 # generator of the builder will add bundle stuff depending on output name
2413 bundle_installer = env.installer(env['win_installer'].replace('.exe', '-bundle.exe'),
2414 '$TOP_SRCDIR/development/Win32/packaging/installer/lyx.nsi')
2415 env.Depends(bundle_installer, 'install')
2416 env.Depends(bundle_installer, installer_files)
2417 env.Alias('installer', bundle_installer)
2420 Alias('all', ['lyx', 'client', 'tex2lyx'])