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
356 # full path name is used to build msvs project files
357 # and to replace TOP_SRCDIR in package.C
358 env['TOP_SRCDIR'] = Dir(top_src_dir).abspath
360 # determine share_dir etc
361 packaging_method = env.get('packaging')
362 if packaging_method == 'windows':
363 share_dir = 'Resources'
364 man_dir = 'Resources/man/man1'
365 locale_dir = 'Resources/locale'
367 share_dir = 'share/lyx'
368 locale_dir = 'share/locale'
369 if platform_name == 'cygwin':
370 man_dir = 'share/man/man1'
374 # program suffix: can be yes, or a string
375 if env.has_key('version_suffix'):
376 if env['version_suffix'] in true_strings:
377 program_suffix = package_version
378 elif env['version_suffix'] in false_strings:
381 program_suffix = env['version_suffix']
386 # whether or not add suffix to file and directory names
387 add_suffix = packaging_method != 'windows'
388 # LYX_DIR are different (used in Package.cpp.in)
390 env['LYX_DIR'] = Dir(os.path.join(prefix, share_dir + program_suffix)).abspath
392 env['LYX_DIR'] = Dir(os.path.join(prefix, share_dir)).abspath
393 # we need absolute path for package.C
394 env['LOCALEDIR'] = Dir(os.path.join(prefix, locale_dir)).abspath
397 #---------------------------------------------------------
398 # Setting building environment (Tools, compiler flags etc)
399 #---------------------------------------------------------
401 # Since Tool('mingw') will reset CCFLAGS etc, this should be
402 # done before getEnvVariable
403 if platform_name == 'win32':
409 env.AppendUnique(CPPPATH = ['#c:/MinGW/include'])
410 # fix a scons winres bug (there is a missing space between ${RCINCPREFIX} and ${SOURCE.dir}
412 env['RCCOM'] = '$RC $_CPPDEFFLAGS $RCINCFLAGS ${RCINCPREFIX} ${SOURCE.dir} $RCFLAGS -i $SOURCE -o $TARGET'
415 # we differentiate between hard-coded options and default options
416 # hard-coded options are required and will always be there
417 # default options can be replaced by enviromental variables or command line options
418 CCFLAGS_required = []
419 LINKFLAGS_required = []
422 # if we use ms vc, the commands are fine (cl.exe and link.exe)
424 # C4819: The file contains a character that cannot be represented
425 # in the current code page (number)
426 # C4996: foo was decleared deprecated
427 CCFLAGS_required.append('/EHsc')
429 CCFLAGS_default.extend(['/wd4819', '/wd4996', '/nologo', '/MDd'])
430 # the flags are also needed in C mode (for intl lib)
431 C_CCFLAGS.extend(['/wd4819', '/wd4996', '/nologo', '/MDd'])
433 CCFLAGS_default.extend(['/wd4819', '/wd4996', '/nologo', '/MD'])
434 C_CCFLAGS.extend(['/wd4819', '/wd4996', '/nologo', '/MD'])
436 # for debug/release mode
437 if env.has_key('optimization') and env['optimization'] is not None:
438 # if user supplies optimization flags, use it anyway
439 CCFLAGS_required.extend(env['optimization'].split())
440 # and do not use default
441 set_default_optimization_flags = False
443 set_default_optimization_flags = True
447 CCFLAGS_required.append('/Zi')
448 LINKFLAGS_required.extend(['/debug', '/map'])
450 CCFLAGS_required.append('-g')
451 CCFLAGS_default.append('-O')
452 elif mode == 'release' and set_default_optimization_flags:
454 CCFLAGS_default.append('/O2')
456 CCFLAGS_default.append('-O2')
458 # msvc uses separate tools for profiling
459 if env.has_key('profiling') and env['profiling']:
461 print 'Visual C++ does not use profiling options'
463 CCFLAGS_required.append('-pg')
464 LINKFLAGS_required.append('-pg')
466 if env.has_key('warnings') and env['warnings']:
468 CCFLAGS_default.append('/W2')
470 # Note: autotools detect gxx version and pass -W for 3.x
471 # and -Wextra for other versions of gcc
472 CCFLAGS_default.append('-Wall')
474 # Now, set the variables as follows:
475 # 1. if command line option exists: replace default
476 # 2. then if s envronment variable exists: replace default
477 # 3. set variable to required + default
478 def setEnvVariable(env, name, required = None, default = None, split = True):
479 ''' env: environment to set variable
481 required: hardcoded options
482 default: default options that can be replaced by command line or
483 environment variables
484 split: whether or not split obtained variable like '-02 -g'
486 # 1. ARGUMENTS is already set to env[name], override default.
487 if ARGUMENTS.has_key(name):
488 # env[name] may be rewritten when building tools are reloaded
489 # if that is the case, commandline option will override it.
490 env[name] = ARGUMENTS[name]
492 # then use environment default
493 elif os.environ.has_key(name):
494 print "Acquiring variable %s from system environment: %s" % (name, os.environ[name])
495 default = os.environ[name]
497 default = default.split()
498 # the real value should be env[name] + default + required
501 if env.has_key(name):
502 value = str(env[name]).split()
503 if required is not None:
505 if default is not None:
509 if env.has_key(name):
510 value = str(env[name])
511 if required is not None:
512 value += " " + required
513 if default is not None:
514 value += " " + default
516 # print name, env[name]
518 setEnvVariable(env, 'DESTDIR', split=False)
519 setEnvVariable(env, 'CC')
520 setEnvVariable(env, 'LINK')
521 setEnvVariable(env, 'CPP')
522 setEnvVariable(env, 'CXX')
523 setEnvVariable(env, 'CXXCPP')
524 setEnvVariable(env, 'CCFLAGS', CCFLAGS_required, CCFLAGS_default)
525 setEnvVariable(env, 'CXXFLAGS')
526 setEnvVariable(env, 'CPPFLAGS')
527 setEnvVariable(env, 'LINKFLAGS', LINKFLAGS_required)
529 # if DESTDIR is not set...
530 if env.has_key('dest_dir'):
531 print "This option is obsolete. Please use DESTDIR instead."
532 env['DESTDIR'] = env['dest_dir']
535 # extra_inc_path and extra_lib_path
538 if env.has_key('extra_inc_path') and env['extra_inc_path']:
539 extra_inc_paths.append(env['extra_inc_path'])
540 if env.has_key('extra_lib_path') and env['extra_lib_path']:
541 env.AppendUnique(LIBPATH = [env['extra_lib_path']])
542 if env.has_key('extra_inc_path1') and env['extra_inc_path1']:
543 extra_inc_paths.append(env['extra_inc_path1'])
544 if env.has_key('extra_lib_path1') and env['extra_lib_path1']:
545 env.AppendUnique(LIBPATH = [env['extra_lib_path1']])
546 if env.has_key('extra_bin_path') and env['extra_bin_path']:
547 # only the first one is needed (a scons bug?)
548 os.environ['PATH'] += os.pathsep + env['extra_bin_path']
549 env.PrependENVPath('PATH', env['extra_bin_path'])
550 # extra_inc_paths will be used later by intlenv etc
551 env.AppendUnique(CPPPATH = extra_inc_paths)
554 #----------------------------------------------------------
556 #----------------------------------------------------------
558 conf = Configure(env,
560 'CheckPkgConfig' : utils.checkPkgConfig,
561 'CheckPackage' : utils.checkPackage,
562 'CheckMkdirOneArg' : utils.checkMkdirOneArg,
563 'CheckSelectArgType' : utils.checkSelectArgType,
564 'CheckBoostLibraries' : utils.checkBoostLibraries,
565 'CheckCommand' : utils.checkCommand,
566 'CheckNSIS' : utils.checkNSIS,
567 'CheckCXXGlobalCstd' : utils.checkCXXGlobalCstd,
568 'CheckLC_MESSAGES' : utils.checkLC_MESSAGES,
569 'CheckIconvConst' : utils.checkIconvConst,
570 'CheckSizeOfWChar' : utils.checkSizeOfWChar,
571 'CheckDeclaration' : utils.checkDeclaration,
575 # When using msvc, windows.h is required
576 if use_vc and not conf.CheckCHeader('windows.h'):
577 print 'Windows.h is not found. Please install Windows Platform SDK.'
578 print 'Please check config.log for more information.'
581 # pkg-config? (if not, we use hard-coded options)
582 if conf.CheckPkgConfig('0.15.0'):
583 env['HAS_PKG_CONFIG'] = True
585 print 'pkg-config >= 0.1.50 is not found'
586 env['HAS_PKG_CONFIG'] = False
588 # zlib? This is required.
589 if (not use_vc and not conf.CheckLibWithHeader('z', 'zlib.h', 'C')) \
590 or (use_vc and not conf.CheckLibWithHeader('zdll', 'zlib.h', 'C')):
591 print 'Did not find zdll.lib or zlib.h, exiting!'
592 print 'Please check config.log for more information.'
594 if conf.CheckLib('iconv'):
595 env['ICONV_LIB'] = 'iconv'
596 elif conf.CheckLib('libiconv'):
597 env['ICONV_LIB'] = 'libiconv'
598 elif conf.CheckFunc('iconv_open'):
599 env['ICONV_LIB'] = None
601 print 'Did not find iconv or libiconv, exiting!'
602 print 'Please check config.log for more information.'
607 if conf.CheckLib('socket'):
608 socket_libs.append('socket')
609 # nsl is the network services library and provides a
610 # transport-level interface to networking services.
611 if conf.CheckLib('nsl'):
612 socket_libs.append('nsl')
614 # check available boost libs (since lyx1.4 does not use iostream)
616 for lib in ['signals', 'regex', 'filesystem', 'iostreams']:
617 if os.path.isdir(os.path.join(top_src_dir, 'boost', 'libs', lib)):
618 boost_libs.append(lib)
620 # check boost libraries
621 boost_opt = ARGUMENTS.get('boost', 'auto')
622 # check for system boost
623 lib_paths = env['LIBPATH'] + ['/usr/lib', '/usr/local/lib']
624 inc_paths = env['CPPPATH'] + ['/usr/include', '/usr/local/include']
625 # default to $BUILDDIR/libs (use None since this path will be added anyway)
627 # here I assume that all libraries are in the same directory
628 if boost_opt == 'included':
629 boost_libraries = ['included_boost_%s' % x for x in boost_libs]
630 included_boost = True
631 env['BOOST_INC_PATH'] = '$TOP_SRCDIR/boost'
632 elif boost_opt == 'auto':
633 res = conf.CheckBoostLibraries(boost_libs, lib_paths, inc_paths, boost_version, mode == 'debug')
634 # if not found, use local boost
636 boost_libraries = ['included_boost_%s' % x for x in boost_libs]
637 included_boost = True
638 env['BOOST_INC_PATH'] = '$TOP_SRCDIR/boost'
640 included_boost = False
641 (boost_libraries, boost_libpath, env['BOOST_INC_PATH']) = res
642 elif boost_opt == 'system':
643 res = conf.CheckBoostLibraries(boost_libs, lib_paths, inc_paths, boost_version, mode == 'debug')
645 print "Can not find system boost libraries with version %s " % boost_version
646 print "Please supply a path through extra_lib_path and try again."
647 print "Or use boost=included to use included boost libraries."
650 included_boost = False
651 (boost_libraries, boost_libpath, env['BOOST_INC_PATH']) = res
654 if boost_libpath is not None:
655 env.AppendUnique(LIBPATH = [boost_libpath])
658 env['ENABLE_NLS'] = env['nls']
660 if not env['ENABLE_NLS']:
662 included_gettext = False
664 # check gettext libraries
665 gettext_opt = ARGUMENTS.get('gettext', 'auto')
666 # check for system gettext
668 if gettext_opt in ['auto', 'system']:
669 if conf.CheckFunc('gettext'):
670 included_gettext = False
673 elif conf.CheckLib('intl'):
674 included_gettext = False
678 if gettext_opt == 'system':
679 print "Can not find system gettext library"
680 print "Please supply a path through extra_lib_path and try again."
681 print "Or use gettext=included to use included gettext libraries."
683 # now, auto and succ = false, or gettext=included
685 # we do not need to set LIBPATH now.
686 included_gettext = True
687 intl_libs = ['included_intl']
691 # check for msgfmt command
692 env['MSGFMT'] = conf.CheckCommand('msgfmt')
693 env['MSGMERGE'] = conf.CheckCommand('msgmerge')
694 env['XGETTEXT'] = conf.CheckCommand('xgettext')
695 env['MSGUNIQ'] = conf.CheckCommand('msguniq')
697 # if under windows, check the nsis compiler
698 if platform_name == 'win32':
699 env['NSIS'] = conf.CheckNSIS()
701 # cygwin packaging requires the binaries to be stripped
702 if platform_name == 'cygwin':
703 env['STRIP'] = conf.CheckCommand('strip')
706 # Customized builders
708 # install customized builders
709 env['BUILDERS']['substFile'] = Builder(action = utils.env_subst)
710 env['BUILDERS']['installTOC'] = Builder(action = utils.env_toc)
711 env['BUILDERS']['potfiles'] = Builder(action = utils.env_potfiles)
714 #----------------------------------------------------------
715 # Generating config.h
716 #----------------------------------------------------------
717 aspell_lib = 'aspell'
718 # assume that we use aspell, aspelld compiled for msvc
719 if platform_name == 'win32' and mode == 'debug' and use_vc:
720 aspell_lib = 'aspelld'
722 # check the existence of config.h
723 config_h = os.path.join(env.Dir('$BUILDDIR/src').path, 'config.h')
724 boost_config_h = os.path.join(env.Dir('$BUILDDIR/boost').path, 'config.h')
726 print "Creating %s..." % boost_config_h
728 utils.createConfigFile(conf,
729 config_file = boost_config_h,
730 config_pre = r'''/* boost/config.h. Generated by SCons. */
735 * This file is part of LyX, the document processor.
736 * Licence details can be found in the file COPYING.
738 * This is the compilation configuration file for LyX.
739 * It was generated by scon.
740 * You might want to change some of the defaults if something goes wrong
741 * during the compilation.
744 #ifndef _BOOST_CONFIG_H
745 #define _BOOST_CONFIG_H
748 ('ostream', 'HAVE_OSTREAM', 'cxx'),
749 ('locale', 'HAVE_LOCALE', 'cxx'),
750 ('sstream', 'HAVE_SSTREAM', 'cxx'),
751 #('newapis.h', 'HAVE_NEWAPIS_H', 'c'),
754 (env.has_key('assertions') and env['assertions'],
756 'Define if you want assertions to be enabled in the code'
760 ('wchar_t', 'HAVE_WCHAR_T', None),
764 #if defined(HAVE_OSTREAM) && defined(HAVE_LOCALE) && defined(HAVE_SSTREAM)
765 # define USE_BOOST_FORMAT 1
767 # define USE_BOOST_FORMAT 0
770 #if !defined(ENABLE_ASSERTIONS)
771 # define BOOST_DISABLE_ASSERTS 1
773 #define BOOST_ENABLE_ASSERT_HANDLER 1
775 #define BOOST_DISABLE_THREADS 1
776 #define BOOST_NO_WSTRING 1
779 # define BOOST_POSIX 1
780 # define BOOST_POSIX_API 1
781 # define BOOST_POSIX_PATH 1
784 #define BOOST_ALL_NO_LIB 1
786 #if defined(HAVE_NEWAPIS_H)
787 # define WANT_GETFILEATTRIBUTESEX_WRAPPER 1
791 * the FreeBSD libc uses UCS4, but libstdc++ has no proper wchar_t
792 * support compiled in:
793 * http://gcc.gnu.org/onlinedocs/libstdc++/faq/index.html#3_9
794 * And we are not interested at all what libc
795 * does: What we need is a 32bit wide wchar_t, and a libstdc++ that
796 * has the needed wchar_t support and uses UCS4. Whether it
797 * implements this with the help of libc, or whether it has own code
798 * does not matter for us, because we don't use libc directly (Georg)
800 #if defined(HAVE_WCHAR_T) && SIZEOF_WCHAR_T == 4 && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
808 print "\nGenerating %s..." % config_h
810 # AIKSAURUS_H_LOCATION
811 if (conf.CheckCXXHeader("Aiksaurus.h")):
812 aik_location = '<Aiksaurus.h>'
813 elif (conf.CheckCXXHeader("Aiksaurus/Aiksaurus.h")):
814 aik_location = '<Aiksaurus/Aiksaurus.h>'
818 # determine headers to use
819 spell_opt = ARGUMENTS.get('spell', 'auto')
820 env['USE_ASPELL'] = False
821 env['USE_PSPELL'] = False
822 env['USE_ISPELL'] = False
823 if spell_opt in ['auto', 'aspell'] and conf.CheckLib(aspell_lib):
824 spell_engine = 'USE_ASPELL'
825 elif spell_opt in ['auto', 'pspell'] and conf.CheckLib('pspell'):
826 spell_engine = 'USE_PSPELL'
827 elif spell_opt in ['auto', 'ispell'] and conf.CheckLib('ispell'):
828 spell_engine = 'USE_ISPELL'
832 if spell_engine is not None:
833 env[spell_engine] = True
835 if spell_opt == 'auto':
836 print "Warning: Can not locate any spell checker"
837 elif spell_opt != 'no':
838 print "Warning: Can not locate specified spell checker:", spell_opt
839 print 'Please check config.log for more information.'
842 # check arg types of select function
843 (select_arg1, select_arg234, select_arg5) = conf.CheckSelectArgType()
845 # check the size of wchar_t
846 sizeof_wchar_t = conf.CheckSizeOfWChar()
848 if sizeof_wchar_t == 0:
849 print 'Error: Can not determine the size of wchar_t.'
850 print 'Please check config.log for more information.'
854 # fill in the version info
855 env['VERSION_INFO'] = '''Configuration
857 Special build flags: %s
859 C Compiler flags: %s %s
861 C++ Compiler LyX flags: %s
862 C++ Compiler flags: %s %s
864 Linker user flags: %s
866 Builing directory: %s
869 include search path: %s
875 ''' % (platform_name,
876 env.subst('$CCFLAGS'), env.subst('$CC'),
877 env.subst('$CPPFLAGS'), env.subst('$CFLAGS'),
878 env.subst('$CXX'), env.subst('$CXXFLAGS'),
879 env.subst('$CPPFLAGS'), env.subst('$CXXFLAGS'),
880 env.subst('$LINKFLAGS'), env.subst('$LINKFLAGS'),
881 env.subst('$LOCALLIBPATH'),
882 env.subst('$LIBPATH'), str(boost_libraries),
883 env.subst('$CPPPATH'),
884 frontend, packaging_method,
885 prefix, env['LYX_DIR'])
889 result = utils.createConfigFile(conf,
890 config_file = config_h,
891 config_pre = r'''/* config.h. Generated by SCons. */
896 * This file is part of LyX, the document processor.
897 * Licence details can be found in the file COPYING.
899 * This is the compilation configuration file for LyX.
900 * It was generated by scon.
901 * You might want to change some of the defaults if something goes wrong
902 * during the compilation.
909 ('io.h', 'HAVE_IO_H', 'c'),
910 ('limits.h', 'HAVE_LIMITS_H', 'c'),
911 ('locale.h', 'HAVE_LOCALE_H', 'c'),
912 ('process.h', 'HAVE_PROCESS_H', 'c'),
913 ('stdlib.h', 'HAVE_STDLIB_H', 'c'),
914 ('sys/stat.h', 'HAVE_SYS_STAT_H', 'c'),
915 ('sys/time.h', 'HAVE_SYS_TIME_H', 'c'),
916 ('sys/types.h', 'HAVE_SYS_TYPES_H', 'c'),
917 ('sys/utime.h', 'HAVE_SYS_UTIME_H', 'c'),
918 ('sys/socket.h', 'HAVE_SYS_SOCKET_H', 'c'),
919 ('unistd.h', 'HAVE_UNISTD_H', 'c'),
920 ('utime.h', 'HAVE_UTIME_H', 'c'),
921 ('direct.h', 'HAVE_DIRECT_H', 'c'),
922 ('istream', 'HAVE_ISTREAM', 'cxx'),
923 ('ios', 'HAVE_IOS', 'cxx'),
926 ('open', 'HAVE_OPEN', None),
927 ('chmod', 'HAVE_CHMOD', None),
928 ('close', 'HAVE_CLOSE', None),
929 ('popen', 'HAVE_POPEN', None),
930 ('pclose', 'HAVE_PCLOSE', None),
931 ('_open', 'HAVE__OPEN', None),
932 ('_close', 'HAVE__CLOSE', None),
933 ('_popen', 'HAVE__POPEN', None),
934 ('_pclose', 'HAVE__PCLOSE', None),
935 ('getpid', 'HAVE_GETPID', None),
936 ('_getpid', 'HAVE__GETPID', None),
937 ('mkdir', 'HAVE_MKDIR', None),
938 ('_mkdir', 'HAVE__MKDIR', None),
939 ('mktemp', 'HAVE_MKTEMP', None),
940 ('mkstemp', 'HAVE_MKSTEMP', None),
941 ('strerror', 'HAVE_STRERROR', None),
942 ('getcwd', 'HAVE_GETCWD', None),
943 ('setenv', 'HAVE_SETENV', None),
944 ('putenv', 'HAVE_PUTENV', None),
945 ('fcntl', 'HAVE_FCNTL', None),
946 ('mkfifo', 'HAVE_MKFIFO', None),
949 ('mkstemp', 'HAVE_DECL_MKSTEMP', ['unistd.h', 'stdlib.h']),
952 ('std::istreambuf_iterator<std::istream>', 'HAVE_DECL_ISTREAMBUF_ITERATOR',
953 '#include <streambuf>\n#include <istream>'),
954 ('wchar_t', 'HAVE_WCHAR_T', None),
955 ('mode_t', 'HAVE_MODE_T', "#include <sys/types.h>"),
958 ('gdi32', 'HAVE_LIBGDI32'),
959 (('Aiksaurus', 'libAiksaurus'), 'HAVE_LIBAIKSAURUS', 'AIKSAURUS_LIB'),
962 (conf.CheckType('pid_t', includes='#include <sys/types.h>'),
964 'Define is sys/types.h does not have pid_t',
968 (conf.CheckCXXGlobalCstd(),
970 'Define if your C++ compiler puts C library functions in the global namespace'
972 (conf.CheckMkdirOneArg(),
973 'MKDIR_TAKES_ONE_ARG',
974 'Define if mkdir takes only one argument.'
976 (conf.CheckIconvConst(),
978 'Define as const if the declaration of iconv() needs const.',
979 '#define ICONV_CONST const',
980 '#define ICONV_CONST',
982 (conf.CheckLC_MESSAGES(),
984 'Define if your <locale.h> file defines LC_MESSAGES.'
986 (devel_version, 'DEVEL_VERSION', 'Whether or not a development version'),
989 "Define to 1 if translation of program messages to the user's native anguage is requested.",
991 (env['nls'] and not included_gettext,
993 'Define to 1 if using system gettext library'
995 (env.has_key('concept_checks') and env['concept_checks'],
996 '_GLIBCXX_CONCEPT_CHECKS',
997 'libstdc++ concept checking'
999 (env.has_key('stdlib_debug') and env['stdlib_debug'],
1001 'libstdc++ debug mode'
1003 (env.has_key('stdlib_debug') and env['stdlib_debug'],
1004 '_GLIBCXX_DEBUG_PEDANTIC',
1005 'libstdc++ pedantic debug mode'
1007 (os.name != 'nt', 'BOOST_POSIX',
1008 'Indicates to boost < 1.34 which API to use (posix or windows).'
1010 (os.name != 'nt', 'BOOST_POSIX_API',
1011 'Indicates to boost 1.34 which API to use (posix or windows).'
1013 (os.name != 'nt', 'BOOST_POSIX_PATH',
1014 'Indicates to boost 1.34 which path style to use (posix or windows).'
1016 (spell_engine is not None, spell_engine,
1017 'Spell engine to use'
1019 # we need to know the byte order for unicode conversions
1020 (sys.byteorder == 'big', 'WORDS_BIGENDIAN',
1021 'Define to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX).'
1025 ('#define PACKAGE "%s%s"' % (package, program_suffix),
1027 ('#define PACKAGE_BUGREPORT "%s"' % package_bugreport,
1028 'Define to the address where bug reports for this package should be sent.'),
1029 ('#define PACKAGE_NAME "%s"' % package_name,
1030 'Define to the full name of this package.'),
1031 ('#define PACKAGE_STRING "%s"' % package_string,
1032 'Define to the full name and version of this package.'),
1033 ('#define PACKAGE_TARNAME "%s"' % package_tarname,
1034 'Define to the one symbol short name of this package.'),
1035 ('#define PACKAGE_VERSION "%s"' % package_version,
1036 'Define to the version of this package.'),
1037 ('#define VERSION_INFO "%s"' % env['VERSION_INFO'].replace('\n', '\\n'),
1038 'Full version info'),
1039 ('#define LYX_DATE "%s"' % lyx_date,
1041 ('#define PROGRAM_SUFFIX "%s"' % program_suffix,
1042 'Program version suffix'),
1043 ('#define LYX_ABS_INSTALLED_DATADIR "%s"' % env.subst('$LYX_DIR'),
1044 'Hard coded system support directory'),
1045 ('#define LYX_ABS_INSTALLED_LOCALEDIR "%s"' % env.subst('$LOCALEDIR'),
1046 'Hard coded locale directory'),
1047 ('#define LYX_ABS_TOP_SRCDIR "%s"' % env.subst('$TOP_SRCDIR'),
1048 'Top source directory'),
1049 ('#define BOOST_ALL_NO_LIB 1',
1050 'disable automatic linking of boost libraries.'),
1051 ('#define USE_%s_PACKAGING 1' % packaging_method.upper(),
1052 'Packaging method'),
1053 ('#define AIKSAURUS_H_LOCATION ' + aik_location,
1054 'Aiksaurus include file'),
1055 ('#define SELECT_TYPE_ARG1 %s' % select_arg1,
1056 "Define to the type of arg 1 for `select'."),
1057 ('#define SELECT_TYPE_ARG234 %s' % select_arg234,
1058 "Define to the type of arg 2, 3, 4 for `select'."),
1059 ('#define SELECT_TYPE_ARG5 %s' % select_arg5,
1060 "Define to the type of arg 5 for `select'."),
1061 ('#define SIZEOF_WCHAR_T %d' % sizeof_wchar_t,
1062 'Define to be the size of type wchar_t'),
1064 config_post = '''/************************************************************
1065 ** You should not need to change anything beyond this point */
1067 #ifndef HAVE_STRERROR
1068 #if defined(__cplusplus)
1071 char * strerror(int n);
1074 #include <../boost/config.h>
1080 # these keys are needed in env
1081 for key in ['USE_ASPELL', 'USE_PSPELL', 'USE_ISPELL', 'HAVE_FCNTL',\
1082 'HAVE_LIBGDI32', 'HAVE_LIBAIKSAURUS', 'AIKSAURUS_LIB']:
1083 # USE_ASPELL etc does not go through result
1084 if result.has_key(key):
1085 env[key] = result[key]
1088 # if nls=yes and gettext=included, create intl/config.h
1089 # intl/libintl.h etc
1091 intl_config_h = os.path.join(env.Dir('$BUILDDIR/intl').path, 'config.h')
1092 if env['nls'] and included_gettext:
1094 print "Creating %s..." % intl_config_h
1096 # create intl/config.h
1097 result = utils.createConfigFile(conf,
1098 config_file = intl_config_h,
1099 config_pre = r'''/* intl/config.h. Generated by SCons. */
1104 * This file is part of LyX, the document processor.
1105 * Licence details can be found in the file COPYING.
1107 * This is the compilation configuration file for LyX.
1108 * It was generated by scon.
1109 * You might want to change some of the defaults if something goes wrong
1110 * during the compilation.
1113 #ifndef _INTL_CONFIG_H
1114 #define _INTL_CONFIG_H
1117 ('unistd.h', 'HAVE_UNISTD_H', 'c'),
1118 ('inttypes.h', 'HAVE_INTTYPES_H', 'c'),
1119 ('string.h', 'HAVE_STRING_H', 'c'),
1120 ('strings.h', 'HAVE_STRINGS_H', 'c'),
1121 ('argz.h', 'HAVE_ARGZ_H', 'c'),
1122 ('limits.h', 'HAVE_LIMITS_H', 'c'),
1123 ('alloca.h', 'HAVE_ALLOCA_H', 'c'),
1124 ('stddef.h', 'HAVE_STDDEF_H', 'c'),
1125 ('stdint.h', 'HAVE_STDINT_H', 'c'),
1126 ('sys/param.h', 'HAVE_SYS_PARAM_H', 'c'),
1129 ('getcwd', 'HAVE_GETCWD', None),
1130 ('stpcpy', 'HAVE_STPCPY', None),
1131 ('strcasecmp', 'HAVE_STRCASECMP', None),
1132 ('strdup', 'HAVE_STRDUP', None),
1133 ('strtoul', 'HAVE_STRTOUL', None),
1134 ('alloca', 'HAVE_ALLOCA', None),
1135 ('__fsetlocking', 'HAVE___FSETLOCKING', None),
1136 ('mempcpy', 'HAVE_MEMPCPY', None),
1137 ('__argz_count', 'HAVE___ARGZ_COUNT', None),
1138 ('__argz_next', 'HAVE___ARGZ_NEXT', None),
1139 ('__argz_stringify', 'HAVE___ARGZ_STRINGIFY', None),
1140 ('setlocale', 'HAVE_SETLOCALE', None),
1141 ('tsearch', 'HAVE_TSEARCH', None),
1142 ('getegid', 'HAVE_GETEGID', None),
1143 ('getgid', 'HAVE_GETGID', None),
1144 ('getuid', 'HAVE_GETUID', None),
1145 ('wcslen', 'HAVE_WCSLEN', None),
1146 ('asprintf', 'HAVE_ASPRINTF', None),
1147 ('wprintf', 'HAVE_WPRINTF', None),
1148 ('snprintf', 'HAVE_SNPRINTF', None),
1149 ('printf', 'HAVE_POSIX_PRINTF', None),
1150 ('fcntl', 'HAVE_FCNTL', None),
1153 ('intmax_t', 'HAVE_INTMAX_T', None),
1154 ('long double', 'HAVE_LONG_DOUBLE', None),
1155 ('long long', 'HAVE_LONG_LONG', None),
1156 ('wchar_t', 'HAVE_WCHAR_T', None),
1157 ('wint_t', 'HAVE_WINT_T', None),
1158 ('uintmax_t', 'HAVE_INTTYPES_H_WITH_UINTMAX', '#include <inttypes.h>'),
1159 ('uintmax_t', 'HAVE_STDINT_H_WITH_UINTMAX', '#include <stdint.h>'),
1165 (conf.CheckLC_MESSAGES(),
1167 'Define if your <locale.h> file defines LC_MESSAGES.'
1169 (conf.CheckIconvConst(),
1171 'Define as const if the declaration of iconv() needs const.',
1172 '#define ICONV_CONST const',
1173 '#define ICONV_CONST',
1175 (conf.CheckType('intmax_t', includes='#include <stdint.h>') or \
1176 conf.CheckType('intmax_t', includes='#include <inttypes.h>'),
1178 "Define to 1 if you have the `intmax_t' type."
1180 (env.has_key('nls') and env['nls'],
1182 "Define to 1 if translation of program messages to the user's native anguage is requested.",
1186 ('#define HAVE_ICONV 1', 'Define if iconv or libiconv is found'),
1187 ('#define SIZEOF_WCHAR_T %d' % sizeof_wchar_t,
1188 'Define to be the size of type wchar_t'),
1190 config_post = '#endif'
1193 # these keys are needed in env
1194 for key in ['HAVE_ASPRINTF', 'HAVE_WPRINTF', 'HAVE_SNPRINTF', \
1195 'HAVE_POSIX_PRINTF', 'HAVE_LIBC']:
1196 # USE_ASPELL etc does not go through result
1197 if result.has_key(key):
1198 env[key] = result[key]
1201 # this looks misplaced, but intl/libintl.h is needed by src/message.C
1202 if env['nls'] and included_gettext:
1203 # libgnuintl.h.in => libintl.h
1204 env.Depends('$TOP_SRCDIR/intl/libintl.h', '$BUILDDIR/intl/config.h')
1205 env.substFile('$BUILDDIR/intl/libintl.h', '$TOP_SRCDIR/intl/libgnuintl.h.in')
1206 env.Command('$BUILDDIR/intl/libgnuintl.h', '$BUILDDIR/intl/libintl.h',
1207 [Copy('$TARGET', '$SOURCE')])
1210 # Finish auto-configuration
1213 #----------------------------------------------------------
1214 # Now set up our build process accordingly
1215 #----------------------------------------------------------
1217 if env['ICONV_LIB'] is None:
1220 system_libs = [env['ICONV_LIB']]
1221 if platform_name in ['win32', 'cygwin']:
1222 # the final link step needs stdc++ to succeed under mingw
1223 # FIXME: shouldn't g++ automatically link to stdc++?
1225 system_libs += ['ole32', 'shlwapi', 'shell32', 'advapi32', 'zdll']
1227 system_libs += ['shlwapi', 'stdc++', 'z']
1228 elif platform_name == 'cygwin' and env['X11']:
1229 system_libs += ['GL', 'Xmu', 'Xi', 'Xrender', 'Xrandr',
1230 'Xcursor', 'Xft', 'freetype', 'fontconfig', 'Xext', 'X11', 'SM', 'ICE',
1231 'resolv', 'pthread', 'z']
1233 system_libs += ['z']
1236 ('HAVE_LIBGDI32', 'gdi32'),
1237 ('HAVE_LIBAIKSAURUS', env['AIKSAURUS_LIB']),
1238 ('USE_ASPELL', aspell_lib),
1239 ('USE_ISPELL', 'ispell'),
1240 ('USE_PSPELL', 'pspell'),
1245 system_libs.append(lib[1])
1248 # Build parameters CPPPATH etc
1251 env.AppendUnique(LIBPATH = ['/usr/X11R6/lib'])
1254 # boost: for boost header files
1255 # BUILDDIR/src: for config.h
1256 # TOP_SRCDIR/src: for support/* etc
1258 env['CPPPATH'] += ['$BUILDDIR/src', '$TOP_SRCDIR/src']
1260 # Separating boost directories from CPPPATH stops scons from building
1261 # the dependency tree for boost header files, and effectively reduce
1262 # the null build time of lyx from 29s to 16s. Since lyx may tweak local
1263 # boost headers, the following is not 100% safe.
1264 # env.AppendUnique(CPPPATH = ['$BOOST_INC_PATH'])
1265 env.PrependUnique(CCFLAGS = ['$INCPREFIX$BOOST_INC_PATH'])
1267 # for intl/config.h, intl/libintl.h and intl/libgnuintl.h
1268 if env['nls'] and included_gettext:
1269 env['CPPPATH'].append('$BUILDDIR/intl')
1273 # A Link script for cygwin see
1274 # http://www.cygwin.com/ml/cygwin/2004-09/msg01101.html
1275 # http://www.cygwin.com/ml/cygwin-apps/2004-09/msg00309.html
1278 if platform_name == 'cygwin':
1279 ld_script_path = '/tmp'
1280 ld_script = utils.installCygwinLDScript(ld_script_path)
1281 env.AppendUnique(LINKFLAGS = ['-Wl,--enable-runtime-pseudo-reloc',
1282 '-Wl,--script,%s' % ld_script, '-Wl,-s'])
1285 #---------------------------------------------------------
1286 # Frontend related variables (QTDIR etc)
1287 #---------------------------------------------------------
1290 # create a separate environment so that other files do not have
1291 # to be built with all the include directories etc
1293 if frontend == 'qt4':
1294 frontend_env = env.Copy()
1296 # handle qt related user specified paths
1297 # set environment so that moc etc can be found even if its path is not set properly
1298 if frontend_env.has_key('qt_dir') and frontend_env['qt_dir']:
1299 frontend_env['QTDIR'] = frontend_env['qt_dir']
1300 if os.path.isdir(os.path.join(frontend_env['qt_dir'], 'bin')):
1301 os.environ['PATH'] += os.pathsep + os.path.join(frontend_env['qt_dir'], 'bin')
1302 frontend_env.PrependENVPath('PATH', os.path.join(frontend_env['qt_dir'], 'bin'))
1303 if os.path.isdir(os.path.join(frontend_env['qt_dir'], 'lib')):
1304 frontend_env.PrependENVPath('PKG_CONFIG_PATH', os.path.join(frontend_env['qt_dir'], 'lib'))
1306 # if separate qt_lib_path is given
1307 if frontend_env.has_key('qt_lib_path') and frontend_env['qt_lib_path']:
1308 qt_lib_path = frontend_env.subst('$qt_lib_path')
1309 frontend_env.AppendUnique(LIBPATH = [qt_lib_path])
1310 frontend_env.PrependENVPath('PKG_CONFIG_PATH', qt_lib_path)
1314 # if separate qt_inc_path is given
1315 if frontend_env.has_key('qt_inc_path') and frontend_env['qt_inc_path']:
1316 qt_inc_path = frontend_env['qt_inc_path']
1320 # local qt4 toolset from
1321 # http://www.iua.upf.es/~dgarcia/Codders/sconstools.html
1323 # NOTE: I have to patch qt4.py since it does not automatically
1324 # process .C file!!! (add to cxx_suffixes )
1326 frontend_env.Tool('qt4', [scons_dir])
1327 frontend_env['QT_AUTOSCAN'] = 0
1328 frontend_env['QT4_AUTOSCAN'] = 0
1329 frontend_env['QT4_UICDECLFLAGS'] = '-tr lyx::qt_'
1331 if qt_lib_path is None:
1332 qt_lib_path = os.path.join(frontend_env.subst('$QTDIR'), 'lib')
1333 if qt_inc_path is None:
1334 qt_inc_path = os.path.join(frontend_env.subst('$QTDIR'), 'include')
1337 conf = Configure(frontend_env,
1339 'CheckPackage' : utils.checkPackage,
1340 'CheckCommand' : utils.checkCommand,
1345 # first: try pkg_config
1346 if frontend_env['HAS_PKG_CONFIG']:
1347 succ = conf.CheckPackage('QtCore') or conf.CheckPackage('QtCore4')
1348 # FIXME: use pkg_config information?
1349 #frontend_env['QT4_PKG_CONFIG'] = succ
1350 # second: try to link to it
1352 # Under linux, I can test the following perfectly
1353 # Under windows, lib names need to passed as libXXX4.a ...
1354 if platform_name == 'win32':
1355 succ = conf.CheckLibWithHeader('QtCore4', 'QtGui/QApplication', 'c++', 'QApplication qapp();')
1357 succ = conf.CheckLibWithHeader('QtCore', 'QtGui/QApplication', 'c++', 'QApplication qapp();')
1358 # still can not find it
1360 print 'Did not find qt libraries, exiting!'
1361 print 'Please check config.log for more information.'
1364 # Now, determine the correct suffix:
1365 qt_libs = ['QtCore', 'QtGui']
1366 if platform_name == 'win32':
1367 if mode == 'debug' and use_vc and \
1368 conf.CheckLibWithHeader('QtCored4', 'QtGui/QApplication', 'c++', 'QApplication qapp();'):
1369 qt_lib_suffix = 'd4'
1370 use_qt_debug_libs = True
1373 use_qt_debug_libs = False
1375 if mode == 'debug' and conf.CheckLibWithHeader('QtCore_debug', 'QtGui/QApplication', 'c++', 'QApplication qapp();'):
1376 qt_lib_suffix = '_debug'
1377 use_qt_debug_libs = True
1380 use_qt_debug_libs = False
1381 frontend_env.EnableQt4Modules(qt_libs, debug = (mode == 'debug' and use_qt_debug_libs))
1382 frontend_libs = [x + qt_lib_suffix for x in qt_libs]
1383 qtcore_lib = ['QtCore' + qt_lib_suffix]
1385 # check uic and moc commands for qt frontends
1386 if conf.CheckCommand('uic') == None or conf.CheckCommand('moc') == None:
1387 print 'uic or moc command is not found for frontend', frontend
1390 # now, if msvc2005 is used, we will need to embed lyx.exe.manifest to lyx.exe
1391 # NOTE: previously, lyx.exe had to be linked to some qt manifest to work.
1392 # For some unknown changes in msvc or qt, this is no longer needed.
1394 frontend_env['LINKCOM'] = [frontend_env['LINKCOM'], \
1395 'mt.exe /MANIFEST %s /outputresource:$TARGET;1' % \
1396 env.File('$BUILDDIR/lyx.exe.manifest').path]
1398 frontend_env = conf.Finish()
1403 print env['VERSION_INFO']
1406 # Mingw command line may be too short for our link usage,
1407 # Here we use a trick from scons wiki
1408 # http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/LongCmdLinesOnWin32
1410 # I also would like to add logging (commands only) capacity to the
1412 logfile = env.get('logfile', default_log_file)
1413 if logfile != '' or platform_name == 'win32':
1415 utils.setLoggedSpawn(env, logfile, longarg = (platform_name == 'win32'),
1416 info = '''# This is a log of commands used by scons to build lyx
1420 ''' % (time.asctime(), ' '.join(sys.argv),
1421 env['VERSION_INFO'].replace('\n','\n# ')) )
1426 # -h will print out help info
1427 Help(opts.GenerateHelpText(env))
1430 #----------------------------------------------------------
1432 #----------------------------------------------------------
1433 # this has been the source of problems on some platforms...
1434 # I find that I need to supply it with full path name
1435 env.SConsignFile(os.path.join(Dir(env['BUILDDIR']).abspath, '.sconsign'))
1436 # this usage needs further investigation.
1437 #env.CacheDir('%s/Cache/%s' % (env['BUILDDIR'], frontend))
1438 env.BuildDir('$BUILDDIR/boost', '$TOP_SRCDIR/boost/libs', duplicate = 0)
1439 env.BuildDir('$BUILDDIR/intl', '$TOP_SRCDIR/intl', duplicate = 0)
1440 env.BuildDir('$BUILDDIR/src', '$TOP_SRCDIR/src', duplicate = 0)
1441 frontend_env.BuildDir('$BUILDDIR/src', '$TOP_SRCDIR/src', duplicate = 0)
1443 print "Building all targets recursively"
1445 def libExists(libname):
1446 ''' Check whether or not lib $LOCALLIBNAME/libname already exists'''
1447 return os.path.isfile(File(env.subst('$LOCALLIBPATH/${LIBPREFIX}%s$LIBSUFFIX'%libname)).abspath)
1450 if (included_boost and not libExists('included_boost_regex')) or 'boost' in BUILD_TARGETS:
1454 for lib in boost_libs:
1455 boostlib = env.StaticLibrary(
1456 target = '$LOCALLIBPATH/included_boost_%s' % lib,
1457 source = ['$BUILDDIR/boost/%s/src/%s' % (lib, x) for x in eval('boost_libs_%s_src_files' % lib)],
1458 # do not use global CPPPATH because src/config.h will mess up with boost/config.h
1459 CPPPATH = ['$BUILDDIR/boost'] + extra_inc_paths,
1460 CCFLAGS = ['$CCFLAGS', '$INCPREFIX$TOP_SRCDIR/boost', '-DBOOST_USER_CONFIG="<config.h>"']
1462 Alias('boost', boostlib)
1465 if (included_gettext and not libExists('included_intl')) or 'intl' in BUILD_TARGETS:
1470 r'-DLOCALEDIR=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1471 r'-DLOCALE_ALIAS_PATH=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1472 r'-DLIBDIR=\"' + env['TOP_SRCDIR'].replace('\\', '\\\\') + r'/lib\"',
1474 '-DENABLE_RELOCATABLE=1',
1476 r'-DINSTALLDIR=\"' + prefix.replace('\\', '\\\\') + r'/lib\"',
1478 '-Dset_relocation_prefix=libintl_set_relocation_prefix',
1479 '-Drelocate=libintl_relocate',
1480 '-DDEPENDS_ON_LIBICONV=1',
1484 INTL_CCFLAGS.extend(['/Dinline#', '/D__attribute__(x)#', '/Duintmax_t=UINT_MAX'])
1486 intl = env.StaticLibrary(
1487 target = '$LOCALLIBPATH/included_intl',
1489 CCFLAGS = INTL_CCFLAGS,
1490 # do not use global CPPPATH because src/config.h will mess up with intl/config.h
1491 CPPPATH = ['$BUILDDIR/intl'] + extra_inc_paths,
1492 source = ['$BUILDDIR/intl/%s' % x for x in intl_files]
1499 support = frontend_env.StaticLibrary(
1500 target = '$LOCALLIBPATH/support',
1501 source = ['$BUILDDIR/src/support/%s' % x for x in src_support_files] + \
1502 ['$BUILDDIR/src/support/minizip/%s' % x for x in src_support_minizip_files],
1506 '-DQT_CLEAN_NAMESPACE',
1511 CPPPATH = ['$CPPPATH', '$TOP_SRCDIR/src/support/minizip']
1513 Alias('support', support)
1519 mathed = env.StaticLibrary(
1520 target = '$LOCALLIBPATH/mathed',
1521 source = ['$BUILDDIR/src/mathed/%s' % x for x in src_mathed_files]
1523 Alias('mathed', mathed)
1529 insets = env.StaticLibrary(
1530 target = '$LOCALLIBPATH/insets',
1531 source = ['$BUILDDIR/src/insets/%s' % x for x in src_insets_files]
1533 Alias('insets', insets)
1539 frontends = env.StaticLibrary(
1540 target = '$LOCALLIBPATH/frontends',
1541 source = ['$BUILDDIR/src/frontends/%s' % x for x in src_frontends_files]
1543 Alias('frontends', frontends)
1549 graphics = env.StaticLibrary(
1550 target = '$LOCALLIBPATH/graphics',
1551 source = ['$BUILDDIR/src/graphics/%s' % x for x in src_graphics_files]
1553 Alias('graphics', graphics)
1557 # src/frontends/controllers
1559 controllers = env.StaticLibrary(
1560 target = '$LOCALLIBPATH/controllers',
1561 source = ['$BUILDDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files]
1563 Alias('controllers', controllers)
1569 frontend_env['QT4_MOCHPREFIX'] = ''
1570 frontend_env['QT4_MOCHSUFFIX'] = '_moc.cpp'
1572 # tells scons how to get these moced files, although not all moced files are needed
1573 # (or are actually generated).
1574 qt4_moced_files = [frontend_env.Moc4('$BUILDDIR/src/frontends/qt4/%s' % x)
1575 for x in src_frontends_qt4_header_files ]
1576 resources = [frontend_env.Uic4('$BUILDDIR/src/frontends/qt4/ui/%s' % x.split('.')[0])
1577 for x in src_frontends_qt4_ui_files]
1580 # moc qt4_moc_files, the moced files are included in the original files
1582 qt4 = frontend_env.StaticLibrary(
1583 target = '$LOCALLIBPATH/qt4',
1584 source = ['$BUILDDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_files],
1588 '$BUILDDIR/src/images',
1589 '$BUILDDIR/src/frontends',
1590 '$BUILDDIR/src/frontends/qt4',
1591 '$BUILDDIR/src/frontends/qt4/ui',
1592 '$BUILDDIR/src/frontends/controllers'
1597 '-DQT_CLEAN_NAMESPACE',
1609 if env['HAVE_FCNTL']:
1610 client = frontend_env.Program(
1611 target = '$BUILDDIR/src/client/lyxclient',
1612 LIBS = ['support'] + intl_libs + system_libs +
1613 socket_libs + boost_libraries + qtcore_lib,
1614 source = ['$BUILDDIR/src/client/%s' % x for x in src_client_files] + \
1615 utils.createResFromIcon(frontend_env, 'lyx_32x32.ico', '$LOCALLIBPATH/client.rc')
1617 Alias('client', frontend_env.Command(os.path.join('$BUILDDIR', os.path.split(str(client[0]))[1]),
1618 client, [Copy('$TARGET', '$SOURCE')]))
1621 Alias('client', client)
1627 for file in src_tex2lyx_copied_files:
1628 frontend_env.Command('$BUILDDIR/src/tex2lyx/'+file, '$TOP_SRCDIR/src/'+file,
1629 [Copy('$TARGET', '$SOURCE')])
1631 tex2lyx = frontend_env.Program(
1632 target = '$BUILDDIR/src/tex2lyx/tex2lyx',
1633 LIBS = ['support'] + boost_libraries + intl_libs + system_libs + qtcore_lib,
1634 source = ['$BUILDDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_files + src_tex2lyx_copied_files] + \
1635 utils.createResFromIcon(frontend_env, 'lyx_32x32.ico', '$LOCALLIBPATH/tex2lyx.rc'),
1636 CPPPATH = ['$BUILDDIR/src/tex2lyx', '$CPPPATH'],
1637 LIBPATH = ['#$LOCALLIBPATH', '$LIBPATH'],
1638 CCFLAGS = ['$CCFLAGS', '-DTEX2LYX'],
1640 Alias('tex2lyx', frontend_env.Command(os.path.join('$BUILDDIR', os.path.split(str(tex2lyx[0]))[1]),
1641 tex2lyx, [Copy('$TARGET', '$SOURCE')]))
1642 Alias('tex2lyx', tex2lyx)
1648 if env.has_key('USE_ASPELL') and env['USE_ASPELL']:
1649 src_post_files.append('ASpell.cpp')
1650 elif env.has_key('USE_PSPELL') and env['USE_PSPELL']:
1651 src_post_files.append('PSpell.cpp')
1652 elif env.has_key('USE_ISPELL') and env['USE_ISPELL']:
1653 src_post_files.append('ISpell.cpp')
1655 # msvc requires at least one source file with main()
1656 # so I exclude main.cpp from lyxbase
1657 lyxbase_pre = env.StaticLibrary(
1658 target = '$LOCALLIBPATH/lyxbase_pre',
1659 source = ['$BUILDDIR/src/%s' % x for x in src_pre_files]
1661 lyxbase_post = env.StaticLibrary(
1662 target = '$LOCALLIBPATH/lyxbase_post',
1663 source = ["$BUILDDIR/src/%s" % x for x in src_post_files]
1665 Alias('lyxbase', lyxbase_pre)
1666 Alias('lyxbase', lyxbase_post)
1670 # Build lyx with given frontend
1672 lyx = frontend_env.Program(
1673 target = '$BUILDDIR/lyx',
1674 source = ['$BUILDDIR/src/main.cpp'] + \
1675 utils.createResFromIcon(frontend_env, 'lyx_32x32.ico', '$LOCALLIBPATH/lyx.rc'),
1696 if use_vc and 'msvs_projects' in BUILD_TARGETS:
1697 def build_project(target, full_target = None,
1698 src = [], inc = [], res = []):
1699 ''' build mavs project files
1700 target: alias (correspond to directory name)
1701 full_target: full path/filename of the target
1706 For non-debug-able targets like static libraries, target (alias) is
1707 enough to build the target. For executable targets, msvs need to know
1708 the full path to start debug them.
1711 if full_target is None:
1712 build_target = target
1714 build_target = full_target
1716 proj = env.MSVSProject(
1717 target = target + env['MSVSPROJECTSUFFIX'],
1718 # this allows easy access to header files (along with source)
1719 srcs = [env.subst(x) for x in src + inc],
1720 incs = [env.subst('$TOP_SRCDIR/src/config.h')],
1721 localincs = [env.subst(x) for x in inc],
1722 resources = [env.subst(x) for x in res],
1723 buildtarget = build_target,
1727 Alias('msvs_projects', proj)
1729 build_project('client', src = ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_files],
1730 inc = ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_header_files],
1731 full_target = File(env.subst('$BUILDDIR/src/client/lyxclient$PROGSUFFIX')).abspath)
1733 build_project('tex2lyx', src = ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_files],
1734 inc = ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_header_files],
1735 full_target = File(env.subst('$BUILDDIR/src/tex2lyx/tex2lyx$PROGSUFFIX')).abspath)
1737 build_project('lyx',
1738 src = ['$TOP_SRCDIR/src/%s' % x for x in src_pre_files + src_post_files + ['version.cpp']] + \
1739 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_files + ['Package.cpp'] ] + \
1740 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_files] + \
1741 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_files] + \
1742 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_files] + \
1743 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_files] + \
1744 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files] + \
1745 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_files],
1746 inc = ['$TOP_SRCDIR/src/%s' % x for x in src_header_files] + \
1747 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files] + \
1748 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_header_files] + \
1749 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files] + \
1750 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files] + \
1751 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files] + \
1752 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files] + \
1753 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_header_files],
1754 res = ['$TOP_SRCDIR/src/frontends/qt4/ui/%s' % x for x in src_frontends_qt4_ui_files],
1755 full_target = File(env.subst('$BUILDDIR/lyx$PROGSUFFIX')).abspath)
1758 if 'update_po' in BUILD_TARGETS:
1762 print 'Updating po/*.po files...'
1764 # whether or not update po files
1765 if not env['XGETTEXT'] or not env['MSGMERGE'] or not env['MSGUNIQ']:
1766 print 'xgettext or msgmerge does not exist. Cannot merge po files'
1768 # rebuild POTFILES.in
1769 POTFILES_in = env.potfiles('$TOP_SRCDIR/po/POTFILES.in',
1770 ['$TOP_SRCDIR/src/%s' % x for x in src_header_files + src_pre_files + src_post_files + \
1771 src_extra_src_files] + \
1772 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files + src_support_files + \
1773 src_support_extra_header_files + src_support_extra_src_files] + \
1774 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_header_files + src_mathed_files] + \
1775 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files + src_insets_files] + \
1776 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files + src_frontends_files] + \
1777 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files + src_graphics_files] + \
1778 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files + src_frontends_controllers_files] + \
1779 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_header_files + src_frontends_qt4_files + src_frontends_qt4_moc_files] + \
1780 ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_header_files + src_client_files ] + \
1781 ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_header_files + src_tex2lyx_files ]
1783 Alias('update_po', POTFILES_in)
1784 # build language_l10n.pot, ui_l10n.pot, layouts_l10n.pot, qt4_l10n.pot, external_l10n
1785 # and combine them to lyx.po
1786 env['LYX_POT'] = 'python $TOP_SRCDIR/po/lyx_pot.py'
1787 lyx_po = env.Command('$BUILDDIR/po/lyx.po',
1788 env.Command('$BUILDDIR/po/all.po',
1789 [env.Command('$BUILDDIR/po/qt4_l10n.pot',
1790 ['$TOP_SRCDIR/src/frontends/qt4/ui/%s' % x for x in src_frontends_qt4_ui_files],
1791 '$LYX_POT -b $TOP_SRCDIR -t qt4 -o $TARGET $SOURCES'),
1792 env.Command('$BUILDDIR/po/layouts_l10n.pot',
1793 ['$TOP_SRCDIR/lib/layouts/%s' % x for x in lib_layouts_files + lib_layouts_inc_files + lib_layouts_module_files],
1794 '$LYX_POT -b $TOP_SRCDIR -t layouts -o $TARGET $SOURCES'),
1795 env.Command('$BUILDDIR/po/languages_l10n.pot', '$TOP_SRCDIR/lib/languages',
1796 '$LYX_POT -b $TOP_SRCDIR -t languages -o $TARGET $SOURCES'),
1797 env.Command('$BUILDDIR/po/ui_l10n.pot',
1798 ['$TOP_SRCDIR/lib/ui/%s' % x for x in lib_ui_files],
1799 '$LYX_POT -b $TOP_SRCDIR -t ui -o $TARGET $SOURCES'),
1800 env.Command('$BUILDDIR/po/external_l10n.pot', '$TOP_SRCDIR/lib/external_templates',
1801 '$LYX_POT -b $TOP_SRCDIR -t external -o $TARGET $SOURCES'),
1803 ['$MSGUNIQ -o $TARGET $SOURCE',
1804 '''$XGETTEXT --default-domain=${TARGET.base} \
1805 --directory=$TOP_SRCDIR --add-comments=TRANSLATORS: \
1806 --language=C++ --join-existing \
1807 --keyword=_ --keyword=N_ --keyword=B_ --keyword=qt_ \
1808 --files-from=$TOP_SRCDIR/po/POTFILES.in \
1809 --copyright-holder="LyX Developers" \
1810 --msgid-bugs-address="lyx-devel@lists.lyx.org" ''']
1812 env.Depends(lyx_po, POTFILES_in)
1813 # copy lyx.po to lyx.pot
1814 lyx_pot = env.Command('$BUILDDIR/po/lyx.pot', lyx_po,
1815 Copy('$TARGET', '$SOURCE'))
1818 # files to translate
1819 transfiles = glob.glob(os.path.join(env.Dir('$TOP_SRCDIR/po').abspath, '*.po'))
1820 # possibly *only* handle these languages
1822 if env.has_key('languages'):
1823 languages = env.make_list(env['languages'])
1824 # merge. if I use lan.po as $TARGET, it will be removed
1825 # before it is merged. In this builder,
1826 # $BUILDDIR/po/lang.po is merged from po/lang.po and $BUILDDIR/po/lyx.pot
1827 # and is copied to po/lang.po
1828 env['BUILDERS']['msgmerge'] = Builder(action=[
1829 '$MSGMERGE $TOP_SRCDIR/po/${TARGET.filebase}.po $SOURCE -o $TARGET',
1830 Copy('$TOP_SRCDIR/po/${TARGET.filebase}.po', '$TARGET')]
1832 # for each po file, generate pot
1833 for po_file in transfiles:
1835 fname = os.path.split(po_file)[1]
1837 country = fname.split('.')[0]
1839 if not languages or country in languages:
1840 # merge po files, the generated lan.po_new file is copied to lan.po file.
1841 po = env.msgmerge('$BUILDDIR/po/%s.po' % country, lyx_pot)
1842 env.Depends(po, POTFILES_in)
1843 Alias('update_po', po)
1846 # if 'install' is not in the target, do not process this
1847 if 'install' in BUILD_TARGETS or 'installer' in BUILD_TARGETS:
1849 # this part is a bit messy right now. Since scons will provide
1850 # --DESTDIR option soon, at least the dest_dir handling can be
1859 # files to translate
1860 transfiles = glob.glob(os.path.join(env.subst('$TOP_SRCDIR'), 'po', '*.po'))
1861 # possibly *only* handle these languages
1863 if env.has_key('languages'):
1864 languages = env.make_list(env['lanauges'])
1865 # use defulat msgfmt
1867 if not env['MSGFMT']:
1868 print 'msgfmt does not exist. Can not process po files'
1871 env['BUILDERS']['Transfiles'] = Builder(action='$MSGFMT $SOURCE -c --statistics -o $TARGET',suffix='.gmo',src_suffix='.po')
1873 for f in transfiles:
1875 fname = os.path.split(f)[1]
1877 country = fname.split('.')[0]
1879 if not languages or country in languages:
1880 gmo_files.extend(env.Transfiles(f))
1881 # how to join dest_dir and prefix
1882 def joinPaths(path1, path2):
1883 ''' join path1 and path2, do not use os.path.join because
1884 under window, c:\destdir\d:\program is invalid '''
1886 return os.path.normpath(path2)
1887 # separate drive letter
1888 (drive, path) = os.path.splitdrive(os.path.normpath(path2))
1889 # ignore drive letter, so c:\destdir + c:\program = c:\destdir\program
1890 return os.path.join(os.path.normpath(path1), path[1:])
1892 # install to dest_dir/prefix
1893 dest_dir = env.get('DESTDIR', '')
1894 dest_prefix_dir = joinPaths(dest_dir, env.Dir(prefix).abspath)
1895 # create the directory if needed
1896 if not os.path.isdir(dest_prefix_dir):
1898 os.makedirs(dest_prefix_dir)
1901 if not os.path.isdir(dest_prefix_dir):
1902 print 'Can not create directory', dest_prefix_dir
1905 if env.has_key('exec_prefix'):
1906 bin_dest_dir = joinPaths(dest_dir, Dir(env['exec_prefix']).abspath)
1908 bin_dest_dir = os.path.join(dest_prefix_dir, 'bin')
1910 share_dest_dir = os.path.join(dest_prefix_dir, share_dir + program_suffix)
1912 share_dest_dir = os.path.join(dest_prefix_dir, share_dir)
1913 man_dest_dir = os.path.join(dest_prefix_dir, man_dir)
1914 locale_dest_dir = os.path.join(dest_prefix_dir, locale_dir)
1915 env['LYX2LYX_DEST'] = os.path.join(share_dest_dir, 'lyx2lyx')
1919 # install executables (lyxclient may be None)
1922 version_suffix = program_suffix
1926 # install lyx, if in release mode, try to strip the binary
1927 if env.has_key('STRIP') and env['STRIP'] is not None and mode != 'debug':
1928 # create a builder to strip and install
1929 env['BUILDERS']['StripInstallAs'] = Builder(action='$STRIP $SOURCE -o $TARGET')
1931 # install executables
1932 for (name, obj) in (('lyx', lyx), ('tex2lyx', tex2lyx), ('client', client)):
1935 target_name = os.path.split(str(obj[0]))[1].replace(name, '%s%s' % (name, version_suffix))
1936 target = os.path.join(bin_dest_dir, target_name)
1937 if env['BUILDERS'].has_key('StripInstallAs'):
1938 env.StripInstallAs(target, obj)
1940 env.InstallAs(target, obj)
1941 Alias('install', target)
1945 for (dir,files) in [
1947 ('bind', lib_bind_files),
1948 ('bind/de', lib_bind_de_files),
1949 ('bind/fi', lib_bind_fi_files),
1950 ('bind/pt', lib_bind_pt_files),
1951 ('bind/sv', lib_bind_sv_files),
1952 ('doc', lib_doc_files),
1953 ('doc/biblio', lib_doc_biblio_files),
1954 ('doc/clipart', lib_doc_clipart_files),
1955 ('doc/cs', lib_doc_cs_files),
1956 ('doc/da', lib_doc_da_files),
1957 ('doc/de', lib_doc_de_files),
1958 ('doc/de/clipart', lib_doc_de_clipart_files),
1959 ('doc/es', lib_doc_es_files),
1960 ('doc/es/clipart', lib_doc_es_clipart_files),
1961 ('doc/eu', lib_doc_eu_files),
1962 ('doc/fr', lib_doc_fr_files),
1963 ('doc/he', lib_doc_he_files),
1964 ('doc/hu', lib_doc_hu_files),
1965 ('doc/it', lib_doc_it_files),
1966 ('doc/nl', lib_doc_nl_files),
1967 ('doc/nb', lib_doc_nb_files),
1968 ('doc/pl', lib_doc_pl_files),
1969 ('doc/pt', lib_doc_pt_files),
1970 ('doc/ro', lib_doc_ro_files),
1971 ('doc/ru', lib_doc_ru_files),
1972 ('doc/sk', lib_doc_sk_files),
1973 ('doc/sl', lib_doc_sl_files),
1974 ('doc/sv', lib_doc_sv_files),
1975 ('examples', lib_examples_files),
1976 ('examples/ca', lib_examples_ca_files),
1977 ('examples/cs', lib_examples_cs_files),
1978 ('examples/da', lib_examples_da_files),
1979 ('examples/de', lib_examples_de_files),
1980 ('examples/es', lib_examples_es_files),
1981 ('examples/eu', lib_examples_eu_files),
1982 ('examples/fa', lib_examples_fa_files),
1983 ('examples/fr', lib_examples_fr_files),
1984 ('examples/he', lib_examples_he_files),
1985 ('examples/hu', lib_examples_hu_files),
1986 ('examples/it', lib_examples_it_files),
1987 ('examples/nl', lib_examples_nl_files),
1988 ('examples/pl', lib_examples_pl_files),
1989 ('examples/pt', lib_examples_pt_files),
1990 ('examples/ru', lib_examples_ru_files),
1991 ('examples/sl', lib_examples_sl_files),
1992 ('examples/ro', lib_examples_ro_files),
1993 ('fonts', lib_fonts_files),
1994 ('images', lib_images_files),
1995 ('images/math', lib_images_math_files),
1996 ('kbd', lib_kbd_files),
1997 ('layouts', lib_layouts_files + lib_layouts_inc_files),
1998 ('lyx2lyx', lib_lyx2lyx_files),
1999 ('scripts', lib_scripts_files),
2000 ('templates', lib_templates_files),
2001 ('tex', lib_tex_files),
2002 ('ui', lib_ui_files)]:
2003 dirs.append(env.Install(os.path.join(share_dest_dir, dir),
2004 [env.subst('$TOP_SRCDIR/lib/%s/%s' % (dir, file)) for file in files]))
2005 Alias('install', dirs)
2007 # subst and install lyx2lyx_version.py which is not in scons_manifest.py
2008 env.Depends(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py', '$BUILDDIR/src/config.h')
2009 env.substFile(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py',
2010 '$TOP_SRCDIR/lib/lyx2lyx/lyx2lyx_version.py.in')
2011 Alias('install', share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2012 sys.path.append(share_dest_dir + '/lyx2lyx')
2014 # generate TOC files for each doc
2015 languages = depend.all_documents(env.Dir('$TOP_SRCDIR/lib/doc').abspath)
2017 for lang in languages.keys():
2018 if os.path.isdir(os.path.join(env.Dir('$TOP_SRCDIR/lib/doc').abspath, lang)):
2019 toc = env.installTOC(os.path.join(share_dest_dir, 'doc', lang, 'TOC.lyx'),
2022 # doc_toc.build_toc needs a installed version of lyx2lyx to execute
2023 env.Depends(toc, share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2025 # this is for English
2026 toc = env.installTOC(os.path.join(share_dest_dir, 'doc', 'TOC.lyx'),
2029 env.Depends(toc, share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2030 Alias('install', tocs)
2032 if platform_name == 'cygwin':
2033 # cygwin packaging requires a file /usr/share/doc/Cygwin/foot-vendor-suffix.README
2034 Cygwin_README = os.path.join(dest_prefix_dir, 'share', 'doc', 'Cygwin',
2035 '%s-%s.README' % (package, package_cygwin_version))
2036 env.InstallAs(Cygwin_README,
2037 os.path.join(env.subst('$TOP_SRCDIR'), 'README.cygwin'))
2038 Alias('install', Cygwin_README)
2039 # also a directory /usr/share/doc/lyx for README etc
2040 Cygwin_Doc = os.path.join(dest_prefix_dir, 'share', 'doc', package)
2041 env.Install(Cygwin_Doc, [os.path.join(env.subst('$TOP_SRCDIR'), x) for x in \
2042 ['INSTALL', 'README', 'README.Cygwin', 'RELEASE-NOTES', 'COPYING', 'ANNOUNCE']])
2043 Alias('install', Cygwin_Doc)
2044 # cygwin fonts also need to be installed
2045 Cygwin_fonts = os.path.join(share_dest_dir, 'fonts')
2046 env.Install(Cygwin_fonts,
2047 [env.subst('$TOP_SRCDIR/development/Win32/packaging/bakoma/%s' % file) \
2048 for file in win32_bakoma_fonts])
2049 Alias('install', Cygwin_fonts)
2050 # we also need a post installation script
2051 tmp_script = utils.installCygwinPostinstallScript('/tmp')
2052 postinstall_path = os.path.join(dest_dir, 'etc', 'postinstall')
2053 env.Install(postinstall_path, tmp_script)
2054 Alias('install', postinstall_path)
2056 env.InstallAs(os.path.join(man_dest_dir, 'lyx' + version_suffix + '.1'),
2057 env.subst('$TOP_SRCDIR/lyx.man'))
2058 env.InstallAs(os.path.join(man_dest_dir, 'tex2lyx' + version_suffix + '.1'),
2059 env.subst('$TOP_SRCDIR/src/tex2lyx/tex2lyx.man'))
2060 env.InstallAs(os.path.join(man_dest_dir, 'lyxclient' + version_suffix + '.1'),
2061 env.subst('$TOP_SRCDIR/src/client/lyxclient.man'))
2062 Alias('install', [os.path.join(man_dest_dir, x + version_suffix + '.1') for
2063 x in ['lyx', 'tex2lyx', 'lyxclient']])
2065 # ru.gmo ==> ru/LC_MESSAGES/lyxSUFFIX.mo
2066 for gmo in gmo_files:
2067 lan = os.path.split(str(gmo))[1].split('.')[0]
2068 dest_file = os.path.join(locale_dest_dir, lan, 'LC_MESSAGES', 'lyx' + program_suffix + '.mo')
2069 env.InstallAs(dest_file, gmo)
2070 Alias('install', dest_file)
2073 if 'installer' in BUILD_TARGETS:
2075 # build windows installer using NSIS
2078 # There is a nsis builder on scons wiki but it does not work with
2079 # our lyx.nsi because it does not dig through all the include directives
2080 # and find the dependencies automatically. Also, it can not parse
2081 # OutFile in lyx.nsi since it is defined as SETUP_EXE which is in turn
2082 # something rely on date.
2083 # Because of this, I am doing a simple nsis builder here.
2084 if platform_name != 'win32':
2085 print 'installer target is only available for windows platform'
2087 if mode != 'release':
2088 print 'installer has to be built in release mode (use option mode=release)'
2090 installer_files = ['$TOP_SRCDIR/development/Win32/packaging/installer/%s' \
2091 % x for x in development_Win32_packaging_installer] + \
2092 ['$TOP_SRCDIR/development/Win32/packaging/installer/components/%s' \
2093 % x for x in development_Win32_packaging_installer_components] + \
2094 ['$TOP_SRCDIR/development/Win32/packaging/installer/dialogs/%s' \
2095 % x for x in development_Win32_packaging_installer_dialogs] + \
2096 ['$TOP_SRCDIR/development/Win32/packaging/installer/graphics/%s' \
2097 % x for x in development_Win32_packaging_installer_graphics] + \
2098 ['$TOP_SRCDIR/development/Win32/packaging/installer/include/%s' \
2099 % x for x in development_Win32_packaging_installer_include] + \
2100 ['$TOP_SRCDIR/development/Win32/packaging/installer/lang/%s' \
2101 % x for x in development_Win32_packaging_installer_lang]
2102 if env.has_key('NSIS') and env['NSIS'] is not None:
2103 # create a builder to strip and install
2104 env['BUILDERS']['installer'] = Builder(generator=utils.env_nsis)
2106 print 'No nsis compiler is found. Existing...'
2108 if not env.has_key('win_installer') or env['win_installer'] is None:
2110 env['win_installer'] = '%s-%s-%s-Installer.exe' % (package_name, package_version, time.strftime('%Y-%m-%d'))
2112 env['win_installer'] = '%s-%s-Installer.exe' % (package_name, package_version)
2113 # provide default setting
2114 if not env.has_key('deps_dir') or env['deps_dir'] is None:
2115 env['deps_dir'] = os.path.join(env.Dir('$TOP_SRCDIR').abspath, 'lyx-windows-deps-msvc-qt4')
2116 if not os.path.isdir(env.Dir('$deps_dir').abspath):
2117 print 'Development dependency package is not found.'
2120 env['deps_dir'] = env.Dir('$deps_dir').abspath
2122 if env.has_key('bundle_dir') and os.path.isdir(env.Dir('$bundle_dir').abspath):
2123 env['bundle_dir'] = env.Dir('$bundle_dir').abspath
2124 elif os.path.isdir(os.path.join(env.Dir('$TOP_SRCDIR').abspath, 'lyx-windows-bundle-deps')):
2125 env['bundle_dir'] = os.path.join(env.Dir('$TOP_SRCDIR').abspath, 'lyx-windows-bundle-deps')
2127 env['bundle_dir'] = None
2128 # if absolute path is given, use it, otherwise, write to current directory
2129 if not (':' in env['win_installer'] or '/' in env['win_installer'] or '\\' in env['win_installer']):
2130 env['win_installer'] = os.path.join(env.Dir('$BUILDDIR').abspath, env['win_installer'])
2131 env.Append(NSISDEFINES={
2132 'ExeFile':env['win_installer'],
2133 'BundleExeFile':env['win_installer'].replace('.exe', '-bundle.exe'),
2134 'FilesLyx':env.Dir(dest_prefix_dir).abspath,
2135 'FilesDeps':env['deps_dir'],
2136 'FilesBundle':env['bundle_dir'],
2138 installer = env.installer(env['win_installer'],
2139 '$TOP_SRCDIR/development/Win32/packaging/installer/lyx.nsi')
2140 # since I can not use a scanner, explicit dependent is required
2141 env.Depends(installer, 'install')
2142 env.Depends(installer, installer_files)
2143 env.Alias('installer', installer)
2144 # also generate bundle?
2145 if env.has_key('bundle') and env['bundle']:
2146 if env['bundle_dir'] is None or not os.path.isdir(env['bundle_dir']):
2147 print 'Bundle directory does not exist (default to %s\lyx-windows-bundle-deps.' % env.Dir('$TOP_SRCDIR').abspath
2148 print 'Use bundle_dir option to specify'
2150 # generator of the builder will add bundle stuff depending on output name
2151 bundle_installer = env.installer(env['win_installer'].replace('.exe', '-bundle.exe'),
2152 '$TOP_SRCDIR/development/Win32/packaging/installer/lyx.nsi')
2153 env.Depends(bundle_installer, 'install')
2154 env.Depends(bundle_installer, installer_files)
2155 env.Alias('installer', bundle_installer)
2158 Alias('all', ['lyx', 'client', 'tex2lyx'])