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 # scons asks for 1.5.2, lyx requires 2.3
40 EnsurePythonVersion(2, 3)
41 # Please use at least 0.96.92 (not 0.96.1)
42 EnsureSConsVersion(0, 96)
43 # also check for minor version number for scons 0.96
44 from SCons import __version__
45 # allow the use of snapshot version of scons
46 __version__ = __version__.split('d')[0]
47 version = map(int, __version__.split('.'))
48 if version[0] == 0 and version[1] == 96 and version[2] < 92:
49 print "Scons >= 0.96.92 is required."
53 #----------------------------------------------------------
55 #----------------------------------------------------------
57 # some global settings
59 # get version number from configure.ac so that JMarc does
60 # not have to change SConstruct during lyx release
61 package_version, lyx_date = utils.getVerFromConfigure(top_src_dir)
62 package_cygwin_version = '%s-1' % package_version
63 boost_version = ['1_34']
65 if 'svn' in package_version:
67 default_build_mode = 'debug'
70 default_build_mode = 'release'
73 package_bugreport = 'lyx-devel@lists.lyx.org'
75 package_tarname = 'lyx'
76 package_string = '%s %s' % (package_name, package_version)
78 # various cache/log files
79 default_log_file = 'scons_lyx.log'
80 opt_cache_file = 'opt.cache'
83 #----------------------------------------------------------
84 # platform dependent settings
85 #----------------------------------------------------------
88 platform_name = 'win32'
89 default_prefix = 'c:/program files/lyx'
90 default_with_x = False
91 default_packaging_method = 'windows'
92 elif os.name == 'posix' and sys.platform != 'cygwin':
93 platform_name = sys.platform
94 default_prefix = '/usr/local'
96 default_packaging_method = 'posix'
97 elif os.name == 'posix' and sys.platform == 'cygwin':
98 platform_name = 'cygwin'
99 default_prefix = '/usr'
100 default_with_x = True
101 default_packaging_method = 'posix'
102 elif os.name == 'darwin':
103 platform_name = 'macosx'
104 # FIXME: macOSX default prefix?
106 default_with_x = False
107 default_packaging_method = 'macosx'
108 else: # unsupported system, assume posix behavior
109 platform_name = 'others'
111 default_with_x = True
112 default_packaging_method = 'posix'
114 #---------------------------------------------------------
116 #----------------------------------------------------------
118 # You can set perminant default values in config.py
119 if os.path.isfile('config.py'):
120 print "Getting options from config.py..."
121 print open('config.py').read()
123 opts = Options(['config.py'])
126 EnumOption('frontend', 'Main GUI', 'qt4',
127 allowed_values = ('qt4',) ),
128 # debug or release build
129 EnumOption('mode', 'Building method', default_build_mode,
130 allowed_values = ('debug', 'release') ),
133 'Use included, system boost library, or try sytem boost first.',
134 'auto', allowed_values = (
135 'auto', # detect boost, if not found, use included
136 'included', # always use included boost
137 'system', # always use system boost, fail if can not find
140 EnumOption('gettext',
141 'Use included, system gettext library, or try sytem gettext first',
142 'auto', allowed_values = (
143 'auto', # detect gettext, if not found, use included
144 'included', # always use included gettext
145 'system', # always use system gettext, fail if can not find
148 EnumOption('spell', 'Choose spell checker to use.', 'auto',
149 allowed_values = ('aspell', 'pspell', 'ispell', 'auto', 'no') ),
151 EnumOption('packaging', 'Packaging method to use.', default_packaging_method,
152 allowed_values = ('windows', 'posix', 'macosx')),
154 BoolOption('fast_start', 'This option is obsolete.', False),
155 # No precompiled header support (too troublesome to make it work for msvc)
156 # BoolOption('pch', 'Whether or not use pch', False),
157 # enable assertion, (config.h has ENABLE_ASSERTIOS
158 BoolOption('assertions', 'Use assertions', True),
159 # config.h define _GLIBCXX_CONCEPT_CHECKS
160 # Note: for earlier version of gcc (3.3) define _GLIBCPP_CONCEPT_CHECKS
161 BoolOption('concept_checks', 'Enable concept checks', True),
163 BoolOption('nls', 'Whether or not use native language support', True),
165 BoolOption('profiling', 'Whether or not enable profiling', False),
166 # config.h define _GLIBCXX_DEBUG and _GLIBCXX_DEBUG_PEDANTIC
167 BoolOption('stdlib_debug', 'Whether or not turn on stdlib debug', False),
169 BoolOption('X11', 'Use x11 windows system', default_with_x),
170 # use MS VC++ to build lyx
171 BoolOption('use_vc', 'Use MS VC++ to build lyx (cl.exe will be probed)', None),
173 PathOption('qt_dir', 'Path to qt directory', None),
175 PathOption('qt_inc_path', 'Path to qt include directory', None),
177 PathOption('qt_lib_path', 'Path to qt library directory', None),
178 # extra include and libpath
179 PathOption('extra_inc_path', 'Extra include path', None),
181 PathOption('extra_lib_path', 'Extra library path', None),
183 PathOption('extra_bin_path', 'A convenient way to add a path to $PATH', None),
185 PathOption('extra_inc_path1', 'Extra include path', None),
187 PathOption('extra_lib_path1', 'Extra library path', None),
189 ('rebuild', 'Obsolete option', None),
190 # can be set to a non-existing directory
191 ('prefix', 'install architecture-independent files in PREFIX', default_prefix),
192 # replace the default name and location of the windows installer
193 ('win_installer', 'name or full path to the windows installer', None),
194 # the deps package used to create minimal installer (qt and other libraries)
195 ('deps_dir', 'path to the development depedency packages with zlib, iconv, zlib and qt libraries', None),
196 # whether or not build bundle installer
197 BoolOption('bundle', 'Whether or not build bundle installer', False),
198 # the bundle directory, containing bundled applications
199 PathOption('bundle_dir', 'path to the bundle dependency package with miktex setup.exe etc', None),
200 # build directory, will use $mode if not set
201 ('build_dir', 'Build directory', None),
203 ('version_suffix', 'install lyx as lyx-suffix', None),
204 # how to load options
205 ('load_option', '''load option from previous scons run. option can be
206 yes (default): load all options
207 no: do not load any option
208 opt1,opt2: load specified options
209 -opt1,opt2: load all options other than specified ones''', 'yes'),
211 ('optimization', 'optimization CCFLAGS option.', None),
213 PathOption('exec_prefix', 'install architecture-independent executable files in PREFIX', None),
215 ('logfile', 'save commands (not outputs) to logfile', default_log_file),
216 # provided for backward compatibility
217 ('dest_dir', 'install to DESTDIR. (Provided for backward compatibility only)', None),
218 # environment variable can be set as options.
219 ('DESTDIR', 'install to DESTDIR', None),
220 ('CC', 'replace default $CC', None),
221 ('LINK', 'replace default $LINK', None),
222 ('CPP', 'replace default $CPP', None),
223 ('CXX', 'replace default $CXX', None),
224 ('CXXCPP', 'replace default $CXXCPP', None),
225 ('CCFLAGS', 'replace default $CCFLAGS', None),
226 ('CPPFLAGS', 'replace default $CPPFLAGS', None),
227 ('LINKFLAGS', 'replace default $LINKFLAGS', None),
231 all_options = [x.key for x in opts.options]
233 # copied from SCons/Options/BoolOption.py
234 # We need to use them before a boolean ARGUMENTS option is available
236 true_strings = ('y', 'yes', 'true', 't', '1', 'on' , 'all' )
237 false_strings = ('n', 'no', 'false', 'f', '0', 'off', 'none')
239 if ARGUMENTS.has_key('fast_start'):
240 print 'fast_start option is obsolete'
242 # if load_option=yes (default), load saved comand line options
244 # This option can take value yes/no/opt1,opt2/-opt1,opt2
245 # and tries to be clever in choosing options to load
246 if (not ARGUMENTS.has_key('load_option') or \
247 ARGUMENTS['load_option'] not in false_strings) \
248 and os.path.isfile(opt_cache_file):
249 cache_file = open(opt_cache_file)
250 opt_cache = cPickle.load(cache_file)
252 # import cached options, but we should ignore qt_dir when frontend changes
253 if ARGUMENTS.has_key('frontend') and opt_cache.has_key('frontend') \
254 and ARGUMENTS['frontend'] != opt_cache['frontend'] \
255 and opt_cache.has_key('qt_dir'):
256 opt_cache.pop('qt_dir')
257 # and we do not cache some options (dest_dir is obsolete)
258 for arg in ['load_option', 'dest_dir', 'bundle']:
259 if opt_cache.has_key(arg):
261 # remove obsolete cached keys (well, SConstruct is evolving. :-)
262 for arg in opt_cache.keys():
263 if arg not in all_options:
264 print 'Option %s is obsolete, do not load it' % arg
266 # now, if load_option=opt1,opt2 or -opt1,opt2
267 if ARGUMENTS.has_key('load_option') and \
268 ARGUMENTS['load_option'] not in true_strings + false_strings:
269 # if -opt1,opt2 is specified, do not load these options
270 if ARGUMENTS['load_option'][0] == '-':
271 for arg in ARGUMENTS['load_option'][1:].split(','):
272 if opt_cache.has_key(arg):
274 # if opt1,opt2 is specified, only load specified options
276 args = ARGUMENTS['load_option'].split(',')
277 for arg in opt_cache.keys():
280 # now restore options as if entered from command line
281 for key in opt_cache.keys():
282 if not ARGUMENTS.has_key(key):
283 ARGUMENTS[key] = opt_cache[key]
284 print "Restoring cached option %s=%s" % (key, ARGUMENTS[key])
287 # check if there is unused (or misspelled) argument
288 for arg in ARGUMENTS.keys():
289 if arg not in all_options:
291 print "Unknown option '%s'... exiting." % arg
293 print "Available options are (check 'scons -help' for details):"
294 print ' ' + '\n '.join(textwrap.wrap(', '.join(all_options)))
298 cache_file = open(opt_cache_file, 'w')
299 cPickle.dump(ARGUMENTS, cache_file)
302 #---------------------------------------------------------
303 # Setting up environment
304 #---------------------------------------------------------
306 # I do not really like ENV=os.environ, but you may add it
307 # here if you experience some environment related problem
308 env = Environment(options = opts)
310 # set individual variables since I do not really like ENV = os.environ
311 env['ENV']['PATH'] = os.environ.get('PATH')
312 env['ENV']['HOME'] = os.environ.get('HOME')
313 # these are defined for MSVC
314 env['ENV']['LIB'] = os.environ.get('LIB')
315 env['ENV']['INCLUDE'] = os.environ.get('INCLUDE')
317 # for simplicity, use var instead of env[var]
318 frontend = env['frontend']
319 prefix = env['prefix']
322 if platform_name == 'win32':
323 if env.has_key('use_vc'):
324 use_vc = env['use_vc']
325 if WhereIs('cl.exe') is None:
326 print "cl.exe is not found. Are you using the MSVC environment?"
328 elif WhereIs('cl.exe') is not None:
335 if env.has_key('build_dir') and env['build_dir'] is not None:
336 env['BUILDDIR'] = env['build_dir']
338 # Determine the name of the build $mode
339 env['BUILDDIR'] = '#' + mode
341 # all built libraries will go to build_dir/libs
342 # (This is different from the make file approach)
343 env['LOCALLIBPATH'] = '$BUILDDIR/libs'
344 env.AppendUnique(LIBPATH = ['$LOCALLIBPATH'])
347 # Here is a summary of variables defined in env
349 # 2. undefined options with a non-None default value
350 # 3. compiler commands and flags like CCFLAGS.
351 # MSGFMT used to process po files
352 # 4. Variables that will be used to replace variables in some_file.in
353 # lib/lyx2lyx/lyx2lyx_version.py.in
355 # FIXME Bo: Please look here, that's not needed anymore (Andre')
356 # src/support/Package.cpp.in:
357 # TOP_SRCDIR, LOCALEDIR, LYX_DIR, PROGRAM_SUFFIX
359 # full path name is used to build msvs project files
360 # and to replace TOP_SRCDIR in package.C
361 env['TOP_SRCDIR'] = Dir(top_src_dir).abspath
363 # determine share_dir etc
364 packaging_method = env.get('packaging')
365 if packaging_method == 'windows':
366 share_dir = 'Resources'
367 man_dir = 'Resources/man/man1'
368 locale_dir = 'Resources/locale'
370 share_dir = 'share/lyx'
371 locale_dir = 'share/locale'
372 if platform_name == 'cygwin':
373 man_dir = 'share/man/man1'
377 # program suffix: can be yes, or a string
378 if env.has_key('version_suffix'):
379 if env['version_suffix'] in true_strings:
380 program_suffix = package_version
381 elif env['version_suffix'] in false_strings:
384 program_suffix = env['version_suffix']
388 # FIXME Bo: Please look here, can this be simplified? (Andre')
389 # used by Package.cpp.in
390 env['PROGRAM_SUFFIX'] = program_suffix
392 # whether or not add suffix to file and directory names
393 add_suffix = packaging_method != 'windows'
394 # LYX_DIR are different (used in Package.cpp.in)
396 env['LYX_DIR'] = Dir(os.path.join(prefix, share_dir + program_suffix)).abspath
398 env['LYX_DIR'] = Dir(os.path.join(prefix, share_dir)).abspath
399 # we need absolute path for package.C
400 env['LOCALEDIR'] = Dir(os.path.join(prefix, locale_dir)).abspath
403 #---------------------------------------------------------
404 # Setting building environment (Tools, compiler flags etc)
405 #---------------------------------------------------------
407 # Since Tool('mingw') will reset CCFLAGS etc, this should be
408 # done before getEnvVariable
409 if platform_name == 'win32':
415 env.AppendUnique(CPPPATH = ['#c:/MinGW/include'])
416 # fix a scons winres bug (there is a missing space between ${RCINCPREFIX} and ${SOURCE.dir}
418 env['RCCOM'] = '$RC $_CPPDEFFLAGS $RCINCFLAGS ${RCINCPREFIX} ${SOURCE.dir} $RCFLAGS -i $SOURCE -o $TARGET'
421 # we differentiate between hard-coded options and default options
422 # hard-coded options are required and will always be there
423 # default options can be replaced by enviromental variables or command line options
424 CCFLAGS_required = []
425 LINKFLAGS_required = []
428 # if we use ms vc, the commands are fine (cl.exe and link.exe)
430 # C4819: The file contains a character that cannot be represented
431 # in the current code page (number)
432 # C4996: foo was decleared deprecated
433 CCFLAGS_required.append('/EHsc')
435 CCFLAGS_default.extend(['/wd4819', '/wd4996', '/nologo', '/MDd'])
436 # the flags are also needed in C mode (for intl lib)
437 C_CCFLAGS.extend(['/wd4819', '/wd4996', '/nologo', '/MDd'])
439 CCFLAGS_default.extend(['/wd4819', '/wd4996', '/nologo', '/MD'])
440 C_CCFLAGS.extend(['/wd4819', '/wd4996', '/nologo', '/MD'])
442 # for debug/release mode
443 if env.has_key('optimization') and env['optimization'] is not None:
444 # if user supplies optimization flags, use it anyway
445 CCFLAGS_required.extend(env['optimization'].split())
446 # and do not use default
447 set_default_optimization_flags = False
449 set_default_optimization_flags = True
453 CCFLAGS_required.append('/Zi')
454 LINKFLAGS_required.extend(['/debug', '/map'])
456 CCFLAGS_required.append('-g')
457 CCFLAGS_default.append('-O')
458 elif mode == 'release' and set_default_optimization_flags:
460 CCFLAGS_default.append('/O2')
462 CCFLAGS_default.append('-O2')
464 # msvc uses separate tools for profiling
465 if env.has_key('profiling') and env['profiling']:
467 print 'Visual C++ does not use profiling options'
469 CCFLAGS_required.append('-pg')
470 LINKFLAGS_required.append('-pg')
472 if env.has_key('warnings') and env['warnings']:
474 CCFLAGS_default.append('/W2')
476 # Note: autotools detect gxx version and pass -W for 3.x
477 # and -Wextra for other versions of gcc
478 CCFLAGS_default.append('-Wall')
480 # Now, set the variables as follows:
481 # 1. if command line option exists: replace default
482 # 2. then if s envronment variable exists: replace default
483 # 3. set variable to required + default
484 def setEnvVariable(env, name, required = None, default = None, split = True):
485 ''' env: environment to set variable
487 required: hardcoded options
488 default: default options that can be replaced by command line or
489 environment variables
490 split: whether or not split obtained variable like '-02 -g'
492 # 1. ARGUMENTS is already set to env[name], override default.
493 if ARGUMENTS.has_key(name):
494 # env[name] may be rewritten when building tools are reloaded
495 # if that is the case, commandline option will override it.
496 env[name] = ARGUMENTS[name]
498 # then use environment default
499 elif os.environ.has_key(name):
500 print "Acquiring variable %s from system environment: %s" % (name, os.environ[name])
501 default = os.environ[name]
503 default = default.split()
504 # the real value should be env[name] + default + required
507 if env.has_key(name):
508 value = str(env[name]).split()
509 if required is not None:
511 if default is not None:
515 if env.has_key(name):
516 value = str(env[name])
517 if required is not None:
518 value += " " + required
519 if default is not None:
520 value += " " + default
522 # print name, env[name]
524 setEnvVariable(env, 'DESTDIR', split=False)
525 setEnvVariable(env, 'CC')
526 setEnvVariable(env, 'LINK')
527 setEnvVariable(env, 'CPP')
528 setEnvVariable(env, 'CXX')
529 setEnvVariable(env, 'CXXCPP')
530 setEnvVariable(env, 'CCFLAGS', CCFLAGS_required, CCFLAGS_default)
531 setEnvVariable(env, 'CXXFLAGS')
532 setEnvVariable(env, 'CPPFLAGS')
533 setEnvVariable(env, 'LINKFLAGS', LINKFLAGS_required)
535 # if DESTDIR is not set...
536 if env.has_key('dest_dir'):
537 print "This option is obsolete. Please use DESTDIR instead."
538 env['DESTDIR'] = env['dest_dir']
541 # extra_inc_path and extra_lib_path
544 if env.has_key('extra_inc_path') and env['extra_inc_path']:
545 extra_inc_paths.append(env['extra_inc_path'])
546 if env.has_key('extra_lib_path') and env['extra_lib_path']:
547 env.AppendUnique(LIBPATH = [env['extra_lib_path']])
548 if env.has_key('extra_inc_path1') and env['extra_inc_path1']:
549 extra_inc_paths.append(env['extra_inc_path1'])
550 if env.has_key('extra_lib_path1') and env['extra_lib_path1']:
551 env.AppendUnique(LIBPATH = [env['extra_lib_path1']])
552 if env.has_key('extra_bin_path') and env['extra_bin_path']:
553 # only the first one is needed (a scons bug?)
554 os.environ['PATH'] += os.pathsep + env['extra_bin_path']
555 env.PrependENVPath('PATH', env['extra_bin_path'])
556 # extra_inc_paths will be used later by intlenv etc
557 env.AppendUnique(CPPPATH = extra_inc_paths)
560 #----------------------------------------------------------
562 #----------------------------------------------------------
564 conf = Configure(env,
566 'CheckPkgConfig' : utils.checkPkgConfig,
567 'CheckPackage' : utils.checkPackage,
568 'CheckMkdirOneArg' : utils.checkMkdirOneArg,
569 'CheckSelectArgType' : utils.checkSelectArgType,
570 'CheckBoostLibraries' : utils.checkBoostLibraries,
571 'CheckCommand' : utils.checkCommand,
572 'CheckNSIS' : utils.checkNSIS,
573 'CheckCXXGlobalCstd' : utils.checkCXXGlobalCstd,
574 'CheckLC_MESSAGES' : utils.checkLC_MESSAGES,
575 'CheckIconvConst' : utils.checkIconvConst,
576 'CheckSizeOfWChar' : utils.checkSizeOfWChar,
577 'CheckDeclaration' : utils.checkDeclaration,
581 # When using msvc, windows.h is required
582 if use_vc and not conf.CheckCHeader('windows.h'):
583 print 'Windows.h is not found. Please install Windows Platform SDK.'
584 print 'Please check config.log for more information.'
587 # pkg-config? (if not, we use hard-coded options)
588 if conf.CheckPkgConfig('0.15.0'):
589 env['HAS_PKG_CONFIG'] = True
591 print 'pkg-config >= 0.1.50 is not found'
592 env['HAS_PKG_CONFIG'] = False
594 # zlib? This is required.
595 if (not use_vc and not conf.CheckLibWithHeader('z', 'zlib.h', 'C')) \
596 or (use_vc and not conf.CheckLibWithHeader('zdll', 'zlib.h', 'C')):
597 print 'Did not find zdll.lib or zlib.h, exiting!'
598 print 'Please check config.log for more information.'
600 if conf.CheckLib('iconv'):
601 env['ICONV_LIB'] = 'iconv'
602 elif conf.CheckLib('libiconv'):
603 env['ICONV_LIB'] = 'libiconv'
604 elif conf.CheckFunc('iconv_open'):
605 env['ICONV_LIB'] = None
607 print 'Did not find iconv or libiconv, exiting!'
608 print 'Please check config.log for more information.'
613 if conf.CheckLib('socket'):
614 socket_libs.append('socket')
615 # nsl is the network services library and provides a
616 # transport-level interface to networking services.
617 if conf.CheckLib('nsl'):
618 socket_libs.append('nsl')
620 # check available boost libs (since lyx1.4 does not use iostream)
622 for lib in ['signals', 'regex', 'filesystem', 'iostreams']:
623 if os.path.isdir(os.path.join(top_src_dir, 'boost', 'libs', lib)):
624 boost_libs.append(lib)
626 # check boost libraries
627 boost_opt = ARGUMENTS.get('boost', 'auto')
628 # check for system boost
629 lib_paths = env['LIBPATH'] + ['/usr/lib', '/usr/local/lib']
630 inc_paths = env['CPPPATH'] + ['/usr/include', '/usr/local/include']
631 # default to $BUILDDIR/libs (use None since this path will be added anyway)
633 # here I assume that all libraries are in the same directory
634 if boost_opt == 'included':
635 boost_libraries = ['included_boost_%s' % x for x in boost_libs]
636 included_boost = True
637 env['BOOST_INC_PATH'] = '$TOP_SRCDIR/boost'
638 elif boost_opt == 'auto':
639 res = conf.CheckBoostLibraries(boost_libs, lib_paths, inc_paths, boost_version, mode == 'debug')
640 # if not found, use local boost
642 boost_libraries = ['included_boost_%s' % x for x in boost_libs]
643 included_boost = True
644 env['BOOST_INC_PATH'] = '$TOP_SRCDIR/boost'
646 included_boost = False
647 (boost_libraries, boost_libpath, env['BOOST_INC_PATH']) = res
648 elif boost_opt == 'system':
649 res = conf.CheckBoostLibraries(boost_libs, lib_paths, inc_paths, boost_version, mode == 'debug')
651 print "Can not find system boost libraries with version %s " % boost_version
652 print "Please supply a path through extra_lib_path and try again."
653 print "Or use boost=included to use included boost libraries."
656 included_boost = False
657 (boost_libraries, boost_libpath, env['BOOST_INC_PATH']) = res
660 if boost_libpath is not None:
661 env.AppendUnique(LIBPATH = [boost_libpath])
664 env['ENABLE_NLS'] = env['nls']
666 if not env['ENABLE_NLS']:
668 included_gettext = False
670 # check gettext libraries
671 gettext_opt = ARGUMENTS.get('gettext', 'auto')
672 # check for system gettext
674 if gettext_opt in ['auto', 'system']:
675 if conf.CheckFunc('gettext'):
676 included_gettext = False
679 elif conf.CheckLib('intl'):
680 included_gettext = False
684 if gettext_opt == 'system':
685 print "Can not find system gettext library"
686 print "Please supply a path through extra_lib_path and try again."
687 print "Or use gettext=included to use included gettext libraries."
689 # now, auto and succ = false, or gettext=included
691 # we do not need to set LIBPATH now.
692 included_gettext = True
693 intl_libs = ['included_intl']
697 # check for msgfmt command
698 env['MSGFMT'] = conf.CheckCommand('msgfmt')
699 env['MSGMERGE'] = conf.CheckCommand('msgmerge')
700 env['XGETTEXT'] = conf.CheckCommand('xgettext')
701 env['MSGUNIQ'] = conf.CheckCommand('msguniq')
703 # if under windows, check the nsis compiler
704 if platform_name == 'win32':
705 env['NSIS'] = conf.CheckNSIS()
707 # cygwin packaging requires the binaries to be stripped
708 if platform_name == 'cygwin':
709 env['STRIP'] = conf.CheckCommand('strip')
712 # Customized builders
714 # install customized builders
715 env['BUILDERS']['substFile'] = Builder(action = utils.env_subst)
716 env['BUILDERS']['installTOC'] = Builder(action = utils.env_toc)
717 env['BUILDERS']['potfiles'] = Builder(action = utils.env_potfiles)
720 #----------------------------------------------------------
721 # Generating config.h
722 #----------------------------------------------------------
723 aspell_lib = 'aspell'
724 # assume that we use aspell, aspelld compiled for msvc
725 if platform_name == 'win32' and mode == 'debug' and use_vc:
726 aspell_lib = 'aspelld'
728 # check the existence of config.h
729 config_h = os.path.join(env.Dir('$BUILDDIR/src').path, 'config.h')
730 boost_config_h = os.path.join(env.Dir('$BUILDDIR/boost').path, 'config.h')
732 print "Creating %s..." % boost_config_h
734 utils.createConfigFile(conf,
735 config_file = boost_config_h,
736 config_pre = r'''/* boost/config.h. Generated by SCons. */
741 * This file is part of LyX, the document processor.
742 * Licence details can be found in the file COPYING.
744 * This is the compilation configuration file for LyX.
745 * It was generated by scon.
746 * You might want to change some of the defaults if something goes wrong
747 * during the compilation.
750 #ifndef _BOOST_CONFIG_H
751 #define _BOOST_CONFIG_H
754 ('ostream', 'HAVE_OSTREAM', 'cxx'),
755 ('locale', 'HAVE_LOCALE', 'cxx'),
756 ('sstream', 'HAVE_SSTREAM', 'cxx'),
757 #('newapis.h', 'HAVE_NEWAPIS_H', 'c'),
760 (env.has_key('assertions') and env['assertions'],
762 'Define if you want assertions to be enabled in the code'
766 ('wchar_t', 'HAVE_WCHAR_T', None),
770 #if defined(HAVE_OSTREAM) && defined(HAVE_LOCALE) && defined(HAVE_SSTREAM)
771 # define USE_BOOST_FORMAT 1
773 # define USE_BOOST_FORMAT 0
776 #if !defined(ENABLE_ASSERTIONS)
777 # define BOOST_DISABLE_ASSERTS 1
779 #define BOOST_ENABLE_ASSERT_HANDLER 1
781 #define BOOST_DISABLE_THREADS 1
782 #define BOOST_NO_WSTRING 1
785 # define BOOST_POSIX 1
786 # define BOOST_POSIX_API 1
787 # define BOOST_POSIX_PATH 1
790 #define BOOST_ALL_NO_LIB 1
792 #if defined(HAVE_NEWAPIS_H)
793 # define WANT_GETFILEATTRIBUTESEX_WRAPPER 1
797 * the FreeBSD libc uses UCS4, but libstdc++ has no proper wchar_t
798 * support compiled in:
799 * http://gcc.gnu.org/onlinedocs/libstdc++/faq/index.html#3_9
800 * And we are not interested at all what libc
801 * does: What we need is a 32bit wide wchar_t, and a libstdc++ that
802 * has the needed wchar_t support and uses UCS4. Whether it
803 * implements this with the help of libc, or whether it has own code
804 * does not matter for us, because we don't use libc directly (Georg)
806 #if defined(HAVE_WCHAR_T) && SIZEOF_WCHAR_T == 4 && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
814 print "\nGenerating %s..." % config_h
816 # AIKSAURUS_H_LOCATION
817 if (conf.CheckCXXHeader("Aiksaurus.h")):
818 aik_location = '<Aiksaurus.h>'
819 elif (conf.CheckCXXHeader("Aiksaurus/Aiksaurus.h")):
820 aik_location = '<Aiksaurus/Aiksaurus.h>'
824 # determine headers to use
825 spell_opt = ARGUMENTS.get('spell', 'auto')
826 env['USE_ASPELL'] = False
827 env['USE_PSPELL'] = False
828 env['USE_ISPELL'] = False
829 if spell_opt in ['auto', 'aspell'] and conf.CheckLib(aspell_lib):
830 spell_engine = 'USE_ASPELL'
831 elif spell_opt in ['auto', 'pspell'] and conf.CheckLib('pspell'):
832 spell_engine = 'USE_PSPELL'
833 elif spell_opt in ['auto', 'ispell'] and conf.CheckLib('ispell'):
834 spell_engine = 'USE_ISPELL'
838 if spell_engine is not None:
839 env[spell_engine] = True
841 if spell_opt == 'auto':
842 print "Warning: Can not locate any spell checker"
843 elif spell_opt != 'no':
844 print "Warning: Can not locate specified spell checker:", spell_opt
845 print 'Please check config.log for more information.'
848 # check arg types of select function
849 (select_arg1, select_arg234, select_arg5) = conf.CheckSelectArgType()
851 # check the size of wchar_t
852 sizeof_wchar_t = conf.CheckSizeOfWChar()
854 if sizeof_wchar_t == 0:
855 print 'Error: Can not determine the size of wchar_t.'
856 print 'Please check config.log for more information.'
860 # fill in the version info
861 env['VERSION_INFO'] = '''Configuration
863 Special build flags: %s
865 C Compiler flags: %s %s
867 C++ Compiler LyX flags: %s
868 C++ Compiler flags: %s %s
870 Linker user flags: %s
872 Builing directory: %s
873 Local library directory: %s
876 include search path: %s
882 ''' % (platform_name,
883 env.subst('$CCFLAGS'), env.subst('$CC'),
884 env.subst('$CPPFLAGS'), env.subst('$CFLAGS'),
885 env.subst('$CXX'), env.subst('$CXXFLAGS'),
886 env.subst('$CPPFLAGS'), env.subst('$CXXFLAGS'),
887 env.subst('$LINKFLAGS'), env.subst('$LINKFLAGS'),
888 env.subst('$BUILDDIR'), env.subst('$LOCALLIBPATH'),
889 str(env['LIBPATH']), str(boost_libraries),
891 frontend, packaging_method,
892 prefix, env['LYX_DIR'])
896 result = utils.createConfigFile(conf,
897 config_file = config_h,
898 config_pre = r'''/* config.h. Generated by SCons. */
903 * This file is part of LyX, the document processor.
904 * Licence details can be found in the file COPYING.
906 * This is the compilation configuration file for LyX.
907 * It was generated by scon.
908 * You might want to change some of the defaults if something goes wrong
909 * during the compilation.
916 ('io.h', 'HAVE_IO_H', 'c'),
917 ('limits.h', 'HAVE_LIMITS_H', 'c'),
918 ('locale.h', 'HAVE_LOCALE_H', 'c'),
919 ('process.h', 'HAVE_PROCESS_H', 'c'),
920 ('stdlib.h', 'HAVE_STDLIB_H', 'c'),
921 ('sys/stat.h', 'HAVE_SYS_STAT_H', 'c'),
922 ('sys/time.h', 'HAVE_SYS_TIME_H', 'c'),
923 ('sys/types.h', 'HAVE_SYS_TYPES_H', 'c'),
924 ('sys/utime.h', 'HAVE_SYS_UTIME_H', 'c'),
925 ('sys/socket.h', 'HAVE_SYS_SOCKET_H', 'c'),
926 ('unistd.h', 'HAVE_UNISTD_H', 'c'),
927 ('utime.h', 'HAVE_UTIME_H', 'c'),
928 ('direct.h', 'HAVE_DIRECT_H', 'c'),
929 ('istream', 'HAVE_ISTREAM', 'cxx'),
930 ('ios', 'HAVE_IOS', 'cxx'),
933 ('open', 'HAVE_OPEN', None),
934 ('chmod', 'HAVE_CHMOD', None),
935 ('close', 'HAVE_CLOSE', None),
936 ('popen', 'HAVE_POPEN', None),
937 ('pclose', 'HAVE_PCLOSE', None),
938 ('_open', 'HAVE__OPEN', None),
939 ('_close', 'HAVE__CLOSE', None),
940 ('_popen', 'HAVE__POPEN', None),
941 ('_pclose', 'HAVE__PCLOSE', None),
942 ('getpid', 'HAVE_GETPID', None),
943 ('_getpid', 'HAVE__GETPID', None),
944 ('mkdir', 'HAVE_MKDIR', None),
945 ('_mkdir', 'HAVE__MKDIR', None),
946 ('mktemp', 'HAVE_MKTEMP', None),
947 ('mkstemp', 'HAVE_MKSTEMP', None),
948 ('strerror', 'HAVE_STRERROR', None),
949 ('getcwd', 'HAVE_GETCWD', None),
950 ('setenv', 'HAVE_SETENV', None),
951 ('putenv', 'HAVE_PUTENV', None),
952 ('fcntl', 'HAVE_FCNTL', None),
953 ('mkfifo', 'HAVE_MKFIFO', None),
956 ('mkstemp', 'HAVE_DECL_MKSTEMP', ['unistd.h', 'stdlib.h']),
959 ('std::istreambuf_iterator<std::istream>', 'HAVE_DECL_ISTREAMBUF_ITERATOR',
960 '#include <streambuf>\n#include <istream>'),
961 ('wchar_t', 'HAVE_WCHAR_T', None),
962 ('mode_t', 'HAVE_MODE_T', "#include <sys/types.h>"),
965 ('gdi32', 'HAVE_LIBGDI32'),
966 (('Aiksaurus', 'libAiksaurus'), 'HAVE_LIBAIKSAURUS', 'AIKSAURUS_LIB'),
969 (conf.CheckType('pid_t', includes='#include <sys/types.h>'),
971 'Define is sys/types.h does not have pid_t',
975 (conf.CheckCXXGlobalCstd(),
977 'Define if your C++ compiler puts C library functions in the global namespace'
979 (conf.CheckMkdirOneArg(),
980 'MKDIR_TAKES_ONE_ARG',
981 'Define if mkdir takes only one argument.'
983 (conf.CheckIconvConst(),
985 'Define as const if the declaration of iconv() needs const.',
986 '#define ICONV_CONST const',
987 '#define ICONV_CONST',
989 (conf.CheckLC_MESSAGES(),
991 'Define if your <locale.h> file defines LC_MESSAGES.'
993 (devel_version, 'DEVEL_VERSION', 'Whether or not a development version'),
996 "Define to 1 if translation of program messages to the user's native anguage is requested.",
998 (env['nls'] and not included_gettext,
1000 'Define to 1 if using system gettext library'
1002 (env.has_key('concept_checks') and env['concept_checks'],
1003 '_GLIBCXX_CONCEPT_CHECKS',
1004 'libstdc++ concept checking'
1006 (env.has_key('stdlib_debug') and env['stdlib_debug'],
1008 'libstdc++ debug mode'
1010 (env.has_key('stdlib_debug') and env['stdlib_debug'],
1011 '_GLIBCXX_DEBUG_PEDANTIC',
1012 'libstdc++ pedantic debug mode'
1014 (os.name != 'nt', 'BOOST_POSIX',
1015 'Indicates to boost < 1.34 which API to use (posix or windows).'
1017 (os.name != 'nt', 'BOOST_POSIX_API',
1018 'Indicates to boost 1.34 which API to use (posix or windows).'
1020 (os.name != 'nt', 'BOOST_POSIX_PATH',
1021 'Indicates to boost 1.34 which path style to use (posix or windows).'
1023 (spell_engine is not None, spell_engine,
1024 'Spell engine to use'
1026 # we need to know the byte order for unicode conversions
1027 (sys.byteorder == 'big', 'WORDS_BIGENDIAN',
1028 'Define to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX).'
1032 ('#define PACKAGE "%s%s"' % (package, program_suffix),
1034 ('#define PACKAGE_BUGREPORT "%s"' % package_bugreport,
1035 'Define to the address where bug reports for this package should be sent.'),
1036 ('#define PACKAGE_NAME "%s"' % package_name,
1037 'Define to the full name of this package.'),
1038 ('#define PACKAGE_STRING "%s"' % package_string,
1039 'Define to the full name and version of this package.'),
1040 ('#define PACKAGE_TARNAME "%s"' % package_tarname,
1041 'Define to the one symbol short name of this package.'),
1042 ('#define PACKAGE_VERSION "%s"' % package_version,
1043 'Define to the version of this package.'),
1044 ('#define VERSION_INFO "%s"' % env['VERSION_INFO'].replace('\n', '\\n'),
1045 'Full version info'),
1046 ('#define LYX_DATE "%s"' % lyx_date,
1048 ('#define PROGRAM_SUFFIX "%s"' % '$PROGRAM_SUFFIX',
1049 'Program version suffix'),
1050 ('#define LYX_ABS_INSTALLED_DATADIR "%s"' % '$LYX_DIR',
1051 'Hard coded system support directory'),
1052 ('#define LYX_ABS_INSTALLED_LOCALEDIR "%s"' % '$LOCALEDIR',
1053 'Hard coded locale directory'),
1054 ('#define LYX_ABS_TOP_SRCDIR "%s"' % '$TOP_SRCDIR',
1055 'Top source directory'),
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()
1410 print env['VERSION_INFO']
1413 # Mingw command line may be too short for our link usage,
1414 # Here we use a trick from scons wiki
1415 # http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/LongCmdLinesOnWin32
1417 # I also would like to add logging (commands only) capacity to the
1419 logfile = env.get('logfile', default_log_file)
1420 if logfile != '' or platform_name == 'win32':
1422 utils.setLoggedSpawn(env, logfile, longarg = (platform_name == 'win32'),
1423 info = '''# This is a log of commands used by scons to build lyx
1427 ''' % (time.asctime(), ' '.join(sys.argv),
1428 env['VERSION_INFO'].replace('\n','\n# ')) )
1433 # -h will print out help info
1434 Help(opts.GenerateHelpText(env))
1437 #----------------------------------------------------------
1439 #----------------------------------------------------------
1440 # this has been the source of problems on some platforms...
1441 # I find that I need to supply it with full path name
1442 env.SConsignFile(os.path.join(Dir(env['BUILDDIR']).abspath, '.sconsign'))
1443 # this usage needs further investigation.
1444 #env.CacheDir('%s/Cache/%s' % (env['BUILDDIR'], frontend))
1445 env.BuildDir('$BUILDDIR/boost', '$TOP_SRCDIR/boost/libs', duplicate = 0)
1446 env.BuildDir('$BUILDDIR/intl', '$TOP_SRCDIR/intl', duplicate = 0)
1447 env.BuildDir('$BUILDDIR/src', '$TOP_SRCDIR/src', duplicate = 0)
1448 frontend_env.BuildDir('$BUILDDIR/src', '$TOP_SRCDIR/src', duplicate = 0)
1450 print "Building all targets recursively"
1452 def libExists(libname):
1453 ''' Check whether or not lib $LOCALLIBNAME/libname already exists'''
1454 return os.path.isfile(File(env.subst('$LOCALLIBPATH/${LIBPREFIX}%s$LIBSUFFIX'%libname)).abspath)
1457 if (included_boost and not libExists('included_boost_regex')) or 'boost' in BUILD_TARGETS:
1461 for lib in boost_libs:
1462 boostlib = env.StaticLibrary(
1463 target = '$LOCALLIBPATH/included_boost_%s' % lib,
1464 source = ['$BUILDDIR/boost/%s/src/%s' % (lib, x) for x in eval('boost_libs_%s_src_files' % lib)],
1465 # do not use global CPPPATH because src/config.h will mess up with boost/config.h
1466 CPPPATH = ['$BUILDDIR/boost'] + extra_inc_paths,
1467 CCFLAGS = ['$CCFLAGS', '$INCPREFIX$TOP_SRCDIR/boost', '-DBOOST_USER_CONFIG="<config.h>"']
1469 Alias('boost', boostlib)
1472 if (included_gettext and not libExists('included_intl')) or 'intl' in BUILD_TARGETS:
1477 r'-DLOCALEDIR=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1478 r'-DLOCALE_ALIAS_PATH=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1479 r'-DLIBDIR=\"' + env['TOP_SRCDIR'].replace('\\', '\\\\') + r'/lib\"',
1481 '-DENABLE_RELOCATABLE=1',
1483 r'-DINSTALLDIR=\"' + prefix.replace('\\', '\\\\') + r'/lib\"',
1485 '-Dset_relocation_prefix=libintl_set_relocation_prefix',
1486 '-Drelocate=libintl_relocate',
1487 '-DDEPENDS_ON_LIBICONV=1',
1491 INTL_CCFLAGS.extend(['/Dinline#', '/D__attribute__(x)#', '/Duintmax_t=UINT_MAX'])
1493 intl = env.StaticLibrary(
1494 target = '$LOCALLIBPATH/included_intl',
1496 CCFLAGS = INTL_CCFLAGS,
1497 # do not use global CPPPATH because src/config.h will mess up with intl/config.h
1498 CPPPATH = ['$BUILDDIR/intl'] + extra_inc_paths,
1499 source = ['$BUILDDIR/intl/%s' % x for x in intl_files]
1506 frontend_env.Depends('$BUILDDIR/src/support/Package.cpp', '$BUILDDIR/src/config.h')
1507 Package_cpp = env.substFile('$BUILDDIR/src/support/Package.cpp', '$TOP_SRCDIR/src/support/Package.cpp.in')
1509 support = frontend_env.StaticLibrary(
1510 target = '$LOCALLIBPATH/support',
1511 source = ['$BUILDDIR/src/support/%s' % x for x in src_support_files] + Package_cpp + \
1512 ['$BUILDDIR/src/support/minizip/%s' % x for x in src_support_minizip_files],
1516 '-DQT_CLEAN_NAMESPACE',
1521 CPPPATH = ['$CPPPATH', '$TOP_SRCDIR/src/support/minizip']
1523 Alias('support', support)
1529 mathed = env.StaticLibrary(
1530 target = '$LOCALLIBPATH/mathed',
1531 source = ['$BUILDDIR/src/mathed/%s' % x for x in src_mathed_files]
1533 Alias('mathed', mathed)
1539 insets = env.StaticLibrary(
1540 target = '$LOCALLIBPATH/insets',
1541 source = ['$BUILDDIR/src/insets/%s' % x for x in src_insets_files]
1543 Alias('insets', insets)
1549 frontends = env.StaticLibrary(
1550 target = '$LOCALLIBPATH/frontends',
1551 source = ['$BUILDDIR/src/frontends/%s' % x for x in src_frontends_files]
1553 Alias('frontends', frontends)
1559 graphics = env.StaticLibrary(
1560 target = '$LOCALLIBPATH/graphics',
1561 source = ['$BUILDDIR/src/graphics/%s' % x for x in src_graphics_files]
1563 Alias('graphics', graphics)
1567 # src/frontends/controllers
1569 controllers = env.StaticLibrary(
1570 target = '$LOCALLIBPATH/controllers',
1571 source = ['$BUILDDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files]
1573 Alias('controllers', controllers)
1579 frontend_env['QT4_MOCHPREFIX'] = ''
1580 frontend_env['QT4_MOCHSUFFIX'] = '_moc.cpp'
1582 # tells scons how to get these moced files, although not all moced files are needed
1583 # (or are actually generated).
1584 qt4_moced_files = [frontend_env.Moc4('$BUILDDIR/src/frontends/qt4/%s' % x)
1585 for x in src_frontends_qt4_header_files ]
1586 resources = [frontend_env.Uic4('$BUILDDIR/src/frontends/qt4/ui/%s' % x.split('.')[0])
1587 for x in src_frontends_qt4_ui_files]
1590 # moc qt4_moc_files, the moced files are included in the original files
1592 qt4 = frontend_env.StaticLibrary(
1593 target = '$LOCALLIBPATH/qt4',
1594 source = ['$BUILDDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_files],
1598 '$BUILDDIR/src/images',
1599 '$BUILDDIR/src/frontends',
1600 '$BUILDDIR/src/frontends/qt4',
1601 '$BUILDDIR/src/frontends/qt4/ui',
1602 '$BUILDDIR/src/frontends/controllers'
1607 '-DQT_CLEAN_NAMESPACE',
1619 if env['HAVE_FCNTL']:
1620 client = frontend_env.Program(
1621 target = '$BUILDDIR/src/client/lyxclient',
1622 LIBS = ['support'] + intl_libs + system_libs +
1623 socket_libs + boost_libraries + qtcore_lib,
1624 source = ['$BUILDDIR/src/client/%s' % x for x in src_client_files] + \
1625 utils.createResFromIcon(frontend_env, 'lyx_32x32.ico', '$LOCALLIBPATH/client.rc')
1627 Alias('client', frontend_env.Command(os.path.join('$BUILDDIR', os.path.split(str(client[0]))[1]),
1628 client, [Copy('$TARGET', '$SOURCE')]))
1631 Alias('client', client)
1637 for file in src_tex2lyx_copied_files:
1638 frontend_env.Command('$BUILDDIR/src/tex2lyx/'+file, '$TOP_SRCDIR/src/'+file,
1639 [Copy('$TARGET', '$SOURCE')])
1641 tex2lyx = frontend_env.Program(
1642 target = '$BUILDDIR/src/tex2lyx/tex2lyx',
1643 LIBS = ['support'] + boost_libraries + intl_libs + system_libs + qtcore_lib,
1644 source = ['$BUILDDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_files + src_tex2lyx_copied_files] + \
1645 utils.createResFromIcon(frontend_env, 'lyx_32x32.ico', '$LOCALLIBPATH/tex2lyx.rc'),
1646 CPPPATH = ['$BUILDDIR/src/tex2lyx', '$CPPPATH'],
1647 LIBPATH = ['#$LOCALLIBPATH', '$LIBPATH'],
1648 CCFLAGS = ['$CCFLAGS', '-DTEX2LYX'],
1650 Alias('tex2lyx', frontend_env.Command(os.path.join('$BUILDDIR', os.path.split(str(tex2lyx[0]))[1]),
1651 tex2lyx, [Copy('$TARGET', '$SOURCE')]))
1652 Alias('tex2lyx', tex2lyx)
1658 if env.has_key('USE_ASPELL') and env['USE_ASPELL']:
1659 src_post_files.append('ASpell.cpp')
1660 elif env.has_key('USE_PSPELL') and env['USE_PSPELL']:
1661 src_post_files.append('PSpell.cpp')
1662 elif env.has_key('USE_ISPELL') and env['USE_ISPELL']:
1663 src_post_files.append('ISpell.cpp')
1665 # msvc requires at least one source file with main()
1666 # so I exclude main.cpp from lyxbase
1667 lyxbase_pre = env.StaticLibrary(
1668 target = '$LOCALLIBPATH/lyxbase_pre',
1669 source = ['$BUILDDIR/src/%s' % x for x in src_pre_files]
1671 lyxbase_post = env.StaticLibrary(
1672 target = '$LOCALLIBPATH/lyxbase_post',
1673 source = ["$BUILDDIR/src/%s" % x for x in src_post_files]
1675 Alias('lyxbase', lyxbase_pre)
1676 Alias('lyxbase', lyxbase_post)
1680 # Build lyx with given frontend
1682 lyx = frontend_env.Program(
1683 target = '$BUILDDIR/lyx',
1684 source = ['$BUILDDIR/src/main.cpp'] + \
1685 utils.createResFromIcon(frontend_env, 'lyx_32x32.ico', '$LOCALLIBPATH/lyx.rc'),
1706 if use_vc and 'msvs_projects' in BUILD_TARGETS:
1707 def build_project(target, full_target = None,
1708 src = [], inc = [], res = []):
1709 ''' build mavs project files
1710 target: alias (correspond to directory name)
1711 full_target: full path/filename of the target
1716 For non-debug-able targets like static libraries, target (alias) is
1717 enough to build the target. For executable targets, msvs need to know
1718 the full path to start debug them.
1721 if full_target is None:
1722 build_target = target
1724 build_target = full_target
1726 proj = env.MSVSProject(
1727 target = target + env['MSVSPROJECTSUFFIX'],
1728 # this allows easy access to header files (along with source)
1729 srcs = [env.subst(x) for x in src + inc],
1730 incs = [env.subst('$TOP_SRCDIR/src/config.h')],
1731 localincs = [env.subst(x) for x in inc],
1732 resources = [env.subst(x) for x in res],
1733 buildtarget = build_target,
1737 Alias('msvs_projects', proj)
1739 build_project('client', src = ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_files],
1740 inc = ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_header_files],
1741 full_target = File(env.subst('$BUILDDIR/src/client/lyxclient$PROGSUFFIX')).abspath)
1743 build_project('tex2lyx', src = ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_files],
1744 inc = ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_header_files],
1745 full_target = File(env.subst('$BUILDDIR/src/tex2lyx/tex2lyx$PROGSUFFIX')).abspath)
1747 build_project('lyx',
1748 src = ['$TOP_SRCDIR/src/%s' % x for x in src_pre_files + src_post_files + ['version.cpp']] + \
1749 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_files + ['Package.cpp'] ] + \
1750 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_files] + \
1751 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_files] + \
1752 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_files] + \
1753 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_files] + \
1754 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files] + \
1755 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_files],
1756 inc = ['$TOP_SRCDIR/src/%s' % x for x in src_header_files] + \
1757 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files] + \
1758 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_header_files] + \
1759 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files] + \
1760 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files] + \
1761 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files] + \
1762 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files] + \
1763 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_header_files],
1764 res = ['$TOP_SRCDIR/src/frontends/qt4/ui/%s' % x for x in src_frontends_qt4_ui_files],
1765 full_target = File(env.subst('$BUILDDIR/lyx$PROGSUFFIX')).abspath)
1768 if 'update_po' in BUILD_TARGETS:
1772 print 'Updating po/*.po files...'
1774 # whether or not update po files
1775 if not env['XGETTEXT'] or not env['MSGMERGE'] or not env['MSGUNIQ']:
1776 print 'xgettext or msgmerge does not exist. Cannot merge po files'
1778 # rebuild POTFILES.in
1779 POTFILES_in = env.potfiles('$TOP_SRCDIR/po/POTFILES.in',
1780 ['$TOP_SRCDIR/src/%s' % x for x in src_header_files + src_pre_files + src_post_files + \
1781 src_extra_src_files] + \
1782 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files + src_support_files + \
1783 src_support_extra_header_files + src_support_extra_src_files] + \
1784 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_header_files + src_mathed_files] + \
1785 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files + src_insets_files] + \
1786 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files + src_frontends_files] + \
1787 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files + src_graphics_files] + \
1788 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files + src_frontends_controllers_files] + \
1789 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_header_files + src_frontends_qt4_files + src_frontends_qt4_moc_files] + \
1790 ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_header_files + src_client_files ] + \
1791 ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_header_files + src_tex2lyx_files ]
1793 Alias('update_po', POTFILES_in)
1794 # build language_l10n.pot, ui_l10n.pot, layouts_l10n.pot, qt4_l10n.pot, external_l10n
1795 # and combine them to lyx.po
1796 env['LYX_POT'] = 'python $TOP_SRCDIR/po/lyx_pot.py'
1797 lyx_po = env.Command('$BUILDDIR/po/lyx.po',
1798 env.Command('$BUILDDIR/po/all.po',
1799 [env.Command('$BUILDDIR/po/qt4_l10n.pot',
1800 ['$TOP_SRCDIR/src/frontends/qt4/ui/%s' % x for x in src_frontends_qt4_ui_files],
1801 '$LYX_POT -b $TOP_SRCDIR -t qt4 -o $TARGET $SOURCES'),
1802 env.Command('$BUILDDIR/po/layouts_l10n.pot',
1803 ['$TOP_SRCDIR/lib/layouts/%s' % x for x in lib_layouts_files + lib_layouts_inc_files],
1804 '$LYX_POT -b $TOP_SRCDIR -t layouts -o $TARGET $SOURCES'),
1805 env.Command('$BUILDDIR/po/languages_l10n.pot', '$TOP_SRCDIR/lib/languages',
1806 '$LYX_POT -b $TOP_SRCDIR -t languages -o $TARGET $SOURCES'),
1807 env.Command('$BUILDDIR/po/ui_l10n.pot',
1808 ['$TOP_SRCDIR/lib/ui/%s' % x for x in lib_ui_files],
1809 '$LYX_POT -b $TOP_SRCDIR -t ui -o $TARGET $SOURCES'),
1810 env.Command('$BUILDDIR/po/external_l10n.pot', '$TOP_SRCDIR/lib/external_templates',
1811 '$LYX_POT -b $TOP_SRCDIR -t external -o $TARGET $SOURCES'),
1813 ['$MSGUNIQ -o $TARGET $SOURCE',
1814 '''$XGETTEXT --default-domain=${TARGET.base} \
1815 --directory=$TOP_SRCDIR --add-comments=TRANSLATORS: \
1816 --language=C++ --join-existing \
1817 --keyword=_ --keyword=N_ --keyword=B_ --keyword=qt_ \
1818 --files-from=$TOP_SRCDIR/po/POTFILES.in \
1819 --copyright-holder="LyX Developers" \
1820 --msgid-bugs-address="lyx-devel@lists.lyx.org" ''']
1822 env.Depends(lyx_po, POTFILES_in)
1823 # copy lyx.po to lyx.pot
1824 lyx_pot = env.Command('$BUILDDIR/po/lyx.pot', lyx_po,
1825 Copy('$TARGET', '$SOURCE'))
1828 # files to translate
1829 transfiles = glob.glob(os.path.join(env.Dir('$TOP_SRCDIR/po').abspath, '*.po'))
1830 # possibly *only* handle these languages
1832 if env.has_key('languages'):
1833 languages = env.make_list(env['languages'])
1834 # merge. if I use lan.po as $TARGET, it will be removed
1835 # before it is merged. In this builder,
1836 # $BUILDDIR/po/lang.po is merged from po/lang.po and $BUILDDIR/po/lyx.pot
1837 # and is copied to po/lang.po
1838 env['BUILDERS']['msgmerge'] = Builder(action=[
1839 '$MSGMERGE $TOP_SRCDIR/po/${TARGET.filebase}.po $SOURCE -o $TARGET',
1840 Copy('$TOP_SRCDIR/po/${TARGET.filebase}.po', '$TARGET')]
1842 # for each po file, generate pot
1843 for po_file in transfiles:
1845 fname = os.path.split(po_file)[1]
1847 country = fname.split('.')[0]
1849 if not languages or country in languages:
1850 # merge po files, the generated lan.po_new file is copied to lan.po file.
1851 po = env.msgmerge('$BUILDDIR/po/%s.po' % country, lyx_pot)
1852 env.Depends(po, POTFILES_in)
1853 Alias('update_po', po)
1856 # if 'install' is not in the target, do not process this
1857 if 'install' in BUILD_TARGETS or 'installer' in BUILD_TARGETS:
1859 # this part is a bit messy right now. Since scons will provide
1860 # --DESTDIR option soon, at least the dest_dir handling can be
1869 # files to translate
1870 transfiles = glob.glob(os.path.join(env.subst('$TOP_SRCDIR'), 'po', '*.po'))
1871 # possibly *only* handle these languages
1873 if env.has_key('languages'):
1874 languages = env.make_list(env['lanauges'])
1875 # use defulat msgfmt
1877 if not env['MSGFMT']:
1878 print 'msgfmt does not exist. Can not process po files'
1881 env['BUILDERS']['Transfiles'] = Builder(action='$MSGFMT $SOURCE -c --statistics -o $TARGET',suffix='.gmo',src_suffix='.po')
1883 for f in transfiles:
1885 fname = os.path.split(f)[1]
1887 country = fname.split('.')[0]
1889 if not languages or country in languages:
1890 gmo_files.extend(env.Transfiles(f))
1891 # how to join dest_dir and prefix
1892 def joinPaths(path1, path2):
1893 ''' join path1 and path2, do not use os.path.join because
1894 under window, c:\destdir\d:\program is invalid '''
1896 return os.path.normpath(path2)
1897 # separate drive letter
1898 (drive, path) = os.path.splitdrive(os.path.normpath(path2))
1899 # ignore drive letter, so c:\destdir + c:\program = c:\destdir\program
1900 return os.path.join(os.path.normpath(path1), path[1:])
1902 # install to dest_dir/prefix
1903 dest_dir = env.get('DESTDIR', '')
1904 dest_prefix_dir = joinPaths(dest_dir, env.Dir(prefix).abspath)
1905 # create the directory if needed
1906 if not os.path.isdir(dest_prefix_dir):
1908 os.makedirs(dest_prefix_dir)
1911 if not os.path.isdir(dest_prefix_dir):
1912 print 'Can not create directory', dest_prefix_dir
1915 if env.has_key('exec_prefix'):
1916 bin_dest_dir = joinPaths(dest_dir, Dir(env['exec_prefix']).abspath)
1918 bin_dest_dir = os.path.join(dest_prefix_dir, 'bin')
1920 share_dest_dir = os.path.join(dest_prefix_dir, share_dir + program_suffix)
1922 share_dest_dir = os.path.join(dest_prefix_dir, share_dir)
1923 man_dest_dir = os.path.join(dest_prefix_dir, man_dir)
1924 locale_dest_dir = os.path.join(dest_prefix_dir, locale_dir)
1925 env['LYX2LYX_DEST'] = os.path.join(share_dest_dir, 'lyx2lyx')
1929 # install executables (lyxclient may be None)
1932 version_suffix = program_suffix
1936 # install lyx, if in release mode, try to strip the binary
1937 if env.has_key('STRIP') and env['STRIP'] is not None and mode != 'debug':
1938 # create a builder to strip and install
1939 env['BUILDERS']['StripInstallAs'] = Builder(action='$STRIP $SOURCE -o $TARGET')
1941 # install executables
1942 for (name, obj) in (('lyx', lyx), ('tex2lyx', tex2lyx), ('client', client)):
1945 target_name = os.path.split(str(obj[0]))[1].replace(name, '%s%s' % (name, version_suffix))
1946 target = os.path.join(bin_dest_dir, target_name)
1947 if env['BUILDERS'].has_key('StripInstallAs'):
1948 env.StripInstallAs(target, obj)
1950 env.InstallAs(target, obj)
1951 Alias('install', target)
1955 for (dir,files) in [
1957 ('bind', lib_bind_files),
1958 ('bind/de', lib_bind_de_files),
1959 ('bind/fi', lib_bind_fi_files),
1960 ('bind/pt', lib_bind_pt_files),
1961 ('bind/sv', lib_bind_sv_files),
1962 ('doc', lib_doc_files),
1963 ('doc/biblio', lib_doc_biblio_files),
1964 ('doc/clipart', lib_doc_clipart_files),
1965 ('doc/cs', lib_doc_cs_files),
1966 ('doc/da', lib_doc_da_files),
1967 ('doc/de', lib_doc_de_files),
1968 ('doc/de/clipart', lib_doc_de_clipart_files),
1969 ('doc/es', lib_doc_es_files),
1970 ('doc/es/clipart', lib_doc_es_clipart_files),
1971 ('doc/eu', lib_doc_eu_files),
1972 ('doc/fr', lib_doc_fr_files),
1973 ('doc/he', lib_doc_he_files),
1974 ('doc/hu', lib_doc_hu_files),
1975 ('doc/it', lib_doc_it_files),
1976 ('doc/nl', lib_doc_nl_files),
1977 ('doc/nb', lib_doc_nb_files),
1978 ('doc/pl', lib_doc_pl_files),
1979 ('doc/pt', lib_doc_pt_files),
1980 ('doc/ro', lib_doc_ro_files),
1981 ('doc/ru', lib_doc_ru_files),
1982 ('doc/sk', lib_doc_sk_files),
1983 ('doc/sl', lib_doc_sl_files),
1984 ('doc/sv', lib_doc_sv_files),
1985 ('examples', lib_examples_files),
1986 ('examples/ca', lib_examples_ca_files),
1987 ('examples/cs', lib_examples_cs_files),
1988 ('examples/da', lib_examples_da_files),
1989 ('examples/de', lib_examples_de_files),
1990 ('examples/es', lib_examples_es_files),
1991 ('examples/eu', lib_examples_eu_files),
1992 ('examples/fa', lib_examples_fa_files),
1993 ('examples/fr', lib_examples_fr_files),
1994 ('examples/he', lib_examples_he_files),
1995 ('examples/hu', lib_examples_hu_files),
1996 ('examples/it', lib_examples_it_files),
1997 ('examples/nl', lib_examples_nl_files),
1998 ('examples/pl', lib_examples_pl_files),
1999 ('examples/pt', lib_examples_pt_files),
2000 ('examples/ru', lib_examples_ru_files),
2001 ('examples/sl', lib_examples_sl_files),
2002 ('examples/ro', lib_examples_ro_files),
2003 ('fonts', lib_fonts_files),
2004 ('images', lib_images_files),
2005 ('images/math', lib_images_math_files),
2006 ('kbd', lib_kbd_files),
2007 ('layouts', lib_layouts_files + lib_layouts_inc_files),
2008 ('lyx2lyx', lib_lyx2lyx_files),
2009 ('scripts', lib_scripts_files),
2010 ('templates', lib_templates_files),
2011 ('tex', lib_tex_files),
2012 ('ui', lib_ui_files)]:
2013 dirs.append(env.Install(os.path.join(share_dest_dir, dir),
2014 [env.subst('$TOP_SRCDIR/lib/%s/%s' % (dir, file)) for file in files]))
2015 Alias('install', dirs)
2017 # subst and install lyx2lyx_version.py which is not in scons_manifest.py
2018 env.Depends(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py', '$BUILDDIR/src/config.h')
2019 env.substFile(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py',
2020 '$TOP_SRCDIR/lib/lyx2lyx/lyx2lyx_version.py.in')
2021 Alias('install', share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2022 sys.path.append(share_dest_dir + '/lyx2lyx')
2024 # generate TOC files for each doc
2025 languages = depend.all_documents(env.Dir('$TOP_SRCDIR/lib/doc').abspath)
2027 for lang in languages.keys():
2028 if os.path.isdir(os.path.join(env.Dir('$TOP_SRCDIR/lib/doc').abspath, lang)):
2029 toc = env.installTOC(os.path.join(share_dest_dir, 'doc', lang, 'TOC.lyx'),
2032 # doc_toc.build_toc needs a installed version of lyx2lyx to execute
2033 env.Depends(toc, share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2035 # this is for English
2036 toc = env.installTOC(os.path.join(share_dest_dir, 'doc', 'TOC.lyx'),
2039 env.Depends(toc, share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2040 Alias('install', tocs)
2042 if platform_name == 'cygwin':
2043 # cygwin packaging requires a file /usr/share/doc/Cygwin/foot-vendor-suffix.README
2044 Cygwin_README = os.path.join(dest_prefix_dir, 'share', 'doc', 'Cygwin',
2045 '%s-%s.README' % (package, package_cygwin_version))
2046 env.InstallAs(Cygwin_README,
2047 os.path.join(env.subst('$TOP_SRCDIR'), 'README.cygwin'))
2048 Alias('install', Cygwin_README)
2049 # also a directory /usr/share/doc/lyx for README etc
2050 Cygwin_Doc = os.path.join(dest_prefix_dir, 'share', 'doc', package)
2051 env.Install(Cygwin_Doc, [os.path.join(env.subst('$TOP_SRCDIR'), x) for x in \
2052 ['INSTALL', 'README', 'README.Cygwin', 'RELEASE-NOTES', 'COPYING', 'ANNOUNCE']])
2053 Alias('install', Cygwin_Doc)
2054 # cygwin fonts also need to be installed
2055 Cygwin_fonts = os.path.join(share_dest_dir, 'fonts')
2056 env.Install(Cygwin_fonts,
2057 [env.subst('$TOP_SRCDIR/development/Win32/packaging/bakoma/%s' % file) \
2058 for file in win32_bakoma_fonts])
2059 Alias('install', Cygwin_fonts)
2060 # we also need a post installation script
2061 tmp_script = utils.installCygwinPostinstallScript('/tmp')
2062 postinstall_path = os.path.join(dest_dir, 'etc', 'postinstall')
2063 env.Install(postinstall_path, tmp_script)
2064 Alias('install', postinstall_path)
2066 env.InstallAs(os.path.join(man_dest_dir, 'lyx' + version_suffix + '.1'),
2067 env.subst('$TOP_SRCDIR/lyx.man'))
2068 env.InstallAs(os.path.join(man_dest_dir, 'tex2lyx' + version_suffix + '.1'),
2069 env.subst('$TOP_SRCDIR/src/tex2lyx/tex2lyx.man'))
2070 env.InstallAs(os.path.join(man_dest_dir, 'lyxclient' + version_suffix + '.1'),
2071 env.subst('$TOP_SRCDIR/src/client/lyxclient.man'))
2072 Alias('install', [os.path.join(man_dest_dir, x + version_suffix + '.1') for
2073 x in ['lyx', 'tex2lyx', 'lyxclient']])
2075 # ru.gmo ==> ru/LC_MESSAGES/lyxSUFFIX.mo
2076 for gmo in gmo_files:
2077 lan = os.path.split(str(gmo))[1].split('.')[0]
2078 dest_file = os.path.join(locale_dest_dir, lan, 'LC_MESSAGES', 'lyx' + program_suffix + '.mo')
2079 env.InstallAs(dest_file, gmo)
2080 Alias('install', dest_file)
2083 if 'installer' in BUILD_TARGETS:
2085 # build windows installer using NSIS
2088 # There is a nsis builder on scons wiki but it does not work with
2089 # our lyx.nsi because it does not dig through all the include directives
2090 # and find the dependencies automatically. Also, it can not parse
2091 # OutFile in lyx.nsi since it is defined as SETUP_EXE which is in turn
2092 # something rely on date.
2093 # Because of this, I am doing a simple nsis builder here.
2094 if platform_name != 'win32':
2095 print 'installer target is only available for windows platform'
2097 if mode != 'release':
2098 print 'installer has to be built in release mode (use option mode=release)'
2100 installer_files = ['$TOP_SRCDIR/development/Win32/packaging/installer/%s' \
2101 % x for x in development_Win32_packaging_installer] + \
2102 ['$TOP_SRCDIR/development/Win32/packaging/installer/components/%s' \
2103 % x for x in development_Win32_packaging_installer_components] + \
2104 ['$TOP_SRCDIR/development/Win32/packaging/installer/dialogs/%s' \
2105 % x for x in development_Win32_packaging_installer_dialogs] + \
2106 ['$TOP_SRCDIR/development/Win32/packaging/installer/graphics/%s' \
2107 % x for x in development_Win32_packaging_installer_graphics] + \
2108 ['$TOP_SRCDIR/development/Win32/packaging/installer/include/%s' \
2109 % x for x in development_Win32_packaging_installer_include] + \
2110 ['$TOP_SRCDIR/development/Win32/packaging/installer/lang/%s' \
2111 % x for x in development_Win32_packaging_installer_lang]
2112 if env.has_key('NSIS') and env['NSIS'] is not None:
2113 # create a builder to strip and install
2114 env['BUILDERS']['installer'] = Builder(generator=utils.env_nsis)
2116 print 'No nsis compiler is found. Existing...'
2118 if not env.has_key('win_installer') or env['win_installer'] is None:
2120 env['win_installer'] = '%s-%s-%s-Installer.exe' % (package_name, package_version, time.strftime('%Y-%m-%d'))
2122 env['win_installer'] = '%s-%s-Installer.exe' % (package_name, package_version)
2123 # provide default setting
2124 if not env.has_key('deps_dir') or env['deps_dir'] is None:
2125 env['deps_dir'] = os.path.join(env.Dir('$TOP_SRCDIR').abspath, 'lyx-windows-deps-msvc-qt4')
2126 if not os.path.isdir(env.Dir('$deps_dir').abspath):
2127 print 'Development dependency package is not found.'
2130 env['deps_dir'] = env.Dir('$deps_dir').abspath
2132 if env.has_key('bundle_dir') and os.path.isdir(env.Dir('$bundle_dir').abspath):
2133 env['bundle_dir'] = env.Dir('$bundle_dir').abspath
2134 elif os.path.isdir(os.path.join(env.Dir('$TOP_SRCDIR').abspath, 'lyx-windows-bundle-deps')):
2135 env['bundle_dir'] = os.path.join(env.Dir('$TOP_SRCDIR').abspath, 'lyx-windows-bundle-deps')
2137 env['bundle_dir'] = None
2138 # if absolute path is given, use it, otherwise, write to current directory
2139 if not (':' in env['win_installer'] or '/' in env['win_installer'] or '\\' in env['win_installer']):
2140 env['win_installer'] = os.path.join(env.Dir('$BUILDDIR').abspath, env['win_installer'])
2141 env.Append(NSISDEFINES={
2142 'ExeFile':env['win_installer'],
2143 'BundleExeFile':env['win_installer'].replace('.exe', '-bundle.exe'),
2144 'FilesLyx':env.Dir(dest_prefix_dir).abspath,
2145 'FilesDeps':env['deps_dir'],
2146 'FilesBundle':env['bundle_dir'],
2148 installer = env.installer(env['win_installer'],
2149 '$TOP_SRCDIR/development/Win32/packaging/installer/lyx.nsi')
2150 # since I can not use a scanner, explicit dependent is required
2151 env.Depends(installer, 'install')
2152 env.Depends(installer, installer_files)
2153 env.Alias('installer', installer)
2154 # also generate bundle?
2155 if env.has_key('bundle') and env['bundle']:
2156 if env['bundle_dir'] is None or not os.path.isdir(env['bundle_dir']):
2157 print 'Bundle directory does not exist (default to %s\lyx-windows-bundle-deps.' % env.Dir('$TOP_SRCDIR').abspath
2158 print 'Use bundle_dir option to specify'
2160 # generator of the builder will add bundle stuff depending on output name
2161 bundle_installer = env.installer(env['win_installer'].replace('.exe', '-bundle.exe'),
2162 '$TOP_SRCDIR/development/Win32/packaging/installer/lyx.nsi')
2163 env.Depends(bundle_installer, 'install')
2164 env.Depends(bundle_installer, installer_files)
2165 env.Alias('installer', bundle_installer)
2168 Alias('all', ['lyx', 'client', 'tex2lyx'])