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),
193 ('rebuild', 'Obsolete option', None),
194 # can be set to a non-existing directory
195 ('prefix', 'install architecture-independent files in PREFIX', default_prefix),
196 # replace the default name and location of the windows installer
197 ('win_installer', 'name or full path to the windows installer', None),
198 # the deps package used to create minimal installer (qt and other libraries)
199 ('deps_dir', 'path to the development depedency packages with zlib, iconv, zlib and qt libraries', None),
200 # whether or not build bundle installer
201 BoolOption('bundle', 'Whether or not build bundle installer', False),
202 # the bundle directory, containing bundled applications
203 PathOption('bundle_dir', 'path to the bundle dependency package with miktex setup.exe etc', None),
204 # build directory, will use $mode if not set
205 ('build_dir', 'Build directory', None),
207 ('version_suffix', 'install lyx as lyx-suffix', None),
208 # how to load options
209 ('load_option', '''load option from previous scons run. option can be
210 yes (default): load all options
211 no: do not load any option
212 opt1,opt2: load specified options
213 -opt1,opt2: load all options other than specified ones''', 'yes'),
215 ('optimization', 'optimization CCFLAGS option.', None),
217 PathOption('exec_prefix', 'install architecture-independent executable files in PREFIX', None),
219 ('logfile', 'save commands (not outputs) to logfile', default_log_file),
220 # provided for backward compatibility
221 ('dest_dir', 'install to DESTDIR. (Provided for backward compatibility only)', None),
222 # environment variable can be set as options.
223 ('DESTDIR', 'install to DESTDIR', None),
224 ('CC', 'replace default $CC', None),
225 ('LINK', 'replace default $LINK', None),
226 ('CPP', 'replace default $CPP', None),
227 ('CXX', 'replace default $CXX', None),
228 ('CXXCPP', 'replace default $CXXCPP', None),
229 ('CCFLAGS', 'replace default $CCFLAGS', None),
230 ('CPPFLAGS', 'replace default $CPPFLAGS', None),
231 ('LINKFLAGS', 'replace default $LINKFLAGS', None),
235 all_options = [x.key for x in opts.options]
237 # copied from SCons/Options/BoolOption.py
238 # We need to use them before a boolean ARGUMENTS option is available
240 true_strings = ('y', 'yes', 'true', 't', '1', 'on' , 'all' )
241 false_strings = ('n', 'no', 'false', 'f', '0', 'off', 'none')
243 if ARGUMENTS.has_key('fast_start'):
244 print 'fast_start option is obsolete'
246 # if load_option=yes (default), load saved comand line options
248 # This option can take value yes/no/opt1,opt2/-opt1,opt2
249 # and tries to be clever in choosing options to load
250 if (not ARGUMENTS.has_key('load_option') or \
251 ARGUMENTS['load_option'] not in false_strings) \
252 and os.path.isfile(opt_cache_file):
253 cache_file = open(opt_cache_file)
254 opt_cache = cPickle.load(cache_file)
256 # import cached options, but we should ignore qt_dir when frontend changes
257 if ARGUMENTS.has_key('frontend') and opt_cache.has_key('frontend') \
258 and ARGUMENTS['frontend'] != opt_cache['frontend'] \
259 and opt_cache.has_key('qt_dir'):
260 opt_cache.pop('qt_dir')
261 # and we do not cache some options (dest_dir is obsolete)
262 for arg in ['load_option', 'dest_dir', 'bundle']:
263 if opt_cache.has_key(arg):
265 # remove obsolete cached keys (well, SConstruct is evolving. :-)
266 for arg in opt_cache.keys():
267 if arg not in all_options:
268 print 'Option %s is obsolete, do not load it' % arg
270 # now, if load_option=opt1,opt2 or -opt1,opt2
271 if ARGUMENTS.has_key('load_option') and \
272 ARGUMENTS['load_option'] not in true_strings + false_strings:
273 # if -opt1,opt2 is specified, do not load these options
274 if ARGUMENTS['load_option'][0] == '-':
275 for arg in ARGUMENTS['load_option'][1:].split(','):
276 if opt_cache.has_key(arg):
278 # if opt1,opt2 is specified, only load specified options
280 args = ARGUMENTS['load_option'].split(',')
281 for arg in opt_cache.keys():
284 # now restore options as if entered from command line
285 for key in opt_cache.keys():
286 if not ARGUMENTS.has_key(key):
287 ARGUMENTS[key] = opt_cache[key]
288 print "Restoring cached option %s=%s" % (key, ARGUMENTS[key])
291 # check if there is unused (or misspelled) argument
292 for arg in ARGUMENTS.keys():
293 if arg not in all_options:
295 print "Unknown option '%s'... exiting." % arg
297 print "Available options are (check 'scons -help' for details):"
298 print ' ' + '\n '.join(textwrap.wrap(', '.join(all_options)))
302 cache_file = open(opt_cache_file, 'w')
303 cPickle.dump(ARGUMENTS, cache_file)
306 #---------------------------------------------------------
307 # Setting up environment
308 #---------------------------------------------------------
310 # I do not really like ENV=os.environ, but you may add it
311 # here if you experience some environment related problem
312 env = Environment(options = opts)
314 # set individual variables since I do not really like ENV = os.environ
315 env['ENV']['PATH'] = os.environ.get('PATH')
316 env['ENV']['HOME'] = os.environ.get('HOME')
317 # these are defined for MSVC
318 env['ENV']['LIB'] = os.environ.get('LIB')
319 env['ENV']['INCLUDE'] = os.environ.get('INCLUDE')
321 # for simplicity, use var instead of env[var]
322 frontend = env['frontend']
323 prefix = env['prefix']
326 if platform_name == 'win32':
327 if env.has_key('use_vc'):
328 use_vc = env['use_vc']
329 if WhereIs('cl.exe') is None:
330 print "cl.exe is not found. Are you using the MSVC environment?"
332 elif WhereIs('cl.exe') is not None:
339 if env.has_key('build_dir') and env['build_dir'] is not None:
340 env['BUILDDIR'] = env['build_dir']
342 # Determine the name of the build $mode
343 env['BUILDDIR'] = '#' + mode
345 # all built libraries will go to build_dir/libs
346 # (This is different from the make file approach)
347 env['LOCALLIBPATH'] = '$BUILDDIR/libs'
348 env.AppendUnique(LIBPATH = ['$LOCALLIBPATH'])
351 # Here is a summary of variables defined in env
353 # 2. undefined options with a non-None default value
354 # 3. compiler commands and flags like CCFLAGS.
355 # MSGFMT used to process po files
356 # 4. Variables that will be used to replace variables in some_file.in
357 # src/support/Package.cpp.in:
358 # TOP_SRCDIR, LOCALEDIR, LYX_DIR, PROGRAM_SUFFIX
359 # lib/lyx2lyx/lyx2lyx_version.py.in
362 # full path name is used to build msvs project files
363 # and to replace TOP_SRCDIR in package.C
364 env['TOP_SRCDIR'] = Dir(top_src_dir).abspath
366 # determine share_dir etc
367 packaging_method = env.get('packaging')
368 if packaging_method == 'windows':
369 share_dir = 'Resources'
370 man_dir = 'Resources/man/man1'
371 locale_dir = 'Resources/locale'
373 share_dir = 'share/lyx'
374 locale_dir = 'share/locale'
375 if platform_name == 'cygwin':
376 man_dir = 'share/man/man1'
380 # program suffix: can be yes, or a string
381 if env.has_key('version_suffix'):
382 if env['version_suffix'] in true_strings:
383 program_suffix = package_version
384 elif env['version_suffix'] in false_strings:
387 program_suffix = env['version_suffix']
390 # used by Package.cpp.in
391 env['PROGRAM_SUFFIX'] = program_suffix
393 # whether or not add suffix to file and directory names
394 add_suffix = packaging_method != 'windows'
395 # LYX_DIR are different (used in Package.cpp.in)
397 env['LYX_DIR'] = Dir(os.path.join(prefix, share_dir + program_suffix)).abspath
399 env['LYX_DIR'] = Dir(os.path.join(prefix, share_dir)).abspath
400 # we need absolute path for package.C
401 env['LOCALEDIR'] = Dir(os.path.join(prefix, locale_dir)).abspath
404 #---------------------------------------------------------
405 # Setting building environment (Tools, compiler flags etc)
406 #---------------------------------------------------------
408 # Since Tool('mingw') will reset CCFLAGS etc, this should be
409 # done before getEnvVariable
410 if platform_name == 'win32':
416 env.AppendUnique(CPPPATH = ['#c:/MinGW/include'])
417 # fix a scons winres bug (there is a missing space between ${RCINCPREFIX} and ${SOURCE.dir}
419 env['RCCOM'] = '$RC $_CPPDEFFLAGS $RCINCFLAGS ${RCINCPREFIX} ${SOURCE.dir} $RCFLAGS -i $SOURCE -o $TARGET'
422 # we differentiate between hard-coded options and default options
423 # hard-coded options are required and will always be there
424 # default options can be replaced by enviromental variables or command line options
425 CCFLAGS_required = []
426 LINKFLAGS_required = []
429 # under windows, scons is confused by .C/.c and uses gcc instead of
430 # g++. I am forcing the use of g++ here. This is expected to change
431 # after lyx renames all .C files to .cpp
433 # save the old c compiler and CCFLAGS (used by libintl)
434 C_COMPILER = env.subst('$CC')
435 C_CCFLAGS = env.subst('$CCFLAGS').split()
436 # if we use ms vc, the commands are fine (cl.exe and link.exe)
438 # C4819: The file contains a character that cannot be represented
439 # in the current code page (number)
440 # C4996: foo was decleared deprecated
441 CCFLAGS_required.append('/EHsc')
443 CCFLAGS_default.extend(['/wd4819', '/wd4996', '/nologo', '/MDd'])
444 # the flags are also needed in C mode (for intl lib)
445 C_CCFLAGS.extend(['/wd4819', '/wd4996', '/nologo', '/MDd'])
447 CCFLAGS_default.extend(['/wd4819', '/wd4996', '/nologo', '/MD'])
448 C_CCFLAGS.extend(['/wd4819', '/wd4996', '/nologo', '/MD'])
450 # for debug/release mode
451 if env.has_key('optimization') and env['optimization'] is not None:
452 # if user supplies optimization flags, use it anyway
453 CCFLAGS_required.extend(env['optimization'].split())
454 # and do not use default
455 set_default_optimization_flags = False
457 set_default_optimization_flags = True
461 CCFLAGS_required.append('/Zi')
462 LINKFLAGS_required.extend(['/debug', '/map'])
464 CCFLAGS_required.append('-g')
465 CCFLAGS_default.append('-O')
466 elif mode == 'release' and set_default_optimization_flags:
468 CCFLAGS_default.append('/O2')
470 CCFLAGS_default.append('-O2')
472 # msvc uses separate tools for profiling
473 if env.has_key('profiling') and env['profiling']:
475 print 'Visual C++ does not use profiling options'
477 CCFLAGS_required.append('-pg')
478 LINKFLAGS_required.append('-pg')
480 if env.has_key('warnings') and env['warnings']:
482 CCFLAGS_default.append('/W2')
484 # Note: autotools detect gxx version and pass -W for 3.x
485 # and -Wextra for other versions of gcc
486 CCFLAGS_default.append('-Wall')
488 # Now, set the variables as follows:
489 # 1. if command line option exists: replace default
490 # 2. then if s envronment variable exists: replace default
491 # 3. set variable to required + default
492 def setEnvVariable(env, name, required = None, default = None, split = True):
493 ''' env: environment to set variable
495 required: hardcoded options
496 default: default options that can be replaced by command line or
497 environment variables
498 split: whether or not split obtained variable like '-02 -g'
500 # 1. ARGUMENTS is already set to env[name], override default.
501 if ARGUMENTS.has_key(name):
502 # env[name] may be rewritten when building tools are reloaded
503 # if that is the case, commandline option will override it.
504 env[name] = ARGUMENTS[name]
506 # then use environment default
507 elif os.environ.has_key(name):
508 print "Acquiring variable %s from system environment: %s" % (name, os.environ[name])
509 default = os.environ[name]
511 default = default.split()
512 # the real value should be env[name] + default + required
515 if env.has_key(name):
516 value = str(env[name]).split()
517 if required is not None:
519 if default is not None:
523 if env.has_key(name):
524 value = str(env[name])
525 if required is not None:
526 value += " " + required
527 if default is not None:
528 value += " " + default
530 # print name, env[name]
532 setEnvVariable(env, 'DESTDIR', split=False)
533 setEnvVariable(env, 'CC')
534 setEnvVariable(env, 'LINK')
535 setEnvVariable(env, 'CPP')
536 setEnvVariable(env, 'CXX')
537 setEnvVariable(env, 'CXXCPP')
538 setEnvVariable(env, 'CCFLAGS', CCFLAGS_required, CCFLAGS_default)
539 setEnvVariable(env, 'CXXFLAGS')
540 setEnvVariable(env, 'CPPFLAGS')
541 setEnvVariable(env, 'LINKFLAGS', LINKFLAGS_required)
543 # if DESTDIR is not set...
544 if env.has_key('dest_dir'):
545 print "This option is obsolete. Please use DESTDIR instead."
546 env['DESTDIR'] = env['dest_dir']
549 # extra_inc_path and extra_lib_path
552 if env.has_key('extra_inc_path') and env['extra_inc_path']:
553 extra_inc_paths.append(env['extra_inc_path'])
554 if env.has_key('extra_lib_path') and env['extra_lib_path']:
555 env.AppendUnique(LIBPATH = [env['extra_lib_path']])
556 if env.has_key('extra_inc_path1') and env['extra_inc_path1']:
557 extra_inc_paths.append(env['extra_inc_path1'])
558 if env.has_key('extra_lib_path1') and env['extra_lib_path1']:
559 env.AppendUnique(LIBPATH = [env['extra_lib_path1']])
560 if env.has_key('extra_bin_path') and env['extra_bin_path']:
561 # only the first one is needed (a scons bug?)
562 os.environ['PATH'] += os.pathsep + env['extra_bin_path']
563 env.PrependENVPath('PATH', env['extra_bin_path'])
564 # extra_inc_paths will be used later by intlenv etc
565 env.AppendUnique(CPPPATH = extra_inc_paths)
568 #----------------------------------------------------------
570 #----------------------------------------------------------
572 conf = Configure(env,
574 'CheckPkgConfig' : utils.checkPkgConfig,
575 'CheckPackage' : utils.checkPackage,
576 'CheckMkdirOneArg' : utils.checkMkdirOneArg,
577 'CheckSelectArgType' : utils.checkSelectArgType,
578 'CheckBoostLibraries' : utils.checkBoostLibraries,
579 'CheckCommand' : utils.checkCommand,
580 'CheckNSIS' : utils.checkNSIS,
581 'CheckCXXGlobalCstd' : utils.checkCXXGlobalCstd,
582 'CheckLC_MESSAGES' : utils.checkLC_MESSAGES,
583 'CheckIconvConst' : utils.checkIconvConst,
584 'CheckSizeOfWChar' : utils.checkSizeOfWChar,
585 'CheckDeclaration' : utils.checkDeclaration,
589 # When using msvc, windows.h is required
590 if use_vc and not conf.CheckCHeader('windows.h'):
591 print 'Windows.h is not found. Please install Windows Platform SDK.'
592 print 'Please check config.log for more information.'
595 # pkg-config? (if not, we use hard-coded options)
596 if conf.CheckPkgConfig('0.15.0'):
597 env['HAS_PKG_CONFIG'] = True
599 print 'pkg-config >= 0.1.50 is not found'
600 env['HAS_PKG_CONFIG'] = False
602 # zlib? This is required.
603 if (not use_vc and not conf.CheckLibWithHeader('z', 'zlib.h', 'C')) \
604 or (use_vc and not conf.CheckLibWithHeader('zdll', 'zlib.h', 'C')):
605 print 'Did not find zdll.lib or zlib.h, exiting!'
606 print 'Please check config.log for more information.'
608 if conf.CheckLib('iconv'):
609 env['ICONV_LIB'] = 'iconv'
610 elif conf.CheckLib('libiconv'):
611 env['ICONV_LIB'] = 'libiconv'
612 elif conf.CheckFunc('iconv_open'):
613 env['ICONV_LIB'] = None
615 print 'Did not find iconv or libiconv, exiting!'
616 print 'Please check config.log for more information.'
621 if conf.CheckLib('socket'):
622 socket_libs.append('socket')
623 # nsl is the network services library and provides a
624 # transport-level interface to networking services.
625 if conf.CheckLib('nsl'):
626 socket_libs.append('nsl')
628 # check available boost libs (since lyx1.4 does not use iostream)
630 for lib in ['signals', 'regex', 'filesystem', 'iostreams']:
631 if os.path.isdir(os.path.join(top_src_dir, 'boost', 'libs', lib)):
632 boost_libs.append(lib)
634 # check boost libraries
635 boost_opt = ARGUMENTS.get('boost', 'auto')
636 # check for system boost
637 lib_paths = env['LIBPATH'] + ['/usr/lib', '/usr/local/lib']
638 inc_paths = env['CPPPATH'] + ['/usr/include', '/usr/local/include']
639 # default to $BUILDDIR/libs (use None since this path will be added anyway)
641 # here I assume that all libraries are in the same directory
642 if boost_opt == 'included':
643 boost_libraries = ['included_boost_%s' % x for x in boost_libs]
644 included_boost = True
645 env['BOOST_INC_PATH'] = '$TOP_SRCDIR/boost'
646 elif boost_opt == 'auto':
647 res = conf.CheckBoostLibraries(boost_libs, lib_paths, inc_paths, boost_version, mode == 'debug')
648 # if not found, use local boost
650 boost_libraries = ['included_boost_%s' % x for x in boost_libs]
651 included_boost = True
652 env['BOOST_INC_PATH'] = '$TOP_SRCDIR/boost'
654 included_boost = False
655 (boost_libraries, boost_libpath, env['BOOST_INC_PATH']) = res
656 elif boost_opt == 'system':
657 res = conf.CheckBoostLibraries(boost_libs, lib_paths, inc_paths, boost_version, mode == 'debug')
659 print "Can not find system boost libraries with version %s " % boost_version
660 print "Please supply a path through extra_lib_path and try again."
661 print "Or use boost=included to use included boost libraries."
664 included_boost = False
665 (boost_libraries, boost_libpath, env['BOOST_INC_PATH']) = res
668 if boost_libpath is not None:
669 env.AppendUnique(LIBPATH = [boost_libpath])
672 env['ENABLE_NLS'] = env['nls']
674 if not env['ENABLE_NLS']:
676 included_gettext = False
678 # check gettext libraries
679 gettext_opt = ARGUMENTS.get('gettext', 'auto')
680 # check for system gettext
682 if gettext_opt in ['auto', 'system']:
683 if conf.CheckFunc('gettext'):
684 included_gettext = False
687 elif conf.CheckLib('intl'):
688 included_gettext = False
692 if gettext_opt == 'system':
693 print "Can not find system gettext library"
694 print "Please supply a path through extra_lib_path and try again."
695 print "Or use gettext=included to use included gettext libraries."
697 # now, auto and succ = false, or gettext=included
699 # we do not need to set LIBPATH now.
700 included_gettext = True
701 intl_libs = ['included_intl']
705 # check for msgfmt command
706 env['MSGFMT'] = conf.CheckCommand('msgfmt')
707 env['MSGMERGE'] = conf.CheckCommand('msgmerge')
708 env['XGETTEXT'] = conf.CheckCommand('xgettext')
709 env['MSGUNIQ'] = conf.CheckCommand('msguniq')
711 # if under windows, check the nsis compiler
712 if platform_name == 'win32':
713 env['NSIS'] = conf.CheckNSIS()
715 # cygwin packaging requires the binaries to be stripped
716 if platform_name == 'cygwin':
717 env['STRIP'] = conf.CheckCommand('strip')
720 # Customized builders
722 # install customized builders
723 env['BUILDERS']['substFile'] = Builder(action = utils.env_subst)
724 env['BUILDERS']['installTOC'] = Builder(action = utils.env_toc)
725 env['BUILDERS']['potfiles'] = Builder(action = utils.env_potfiles)
728 #----------------------------------------------------------
729 # Generating config.h
730 #----------------------------------------------------------
731 aspell_lib = 'aspell'
732 # assume that we use aspell, aspelld compiled for msvc
733 if platform_name == 'win32' and mode == 'debug' and use_vc:
734 aspell_lib = 'aspelld'
736 # check the existence of config.h
737 config_h = os.path.join(env.Dir('$BUILDDIR/src').path, 'config.h')
738 boost_config_h = os.path.join(env.Dir('$BUILDDIR/boost').path, 'config.h')
740 print "Creating %s..." % boost_config_h
742 utils.createConfigFile(conf,
743 config_file = boost_config_h,
744 config_pre = r'''/* boost/config.h. Generated by SCons. */
749 * This file is part of LyX, the document processor.
750 * Licence details can be found in the file COPYING.
752 * This is the compilation configuration file for LyX.
753 * It was generated by scon.
754 * You might want to change some of the defaults if something goes wrong
755 * during the compilation.
758 #ifndef _BOOST_CONFIG_H
759 #define _BOOST_CONFIG_H
762 ('ostream', 'HAVE_OSTREAM', 'cxx'),
763 ('locale', 'HAVE_LOCALE', 'cxx'),
764 ('sstream', 'HAVE_SSTREAM', 'cxx'),
765 #('newapis.h', 'HAVE_NEWAPIS_H', 'c'),
768 (env.has_key('assertions') and env['assertions'],
770 'Define if you want assertions to be enabled in the code'
774 ('wchar_t', 'HAVE_WCHAR_T', None),
778 #if defined(HAVE_OSTREAM) && defined(HAVE_LOCALE) && defined(HAVE_SSTREAM)
779 # define USE_BOOST_FORMAT 1
781 # define USE_BOOST_FORMAT 0
784 #if !defined(ENABLE_ASSERTIONS)
785 # define BOOST_DISABLE_ASSERTS 1
787 #define BOOST_ENABLE_ASSERT_HANDLER 1
789 #define BOOST_DISABLE_THREADS 1
790 #define BOOST_NO_WSTRING 1
793 # define BOOST_POSIX 1
794 # define BOOST_POSIX_API 1
795 # define BOOST_POSIX_PATH 1
798 #define BOOST_ALL_NO_LIB 1
800 #if defined(HAVE_NEWAPIS_H)
801 # define WANT_GETFILEATTRIBUTESEX_WRAPPER 1
805 * the FreeBSD libc uses UCS4, but libstdc++ has no proper wchar_t
806 * support compiled in:
807 * http://gcc.gnu.org/onlinedocs/libstdc++/faq/index.html#3_9
808 * And we are not interested at all what libc
809 * does: What we need is a 32bit wide wchar_t, and a libstdc++ that
810 * has the needed wchar_t support and uses UCS4. Whether it
811 * implements this with the help of libc, or whether it has own code
812 * does not matter for us, because we don't use libc directly (Georg)
814 #if defined(HAVE_WCHAR_T) && SIZEOF_WCHAR_T == 4 && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
822 print "\nGenerating %s..." % config_h
824 # AIKSAURUS_H_LOCATION
825 if (conf.CheckCXXHeader("Aiksaurus.h")):
826 aik_location = '<Aiksaurus.h>'
827 elif (conf.CheckCXXHeader("Aiksaurus/Aiksaurus.h")):
828 aik_location = '<Aiksaurus/Aiksaurus.h>'
832 # determine headers to use
833 spell_opt = ARGUMENTS.get('spell', 'auto')
834 env['USE_ASPELL'] = False
835 env['USE_PSPELL'] = False
836 env['USE_ISPELL'] = False
837 if spell_opt in ['auto', 'aspell'] and conf.CheckLib(aspell_lib):
838 spell_engine = 'USE_ASPELL'
839 elif spell_opt in ['auto', 'pspell'] and conf.CheckLib('pspell'):
840 spell_engine = 'USE_PSPELL'
841 elif spell_opt in ['auto', 'ispell'] and conf.CheckLib('ispell'):
842 spell_engine = 'USE_ISPELL'
846 if spell_engine is not None:
847 env[spell_engine] = True
849 if spell_opt == 'auto':
850 print "Warning: Can not locate any spell checker"
851 elif spell_opt != 'no':
852 print "Warning: Can not locate specified spell checker:", spell_opt
853 print 'Please check config.log for more information.'
856 # check arg types of select function
857 (select_arg1, select_arg234, select_arg5) = conf.CheckSelectArgType()
859 # check the size of wchar_t
860 sizeof_wchar_t = conf.CheckSizeOfWChar()
862 if sizeof_wchar_t == 0:
863 print 'Error: Can not determine the size of wchar_t.'
864 print 'Please check config.log for more information.'
868 # fill in the version info
869 env['VERSION_INFO'] = '''Configuration
871 Special build flags: %s
873 C Compiler flags: %s %s
875 C++ Compiler LyX flags: %s
876 C++ Compiler flags: %s %s
878 Linker user flags: %s
880 Builing directory: %s
881 Local library directory: %s
884 include search path: %s
890 ''' % (platform_name,
891 env.subst('$CCFLAGS'), env.subst('$CC'),
892 env.subst('$CPPFLAGS'), env.subst('$CFLAGS'),
893 env.subst('$CXX'), env.subst('$CXXFLAGS'),
894 env.subst('$CPPFLAGS'), env.subst('$CXXFLAGS'),
895 env.subst('$LINKFLAGS'), env.subst('$LINKFLAGS'),
896 env.subst('$BUILDDIR'), env.subst('$LOCALLIBPATH'),
897 str(env['LIBPATH']), str(boost_libraries),
899 frontend, packaging_method,
900 prefix, env['LYX_DIR'])
904 result = utils.createConfigFile(conf,
905 config_file = config_h,
906 config_pre = r'''/* config.h. Generated by SCons. */
911 * This file is part of LyX, the document processor.
912 * Licence details can be found in the file COPYING.
914 * This is the compilation configuration file for LyX.
915 * It was generated by scon.
916 * You might want to change some of the defaults if something goes wrong
917 * during the compilation.
924 ('io.h', 'HAVE_IO_H', 'c'),
925 ('limits.h', 'HAVE_LIMITS_H', 'c'),
926 ('locale.h', 'HAVE_LOCALE_H', 'c'),
927 ('process.h', 'HAVE_PROCESS_H', 'c'),
928 ('stdlib.h', 'HAVE_STDLIB_H', 'c'),
929 ('sys/stat.h', 'HAVE_SYS_STAT_H', 'c'),
930 ('sys/time.h', 'HAVE_SYS_TIME_H', 'c'),
931 ('sys/types.h', 'HAVE_SYS_TYPES_H', 'c'),
932 ('sys/utime.h', 'HAVE_SYS_UTIME_H', 'c'),
933 ('sys/socket.h', 'HAVE_SYS_SOCKET_H', 'c'),
934 ('unistd.h', 'HAVE_UNISTD_H', 'c'),
935 ('utime.h', 'HAVE_UTIME_H', 'c'),
936 ('direct.h', 'HAVE_DIRECT_H', 'c'),
937 ('istream', 'HAVE_ISTREAM', 'cxx'),
938 ('ios', 'HAVE_IOS', 'cxx'),
941 ('open', 'HAVE_OPEN', None),
942 ('chmod', 'HAVE_CHMOD', None),
943 ('close', 'HAVE_CLOSE', None),
944 ('popen', 'HAVE_POPEN', None),
945 ('pclose', 'HAVE_PCLOSE', None),
946 ('_open', 'HAVE__OPEN', None),
947 ('_close', 'HAVE__CLOSE', None),
948 ('_popen', 'HAVE__POPEN', None),
949 ('_pclose', 'HAVE__PCLOSE', None),
950 ('getpid', 'HAVE_GETPID', None),
951 ('_getpid', 'HAVE__GETPID', None),
952 ('mkdir', 'HAVE_MKDIR', None),
953 ('_mkdir', 'HAVE__MKDIR', None),
954 ('mktemp', 'HAVE_MKTEMP', None),
955 ('mkstemp', 'HAVE_MKSTEMP', None),
956 ('strerror', 'HAVE_STRERROR', None),
957 ('getcwd', 'HAVE_GETCWD', None),
958 ('setenv', 'HAVE_SETENV', None),
959 ('putenv', 'HAVE_PUTENV', None),
960 ('fcntl', 'HAVE_FCNTL', None),
961 ('mkfifo', 'HAVE_MKFIFO', None),
964 ('mkstemp', 'HAVE_DECL_MKSTEMP', ['unistd.h', 'stdlib.h']),
967 ('std::istreambuf_iterator<std::istream>', 'HAVE_DECL_ISTREAMBUF_ITERATOR',
968 '#include <streambuf>\n#include <istream>'),
969 ('wchar_t', 'HAVE_WCHAR_T', None),
970 ('mode_t', 'HAVE_MODE_T', "#include <sys/types.h>"),
973 ('gdi32', 'HAVE_LIBGDI32'),
974 (('Aiksaurus', 'libAiksaurus'), 'HAVE_LIBAIKSAURUS', 'AIKSAURUS_LIB'),
977 (conf.CheckType('pid_t', includes='#include <sys/types.h>'),
979 'Define is sys/types.h does not have pid_t',
983 (conf.CheckCXXGlobalCstd(),
985 'Define if your C++ compiler puts C library functions in the global namespace'
987 (conf.CheckMkdirOneArg(),
988 'MKDIR_TAKES_ONE_ARG',
989 'Define if mkdir takes only one argument.'
991 (conf.CheckIconvConst(),
993 'Define as const if the declaration of iconv() needs const.',
994 '#define ICONV_CONST const',
995 '#define ICONV_CONST',
997 (conf.CheckLC_MESSAGES(),
999 'Define if your <locale.h> file defines LC_MESSAGES.'
1001 (devel_version, 'DEVEL_VERSION', 'Whether or not a development version'),
1004 "Define to 1 if translation of program messages to the user's native anguage is requested.",
1006 (env['nls'] and not included_gettext,
1008 'Define to 1 if using system gettext library'
1010 (env.has_key('concept_checks') and env['concept_checks'],
1011 '_GLIBCXX_CONCEPT_CHECKS',
1012 'libstdc++ concept checking'
1014 (env.has_key('stdlib_debug') and env['stdlib_debug'],
1016 'libstdc++ debug mode'
1018 (env.has_key('stdlib_debug') and env['stdlib_debug'],
1019 '_GLIBCXX_DEBUG_PEDANTIC',
1020 'libstdc++ pedantic debug mode'
1022 (os.name != 'nt', 'BOOST_POSIX',
1023 'Indicates to boost < 1.34 which API to use (posix or windows).'
1025 (os.name != 'nt', 'BOOST_POSIX_API',
1026 'Indicates to boost 1.34 which API to use (posix or windows).'
1028 (os.name != 'nt', 'BOOST_POSIX_PATH',
1029 'Indicates to boost 1.34 which path style to use (posix or windows).'
1031 (spell_engine is not None, spell_engine,
1032 'Spell engine to use'
1034 # we need to know the byte order for unicode conversions
1035 (sys.byteorder == 'big', 'WORDS_BIGENDIAN',
1036 'Define to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX).'
1040 ('#define PACKAGE "%s%s"' % (package, program_suffix),
1042 ('#define PACKAGE_BUGREPORT "%s"' % package_bugreport,
1043 'Define to the address where bug reports for this package should be sent.'),
1044 ('#define PACKAGE_NAME "%s"' % package_name,
1045 'Define to the full name of this package.'),
1046 ('#define PACKAGE_STRING "%s"' % package_string,
1047 'Define to the full name and version of this package.'),
1048 ('#define PACKAGE_TARNAME "%s"' % package_tarname,
1049 'Define to the one symbol short name of this package.'),
1050 ('#define PACKAGE_VERSION "%s"' % package_version,
1051 'Define to the version of this package.'),
1052 ('#define VERSION_INFO "%s"' % env['VERSION_INFO'].replace('\n', '\\n'),
1053 'Full version info'),
1054 ('#define LYX_DATE "%s"' % lyx_date,
1056 ('#define BOOST_ALL_NO_LIB 1',
1057 'disable automatic linking of boost libraries.'),
1058 ('#define USE_%s_PACKAGING 1' % packaging_method.upper(),
1059 'Packaging method'),
1060 ('#define AIKSAURUS_H_LOCATION ' + aik_location,
1061 'Aiksaurus include file'),
1062 ('#define SELECT_TYPE_ARG1 %s' % select_arg1,
1063 "Define to the type of arg 1 for `select'."),
1064 ('#define SELECT_TYPE_ARG234 %s' % select_arg234,
1065 "Define to the type of arg 2, 3, 4 for `select'."),
1066 ('#define SELECT_TYPE_ARG5 %s' % select_arg5,
1067 "Define to the type of arg 5 for `select'."),
1068 ('#define SIZEOF_WCHAR_T %d' % sizeof_wchar_t,
1069 'Define to be the size of type wchar_t'),
1071 config_post = '''/************************************************************
1072 ** You should not need to change anything beyond this point */
1074 #ifndef HAVE_STRERROR
1075 #if defined(__cplusplus)
1078 char * strerror(int n);
1081 #include <../boost/config.h>
1087 # these keys are needed in env
1088 for key in ['USE_ASPELL', 'USE_PSPELL', 'USE_ISPELL', 'HAVE_FCNTL',\
1089 'HAVE_LIBGDI32', 'HAVE_LIBAIKSAURUS', 'AIKSAURUS_LIB']:
1090 # USE_ASPELL etc does not go through result
1091 if result.has_key(key):
1092 env[key] = result[key]
1095 # if nls=yes and gettext=included, create intl/config.h
1096 # intl/libintl.h etc
1098 intl_config_h = os.path.join(env.Dir('$BUILDDIR/intl').path, 'config.h')
1099 if env['nls'] and included_gettext:
1101 print "Creating %s..." % intl_config_h
1103 # create intl/config.h
1104 result = utils.createConfigFile(conf,
1105 config_file = intl_config_h,
1106 config_pre = r'''/* intl/config.h. Generated by SCons. */
1111 * This file is part of LyX, the document processor.
1112 * Licence details can be found in the file COPYING.
1114 * This is the compilation configuration file for LyX.
1115 * It was generated by scon.
1116 * You might want to change some of the defaults if something goes wrong
1117 * during the compilation.
1120 #ifndef _INTL_CONFIG_H
1121 #define _INTL_CONFIG_H
1124 ('unistd.h', 'HAVE_UNISTD_H', 'c'),
1125 ('inttypes.h', 'HAVE_INTTYPES_H', 'c'),
1126 ('string.h', 'HAVE_STRING_H', 'c'),
1127 ('strings.h', 'HAVE_STRINGS_H', 'c'),
1128 ('argz.h', 'HAVE_ARGZ_H', 'c'),
1129 ('limits.h', 'HAVE_LIMITS_H', 'c'),
1130 ('alloca.h', 'HAVE_ALLOCA_H', 'c'),
1131 ('stddef.h', 'HAVE_STDDEF_H', 'c'),
1132 ('stdint.h', 'HAVE_STDINT_H', 'c'),
1133 ('sys/param.h', 'HAVE_SYS_PARAM_H', 'c'),
1136 ('getcwd', 'HAVE_GETCWD', None),
1137 ('stpcpy', 'HAVE_STPCPY', None),
1138 ('strcasecmp', 'HAVE_STRCASECMP', None),
1139 ('strdup', 'HAVE_STRDUP', None),
1140 ('strtoul', 'HAVE_STRTOUL', None),
1141 ('alloca', 'HAVE_ALLOCA', None),
1142 ('__fsetlocking', 'HAVE___FSETLOCKING', None),
1143 ('mempcpy', 'HAVE_MEMPCPY', None),
1144 ('__argz_count', 'HAVE___ARGZ_COUNT', None),
1145 ('__argz_next', 'HAVE___ARGZ_NEXT', None),
1146 ('__argz_stringify', 'HAVE___ARGZ_STRINGIFY', None),
1147 ('setlocale', 'HAVE_SETLOCALE', None),
1148 ('tsearch', 'HAVE_TSEARCH', None),
1149 ('getegid', 'HAVE_GETEGID', None),
1150 ('getgid', 'HAVE_GETGID', None),
1151 ('getuid', 'HAVE_GETUID', None),
1152 ('wcslen', 'HAVE_WCSLEN', None),
1153 ('asprintf', 'HAVE_ASPRINTF', None),
1154 ('wprintf', 'HAVE_WPRINTF', None),
1155 ('snprintf', 'HAVE_SNPRINTF', None),
1156 ('printf', 'HAVE_POSIX_PRINTF', None),
1157 ('fcntl', 'HAVE_FCNTL', None),
1160 ('intmax_t', 'HAVE_INTMAX_T', None),
1161 ('long double', 'HAVE_LONG_DOUBLE', None),
1162 ('long long', 'HAVE_LONG_LONG', None),
1163 ('wchar_t', 'HAVE_WCHAR_T', None),
1164 ('wint_t', 'HAVE_WINT_T', None),
1165 ('uintmax_t', 'HAVE_INTTYPES_H_WITH_UINTMAX', '#include <inttypes.h>'),
1166 ('uintmax_t', 'HAVE_STDINT_H_WITH_UINTMAX', '#include <stdint.h>'),
1172 (conf.CheckLC_MESSAGES(),
1174 'Define if your <locale.h> file defines LC_MESSAGES.'
1176 (conf.CheckIconvConst(),
1178 'Define as const if the declaration of iconv() needs const.',
1179 '#define ICONV_CONST const',
1180 '#define ICONV_CONST',
1182 (conf.CheckType('intmax_t', includes='#include <stdint.h>') or \
1183 conf.CheckType('intmax_t', includes='#include <inttypes.h>'),
1185 "Define to 1 if you have the `intmax_t' type."
1187 (env.has_key('nls') and env['nls'],
1189 "Define to 1 if translation of program messages to the user's native anguage is requested.",
1193 ('#define HAVE_ICONV 1', 'Define if iconv or libiconv is found'),
1194 ('#define SIZEOF_WCHAR_T %d' % sizeof_wchar_t,
1195 'Define to be the size of type wchar_t'),
1197 config_post = '#endif'
1200 # these keys are needed in env
1201 for key in ['HAVE_ASPRINTF', 'HAVE_WPRINTF', 'HAVE_SNPRINTF', \
1202 'HAVE_POSIX_PRINTF', 'HAVE_LIBC']:
1203 # USE_ASPELL etc does not go through result
1204 if result.has_key(key):
1205 env[key] = result[key]
1208 # this looks misplaced, but intl/libintl.h is needed by src/message.C
1209 if env['nls'] and included_gettext:
1210 # libgnuintl.h.in => libintl.h
1211 env.Depends('$TOP_SRCDIR/intl/libintl.h', '$BUILDDIR/intl/config.h')
1212 env.substFile('$BUILDDIR/intl/libintl.h', '$TOP_SRCDIR/intl/libgnuintl.h.in')
1213 env.Command('$BUILDDIR/intl/libgnuintl.h', '$BUILDDIR/intl/libintl.h',
1214 [Copy('$TARGET', '$SOURCE')])
1217 # Finish auto-configuration
1220 #----------------------------------------------------------
1221 # Now set up our build process accordingly
1222 #----------------------------------------------------------
1224 if env['ICONV_LIB'] is None:
1227 system_libs = [env['ICONV_LIB']]
1228 if platform_name in ['win32', 'cygwin']:
1229 # the final link step needs stdc++ to succeed under mingw
1230 # FIXME: shouldn't g++ automatically link to stdc++?
1232 system_libs += ['ole32', 'shlwapi', 'shell32', 'advapi32', 'zdll']
1234 system_libs += ['shlwapi', 'stdc++', 'z']
1235 elif platform_name == 'cygwin' and env['X11']:
1236 system_libs += ['GL', 'Xmu', 'Xi', 'Xrender', 'Xrandr',
1237 'Xcursor', 'Xft', 'freetype', 'fontconfig', 'Xext', 'X11', 'SM', 'ICE',
1238 'resolv', 'pthread', 'z']
1240 system_libs += ['z']
1243 ('HAVE_LIBGDI32', 'gdi32'),
1244 ('HAVE_LIBAIKSAURUS', env['AIKSAURUS_LIB']),
1245 ('USE_ASPELL', aspell_lib),
1246 ('USE_ISPELL', 'ispell'),
1247 ('USE_PSPELL', 'pspell'),
1252 system_libs.append(lib[1])
1255 # Build parameters CPPPATH etc
1258 env.AppendUnique(LIBPATH = ['/usr/X11R6/lib'])
1261 # boost: for boost header files
1262 # BUILDDIR/src: for config.h
1263 # TOP_SRCDIR/src: for support/* etc
1265 env['CPPPATH'] += ['$BUILDDIR/src', '$TOP_SRCDIR/src']
1267 # Separating boost directories from CPPPATH stops scons from building
1268 # the dependency tree for boost header files, and effectively reduce
1269 # the null build time of lyx from 29s to 16s. Since lyx may tweak local
1270 # boost headers, the following is not 100% safe.
1271 # env.AppendUnique(CPPPATH = ['$BOOST_INC_PATH'])
1272 env.PrependUnique(CCFLAGS = ['$INCPREFIX$BOOST_INC_PATH'])
1274 # for intl/config.h, intl/libintl.h and intl/libgnuintl.h
1275 if env['nls'] and included_gettext:
1276 env['CPPPATH'].append('$BUILDDIR/intl')
1280 # A Link script for cygwin see
1281 # http://www.cygwin.com/ml/cygwin/2004-09/msg01101.html
1282 # http://www.cygwin.com/ml/cygwin-apps/2004-09/msg00309.html
1285 if platform_name == 'cygwin':
1286 ld_script_path = '/tmp'
1287 ld_script = utils.installCygwinLDScript(ld_script_path)
1288 env.AppendUnique(LINKFLAGS = ['-Wl,--enable-runtime-pseudo-reloc',
1289 '-Wl,--script,%s' % ld_script, '-Wl,-s'])
1292 #---------------------------------------------------------
1293 # Frontend related variables (QTDIR etc)
1294 #---------------------------------------------------------
1297 # create a separate environment so that other files do not have
1298 # to be built with all the include directories etc
1300 if frontend == 'qt4':
1301 frontend_env = env.Copy()
1303 # handle qt related user specified paths
1304 # set environment so that moc etc can be found even if its path is not set properly
1305 if frontend_env.has_key('qt_dir') and frontend_env['qt_dir']:
1306 frontend_env['QTDIR'] = frontend_env['qt_dir']
1307 if os.path.isdir(os.path.join(frontend_env['qt_dir'], 'bin')):
1308 os.environ['PATH'] += os.pathsep + os.path.join(frontend_env['qt_dir'], 'bin')
1309 frontend_env.PrependENVPath('PATH', os.path.join(frontend_env['qt_dir'], 'bin'))
1310 if os.path.isdir(os.path.join(frontend_env['qt_dir'], 'lib')):
1311 frontend_env.PrependENVPath('PKG_CONFIG_PATH', os.path.join(frontend_env['qt_dir'], 'lib'))
1313 # if separate qt_lib_path is given
1314 if frontend_env.has_key('qt_lib_path') and frontend_env['qt_lib_path']:
1315 qt_lib_path = frontend_env.subst('$qt_lib_path')
1316 frontend_env.AppendUnique(LIBPATH = [qt_lib_path])
1317 frontend_env.PrependENVPath('PKG_CONFIG_PATH', qt_lib_path)
1321 # if separate qt_inc_path is given
1322 if frontend_env.has_key('qt_inc_path') and frontend_env['qt_inc_path']:
1323 qt_inc_path = frontend_env['qt_inc_path']
1327 # local qt4 toolset from
1328 # http://www.iua.upf.es/~dgarcia/Codders/sconstools.html
1330 # NOTE: I have to patch qt4.py since it does not automatically
1331 # process .C file!!! (add to cxx_suffixes )
1333 frontend_env.Tool('qt4', [scons_dir])
1334 frontend_env['QT_AUTOSCAN'] = 0
1335 frontend_env['QT4_AUTOSCAN'] = 0
1336 frontend_env['QT4_UICDECLFLAGS'] = '-tr lyx::qt_'
1338 if qt_lib_path is None:
1339 qt_lib_path = os.path.join(frontend_env.subst('$QTDIR'), 'lib')
1340 if qt_inc_path is None:
1341 qt_inc_path = os.path.join(frontend_env.subst('$QTDIR'), 'include')
1344 conf = Configure(frontend_env,
1346 'CheckPackage' : utils.checkPackage,
1347 'CheckCommand' : utils.checkCommand,
1352 # first: try pkg_config
1353 if frontend_env['HAS_PKG_CONFIG']:
1354 succ = conf.CheckPackage('QtCore') or conf.CheckPackage('QtCore4')
1355 # FIXME: use pkg_config information?
1356 #frontend_env['QT4_PKG_CONFIG'] = succ
1357 # second: try to link to it
1359 # Under linux, I can test the following perfectly
1360 # Under windows, lib names need to passed as libXXX4.a ...
1361 if platform_name == 'win32':
1362 succ = conf.CheckLibWithHeader('QtCore4', 'QtGui/QApplication', 'c++', 'QApplication qapp();')
1364 succ = conf.CheckLibWithHeader('QtCore', 'QtGui/QApplication', 'c++', 'QApplication qapp();')
1365 # still can not find it
1367 print 'Did not find qt libraries, exiting!'
1368 print 'Please check config.log for more information.'
1371 # Now, determine the correct suffix:
1372 qt_libs = ['QtCore', 'QtGui']
1373 if platform_name == 'win32':
1374 if mode == 'debug' and use_vc and \
1375 conf.CheckLibWithHeader('QtCored4', 'QtGui/QApplication', 'c++', 'QApplication qapp();'):
1376 qt_lib_suffix = 'd4'
1377 use_qt_debug_libs = True
1380 use_qt_debug_libs = False
1382 if mode == 'debug' and conf.CheckLibWithHeader('QtCore_debug', 'QtGui/QApplication', 'c++', 'QApplication qapp();'):
1383 qt_lib_suffix = '_debug'
1384 use_qt_debug_libs = True
1387 use_qt_debug_libs = False
1388 frontend_env.EnableQt4Modules(qt_libs, debug = (mode == 'debug' and use_qt_debug_libs))
1389 frontend_libs = [x + qt_lib_suffix for x in qt_libs]
1390 qtcore_lib = ['QtCore' + qt_lib_suffix]
1392 # check uic and moc commands for qt frontends
1393 if conf.CheckCommand('uic') == None or conf.CheckCommand('moc') == None:
1394 print 'uic or moc command is not found for frontend', frontend
1397 # now, if msvc2005 is used, we will need to embed lyx.exe.manifest to lyx.exe
1398 # NOTE: previously, lyx.exe had to be linked to some qt manifest to work.
1399 # For some unknown changes in msvc or qt, this is no longer needed.
1401 frontend_env['LINKCOM'] = [frontend_env['LINKCOM'], \
1402 'mt.exe /MANIFEST %s /outputresource:$TARGET;1' % \
1403 env.File('$BUILDDIR/lyx.exe.manifest').path]
1405 frontend_env = conf.Finish()
1412 print env['VERSION_INFO']
1415 # Mingw command line may be too short for our link usage,
1416 # Here we use a trick from scons wiki
1417 # http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/LongCmdLinesOnWin32
1419 # I also would like to add logging (commands only) capacity to the
1421 logfile = env.get('logfile', default_log_file)
1422 if logfile != '' or platform_name == 'win32':
1424 utils.setLoggedSpawn(env, logfile, longarg = (platform_name == 'win32'),
1425 info = '''# This is a log of commands used by scons to build lyx
1429 ''' % (time.asctime(), ' '.join(sys.argv),
1430 env['VERSION_INFO'].replace('\n','\n# ')) )
1435 # -h will print out help info
1436 Help(opts.GenerateHelpText(env))
1440 #----------------------------------------------------------
1442 #----------------------------------------------------------
1443 # this has been the source of problems on some platforms...
1444 # I find that I need to supply it with full path name
1445 env.SConsignFile(os.path.join(Dir(env['BUILDDIR']).abspath, '.sconsign'))
1446 # this usage needs further investigation.
1447 #env.CacheDir('%s/Cache/%s' % (env['BUILDDIR'], frontend))
1448 env.BuildDir('$BUILDDIR/boost', '$TOP_SRCDIR/boost/libs', duplicate = 0)
1449 env.BuildDir('$BUILDDIR/intl', '$TOP_SRCDIR/intl', duplicate = 0)
1450 env.BuildDir('$BUILDDIR/src', '$TOP_SRCDIR/src', duplicate = 0)
1451 frontend_env.BuildDir('$BUILDDIR/src', '$TOP_SRCDIR/src', duplicate = 0)
1453 print "Building all targets recursively"
1455 def libExists(libname):
1456 ''' Check whether or not lib $LOCALLIBNAME/libname already exists'''
1457 return os.path.isfile(File(env.subst('$LOCALLIBPATH/${LIBPREFIX}%s$LIBSUFFIX'%libname)).abspath)
1460 if (included_boost and not libExists('included_boost_regex')) or 'boost' in BUILD_TARGETS:
1464 for lib in boost_libs:
1465 boostlib = env.StaticLibrary(
1466 target = '$LOCALLIBPATH/included_boost_%s' % lib,
1467 source = ['$BUILDDIR/boost/%s/src/%s' % (lib, x) for x in eval('boost_libs_%s_src_files' % lib)],
1468 # do not use global CPPPATH because src/config.h will mess up with boost/config.h
1469 CPPPATH = ['$BUILDDIR/boost'] + extra_inc_paths,
1470 CCFLAGS = ['$CCFLAGS', '$INCPREFIX$TOP_SRCDIR/boost', '-DBOOST_USER_CONFIG="<config.h>"']
1472 Alias('boost', boostlib)
1475 if (included_gettext and not libExists('included_intl')) or 'intl' in BUILD_TARGETS:
1480 r'-DLOCALEDIR=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1481 r'-DLOCALE_ALIAS_PATH=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1482 r'-DLIBDIR=\"' + env['TOP_SRCDIR'].replace('\\', '\\\\') + r'/lib\"',
1484 '-DENABLE_RELOCATABLE=1',
1486 r'-DINSTALLDIR=\"' + prefix.replace('\\', '\\\\') + r'/lib\"',
1488 '-Dset_relocation_prefix=libintl_set_relocation_prefix',
1489 '-Drelocate=libintl_relocate',
1490 '-DDEPENDS_ON_LIBICONV=1',
1494 INTL_CCFLAGS.extend(['/Dinline#', '/D__attribute__(x)#', '/Duintmax_t=UINT_MAX'])
1496 intl = env.StaticLibrary(
1497 target = '$LOCALLIBPATH/included_intl',
1499 CCFLAGS = INTL_CCFLAGS,
1500 # do not use global CPPPATH because src/config.h will mess up with intl/config.h
1501 CPPPATH = ['$BUILDDIR/intl'] + extra_inc_paths,
1502 source = ['$BUILDDIR/intl/%s' % x for x in intl_files]
1508 # Now, src code under src/
1513 frontend_env.Depends('$BUILDDIR/src/support/Package.cpp', '$BUILDDIR/src/config.h')
1514 Package_cpp = env.substFile('$BUILDDIR/src/support/Package.cpp', '$TOP_SRCDIR/src/support/Package.cpp.in')
1516 support = frontend_env.StaticLibrary(
1517 target = '$LOCALLIBPATH/support',
1518 source = ['$BUILDDIR/src/support/%s' % x for x in src_support_files] + Package_cpp + \
1519 ['$BUILDDIR/src/support/minizip/%s' % x for x in src_support_minizip_files],
1523 '-DQT_CLEAN_NAMESPACE',
1528 CPPPATH = ['$CPPPATH', '$TOP_SRCDIR/src/support/minizip']
1530 Alias('support', support)
1536 mathed = env.StaticLibrary(
1537 target = '$LOCALLIBPATH/mathed',
1538 source = ['$BUILDDIR/src/mathed/%s' % x for x in src_mathed_files]
1540 Alias('mathed', mathed)
1546 insets = env.StaticLibrary(
1547 target = '$LOCALLIBPATH/insets',
1548 source = ['$BUILDDIR/src/insets/%s' % x for x in src_insets_files]
1550 Alias('insets', insets)
1556 frontends = env.StaticLibrary(
1557 target = '$LOCALLIBPATH/frontends',
1558 source = ['$BUILDDIR/src/frontends/%s' % x for x in src_frontends_files]
1560 Alias('frontends', frontends)
1566 graphics = env.StaticLibrary(
1567 target = '$LOCALLIBPATH/graphics',
1568 source = ['$BUILDDIR/src/graphics/%s' % x for x in src_graphics_files]
1570 Alias('graphics', graphics)
1574 # src/frontends/controllers
1576 controllers = env.StaticLibrary(
1577 target = '$LOCALLIBPATH/controllers',
1578 source = ['$BUILDDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files]
1580 Alias('controllers', controllers)
1586 frontend_env['QT4_MOCHPREFIX'] = ''
1587 frontend_env['QT4_MOCHSUFFIX'] = '_moc.cpp'
1589 # tells scons how to get these moced files, although not all moced files are needed
1590 # (or are actually generated).
1591 qt4_moced_files = [frontend_env.Moc4('$BUILDDIR/src/frontends/qt4/%s' % x)
1592 for x in src_frontends_qt4_header_files ]
1593 resources = [frontend_env.Uic4('$BUILDDIR/src/frontends/qt4/ui/%s' % x.split('.')[0])
1594 for x in src_frontends_qt4_ui_files]
1597 # moc qt4_moc_files, the moced files are included in the original files
1599 qt4 = frontend_env.StaticLibrary(
1600 target = '$LOCALLIBPATH/qt4',
1601 source = ['$BUILDDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_files],
1605 '$BUILDDIR/src/images',
1606 '$BUILDDIR/src/frontends',
1607 '$BUILDDIR/src/frontends/qt4',
1608 '$BUILDDIR/src/frontends/qt4/ui',
1609 '$BUILDDIR/src/frontends/controllers'
1614 '-DQT_CLEAN_NAMESPACE',
1626 if env['HAVE_FCNTL']:
1627 client = frontend_env.Program(
1628 target = '$BUILDDIR/src/client/lyxclient',
1629 LIBS = ['support'] + intl_libs + system_libs +
1630 socket_libs + boost_libraries + qtcore_lib,
1631 source = ['$BUILDDIR/src/client/%s' % x for x in src_client_files] + \
1632 utils.createResFromIcon(frontend_env, 'lyx_32x32.ico', '$LOCALLIBPATH/client.rc')
1634 Alias('client', frontend_env.Command(os.path.join('$BUILDDIR', os.path.split(str(client[0]))[1]),
1635 client, [Copy('$TARGET', '$SOURCE')]))
1638 Alias('client', client)
1644 for file in src_tex2lyx_copied_files + src_tex2lyx_copied_header_files:
1645 frontend_env.Command('$BUILDDIR/src/tex2lyx/'+file, '$TOP_SRCDIR/src/'+file,
1646 [Copy('$TARGET', '$SOURCE')])
1648 tex2lyx = frontend_env.Program(
1649 target = '$BUILDDIR/src/tex2lyx/tex2lyx',
1650 LIBS = ['support'] + boost_libraries + intl_libs + system_libs + qtcore_lib,
1651 source = ['$BUILDDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_files + src_tex2lyx_copied_files] + \
1652 utils.createResFromIcon(frontend_env, 'lyx_32x32.ico', '$LOCALLIBPATH/tex2lyx.rc'),
1653 CPPPATH = ['$BUILDDIR/src/tex2lyx', '$CPPPATH'],
1654 LIBPATH = ['#$LOCALLIBPATH', '$LIBPATH'],
1656 Alias('tex2lyx', frontend_env.Command(os.path.join('$BUILDDIR', os.path.split(str(tex2lyx[0]))[1]),
1657 tex2lyx, [Copy('$TARGET', '$SOURCE')]))
1658 Alias('tex2lyx', tex2lyx)
1664 if env.has_key('USE_ASPELL') and env['USE_ASPELL']:
1665 src_post_files.append('ASpell.cpp')
1666 elif env.has_key('USE_PSPELL') and env['USE_PSPELL']:
1667 src_post_files.append('PSpell.cpp')
1668 elif env.has_key('USE_ISPELL') and env['USE_ISPELL']:
1669 src_post_files.append('ISpell.cpp')
1671 # msvc requires at least one source file with main()
1672 # so I exclude main.cpp from lyxbase
1673 lyxbase_pre = env.StaticLibrary(
1674 target = '$LOCALLIBPATH/lyxbase_pre',
1675 source = ['$BUILDDIR/src/%s' % x for x in src_pre_files]
1677 lyxbase_post = env.StaticLibrary(
1678 target = '$LOCALLIBPATH/lyxbase_post',
1679 source = ["$BUILDDIR/src/%s" % x for x in src_post_files]
1681 Alias('lyxbase', lyxbase_pre)
1682 Alias('lyxbase', lyxbase_post)
1686 # Build lyx with given frontend
1688 lyx = frontend_env.Program(
1689 target = '$BUILDDIR/lyx',
1690 source = ['$BUILDDIR/src/main.cpp'] + \
1691 utils.createResFromIcon(frontend_env, 'lyx_32x32.ico', '$LOCALLIBPATH/lyx.rc'),
1712 if use_vc and 'msvs_projects' in BUILD_TARGETS:
1713 def build_project(target, full_target = None,
1714 src = [], inc = [], res = []):
1715 ''' build mavs project files
1716 target: alias (correspond to directory name)
1717 full_target: full path/filename of the target
1722 For non-debug-able targets like static libraries, target (alias) is
1723 enough to build the target. For executable targets, msvs need to know
1724 the full path to start debug them.
1727 if full_target is None:
1728 build_target = target
1730 build_target = full_target
1732 proj = env.MSVSProject(
1733 target = target + env['MSVSPROJECTSUFFIX'],
1734 # this allows easy access to header files (along with source)
1735 srcs = [env.subst(x) for x in src + inc],
1736 incs = [env.subst('$TOP_SRCDIR/src/config.h')],
1737 localincs = [env.subst(x) for x in inc],
1738 resources = [env.subst(x) for x in res],
1739 buildtarget = build_target,
1743 Alias('msvs_projects', proj)
1745 build_project('client', src = ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_files],
1746 inc = ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_header_files],
1747 full_target = File(env.subst('$BUILDDIR/src/client/lyxclient$PROGSUFFIX')).abspath)
1749 build_project('tex2lyx', src = ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_files],
1750 inc = ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_header_files],
1751 full_target = File(env.subst('$BUILDDIR/src/tex2lyx/tex2lyx$PROGSUFFIX')).abspath)
1753 build_project('lyx',
1754 src = ['$TOP_SRCDIR/src/%s' % x for x in src_pre_files + src_post_files + ['version.cpp']] + \
1755 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_files + ['Package.cpp'] ] + \
1756 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_files] + \
1757 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_files] + \
1758 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_files] + \
1759 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_files] + \
1760 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files] + \
1761 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_files],
1762 inc = ['$TOP_SRCDIR/src/%s' % x for x in src_header_files] + \
1763 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files] + \
1764 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_header_files] + \
1765 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files] + \
1766 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files] + \
1767 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files] + \
1768 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files] + \
1769 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_header_files],
1770 res = ['$TOP_SRCDIR/src/frontends/qt4/ui/%s' % x for x in src_frontends_qt4_ui_files],
1771 full_target = File(env.subst('$BUILDDIR/lyx$PROGSUFFIX')).abspath)
1774 if 'update_po' in BUILD_TARGETS:
1778 print 'Updating po/*.po files...'
1780 # whether or not update po files
1781 if not env['XGETTEXT'] or not env['MSGMERGE'] or not env['MSGUNIQ']:
1782 print 'xgettext or msgmerge does not exist. Cannot merge po files'
1784 # rebuild POTFILES.in
1785 POTFILES_in = env.potfiles('$TOP_SRCDIR/po/POTFILES.in',
1786 ['$TOP_SRCDIR/src/%s' % x for x in src_header_files + src_pre_files + src_post_files + \
1787 src_extra_src_files] + \
1788 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files + src_support_files + \
1789 src_support_extra_header_files + src_support_extra_src_files] + \
1790 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_header_files + src_mathed_files] + \
1791 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files + src_insets_files] + \
1792 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files + src_frontends_files] + \
1793 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files + src_graphics_files] + \
1794 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files + src_frontends_controllers_files] + \
1795 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_header_files + src_frontends_qt4_files + src_frontends_qt4_moc_files] + \
1796 ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_header_files + src_client_files ] + \
1797 ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_header_files + src_tex2lyx_files ]
1799 Alias('update_po', POTFILES_in)
1800 # build language_l10n.pot, ui_l10n.pot, layouts_l10n.pot, qt4_l10n.pot, external_l10n
1801 # and combine them to lyx.po
1802 env['LYX_POT'] = 'python $TOP_SRCDIR/po/lyx_pot.py'
1803 lyx_po = env.Command('$BUILDDIR/po/lyx.po',
1804 env.Command('$BUILDDIR/po/all.po',
1805 [env.Command('$BUILDDIR/po/qt4_l10n.pot',
1806 ['$TOP_SRCDIR/src/frontends/qt4/ui/%s' % x for x in src_frontends_qt4_ui_files],
1807 '$LYX_POT -b $TOP_SRCDIR -t qt4 -o $TARGET $SOURCES'),
1808 env.Command('$BUILDDIR/po/layouts_l10n.pot',
1809 ['$TOP_SRCDIR/lib/layouts/%s' % x for x in lib_layouts_files + lib_layouts_inc_files],
1810 '$LYX_POT -b $TOP_SRCDIR -t layouts -o $TARGET $SOURCES'),
1811 env.Command('$BUILDDIR/po/languages_l10n.pot', '$TOP_SRCDIR/lib/languages',
1812 '$LYX_POT -b $TOP_SRCDIR -t languages -o $TARGET $SOURCES'),
1813 env.Command('$BUILDDIR/po/ui_l10n.pot',
1814 ['$TOP_SRCDIR/lib/ui/%s' % x for x in lib_ui_files],
1815 '$LYX_POT -b $TOP_SRCDIR -t ui -o $TARGET $SOURCES'),
1816 env.Command('$BUILDDIR/po/external_l10n.pot', '$TOP_SRCDIR/lib/external_templates',
1817 '$LYX_POT -b $TOP_SRCDIR -t external -o $TARGET $SOURCES'),
1819 ['$MSGUNIQ -o $TARGET $SOURCE',
1820 '''$XGETTEXT --default-domain=${TARGET.base} \
1821 --directory=$TOP_SRCDIR --add-comments=TRANSLATORS: \
1822 --language=C++ --join-existing \
1823 --keyword=_ --keyword=N_ --keyword=B_ --keyword=qt_ \
1824 --files-from=$TOP_SRCDIR/po/POTFILES.in \
1825 --copyright-holder="LyX Developers" \
1826 --msgid-bugs-address="lyx-devel@lists.lyx.org" ''']
1828 env.Depends(lyx_po, POTFILES_in)
1829 # copy lyx.po to lyx.pot
1830 lyx_pot = env.Command('$BUILDDIR/po/lyx.pot', lyx_po,
1831 Copy('$TARGET', '$SOURCE'))
1834 # files to translate
1835 transfiles = glob.glob(os.path.join(env.Dir('$TOP_SRCDIR/po').abspath, '*.po'))
1836 # possibly *only* handle these languages
1838 if env.has_key('languages'):
1839 languages = env.make_list(env['languages'])
1840 # merge. if I use lan.po as $TARGET, it will be removed
1841 # before it is merged. In this builder,
1842 # $BUILDDIR/po/lang.po is merged from po/lang.po and $BUILDDIR/po/lyx.pot
1843 # and is copied to po/lang.po
1844 env['BUILDERS']['msgmerge'] = Builder(action=[
1845 '$MSGMERGE $TOP_SRCDIR/po/${TARGET.filebase}.po $SOURCE -o $TARGET',
1846 Copy('$TOP_SRCDIR/po/${TARGET.filebase}.po', '$TARGET')]
1848 # for each po file, generate pot
1849 for po_file in transfiles:
1851 fname = os.path.split(po_file)[1]
1853 country = fname.split('.')[0]
1855 if not languages or country in languages:
1856 # merge po files, the generated lan.po_new file is copied to lan.po file.
1857 po = env.msgmerge('$BUILDDIR/po/%s.po' % country, lyx_pot)
1858 env.Depends(po, POTFILES_in)
1859 Alias('update_po', po)
1862 # if 'install' is not in the target, do not process this
1863 if 'install' in BUILD_TARGETS or 'installer' in BUILD_TARGETS:
1865 # this part is a bit messy right now. Since scons will provide
1866 # --DESTDIR option soon, at least the dest_dir handling can be
1875 # files to translate
1876 transfiles = glob.glob(os.path.join(env.subst('$TOP_SRCDIR'), 'po', '*.po'))
1877 # possibly *only* handle these languages
1879 if env.has_key('languages'):
1880 languages = env.make_list(env['lanauges'])
1881 # use defulat msgfmt
1883 if not env['MSGFMT']:
1884 print 'msgfmt does not exist. Can not process po files'
1887 env['BUILDERS']['Transfiles'] = Builder(action='$MSGFMT $SOURCE -c --statistics -o $TARGET',suffix='.gmo',src_suffix='.po')
1889 for f in transfiles:
1891 fname = os.path.split(f)[1]
1893 country = fname.split('.')[0]
1895 if not languages or country in languages:
1896 gmo_files.extend(env.Transfiles(f))
1897 # how to join dest_dir and prefix
1898 def joinPaths(path1, path2):
1899 ''' join path1 and path2, do not use os.path.join because
1900 under window, c:\destdir\d:\program is invalid '''
1902 return os.path.normpath(path2)
1903 # separate drive letter
1904 (drive, path) = os.path.splitdrive(os.path.normpath(path2))
1905 # ignore drive letter, so c:\destdir + c:\program = c:\destdir\program
1906 return os.path.join(os.path.normpath(path1), path[1:])
1908 # install to dest_dir/prefix
1909 dest_dir = env.get('DESTDIR', '')
1910 dest_prefix_dir = joinPaths(dest_dir, env.Dir(prefix).abspath)
1911 # create the directory if needed
1912 if not os.path.isdir(dest_prefix_dir):
1914 os.makedirs(dest_prefix_dir)
1917 if not os.path.isdir(dest_prefix_dir):
1918 print 'Can not create directory', dest_prefix_dir
1921 if env.has_key('exec_prefix'):
1922 bin_dest_dir = joinPaths(dest_dir, Dir(env['exec_prefix']).abspath)
1924 bin_dest_dir = os.path.join(dest_prefix_dir, 'bin')
1926 share_dest_dir = os.path.join(dest_prefix_dir, share_dir + program_suffix)
1928 share_dest_dir = os.path.join(dest_prefix_dir, share_dir)
1929 man_dest_dir = os.path.join(dest_prefix_dir, man_dir)
1930 locale_dest_dir = os.path.join(dest_prefix_dir, locale_dir)
1931 env['LYX2LYX_DEST'] = os.path.join(share_dest_dir, 'lyx2lyx')
1935 # install executables (lyxclient may be None)
1938 version_suffix = program_suffix
1942 # install lyx, if in release mode, try to strip the binary
1943 if env.has_key('STRIP') and env['STRIP'] is not None and mode != 'debug':
1944 # create a builder to strip and install
1945 env['BUILDERS']['StripInstallAs'] = Builder(action='$STRIP $SOURCE -o $TARGET')
1947 # install executables
1948 for (name, obj) in (('lyx', lyx), ('tex2lyx', tex2lyx), ('client', client)):
1951 target_name = os.path.split(str(obj[0]))[1].replace(name, '%s%s' % (name, version_suffix))
1952 target = os.path.join(bin_dest_dir, target_name)
1953 if env['BUILDERS'].has_key('StripInstallAs'):
1954 env.StripInstallAs(target, obj)
1956 env.InstallAs(target, obj)
1957 Alias('install', target)
1961 for (dir,files) in [
1963 ('bind', lib_bind_files),
1964 ('bind/de', lib_bind_de_files),
1965 ('bind/fi', lib_bind_fi_files),
1966 ('bind/pt', lib_bind_pt_files),
1967 ('bind/sv', lib_bind_sv_files),
1968 ('doc', lib_doc_files),
1969 ('doc/biblio', lib_doc_biblio_files),
1970 ('doc/clipart', lib_doc_clipart_files),
1971 ('doc/cs', lib_doc_cs_files),
1972 ('doc/da', lib_doc_da_files),
1973 ('doc/de', lib_doc_de_files),
1974 ('doc/de/clipart', lib_doc_de_clipart_files),
1975 ('doc/es', lib_doc_es_files),
1976 ('doc/es/clipart', lib_doc_es_clipart_files),
1977 ('doc/eu', lib_doc_eu_files),
1978 ('doc/fr', lib_doc_fr_files),
1979 ('doc/he', lib_doc_he_files),
1980 ('doc/hu', lib_doc_hu_files),
1981 ('doc/it', lib_doc_it_files),
1982 ('doc/nl', lib_doc_nl_files),
1983 ('doc/nb', lib_doc_nb_files),
1984 ('doc/pl', lib_doc_pl_files),
1985 ('doc/pt', lib_doc_pt_files),
1986 ('doc/ro', lib_doc_ro_files),
1987 ('doc/ru', lib_doc_ru_files),
1988 ('doc/sk', lib_doc_sk_files),
1989 ('doc/sl', lib_doc_sl_files),
1990 ('doc/sv', lib_doc_sv_files),
1991 ('examples', lib_examples_files),
1992 ('examples/ca', lib_examples_ca_files),
1993 ('examples/cs', lib_examples_cs_files),
1994 ('examples/da', lib_examples_da_files),
1995 ('examples/de', lib_examples_de_files),
1996 ('examples/es', lib_examples_es_files),
1997 ('examples/eu', lib_examples_eu_files),
1998 ('examples/fa', lib_examples_fa_files),
1999 ('examples/fr', lib_examples_fr_files),
2000 ('examples/he', lib_examples_he_files),
2001 ('examples/hu', lib_examples_hu_files),
2002 ('examples/it', lib_examples_it_files),
2003 ('examples/nl', lib_examples_nl_files),
2004 ('examples/pl', lib_examples_pl_files),
2005 ('examples/pt', lib_examples_pt_files),
2006 ('examples/ru', lib_examples_ru_files),
2007 ('examples/sl', lib_examples_sl_files),
2008 ('examples/ro', lib_examples_ro_files),
2009 ('fonts', lib_fonts_files),
2010 ('images', lib_images_files),
2011 ('images/math', lib_images_math_files),
2012 ('kbd', lib_kbd_files),
2013 ('layouts', lib_layouts_files + lib_layouts_inc_files),
2014 ('lyx2lyx', lib_lyx2lyx_files),
2015 ('scripts', lib_scripts_files),
2016 ('templates', lib_templates_files),
2017 ('tex', lib_tex_files),
2018 ('ui', lib_ui_files)]:
2019 dirs.append(env.Install(os.path.join(share_dest_dir, dir),
2020 [env.subst('$TOP_SRCDIR/lib/%s/%s' % (dir, file)) for file in files]))
2021 Alias('install', dirs)
2023 # subst and install lyx2lyx_version.py which is not in scons_manifest.py
2024 env.Depends(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py', '$BUILDDIR/src/config.h')
2025 env.substFile(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py',
2026 '$TOP_SRCDIR/lib/lyx2lyx/lyx2lyx_version.py.in')
2027 Alias('install', share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2028 sys.path.append(share_dest_dir + '/lyx2lyx')
2030 # generate TOC files for each doc
2031 languages = depend.all_documents(env.Dir('$TOP_SRCDIR/lib/doc').abspath)
2033 for lang in languages.keys():
2034 if os.path.isdir(os.path.join(env.Dir('$TOP_SRCDIR/lib/doc').abspath, lang)):
2035 toc = env.installTOC(os.path.join(share_dest_dir, 'doc', lang, 'TOC.lyx'),
2038 # doc_toc.build_toc needs a installed version of lyx2lyx to execute
2039 env.Depends(toc, share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2041 # this is for English
2042 toc = env.installTOC(os.path.join(share_dest_dir, 'doc', 'TOC.lyx'),
2045 env.Depends(toc, share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2046 Alias('install', tocs)
2048 if platform_name == 'cygwin':
2049 # cygwin packaging requires a file /usr/share/doc/Cygwin/foot-vendor-suffix.README
2050 Cygwin_README = os.path.join(dest_prefix_dir, 'share', 'doc', 'Cygwin',
2051 '%s-%s.README' % (package, package_cygwin_version))
2052 env.InstallAs(Cygwin_README,
2053 os.path.join(env.subst('$TOP_SRCDIR'), 'README.cygwin'))
2054 Alias('install', Cygwin_README)
2055 # also a directory /usr/share/doc/lyx for README etc
2056 Cygwin_Doc = os.path.join(dest_prefix_dir, 'share', 'doc', package)
2057 env.Install(Cygwin_Doc, [os.path.join(env.subst('$TOP_SRCDIR'), x) for x in \
2058 ['INSTALL', 'README', 'README.Cygwin', 'RELEASE-NOTES', 'COPYING', 'ANNOUNCE']])
2059 Alias('install', Cygwin_Doc)
2060 # cygwin fonts also need to be installed
2061 Cygwin_fonts = os.path.join(share_dest_dir, 'fonts')
2062 env.Install(Cygwin_fonts,
2063 [env.subst('$TOP_SRCDIR/development/Win32/packaging/bakoma/%s' % file) \
2064 for file in win32_bakoma_fonts])
2065 Alias('install', Cygwin_fonts)
2066 # we also need a post installation script
2067 tmp_script = utils.installCygwinPostinstallScript('/tmp')
2068 postinstall_path = os.path.join(dest_dir, 'etc', 'postinstall')
2069 env.Install(postinstall_path, tmp_script)
2070 Alias('install', postinstall_path)
2074 env.InstallAs(os.path.join(man_dest_dir, 'lyx' + version_suffix + '.1'),
2075 env.subst('$TOP_SRCDIR/lyx.man'))
2076 env.InstallAs(os.path.join(man_dest_dir, 'tex2lyx' + version_suffix + '.1'),
2077 env.subst('$TOP_SRCDIR/src/tex2lyx/tex2lyx.man'))
2078 env.InstallAs(os.path.join(man_dest_dir, 'lyxclient' + version_suffix + '.1'),
2079 env.subst('$TOP_SRCDIR/src/client/lyxclient.man'))
2080 Alias('install', [os.path.join(man_dest_dir, x + version_suffix + '.1') for
2081 x in ['lyx', 'tex2lyx', 'lyxclient']])
2083 # ru.gmo ==> ru/LC_MESSAGES/lyxSUFFIX.mo
2084 for gmo in gmo_files:
2085 lan = os.path.split(str(gmo))[1].split('.')[0]
2086 dest_file = os.path.join(locale_dest_dir, lan, 'LC_MESSAGES', 'lyx' + program_suffix + '.mo')
2087 env.InstallAs(dest_file, gmo)
2088 Alias('install', dest_file)
2091 if 'install' in BUILD_TARGETS or 'installer' in BUILD_TARGETS:
2093 # build windows installer using NSIS
2096 # There is a nsis builder on scons wiki but it does not work with
2097 # our lyx.nsi because it does not dig through all the include directives
2098 # and find the dependencies automatically. Also, it can not parse
2099 # OutFile in lyx.nsi since it is defined as SETUP_EXE which is in turn
2100 # something rely on date.
2101 # Because of this, I am doing a simple nsis builder here.
2102 if platform_name != 'win32':
2103 print 'installer target is only available for windows platform'
2105 if mode != 'release':
2106 print 'installer has to be built in release mode (use option mode=release)'
2108 installer_files = ['$TOP_SRCDIR/development/Win32/packaging/installer/%s' \
2109 % x for x in development_Win32_packaging_installer] + \
2110 ['$TOP_SRCDIR/development/Win32/packaging/installer/components/%s' \
2111 % x for x in development_Win32_packaging_installer_components] + \
2112 ['$TOP_SRCDIR/development/Win32/packaging/installer/dialogs/%s' \
2113 % x for x in development_Win32_packaging_installer_dialogs] + \
2114 ['$TOP_SRCDIR/development/Win32/packaging/installer/graphics/%s' \
2115 % x for x in development_Win32_packaging_installer_graphics] + \
2116 ['$TOP_SRCDIR/development/Win32/packaging/installer/include/%s' \
2117 % x for x in development_Win32_packaging_installer_include] + \
2118 ['$TOP_SRCDIR/development/Win32/packaging/installer/lang/%s' \
2119 % x for x in development_Win32_packaging_installer_lang]
2120 if env.has_key('NSIS') and env['NSIS'] is not None:
2121 # create a builder to strip and install
2122 env['BUILDERS']['installer'] = Builder(generator=utils.env_nsis)
2124 print 'No nsis compiler is found. Existing...'
2126 if not env.has_key('win_installer') or env['win_installer'] is None:
2128 env['win_installer'] = '%s-%s-%s-Installer.exe' % (package_name, package_version, time.strftime('%Y-%m-%d'))
2130 env['win_installer'] = '%s-%s-Installer.exe' % (package_name, package_version)
2131 # provide default setting
2132 if not env.has_key('deps_dir') or env['deps_dir'] is None:
2133 env['deps_dir'] = os.path.join(env.Dir('$TOP_SRCDIR').abspath, 'lyx-windows-deps-msvc-qt4')
2134 if not os.path.isdir(env.Dir('$deps_dir').abspath):
2135 print 'Development dependency package is not found.'
2138 env['deps_dir'] = env.Dir('$deps_dir').abspath
2140 if env.has_key('bundle_dir') and os.path.isdir(env.Dir('$bundle_dir').abspath):
2141 env['bundle_dir'] = env.Dir('$bundle_dir').abspath
2142 elif os.path.isdir(os.path.join(env.Dir('$TOP_SRCDIR').abspath, 'lyx-windows-bundle-deps')):
2143 env['bundle_dir'] = os.path.join(env.Dir('$TOP_SRCDIR').abspath, 'lyx-windows-bundle-deps')
2145 env['bundle_dir'] = None
2146 # if absolute path is given, use it, otherwise, write to current directory
2147 if not (':' in env['win_installer'] or '/' in env['win_installer'] or '\\' in env['win_installer']):
2148 env['win_installer'] = os.path.join(env.Dir('$BUILDDIR').abspath, env['win_installer'])
2149 env.Append(NSISDEFINES={
2150 'ExeFile':env['win_installer'],
2151 'BundleExeFile':env['win_installer'].replace('.exe', '-bundle.exe'),
2152 'FilesLyx':env.Dir(dest_prefix_dir).abspath,
2153 'FilesDeps':env['deps_dir'],
2154 'FilesBundle':env['bundle_dir'],
2156 installer = env.installer(env['win_installer'],
2157 '$TOP_SRCDIR/development/Win32/packaging/installer/lyx.nsi')
2158 # since I can not use a scanner, explicit dependent is required
2159 env.Depends(installer, 'install')
2160 env.Depends(installer, installer_files)
2161 env.Alias('installer', installer)
2162 # also generate bundle?
2163 if env.has_key('bundle') and env['bundle']:
2164 if env['bundle_dir'] is None or not os.path.isdir(env['bundle_dir']):
2165 print 'Bundle directory does not exist (default to %s\lyx-windows-bundle-deps.' % env.Dir('$TOP_SRCDIR').abspath
2166 print 'Use bundle_dir option to specify'
2168 # generator of the builder will add bundle stuff depending on output name
2169 bundle_installer = env.installer(env['win_installer'].replace('.exe', '-bundle.exe'),
2170 '$TOP_SRCDIR/development/Win32/packaging/installer/lyx.nsi')
2171 env.Depends(bundle_installer, 'install')
2172 env.Depends(bundle_installer, installer_files)
2173 env.Alias('installer', bundle_installer)
2176 Alias('all', ['lyx', 'client', 'tex2lyx'])