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] + \
1520 ['$BUILDDIR/src/support/minizip/%s' % x for x in src_support_minizip_windows_files if platform_name == 'win32'],
1524 '-DQT_CLEAN_NAMESPACE',
1529 CPPPATH = ['$CPPPATH', '$TOP_SRCDIR/src/support/minizip']
1531 Alias('support', support)
1537 mathed = env.StaticLibrary(
1538 target = '$LOCALLIBPATH/mathed',
1539 source = ['$BUILDDIR/src/mathed/%s' % x for x in src_mathed_files]
1541 Alias('mathed', mathed)
1547 insets = env.StaticLibrary(
1548 target = '$LOCALLIBPATH/insets',
1549 source = ['$BUILDDIR/src/insets/%s' % x for x in src_insets_files]
1551 Alias('insets', insets)
1557 frontends = env.StaticLibrary(
1558 target = '$LOCALLIBPATH/frontends',
1559 source = ['$BUILDDIR/src/frontends/%s' % x for x in src_frontends_files]
1561 Alias('frontends', frontends)
1567 graphics = env.StaticLibrary(
1568 target = '$LOCALLIBPATH/graphics',
1569 source = ['$BUILDDIR/src/graphics/%s' % x for x in src_graphics_files]
1571 Alias('graphics', graphics)
1575 # src/frontends/controllers
1577 controllers = env.StaticLibrary(
1578 target = '$LOCALLIBPATH/controllers',
1579 source = ['$BUILDDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files]
1581 Alias('controllers', controllers)
1587 frontend_env['QT4_MOCHPREFIX'] = ''
1588 frontend_env['QT4_MOCHSUFFIX'] = '_moc.cpp'
1590 # tells scons how to get these moced files, although not all moced files are needed
1591 # (or are actually generated).
1592 qt4_moced_files = [frontend_env.Moc4('$BUILDDIR/src/frontends/qt4/%s' % x)
1593 for x in src_frontends_qt4_header_files ]
1594 resources = [frontend_env.Uic4('$BUILDDIR/src/frontends/qt4/ui/%s' % x.split('.')[0])
1595 for x in src_frontends_qt4_ui_files]
1598 # moc qt4_moc_files, the moced files are included in the original files
1600 qt4 = frontend_env.StaticLibrary(
1601 target = '$LOCALLIBPATH/qt4',
1602 source = ['$BUILDDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_files],
1606 '$BUILDDIR/src/images',
1607 '$BUILDDIR/src/frontends',
1608 '$BUILDDIR/src/frontends/qt4',
1609 '$BUILDDIR/src/frontends/qt4/ui',
1610 '$BUILDDIR/src/frontends/controllers'
1615 '-DQT_CLEAN_NAMESPACE',
1627 if env['HAVE_FCNTL']:
1628 client = frontend_env.Program(
1629 target = '$BUILDDIR/src/client/lyxclient',
1630 LIBS = ['support'] + intl_libs + system_libs +
1631 socket_libs + boost_libraries + qtcore_lib,
1632 source = ['$BUILDDIR/src/client/%s' % x for x in src_client_files] + \
1633 utils.createResFromIcon(frontend_env, 'lyx_32x32.ico', '$LOCALLIBPATH/client.rc')
1635 Alias('client', frontend_env.Command(os.path.join('$BUILDDIR', os.path.split(str(client[0]))[1]),
1636 client, [Copy('$TARGET', '$SOURCE')]))
1639 Alias('client', client)
1645 for file in src_tex2lyx_copied_files + src_tex2lyx_copied_header_files:
1646 frontend_env.Command('$BUILDDIR/src/tex2lyx/'+file, '$TOP_SRCDIR/src/'+file,
1647 [Copy('$TARGET', '$SOURCE')])
1649 tex2lyx = frontend_env.Program(
1650 target = '$BUILDDIR/src/tex2lyx/tex2lyx',
1651 LIBS = ['support'] + boost_libraries + intl_libs + system_libs + qtcore_lib,
1652 source = ['$BUILDDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_files + src_tex2lyx_copied_files] + \
1653 utils.createResFromIcon(frontend_env, 'lyx_32x32.ico', '$LOCALLIBPATH/tex2lyx.rc'),
1654 CPPPATH = ['$BUILDDIR/src/tex2lyx', '$CPPPATH'],
1655 LIBPATH = ['#$LOCALLIBPATH', '$LIBPATH'],
1657 Alias('tex2lyx', frontend_env.Command(os.path.join('$BUILDDIR', os.path.split(str(tex2lyx[0]))[1]),
1658 tex2lyx, [Copy('$TARGET', '$SOURCE')]))
1659 Alias('tex2lyx', tex2lyx)
1665 if env.has_key('USE_ASPELL') and env['USE_ASPELL']:
1666 src_post_files.append('ASpell.cpp')
1667 elif env.has_key('USE_PSPELL') and env['USE_PSPELL']:
1668 src_post_files.append('PSpell.cpp')
1669 elif env.has_key('USE_ISPELL') and env['USE_ISPELL']:
1670 src_post_files.append('ISpell.cpp')
1672 # msvc requires at least one source file with main()
1673 # so I exclude main.cpp from lyxbase
1674 lyxbase_pre = env.StaticLibrary(
1675 target = '$LOCALLIBPATH/lyxbase_pre',
1676 source = ['$BUILDDIR/src/%s' % x for x in src_pre_files]
1678 lyxbase_post = env.StaticLibrary(
1679 target = '$LOCALLIBPATH/lyxbase_post',
1680 source = ["$BUILDDIR/src/%s" % x for x in src_post_files]
1682 Alias('lyxbase', lyxbase_pre)
1683 Alias('lyxbase', lyxbase_post)
1687 # Build lyx with given frontend
1689 lyx = frontend_env.Program(
1690 target = '$BUILDDIR/lyx',
1691 source = ['$BUILDDIR/src/main.cpp'] + \
1692 utils.createResFromIcon(frontend_env, 'lyx_32x32.ico', '$LOCALLIBPATH/lyx.rc'),
1713 if use_vc and 'msvs_projects' in BUILD_TARGETS:
1714 def build_project(target, full_target = None,
1715 src = [], inc = [], res = []):
1716 ''' build mavs project files
1717 target: alias (correspond to directory name)
1718 full_target: full path/filename of the target
1723 For non-debug-able targets like static libraries, target (alias) is
1724 enough to build the target. For executable targets, msvs need to know
1725 the full path to start debug them.
1728 if full_target is None:
1729 build_target = target
1731 build_target = full_target
1733 proj = env.MSVSProject(
1734 target = target + env['MSVSPROJECTSUFFIX'],
1735 # this allows easy access to header files (along with source)
1736 srcs = [env.subst(x) for x in src + inc],
1737 incs = [env.subst('$TOP_SRCDIR/src/config.h')],
1738 localincs = [env.subst(x) for x in inc],
1739 resources = [env.subst(x) for x in res],
1740 buildtarget = build_target,
1744 Alias('msvs_projects', proj)
1746 build_project('client', src = ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_files],
1747 inc = ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_header_files],
1748 full_target = File(env.subst('$BUILDDIR/src/client/lyxclient$PROGSUFFIX')).abspath)
1750 build_project('tex2lyx', src = ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_files],
1751 inc = ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_header_files],
1752 full_target = File(env.subst('$BUILDDIR/src/tex2lyx/tex2lyx$PROGSUFFIX')).abspath)
1754 build_project('lyx',
1755 src = ['$TOP_SRCDIR/src/%s' % x for x in src_pre_files + src_post_files + ['version.cpp']] + \
1756 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_files + ['Package.cpp'] ] + \
1757 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_files] + \
1758 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_files] + \
1759 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_files] + \
1760 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_files] + \
1761 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files] + \
1762 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_files + src_frontends_qt4_moc_files],
1763 inc = ['$TOP_SRCDIR/src/%s' % x for x in src_header_files] + \
1764 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files] + \
1765 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_header_files] + \
1766 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files] + \
1767 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files] + \
1768 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files] + \
1769 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files] + \
1770 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_header_files],
1771 res = ['$TOP_SRCDIR/src/frontends/qt4/ui/%s' % x for x in src_frontends_qt4_ui_files],
1772 full_target = File(env.subst('$BUILDDIR/lyx$PROGSUFFIX')).abspath)
1775 if 'update_po' in BUILD_TARGETS:
1779 print 'Updating po/*.po files...'
1781 # whether or not update po files
1782 if not env['XGETTEXT'] or not env['MSGMERGE'] or not env['MSGUNIQ']:
1783 print 'xgettext or msgmerge does not exist. Cannot merge po files'
1785 # rebuild POTFILES.in
1786 POTFILES_in = env.potfiles('$TOP_SRCDIR/po/POTFILES.in',
1787 ['$TOP_SRCDIR/src/%s' % x for x in src_header_files + src_pre_files + src_post_files + \
1788 src_extra_src_files] + \
1789 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files + src_support_files + \
1790 src_support_extra_header_files + src_support_extra_src_files] + \
1791 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_header_files + src_mathed_files] + \
1792 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files + src_insets_files] + \
1793 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files + src_frontends_files] + \
1794 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files + src_graphics_files] + \
1795 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files + src_frontends_controllers_files] + \
1796 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_header_files + src_frontends_qt4_files + src_frontends_qt4_moc_files] + \
1797 ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_header_files + src_client_files ] + \
1798 ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_header_files + src_tex2lyx_files ]
1800 Alias('update_po', POTFILES_in)
1801 # build language_l10n.pot, ui_l10n.pot, layouts_l10n.pot, qt4_l10n.pot, external_l10n
1802 # and combine them to lyx.po
1803 env['LYX_POT'] = 'python $TOP_SRCDIR/po/lyx_pot.py'
1804 lyx_po = env.Command('$BUILDDIR/po/lyx.po',
1805 env.Command('$BUILDDIR/po/all.po',
1806 [env.Command('$BUILDDIR/po/qt4_l10n.pot',
1807 ['$TOP_SRCDIR/src/frontends/qt4/ui/%s' % x for x in src_frontends_qt4_ui_files],
1808 '$LYX_POT -b $TOP_SRCDIR -t qt4 -o $TARGET $SOURCES'),
1809 env.Command('$BUILDDIR/po/layouts_l10n.pot',
1810 ['$TOP_SRCDIR/lib/layouts/%s' % x for x in lib_layouts_files + lib_layouts_inc_files],
1811 '$LYX_POT -b $TOP_SRCDIR -t layouts -o $TARGET $SOURCES'),
1812 env.Command('$BUILDDIR/po/languages_l10n.pot', '$TOP_SRCDIR/lib/languages',
1813 '$LYX_POT -b $TOP_SRCDIR -t languages -o $TARGET $SOURCES'),
1814 env.Command('$BUILDDIR/po/ui_l10n.pot',
1815 ['$TOP_SRCDIR/lib/ui/%s' % x for x in lib_ui_files],
1816 '$LYX_POT -b $TOP_SRCDIR -t ui -o $TARGET $SOURCES'),
1817 env.Command('$BUILDDIR/po/external_l10n.pot', '$TOP_SRCDIR/lib/external_templates',
1818 '$LYX_POT -b $TOP_SRCDIR -t external -o $TARGET $SOURCES'),
1820 ['$MSGUNIQ -o $TARGET $SOURCE',
1821 '''$XGETTEXT --default-domain=${TARGET.base} \
1822 --directory=$TOP_SRCDIR --add-comments=TRANSLATORS: \
1823 --language=C++ --join-existing \
1824 --keyword=_ --keyword=N_ --keyword=B_ --keyword=qt_ \
1825 --files-from=$TOP_SRCDIR/po/POTFILES.in \
1826 --copyright-holder="LyX Developers" \
1827 --msgid-bugs-address="lyx-devel@lists.lyx.org" ''']
1829 env.Depends(lyx_po, POTFILES_in)
1830 # copy lyx.po to lyx.pot
1831 lyx_pot = env.Command('$BUILDDIR/po/lyx.pot', lyx_po,
1832 Copy('$TARGET', '$SOURCE'))
1835 # files to translate
1836 transfiles = glob.glob(os.path.join(env.Dir('$TOP_SRCDIR/po').abspath, '*.po'))
1837 # possibly *only* handle these languages
1839 if env.has_key('languages'):
1840 languages = env.make_list(env['languages'])
1841 # merge. if I use lan.po as $TARGET, it will be removed
1842 # before it is merged. In this builder,
1843 # $BUILDDIR/po/lang.po is merged from po/lang.po and $BUILDDIR/po/lyx.pot
1844 # and is copied to po/lang.po
1845 env['BUILDERS']['msgmerge'] = Builder(action=[
1846 '$MSGMERGE $TOP_SRCDIR/po/${TARGET.filebase}.po $SOURCE -o $TARGET',
1847 Copy('$TOP_SRCDIR/po/${TARGET.filebase}.po', '$TARGET')]
1849 # for each po file, generate pot
1850 for po_file in transfiles:
1852 fname = os.path.split(po_file)[1]
1854 country = fname.split('.')[0]
1856 if not languages or country in languages:
1857 # merge po files, the generated lan.po_new file is copied to lan.po file.
1858 po = env.msgmerge('$BUILDDIR/po/%s.po' % country, lyx_pot)
1859 env.Depends(po, POTFILES_in)
1860 Alias('update_po', po)
1863 # if 'install' is not in the target, do not process this
1864 if 'install' in BUILD_TARGETS or 'installer' in BUILD_TARGETS:
1866 # this part is a bit messy right now. Since scons will provide
1867 # --DESTDIR option soon, at least the dest_dir handling can be
1876 # files to translate
1877 transfiles = glob.glob(os.path.join(env.subst('$TOP_SRCDIR'), 'po', '*.po'))
1878 # possibly *only* handle these languages
1880 if env.has_key('languages'):
1881 languages = env.make_list(env['lanauges'])
1882 # use defulat msgfmt
1884 if not env['MSGFMT']:
1885 print 'msgfmt does not exist. Can not process po files'
1888 env['BUILDERS']['Transfiles'] = Builder(action='$MSGFMT $SOURCE -c --statistics -o $TARGET',suffix='.gmo',src_suffix='.po')
1890 for f in transfiles:
1892 fname = os.path.split(f)[1]
1894 country = fname.split('.')[0]
1896 if not languages or country in languages:
1897 gmo_files.extend(env.Transfiles(f))
1898 # how to join dest_dir and prefix
1899 def joinPaths(path1, path2):
1900 ''' join path1 and path2, do not use os.path.join because
1901 under window, c:\destdir\d:\program is invalid '''
1903 return os.path.normpath(path2)
1904 # separate drive letter
1905 (drive, path) = os.path.splitdrive(os.path.normpath(path2))
1906 # ignore drive letter, so c:\destdir + c:\program = c:\destdir\program
1907 return os.path.join(os.path.normpath(path1), path[1:])
1909 # install to dest_dir/prefix
1910 dest_dir = env.get('DESTDIR', '')
1911 dest_prefix_dir = joinPaths(dest_dir, env.Dir(prefix).abspath)
1912 # create the directory if needed
1913 if not os.path.isdir(dest_prefix_dir):
1915 os.makedirs(dest_prefix_dir)
1918 if not os.path.isdir(dest_prefix_dir):
1919 print 'Can not create directory', dest_prefix_dir
1922 if env.has_key('exec_prefix'):
1923 bin_dest_dir = joinPaths(dest_dir, Dir(env['exec_prefix']).abspath)
1925 bin_dest_dir = os.path.join(dest_prefix_dir, 'bin')
1927 share_dest_dir = os.path.join(dest_prefix_dir, share_dir + program_suffix)
1929 share_dest_dir = os.path.join(dest_prefix_dir, share_dir)
1930 man_dest_dir = os.path.join(dest_prefix_dir, man_dir)
1931 locale_dest_dir = os.path.join(dest_prefix_dir, locale_dir)
1932 env['LYX2LYX_DEST'] = os.path.join(share_dest_dir, 'lyx2lyx')
1936 # install executables (lyxclient may be None)
1939 version_suffix = program_suffix
1943 # install lyx, if in release mode, try to strip the binary
1944 if env.has_key('STRIP') and env['STRIP'] is not None and mode != 'debug':
1945 # create a builder to strip and install
1946 env['BUILDERS']['StripInstallAs'] = Builder(action='$STRIP $SOURCE -o $TARGET')
1948 # install executables
1949 for (name, obj) in (('lyx', lyx), ('tex2lyx', tex2lyx), ('client', client)):
1952 target_name = os.path.split(str(obj[0]))[1].replace(name, '%s%s' % (name, version_suffix))
1953 target = os.path.join(bin_dest_dir, target_name)
1954 if env['BUILDERS'].has_key('StripInstallAs'):
1955 env.StripInstallAs(target, obj)
1957 env.InstallAs(target, obj)
1958 Alias('install', target)
1962 for (dir,files) in [
1964 ('bind', lib_bind_files),
1965 ('bind/de', lib_bind_de_files),
1966 ('bind/fi', lib_bind_fi_files),
1967 ('bind/pt', lib_bind_pt_files),
1968 ('bind/sv', lib_bind_sv_files),
1969 ('doc', lib_doc_files),
1970 ('doc/biblio', lib_doc_biblio_files),
1971 ('doc/clipart', lib_doc_clipart_files),
1972 ('doc/cs', lib_doc_cs_files),
1973 ('doc/da', lib_doc_da_files),
1974 ('doc/de', lib_doc_de_files),
1975 ('doc/de/clipart', lib_doc_de_clipart_files),
1976 ('doc/es', lib_doc_es_files),
1977 ('doc/es/clipart', lib_doc_es_clipart_files),
1978 ('doc/eu', lib_doc_eu_files),
1979 ('doc/fr', lib_doc_fr_files),
1980 ('doc/he', lib_doc_he_files),
1981 ('doc/hu', lib_doc_hu_files),
1982 ('doc/it', lib_doc_it_files),
1983 ('doc/nl', lib_doc_nl_files),
1984 ('doc/nb', lib_doc_nb_files),
1985 ('doc/pl', lib_doc_pl_files),
1986 ('doc/pt', lib_doc_pt_files),
1987 ('doc/ro', lib_doc_ro_files),
1988 ('doc/ru', lib_doc_ru_files),
1989 ('doc/sk', lib_doc_sk_files),
1990 ('doc/sl', lib_doc_sl_files),
1991 ('doc/sv', lib_doc_sv_files),
1992 ('examples', lib_examples_files),
1993 ('examples/ca', lib_examples_ca_files),
1994 ('examples/cs', lib_examples_cs_files),
1995 ('examples/da', lib_examples_da_files),
1996 ('examples/de', lib_examples_de_files),
1997 ('examples/es', lib_examples_es_files),
1998 ('examples/eu', lib_examples_eu_files),
1999 ('examples/fa', lib_examples_fa_files),
2000 ('examples/fr', lib_examples_fr_files),
2001 ('examples/he', lib_examples_he_files),
2002 ('examples/hu', lib_examples_hu_files),
2003 ('examples/it', lib_examples_it_files),
2004 ('examples/nl', lib_examples_nl_files),
2005 ('examples/pl', lib_examples_pl_files),
2006 ('examples/pt', lib_examples_pt_files),
2007 ('examples/ru', lib_examples_ru_files),
2008 ('examples/sl', lib_examples_sl_files),
2009 ('examples/ro', lib_examples_ro_files),
2010 ('fonts', lib_fonts_files),
2011 ('images', lib_images_files),
2012 ('images/math', lib_images_math_files),
2013 ('kbd', lib_kbd_files),
2014 ('layouts', lib_layouts_files + lib_layouts_inc_files),
2015 ('lyx2lyx', lib_lyx2lyx_files),
2016 ('scripts', lib_scripts_files),
2017 ('templates', lib_templates_files),
2018 ('tex', lib_tex_files),
2019 ('ui', lib_ui_files)]:
2020 dirs.append(env.Install(os.path.join(share_dest_dir, dir),
2021 [env.subst('$TOP_SRCDIR/lib/%s/%s' % (dir, file)) for file in files]))
2022 Alias('install', dirs)
2024 # subst and install lyx2lyx_version.py which is not in scons_manifest.py
2025 env.Depends(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py', '$BUILDDIR/src/config.h')
2026 env.substFile(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py',
2027 '$TOP_SRCDIR/lib/lyx2lyx/lyx2lyx_version.py.in')
2028 Alias('install', share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2029 sys.path.append(share_dest_dir + '/lyx2lyx')
2031 # generate TOC files for each doc
2032 languages = depend.all_documents(env.Dir('$TOP_SRCDIR/lib/doc').abspath)
2034 for lang in languages.keys():
2035 if os.path.isdir(os.path.join(env.Dir('$TOP_SRCDIR/lib/doc').abspath, lang)):
2036 toc = env.installTOC(os.path.join(share_dest_dir, 'doc', lang, 'TOC.lyx'),
2039 # doc_toc.build_toc needs a installed version of lyx2lyx to execute
2040 env.Depends(toc, share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2042 # this is for English
2043 toc = env.installTOC(os.path.join(share_dest_dir, 'doc', 'TOC.lyx'),
2046 env.Depends(toc, share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2047 Alias('install', tocs)
2049 if platform_name == 'cygwin':
2050 # cygwin packaging requires a file /usr/share/doc/Cygwin/foot-vendor-suffix.README
2051 Cygwin_README = os.path.join(dest_prefix_dir, 'share', 'doc', 'Cygwin',
2052 '%s-%s.README' % (package, package_cygwin_version))
2053 env.InstallAs(Cygwin_README,
2054 os.path.join(env.subst('$TOP_SRCDIR'), 'README.cygwin'))
2055 Alias('install', Cygwin_README)
2056 # also a directory /usr/share/doc/lyx for README etc
2057 Cygwin_Doc = os.path.join(dest_prefix_dir, 'share', 'doc', package)
2058 env.Install(Cygwin_Doc, [os.path.join(env.subst('$TOP_SRCDIR'), x) for x in \
2059 ['INSTALL', 'README', 'README.Cygwin', 'RELEASE-NOTES', 'COPYING', 'ANNOUNCE']])
2060 Alias('install', Cygwin_Doc)
2061 # cygwin fonts also need to be installed
2062 Cygwin_fonts = os.path.join(share_dest_dir, 'fonts')
2063 env.Install(Cygwin_fonts,
2064 [env.subst('$TOP_SRCDIR/development/Win32/packaging/bakoma/%s' % file) \
2065 for file in win32_bakoma_fonts])
2066 Alias('install', Cygwin_fonts)
2067 # we also need a post installation script
2068 tmp_script = utils.installCygwinPostinstallScript('/tmp')
2069 postinstall_path = os.path.join(dest_dir, 'etc', 'postinstall')
2070 env.Install(postinstall_path, tmp_script)
2071 Alias('install', postinstall_path)
2075 env.InstallAs(os.path.join(man_dest_dir, 'lyx' + version_suffix + '.1'),
2076 env.subst('$TOP_SRCDIR/lyx.man'))
2077 env.InstallAs(os.path.join(man_dest_dir, 'tex2lyx' + version_suffix + '.1'),
2078 env.subst('$TOP_SRCDIR/src/tex2lyx/tex2lyx.man'))
2079 env.InstallAs(os.path.join(man_dest_dir, 'lyxclient' + version_suffix + '.1'),
2080 env.subst('$TOP_SRCDIR/src/client/lyxclient.man'))
2081 Alias('install', [os.path.join(man_dest_dir, x + version_suffix + '.1') for
2082 x in ['lyx', 'tex2lyx', 'lyxclient']])
2084 # ru.gmo ==> ru/LC_MESSAGES/lyxSUFFIX.mo
2085 for gmo in gmo_files:
2086 lan = os.path.split(str(gmo))[1].split('.')[0]
2087 dest_file = os.path.join(locale_dest_dir, lan, 'LC_MESSAGES', 'lyx' + program_suffix + '.mo')
2088 env.InstallAs(dest_file, gmo)
2089 Alias('install', dest_file)
2092 if 'install' in BUILD_TARGETS or 'installer' in BUILD_TARGETS:
2094 # build windows installer using NSIS
2097 # There is a nsis builder on scons wiki but it does not work with
2098 # our lyx.nsi because it does not dig through all the include directives
2099 # and find the dependencies automatically. Also, it can not parse
2100 # OutFile in lyx.nsi since it is defined as SETUP_EXE which is in turn
2101 # something rely on date.
2102 # Because of this, I am doing a simple nsis builder here.
2103 if platform_name != 'win32':
2104 print 'installer target is only available for windows platform'
2106 if mode != 'release':
2107 print 'installer has to be built in release mode (use option mode=release)'
2109 installer_files = ['$TOP_SRCDIR/development/Win32/packaging/installer/%s' \
2110 % x for x in development_Win32_packaging_installer] + \
2111 ['$TOP_SRCDIR/development/Win32/packaging/installer/components/%s' \
2112 % x for x in development_Win32_packaging_installer_components] + \
2113 ['$TOP_SRCDIR/development/Win32/packaging/installer/dialogs/%s' \
2114 % x for x in development_Win32_packaging_installer_dialogs] + \
2115 ['$TOP_SRCDIR/development/Win32/packaging/installer/graphics/%s' \
2116 % x for x in development_Win32_packaging_installer_graphics] + \
2117 ['$TOP_SRCDIR/development/Win32/packaging/installer/include/%s' \
2118 % x for x in development_Win32_packaging_installer_include] + \
2119 ['$TOP_SRCDIR/development/Win32/packaging/installer/lang/%s' \
2120 % x for x in development_Win32_packaging_installer_lang]
2121 if env.has_key('NSIS') and env['NSIS'] is not None:
2122 # create a builder to strip and install
2123 env['BUILDERS']['installer'] = Builder(generator=utils.env_nsis)
2125 print 'No nsis compiler is found. Existing...'
2127 if not env.has_key('win_installer') or env['win_installer'] is None:
2129 env['win_installer'] = '%s-%s-%s-Installer.exe' % (package_name, package_version, time.strftime('%Y-%m-%d'))
2131 env['win_installer'] = '%s-%s-Installer.exe' % (package_name, package_version)
2132 # provide default setting
2133 if not env.has_key('deps_dir') or env['deps_dir'] is None:
2134 env['deps_dir'] = os.path.join(env.Dir('$TOP_SRCDIR').abspath, 'lyx-windows-deps-msvc-qt4')
2135 if not os.path.isdir(env.Dir('$deps_dir').abspath):
2136 print 'Development dependency package is not found.'
2139 env['deps_dir'] = env.Dir('$deps_dir').abspath
2141 if env.has_key('bundle_dir') and os.path.isdir(env.Dir('$bundle_dir').abspath):
2142 env['bundle_dir'] = env.Dir('$bundle_dir').abspath
2143 elif os.path.isdir(os.path.join(env.Dir('$TOP_SRCDIR').abspath, 'lyx-windows-bundle-deps')):
2144 env['bundle_dir'] = os.path.join(env.Dir('$TOP_SRCDIR').abspath, 'lyx-windows-bundle-deps')
2146 env['bundle_dir'] = None
2147 # if absolute path is given, use it, otherwise, write to current directory
2148 if not (':' in env['win_installer'] or '/' in env['win_installer'] or '\\' in env['win_installer']):
2149 env['win_installer'] = os.path.join(env.Dir('$BUILDDIR').abspath, env['win_installer'])
2150 env.Append(NSISDEFINES={
2151 'ExeFile':env['win_installer'],
2152 'BundleExeFile':env['win_installer'].replace('.exe', '-bundle.exe'),
2153 'FilesLyx':env.Dir(dest_prefix_dir).abspath,
2154 'FilesDeps':env['deps_dir'],
2155 'FilesBundle':env['bundle_dir'],
2157 installer = env.installer(env['win_installer'],
2158 '$TOP_SRCDIR/development/Win32/packaging/installer/lyx.nsi')
2159 # since I can not use a scanner, explicit dependent is required
2160 env.Depends(installer, 'install')
2161 env.Depends(installer, installer_files)
2162 env.Alias('installer', installer)
2163 # also generate bundle?
2164 if env.has_key('bundle') and env['bundle']:
2165 if env['bundle_dir'] is None or not os.path.isdir(env['bundle_dir']):
2166 print 'Bundle directory does not exist (default to %s\lyx-windows-bundle-deps.' % env.Dir('$TOP_SRCDIR').abspath
2167 print 'Use bundle_dir option to specify'
2169 # generator of the builder will add bundle stuff depending on output name
2170 bundle_installer = env.installer(env['win_installer'].replace('.exe', '-bundle.exe'),
2171 '$TOP_SRCDIR/development/Win32/packaging/installer/lyx.nsi')
2172 env.Depends(bundle_installer, 'install')
2173 env.Depends(bundle_installer, installer_files)
2174 env.Alias('installer', bundle_installer)
2177 Alias('all', ['lyx', 'client', 'tex2lyx'])