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 # scons_utils.py defines a few utility function
18 sys.path.append('config')
19 import scons_utils as utils
20 # import all file lists
21 from scons_manifest import *
23 #----------------------------------------------------------
24 # Required runtime environment
25 #----------------------------------------------------------
27 # scons asks for 1.5.2, lyx requires 2.3
28 EnsurePythonVersion(2, 3)
29 # Please use at least 0.96.92 (not 0.96.1)
30 EnsureSConsVersion(0, 96)
31 # also check for minor version number for scons 0.96
32 from SCons import __version__
33 version = map(int, __version__.split('.'))
34 if version[0] == 0 and version[1] == 96 and version[2] < 92:
35 print "Scons >= 0.96.92 is required."
38 # determine where I am ...
40 # called as 'cd development/scons; scons'
41 if os.path.isfile('SConstruct'):
44 # called as 'scons -f development/scons/SConstruct'
45 elif os.path.isfile('configure.ac'):
47 scons_dir = 'development/scons'
49 print "scons can only be called from top source directory, with command:"
50 print " $ scons -f development/scons/SConstruct [other options]"
51 print "or from development/scons, with command:"
52 print " $ scons [options]"
56 #----------------------------------------------------------
58 #----------------------------------------------------------
60 # some global settings
62 # get version number from configure.ac so that JMarc does
63 # not have to change SConstruct during lyx release
64 package_version = utils.getVerFromConfigure(top_src_dir)
65 package_cygwin_version = '%s-1' % package_version
66 boost_version = '1_33_1'
68 if 'svn' in package_version:
70 default_build_mode = 'debug'
73 default_build_mode = 'release'
76 package_bugreport = 'lyx-devel@lists.lyx.org'
78 package_tarname = 'lyx'
79 package_string = '%s %s' % (package_name, package_version)
81 # various cache/log files
82 default_log_file = 'scons_lyx.log'
83 opt_cache_file = 'opt.cache'
86 #----------------------------------------------------------
87 # platform dependent settings
88 #----------------------------------------------------------
91 platform_name = 'win32'
92 default_frontend = 'qt4'
93 default_prefix = 'c:/program files/lyx'
94 default_with_x = False
95 default_packaging_method = 'windows'
96 elif os.name == 'posix' and sys.platform != 'cygwin':
97 platform_name = sys.platform
98 default_frontend = 'qt4'
99 default_prefix = '/usr/local'
100 default_with_x = True
101 default_packaging_method = 'posix'
102 elif os.name == 'posix' and sys.platform == 'cygwin':
103 platform_name = 'cygwin'
104 default_frontend = 'qt4'
105 default_prefix = '/usr'
106 default_with_x = True
107 default_packaging_method = 'posix'
108 elif os.name == 'darwin':
109 platform_name = 'macosx'
110 default_frontend = 'qt4'
111 # FIXME: macOSX default prefix?
113 default_with_x = False
114 default_packaging_method = 'macosx'
115 else: # unsupported system, assume posix behavior
116 platform_name = 'others'
117 default_frontend = 'qt4'
119 default_with_x = True
120 default_packaging_method = 'posix'
122 #---------------------------------------------------------
124 #----------------------------------------------------------
126 # You can set perminant default values in config.py
127 if os.path.isfile('config.py'):
128 print "Getting options from config.py..."
129 print open('config.py').read()
131 opts = Options(['config.py'])
134 EnumOption('frontend', 'Main GUI', default_frontend,
135 allowed_values = ('qt4',) ),
136 # debug or release build
137 EnumOption('mode', 'Building method', default_build_mode,
138 allowed_values = ('debug', 'release') ),
141 'Use included, system boost library, or try sytem boost first.',
142 'auto', allowed_values = (
143 'auto', # detect boost, if not found, use included
144 'included', # always use included boost
145 'system', # always use system boost, fail if can not find
148 EnumOption('gettext',
149 'Use included, system gettext library, or try sytem gettext first',
150 'auto', allowed_values = (
151 'auto', # detect gettext, if not found, use included
152 'included', # always use included gettext
153 'system', # always use system gettext, fail if can not find
156 EnumOption('spell', 'Choose spell checker to use.', 'auto',
157 allowed_values = ('aspell', 'pspell', 'ispell', 'auto', 'no') ),
159 EnumOption('packaging', 'Packaging method to use.', default_packaging_method,
160 allowed_values = ('windows', 'posix', 'macosx')),
162 BoolOption('fast_start', 'This option is obsolete.', False),
163 # No precompiled header support (too troublesome to make it work for msvc)
164 # BoolOption('pch', 'Whether or not use pch', False),
165 # enable assertion, (config.h has ENABLE_ASSERTIOS
166 BoolOption('assertions', 'Use assertions', True),
167 # enable warning, (config.h has WITH_WARNINGS)
168 # default to False since MSVC does not have #warning
169 BoolOption('warnings', 'Use warnings', False),
170 # config.h define _GLIBCXX_CONCEPT_CHECKS
171 # Note: for earlier version of gcc (3.3) define _GLIBCPP_CONCEPT_CHECKS
172 BoolOption('concept_checks', 'Enable concept checks', True),
174 BoolOption('nls', 'Whether or not use native language support', True),
176 BoolOption('profiling', 'Whether or not enable profiling', False),
177 # config.h define _GLIBCXX_DEBUG and _GLIBCXX_DEBUG_PEDANTIC
178 BoolOption('stdlib_debug', 'Whether or not turn on stdlib debug', False),
180 BoolOption('X11', 'Use x11 windows system', default_with_x),
181 # use MS VC++ to build lyx
182 BoolOption('use_vc', 'Use MS VC++ to build lyx (cl.exe will be probed)', None),
184 PathOption('qt_dir', 'Path to qt directory', None),
186 PathOption('qt_inc_path', 'Path to qt include directory', None),
188 PathOption('qt_lib_path', 'Path to qt library directory', None),
189 # extra include and libpath
190 PathOption('extra_inc_path', 'Extra include path', None),
192 PathOption('extra_lib_path', 'Extra library path', None),
194 PathOption('extra_bin_path', 'A convenient way to add a path to $PATH', None),
196 PathOption('extra_inc_path1', 'Extra include path', None),
198 PathOption('extra_lib_path1', 'Extra library path', None),
199 # rebuild only specifed, comma separated targets
200 ('rebuild', '''rebuild only specifed, comma separated targets.
201 yes or all (default): rebuild everything
202 no or none: rebuild nothing (usually used for installation)
203 comp1,comp2,...: rebuild specified targets''', None),
204 # can be set to a non-existing directory
205 ('prefix', 'install architecture-independent files in PREFIX', default_prefix),
206 # build directory, will use $mode if not set
207 ('build_dir', 'Build directory', None),
209 ('version_suffix', 'install lyx as lyx-suffix', None),
210 # how to load options
211 ('load_option', '''load option from previous scons run. option can be
212 yes (default): load all options
213 no: do not load any option
214 opt1,opt2: load specified options
215 -opt1,opt2: load all options other than specified ones''', 'yes'),
217 ('optimization', 'optimization CCFLAGS option.', None),
219 PathOption('exec_prefix', 'install architecture-independent executable files in PREFIX', None),
221 ('logfile', 'save commands (not outputs) to logfile', default_log_file),
222 # provided for backward compatibility
223 ('dest_dir', 'install to DESTDIR. (Provided for backward compatibility only)', None),
224 # environment variable can be set as options.
225 ('DESTDIR', 'install to DESTDIR', None),
226 ('CC', 'replace default $CC', None),
227 ('LINK', 'replace default $LINK', None),
228 ('CPP', 'replace default $CPP', None),
229 ('CXX', 'replace default $CXX', None),
230 ('CXXCPP', 'replace default $CXXCPP', None),
231 ('CCFLAGS', 'replace default $CCFLAGS', None),
232 ('CPPFLAGS', 'replace default $CPPFLAGS', None),
233 ('LINKFLAGS', 'replace default $LINKFLAGS', None),
237 all_options = [x.key for x in opts.options]
239 # copied from SCons/Options/BoolOption.py
240 # We need to use them before a boolean ARGUMENTS option is available
242 true_strings = ('y', 'yes', 'true', 't', '1', 'on' , 'all' )
243 false_strings = ('n', 'no', 'false', 'f', '0', 'off', 'none')
245 if ARGUMENTS.has_key('fast_start'):
246 print 'fast_start option is obsolete'
248 # if load_option=yes (default), load saved comand line options
250 # This option can take value yes/no/opt1,opt2/-opt1,opt2
251 # and tries to be clever in choosing options to load
252 if (not ARGUMENTS.has_key('load_option') or \
253 ARGUMENTS['load_option'] not in false_strings) \
254 and os.path.isfile(opt_cache_file):
255 cache_file = open(opt_cache_file)
256 opt_cache = cPickle.load(cache_file)
258 # import cached options, but we should ignore qt_dir when frontend changes
259 if ARGUMENTS.has_key('frontend') and opt_cache.has_key('frontend') \
260 and ARGUMENTS['frontend'] != opt_cache['frontend'] \
261 and opt_cache.has_key('qt_dir'):
262 opt_cache.pop('qt_dir')
263 # and we do not cache some options (dest_dir is obsolete)
264 for arg in ['load_option', 'dest_dir']:
265 if opt_cache.has_key(arg):
267 # remove obsolete cached keys (well, SConstruct is evolving. :-)
268 for arg in opt_cache.keys():
269 if arg not in all_options:
270 print 'Option %s is obsolete, do not load it' % arg
272 # now, if load_option=opt1,opt2 or -opt1,opt2
273 if ARGUMENTS.has_key('load_option') and \
274 ARGUMENTS['load_option'] not in true_strings + false_strings:
275 # if -opt1,opt2 is specified, do not load these options
276 if ARGUMENTS['load_option'][0] == '-':
277 for arg in ARGUMENTS['load_option'][1:].split(','):
278 if opt_cache.has_key(arg):
280 # if opt1,opt2 is specified, only load specified options
282 args = ARGUMENTS['load_option'].split(',')
283 for arg in opt_cache.keys():
286 # now restore options as if entered from command line
287 for key in opt_cache.keys():
288 if not ARGUMENTS.has_key(key):
289 ARGUMENTS[key] = opt_cache[key]
290 print "Restoring cached option %s=%s" % (key, ARGUMENTS[key])
293 # check if there is unused (or misspelled) argument
294 for arg in ARGUMENTS.keys():
295 if arg not in all_options:
297 print "Unknown option '%s'... exiting." % arg
299 print "Available options are (check 'scons -help' for details):"
300 print ' ' + '\n '.join(textwrap.wrap(', '.join(all_options)))
304 cache_file = open(opt_cache_file, 'w')
305 cPickle.dump(ARGUMENTS, cache_file)
308 #---------------------------------------------------------
309 # Setting up environment
310 #---------------------------------------------------------
312 # I do not really like ENV=os.environ, but you may add it
313 # here if you experience some environment related problem
314 env = Environment(options = opts)
316 # set individual variables since I do not really like ENV = os.environ
317 env['ENV']['PATH'] = os.environ.get('PATH')
318 env['ENV']['HOME'] = os.environ.get('HOME')
319 # these are defined for MSVC
320 env['ENV']['LIB'] = os.environ.get('LIB')
321 env['ENV']['INCLUDE'] = os.environ.get('INCLUDE')
323 # for simplicity, use var instead of env[var]
324 frontend = env['frontend']
325 prefix = env['prefix']
328 if platform_name == 'win32':
329 if env.has_key('use_vc'):
330 use_vc = env['use_vc']
331 if WhereIs('cl.exe') is None:
332 print "cl.exe is not found. Are you using the MSVC environment?"
334 elif WhereIs('cl.exe') is not None:
341 # lyx will be built to $build/build_dir so it is possible
342 # to build multiple build_dirs using the same source
343 # $mode can be debug or release
344 if env.has_key('build_dir') and env['build_dir'] is not None:
345 # create the directory if needed
346 if not os.path.isdir(env['build_dir']):
348 os.makedirs(env['build_dir'])
351 if not os.path.isdir(env['build_dir']):
352 print 'Can not create directory', env['build_dir']
354 env['BUILDDIR'] = env['build_dir']
356 # Determine the name of the build $mode
357 env['BUILDDIR'] = '#' + mode
359 # all built libraries will go to build_dir/libs
360 # (This is different from the make file approach)
361 env['LOCALLIBPATH'] = '$BUILDDIR/libs'
362 env.AppendUnique(LIBPATH = ['$LOCALLIBPATH'])
365 # Here is a summary of variables defined in env
367 # 2. undefined options with a non-None default value
368 # 3. compiler commands and flags like CCFLAGS.
369 # MSGFMT used to process po files
370 # 4. Variables that will be used to replace variables in some_file.in
371 # src/support/package.C.in:
372 # TOP_SRCDIR, LOCALEDIR, LYX_DIR, PROGRAM_SUFFIX
373 # lib/lyx2lyx/lyx2lyx_version.py.in
376 # PACKAGE_VERSION, LYX_DATE, VERSION_INFO
378 # full path name is used to build msvs project files
379 # and to replace TOP_SRCDIR in package.C
380 env['TOP_SRCDIR'] = Dir(top_src_dir).abspath
381 # needed by src/version.C.in => src/version.C
382 env['PACKAGE_VERSION'] = package_version
383 env['LYX_DATE'] = time.asctime()
385 # determine share_dir etc
386 packaging_method = env.get('packaging')
387 if packaging_method == 'windows':
388 share_dir = 'Resources'
389 man_dir = 'Resources/man/man1'
390 locale_dir = 'Resources/locale'
392 share_dir = 'share/lyx'
393 locale_dir = 'share/locale'
394 if platform_name == 'cygwin':
395 man_dir = 'share/man/man1'
399 # program suffix: can be yes, or a string
400 if env.has_key('version_suffix'):
401 if env['version_suffix'] in true_strings:
402 program_suffix = package_version
403 elif env['version_suffix'] in false_strings:
406 program_suffix = env['version_suffix']
409 # used by package.C.in
410 env['PROGRAM_SUFFIX'] = program_suffix
412 # whether or not add suffix to file and directory names
413 add_suffix = packaging_method != 'windows'
414 # LYX_DIR are different (used in package.C.in)
416 env['LYX_DIR'] = Dir(os.path.join(prefix, share_dir + program_suffix)).abspath
418 env['LYX_DIR'] = Dir(os.path.join(prefix, share_dir)).abspath
419 # we need absolute path for package.C
420 env['LOCALEDIR'] = Dir(os.path.join(prefix, locale_dir)).abspath
423 #---------------------------------------------------------
424 # Setting building environment (Tools, compiler flags etc)
425 #---------------------------------------------------------
427 # Since Tool('mingw') will reset CCFLAGS etc, this should be
428 # done before getEnvVariable
429 if platform_name == 'win32':
435 env.AppendUnique(CPPPATH = ['#c:/MinGW/include'])
437 # we differentiate between hard-coded options and default options
438 # hard-coded options are required and will always be there
439 # default options can be replaced by enviromental variables or command line options
440 CCFLAGS_required = []
441 LINKFLAGS_required = []
444 # under windows, scons is confused by .C/.c and uses gcc instead of
445 # g++. I am forcing the use of g++ here. This is expected to change
446 # after lyx renames all .C files to .cpp
448 # save the old c compiler and CCFLAGS (used by libintl)
449 C_COMPILER = env.subst('$CC')
450 C_CCFLAGS = env.subst('$CCFLAGS').split()
451 # if we use ms vc, the commands are fine (cl.exe and link.exe)
453 # /TP treat all source code as C++
454 # C4819: The file contains a character that cannot be represented
455 # in the current code page (number)
456 # C4996: foo was decleared deprecated
457 CCFLAGS_required.extend(['/TP', '/EHsc'])
459 CCFLAGS_default.extend(['/wd4819', '/wd4996', '/nologo', '/MDd'])
460 # the flags are also needed in C mode (for intl lib)
461 C_CCFLAGS.extend(['/wd4819', '/wd4996', '/nologo', '/MDd'])
463 CCFLAGS_default.extend(['/wd4819', '/wd4996', '/nologo', '/MD'])
464 C_CCFLAGS.extend(['/wd4819', '/wd4996', '/nologo', '/MD'])
466 if env.has_key('CXX') and env['CXX']:
467 env['CC'] = env.subst('$CXX')
468 env['LINK'] = env.subst('$CXX')
473 # for debug/release mode
474 if env.has_key('optimization') and env['optimization'] is not None:
475 # if user supplies optimization flags, use it anyway
476 CCFLAGS_required.extend(env['optimization'].split())
477 # and do not use default
478 set_default_optimization_flags = False
480 set_default_optimization_flags = True
484 CCFLAGS_required.append('/Zi')
485 LINKFLAGS_required.extend(['/debug', '/map'])
487 CCFLAGS_required.append('-g')
488 CCFLAGS_default.append('-O')
489 elif mode == 'release' and set_default_optimization_flags:
491 CCFLAGS_default.append('/O2')
493 CCFLAGS_default.append('-O2')
495 # msvc uses separate tools for profiling
496 if env.has_key('profiling') and env['profiling']:
498 print 'Visual C++ does not use profiling options'
500 CCFLAGS_required.append('-pg')
501 LINKFLAGS_required.append('-pg')
503 if env.has_key('warnings') and env['warnings']:
505 CCFLAGS_default.append('/W2')
507 # Note: autotools detect gxx version and pass -W for 3.x
508 # and -Wextra for other versions of gcc
509 CCFLAGS_default.append('-Wall')
511 # Now, set the variables as follows:
512 # 1. if command line option exists: replace default
513 # 2. then if s envronment variable exists: replace default
514 # 3. set variable to required + default
515 def setEnvVariable(env, name, required = None, default = None, split = True):
516 ''' env: environment to set variable
518 required: hardcoded options
519 default: default options that can be replaced by command line or
520 environment variables
521 split: whether or not split obtained variable like '-02 -g'
523 # 1. ARGUMENTS is already set to env[name], override default.
524 if ARGUMENTS.has_key(name):
525 # env[name] may be rewritten when building tools are reloaded
526 # if that is the case, commandline option will override it.
527 env[name] = ARGUMENTS[name]
529 # then use environment default
530 elif os.environ.has_key(name):
531 print "Acquiring variable %s from system environment: %s" % (name, os.environ[name])
532 default = os.environ[name]
534 default = default.split()
535 # the real value should be env[name] + default + required
538 if env.has_key(name):
539 value = str(env[name]).split()
540 if required is not None:
542 if default is not None:
546 if env.has_key(name):
547 value = str(env[name])
548 if required is not None:
549 value += " " + required
550 if default is not None:
551 value += " " + default
553 # print name, env[name]
555 setEnvVariable(env, 'DESTDIR', split=False)
556 setEnvVariable(env, 'CC')
557 setEnvVariable(env, 'LINK')
558 setEnvVariable(env, 'CPP')
559 setEnvVariable(env, 'CXX')
560 setEnvVariable(env, 'CXXCPP')
561 setEnvVariable(env, 'CCFLAGS', CCFLAGS_required, CCFLAGS_default)
562 setEnvVariable(env, 'CXXFLAGS')
563 setEnvVariable(env, 'CPPFLAGS')
564 setEnvVariable(env, 'LINKFLAGS', LINKFLAGS_required)
566 # if DESTDIR is not set...
567 if env.has_key('dest_dir'):
568 print "This option is obsolete. Please use DESTDIR instead."
569 env['DESTDIR'] = env['dest_dir']
572 #---------------------------------------------------------
573 # Frontend related variables (QTDIR etc)
574 #---------------------------------------------------------
576 if env.has_key('qt_dir') and env['qt_dir']:
577 env['QTDIR'] = env['qt_dir']
578 elif os.path.isdir(os.environ.get('QTDIR', '/usr/lib/qt-3.3')):
579 env['QTDIR'] = os.environ.get('QTDIR', '/usr/lib/qt-3.3')
581 # if there is a valid QTDIR, set path for lib and bin directories
582 if env.has_key('QTDIR'):
583 # add path to the qt tools
584 if os.path.isdir(os.path.join(env['QTDIR'], 'lib')):
585 env.AppendUnique(LIBPATH = [os.path.join(env['QTDIR'], 'lib')])
586 # set environment so that moc etc can be found even if its path is not set properly
587 if os.path.isdir(os.path.join(env['QTDIR'], 'bin')):
588 os.environ['PATH'] += os.pathsep + os.path.join(env['QTDIR'], 'bin')
589 env.PrependENVPath('PATH', os.path.join(env['QTDIR'], 'bin'))
591 if env.has_key('qt_lib_path') and env['qt_lib_path']:
592 qt_lib_path = env.subst('$qt_lib_path')
593 elif env.has_key('QTDIR') and os.path.isdir(os.path.join(env.subst('$QTDIR'), 'lib')):
594 qt_lib_path = env.subst('$QTDIR/lib')
595 # this is the path for cygwin.
596 elif os.path.isdir(os.path.join('/usr/lib/', frontend, 'lib')):
597 qt_lib_path = '/usr/lib/%s/lib' % frontend
599 print "Qt library directory is not found. Please specify it using qt_lib_path"
601 env.AppendUnique(LIBPATH = [qt_lib_path])
602 # qt4 seems to be using pkg_config
603 env.PrependENVPath('PKG_CONFIG_PATH', qt_lib_path)
605 if env.has_key('qt_inc_path') and env['qt_inc_path']:
606 qt_inc_path = env['qt_inc_path']
607 elif env.has_key('QTDIR') and os.path.isdir(os.path.join(env.subst('$QTDIR'), 'include')):
608 qt_inc_path = '$QTDIR/include'
609 # this is the path for cygwin.
610 elif os.path.isdir('/usr/include/' + frontend):
611 qt_inc_path = '/usr/include/' + frontend
613 print "Qt include directory not found. Please specify it using qt_inc_path"
615 # Note that this CPPPATH is for testing only
616 # it will be removed before calling SConscript
617 env['CPPPATH'] = [qt_inc_path]
620 # extra_inc_path and extra_lib_path
623 if env.has_key('extra_inc_path') and env['extra_inc_path']:
624 extra_inc_paths.append(env['extra_inc_path'])
625 if env.has_key('extra_lib_path') and env['extra_lib_path']:
626 env.AppendUnique(LIBPATH = [env['extra_lib_path']])
627 if env.has_key('extra_inc_path1') and env['extra_inc_path1']:
628 extra_inc_paths.append(env['extra_inc_path1'])
629 if env.has_key('extra_lib_path1') and env['extra_lib_path1']:
630 env.AppendUnique(LIBPATH = [env['extra_lib_path1']])
631 if env.has_key('extra_bin_path') and env['extra_bin_path']:
632 # only the first one is needed (a scons bug?)
633 os.environ['PATH'] += os.pathsep + env['extra_bin_path']
634 env.PrependENVPath('PATH', env['extra_bin_path'])
635 # extra_inc_paths will be used later by intlenv etc
636 env.AppendUnique(CPPPATH = extra_inc_paths)
639 #----------------------------------------------------------
641 #----------------------------------------------------------
643 conf = Configure(env,
645 'CheckPkgConfig' : utils.checkPkgConfig,
646 'CheckPackage' : utils.checkPackage,
647 'CheckMkdirOneArg' : utils.checkMkdirOneArg,
648 'CheckSelectArgType' : utils.checkSelectArgType,
649 'CheckBoostLibraries' : utils.checkBoostLibraries,
650 'CheckCommand' : utils.checkCommand,
651 'CheckCXXGlobalCstd' : utils.checkCXXGlobalCstd,
652 'CheckLC_MESSAGES' : utils.checkLC_MESSAGES,
653 'CheckIconvConst' : utils.checkIconvConst,
654 'CheckSizeOfWChar' : utils.checkSizeOfWChar,
658 # pkg-config? (if not, we use hard-coded options)
659 if conf.CheckPkgConfig('0.15.0'):
660 env['HAS_PKG_CONFIG'] = True
662 print 'pkg-config >= 0.1.50 is not found'
663 env['HAS_PKG_CONFIG'] = False
665 # zlib? This is required.
666 if (not use_vc and not conf.CheckLibWithHeader('z', 'zlib.h', 'C')) \
667 or (use_vc and not conf.CheckLibWithHeader('zdll', 'zlib.h', 'C')):
668 print 'Did not find zdll.lib or zlib.h, exiting!'
670 if conf.CheckLib('iconv'):
671 env['ICONV_LIB'] = 'iconv'
672 elif conf.CheckLib('libiconv'):
673 env['ICONV_LIB'] = 'libiconv'
674 elif conf.CheckFunc('iconv_open'):
675 env['ICONV_LIB'] = None
677 print 'Did not find iconv or libiconv, exiting!'
683 if frontend == 'qt4':
685 # first: try pkg_config
686 if env['HAS_PKG_CONFIG']:
687 succ = conf.CheckPackage('QtCore') or conf.CheckPackage('QtCore4')
688 # FIXME: use pkg_config information?
689 #env['QT4_PKG_CONFIG'] = succ
690 # second: try to link to it
692 # Under linux, I can test the following perfectly
693 # Under windows, lib names need to passed as libXXX4.a ...
694 succ = conf.CheckLibWithHeader('QtCore', 'QtGui/QApplication', 'c++', 'QApplication qapp();') or \
695 conf.CheckLibWithHeader('QtCore4', 'QtGui/QApplication', 'c++', 'QApplication qapp();')
696 # third: try to look up the path
699 for lib in ['QtCore', 'QtGui']:
700 # windows version has something like QtGui4 ...
701 if not (os.path.isfile(os.path.join(qt_lib_path, 'lib%s.a' % lib)) or \
702 os.path.isfile(os.path.join(qt_lib_path, 'lib%s4.a' % lib))):
705 # still can not find it
707 print "Qt4 libraries are found."
709 print 'Did not find qt libraries, exiting!'
712 # now, if msvc2005 is used, we will need that QT_LIB_PATH/QT_LIB.manifest file
714 if frontend == 'qt4':
716 manifest = os.path.join(qt_lib_path, 'QtGuid4.dll.manifest')
718 manifest = os.path.join(qt_lib_path, 'QtGui4.dll.manifest')
719 if os.path.isfile(manifest):
720 env['LINKCOM'] = [env['LINKCOM'], 'mt.exe /MANIFEST %s /outputresource:$TARGET;1' % manifest]
724 if conf.CheckLib('socket'):
725 socket_libs.append('socket')
726 # nsl is the network services library and provides a
727 # transport-level interface to networking services.
728 if conf.CheckLib('nsl'):
729 socket_libs.append('nsl')
731 # check available boost libs (since lyx1.4 does not use iostream)
733 for lib in ['signals', 'regex', 'filesystem', 'iostreams']:
734 if os.path.isdir(os.path.join(top_src_dir, 'boost', 'libs', lib)):
735 boost_libs.append(lib)
737 # check boost libraries
738 boost_opt = ARGUMENTS.get('boost', 'auto')
739 # check for system boost
740 lib_paths = env['LIBPATH'] + ['/usr/lib', '/usr/local/lib']
741 inc_paths = env['CPPPATH'] + ['/usr/include', '/usr/local/include']
742 # default to $BUILDDIR/libs (use None since this path will be added anyway)
744 # here I assume that all libraries are in the same directory
745 if boost_opt == 'included':
746 boost_libraries = ['included_boost_%s' % x for x in boost_libs]
747 included_boost = True
748 env['BOOST_INC_PATH'] = '$TOP_SRCDIR/boost'
749 elif boost_opt == 'auto':
750 res = conf.CheckBoostLibraries(boost_libs, lib_paths, inc_paths, boost_version, mode == 'debug')
751 # if not found, use local boost
753 boost_libraries = ['included_boost_%s' % x for x in boost_libs]
754 included_boost = True
755 env['BOOST_INC_PATH'] = '$TOP_SRCDIR/boost'
757 included_boost = False
758 (boost_libraries, boost_libpath, env['BOOST_INC_PATH']) = res
759 elif boost_opt == 'system':
760 res = conf.CheckBoostLibraries(boost_libs, lib_paths, inc_paths, boost_version, mode == 'debug')
762 print "Can not find system boost libraries with version %s " % boost_version
763 print "Please supply a path through extra_lib_path and try again."
764 print "Or use boost=included to use included boost libraries."
767 included_boost = False
768 (boost_libraries, boost_libpath, env['BOOST_INC_PATH']) = res
771 if boost_libpath is not None:
772 env.AppendUnique(LIBPATH = [boost_libpath])
775 env['ENABLE_NLS'] = env['nls']
777 if not env['ENABLE_NLS']:
779 included_gettext = False
781 # check gettext libraries
782 gettext_opt = ARGUMENTS.get('gettext', 'auto')
783 # check for system gettext
785 if gettext_opt in ['auto', 'system']:
786 if conf.CheckFunc('gettext'):
787 included_gettext = False
790 elif conf.CheckLib('intl'):
791 included_gettext = False
795 if gettext_opt == 'system':
796 print "Can not find system gettext library"
797 print "Please supply a path through extra_lib_path and try again."
798 print "Or use gettext=included to use included gettext libraries."
800 # now, auto and succ = false, or gettext=included
802 # we do not need to set LIBPATH now.
803 included_gettext = True
804 intl_libs = ['included_intl']
808 # check for msgfmt command
809 env['MSGFMT'] = conf.CheckCommand('msgfmt')
811 # cygwin packaging requires the binaries to be stripped
812 if platform_name == 'cygwin':
813 env['STRIP'] = conf.CheckCommand('strip')
815 # check uic and moc commands for qt frontends
816 if frontend[:2] == 'qt' and (conf.CheckCommand('uic') == None \
817 or conf.CheckCommand('moc') == None):
818 print 'uic or moc command is not found for frontend', frontend
822 # Customized builders
824 # install customized builders
825 env['BUILDERS']['substFile'] = Builder(action = utils.env_subst)
828 #----------------------------------------------------------
829 # Generating config.h
830 #----------------------------------------------------------
831 aspell_lib = 'aspell'
832 # assume that we use aspell, aspelld compiled for msvc
833 if platform_name == 'win32' and mode == 'debug' and use_vc:
834 aspell_lib = 'aspelld'
836 # check the existence of config.h
837 config_h = os.path.join(env.Dir('$BUILDDIR/common').path, 'config.h')
838 boost_config_h = os.path.join(env.Dir('$BUILDDIR/boost').path, 'config.h')
840 print "Creating %s..." % boost_config_h
842 utils.createConfigFile(conf,
843 config_file = boost_config_h,
844 config_pre = '''/* boost/config.h. Generated by SCons. */
849 * This file is part of LyX, the document processor.
850 * Licence details can be found in the file COPYING.
852 * This is the compilation configuration file for LyX.
853 * It was generated by scon.
854 * You might want to change some of the defaults if something goes wrong
855 * during the compilation.
858 #ifndef _BOOST_CONFIG_H
859 #define _BOOST_CONFIG_H
862 ('ostream', 'HAVE_OSTREAM', 'cxx'),
863 ('locale', 'HAVE_LOCALE', 'cxx'),
864 ('sstream', 'HAVE_SSTREAM', 'cxx'),
865 #('newapis.h', 'HAVE_NEWAPIS_H', 'c'),
868 (env.has_key('assertions') and env['assertions'],
870 'Define if you want assertions to be enabled in the code'
874 ('wchar_t', 'HAVE_WCHAR_T', None),
878 #if defined(HAVE_OSTREAM) && defined(HAVE_LOCALE) && defined(HAVE_SSTREAM)
879 # define USE_BOOST_FORMAT 1
881 # define USE_BOOST_FORMAT 0
884 #if !defined(ENABLE_ASSERTIONS)
885 # define BOOST_DISABLE_ASSERTS 1
887 #define BOOST_ENABLE_ASSERT_HANDLER 1
889 #define BOOST_DISABLE_THREADS 1
890 #define BOOST_NO_WSTRING 1
893 # define BOOST_POSIX 1
894 # define BOOST_POSIX_API 1
895 # define BOOST_POSIX_PATH 1
898 #define BOOST_ALL_NO_LIB 1
900 #if defined(HAVE_NEWAPIS_H)
901 # define WANT_GETFILEATTRIBUTESEX_WRAPPER 1
904 #if defined(HAVE_WCHAR_T) && SIZEOF_WCHAR_T == 4
905 # define LIBC_WCTYPE_USES_UCS4
912 print "\nGenerating %s..." % config_h
914 # AIKSAURUS_H_LOCATION
915 if (conf.CheckCXXHeader("Aiksaurus.h")):
916 aik_location = '<Aiksaurus.h>'
917 elif (conf.CheckCXXHeader("Aiksaurus/Aiksaurus.h")):
918 aik_location = '<Aiksaurus/Aiksaurus.h>'
922 # determine headers to use
923 spell_opt = ARGUMENTS.get('spell', 'auto')
924 env['USE_ASPELL'] = False
925 env['USE_PSPELL'] = False
926 env['USE_ISPELL'] = False
927 if spell_opt in ['auto', 'aspell'] and conf.CheckLib(aspell_lib):
928 spell_engine = 'USE_ASPELL'
929 elif spell_opt in ['auto', 'pspell'] and conf.CheckLib('pspell'):
930 spell_engine = 'USE_PSPELL'
931 elif spell_opt in ['auto', 'ispell'] and conf.CheckLib('ispell'):
932 spell_engine = 'USE_ISPELL'
936 if spell_engine is not None:
937 env[spell_engine] = True
939 if spell_opt == 'auto':
940 print "Warning: Can not locate any spell checker"
941 elif spell_opt != 'no':
942 print "Warning: Can not locate specified spell checker:", spell_opt
945 # check arg types of select function
946 (select_arg1, select_arg234, select_arg5) = conf.CheckSelectArgType()
948 # check the size of wchar_t
949 sizeof_wchar_t = conf.CheckSizeOfWChar()
951 if sizeof_wchar_t == 0:
952 print 'Error: Can not determine the size of wchar_t.'
957 result = utils.createConfigFile(conf,
958 config_file = config_h,
959 config_pre = '''/* config.h. Generated by SCons. */
964 * This file is part of LyX, the document processor.
965 * Licence details can be found in the file COPYING.
967 * This is the compilation configuration file for LyX.
968 * It was generated by scon.
969 * You might want to change some of the defaults if something goes wrong
970 * during the compilation.
977 ('io.h', 'HAVE_IO_H', 'c'),
978 ('limits.h', 'HAVE_LIMITS_H', 'c'),
979 ('locale.h', 'HAVE_LOCALE_H', 'c'),
980 ('process.h', 'HAVE_PROCESS_H', 'c'),
981 ('stdlib.h', 'HAVE_STDLIB_H', 'c'),
982 ('sys/stat.h', 'HAVE_SYS_STAT_H', 'c'),
983 ('sys/time.h', 'HAVE_SYS_TIME_H', 'c'),
984 ('sys/types.h', 'HAVE_SYS_TYPES_H', 'c'),
985 ('sys/utime.h', 'HAVE_SYS_UTIME_H', 'c'),
986 ('sys/socket.h', 'HAVE_SYS_SOCKET_H', 'c'),
987 ('unistd.h', 'HAVE_UNISTD_H', 'c'),
988 ('utime.h', 'HAVE_UTIME_H', 'c'),
989 ('direct.h', 'HAVE_DIRECT_H', 'c'),
990 ('istream', 'HAVE_ISTREAM', 'cxx'),
991 ('ios', 'HAVE_IOS', 'cxx'),
994 ('open', 'HAVE_OPEN', None),
995 ('chmod', 'HAVE_CHMOD', None),
996 ('close', 'HAVE_CLOSE', None),
997 ('popen', 'HAVE_POPEN', None),
998 ('pclose', 'HAVE_PCLOSE', None),
999 ('_open', 'HAVE__OPEN', None),
1000 ('_close', 'HAVE__CLOSE', None),
1001 ('_popen', 'HAVE__POPEN', None),
1002 ('_pclose', 'HAVE__PCLOSE', None),
1003 ('getpid', 'HAVE_GETPID', None),
1004 ('_getpid', 'HAVE__GETPID', None),
1005 ('mkdir', 'HAVE_MKDIR', None),
1006 ('_mkdir', 'HAVE__MKDIR', None),
1007 ('mktemp', 'HAVE_MKTEMP', None),
1008 ('mkstemp', 'HAVE_MKSTEMP', None),
1009 ('strerror', 'HAVE_STRERROR', None),
1010 ('count', 'HAVE_STD_COUNT', '''
1011 #include <algorithm>
1015 return std::count(a, a+5, 'l');
1018 ('getcwd', 'HAVE_GETCWD', None),
1019 ('setenv', 'HAVE_SETENV', None),
1020 ('putenv', 'HAVE_PUTENV', None),
1021 ('fcntl', 'HAVE_FCNTL', None),
1024 ('std::istreambuf_iterator<std::istream>', 'HAVE_DECL_ISTREAMBUF_ITERATOR',
1025 '#include <streambuf>\n#include <istream>'),
1026 ('wchar_t', 'HAVE_WCHAR_T', None),
1027 ('mode_t', 'HAVE_MODE_T', "#include <sys/types.h>"),
1030 ('gdi32', 'HAVE_LIBGDI32'),
1031 (('Aiksaurus', 'libAiksaurus'), 'HAVE_LIBAIKSAURUS', 'AIKSAURUS_LIB'),
1034 (conf.CheckType('pid_t', includes='#include <sys/types.h>'),
1036 'Define is sys/types.h does not have pid_t',
1038 '#define pid_t int',
1040 (conf.CheckCXXGlobalCstd(),
1042 'Define if your C++ compiler puts C library functions in the global namespace'
1044 (conf.CheckMkdirOneArg(),
1045 'MKDIR_TAKES_ONE_ARG',
1046 'Define if mkdir takes only one argument.'
1048 (conf.CheckIconvConst(),
1050 'Define as const if the declaration of iconv() needs const.',
1051 '#define ICONV_CONST const',
1052 '#define ICONV_CONST',
1054 (conf.CheckLC_MESSAGES(),
1056 'Define if your <locale.h> file defines LC_MESSAGES.'
1058 (devel_version, 'DEVEL_VERSION', 'Whether or not a development version'),
1061 "Define to 1 if translation of program messages to the user's native anguage is requested.",
1063 (env['nls'] and not included_gettext,
1065 'Define to 1 if using system gettext library'
1067 (env.has_key('warnings') and env['warnings'],
1069 'Define this if you want to see the warning directives put here and there by the developpers to get attention'
1071 (env.has_key('concept_checks') and env['concept_checks'],
1072 '_GLIBCXX_CONCEPT_CHECKS',
1073 'libstdc++ concept checking'
1075 (env.has_key('stdlib_debug') and env['stdlib_debug'],
1077 'libstdc++ debug mode'
1079 (env.has_key('stdlib_debug') and env['stdlib_debug'],
1080 '_GLIBCXX_DEBUG_PEDANTIC',
1081 'libstdc++ pedantic debug mode'
1083 (os.name != 'nt', 'BOOST_POSIX',
1084 'Indicates to boost < 1.34 which API to use (posix or windows).'
1086 (os.name != 'nt', 'BOOST_POSIX_API',
1087 'Indicates to boost 1.34 which API to use (posix or windows).'
1089 (os.name != 'nt', 'BOOST_POSIX_PATH',
1090 'Indicates to boost 1.34 which path style to use (posix or windows).'
1092 (spell_engine is not None, spell_engine,
1093 'Spell engine to use'
1095 # we need to know the byte order for unicode conversions
1096 (sys.byteorder == 'big', 'WORDS_BIGENDIAN',
1097 'Define to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX).'
1101 ('#define PACKAGE "%s%s"' % (package, program_suffix),
1103 ('#define PACKAGE_BUGREPORT "%s"' % package_bugreport,
1104 'Define to the address where bug reports for this package should be sent.'),
1105 ('#define PACKAGE_NAME "%s"' % package_name,
1106 'Define to the full name of this package.'),
1107 ('#define PACKAGE_STRING "%s"' % package_string,
1108 'Define to the full name and version of this package.'),
1109 ('#define PACKAGE_TARNAME "%s"' % package_tarname,
1110 'Define to the one symbol short name of this package.'),
1111 ('#define PACKAGE_VERSION "%s"' % package_version,
1112 'Define to the version of this package.'),
1113 ('#define BOOST_ALL_NO_LIB 1',
1114 'disable automatic linking of boost libraries.'),
1115 ('#define USE_%s_PACKAGING 1' % packaging_method.upper(),
1116 'Packaging method'),
1117 ('#define AIKSAURUS_H_LOCATION ' + aik_location,
1118 'Aiksaurus include file'),
1119 ('#define SELECT_TYPE_ARG1 %s' % select_arg1,
1120 "Define to the type of arg 1 for `select'."),
1121 ('#define SELECT_TYPE_ARG234 %s' % select_arg234,
1122 "Define to the type of arg 2, 3, 4 for `select'."),
1123 ('#define SELECT_TYPE_ARG5 %s' % select_arg5,
1124 "Define to the type of arg 5 for `select'."),
1125 ('#define SIZEOF_WCHAR_T %d' % sizeof_wchar_t,
1126 'Define to be the size of type wchar_t'),
1128 config_post = '''/************************************************************
1129 ** You should not need to change anything beyond this point */
1131 #ifndef HAVE_STRERROR
1132 #if defined(__cplusplus)
1135 char * strerror(int n);
1139 #ifndef HAVE_DECL_MKSTEMP
1140 #if defined(__cplusplus)
1147 #include <../boost/config.h>
1153 # these keys are needed in env
1154 for key in ['USE_ASPELL', 'USE_PSPELL', 'USE_ISPELL', 'HAVE_FCNTL',\
1155 'HAVE_LIBGDI32', 'HAVE_LIBAIKSAURUS', 'AIKSAURUS_LIB']:
1156 # USE_ASPELL etc does not go through result
1157 if result.has_key(key):
1158 env[key] = result[key]
1161 # if nls=yes and gettext=included, create intl/config.h
1162 # intl/libintl.h etc
1164 intl_config_h = os.path.join(env.Dir('$BUILDDIR/intl').path, 'config.h')
1165 if env['nls'] and included_gettext:
1167 print "Creating %s..." % intl_config_h
1169 # create intl/config.h
1170 result = utils.createConfigFile(conf,
1171 config_file = intl_config_h,
1172 config_pre = '''/* intl/config.h. Generated by SCons. */
1177 * This file is part of LyX, the document processor.
1178 * Licence details can be found in the file COPYING.
1180 * This is the compilation configuration file for LyX.
1181 * It was generated by scon.
1182 * You might want to change some of the defaults if something goes wrong
1183 * during the compilation.
1190 ('unistd.h', 'HAVE_UNISTD_H', 'c'),
1191 ('inttypes.h', 'HAVE_INTTYPES_H', 'c'),
1192 ('string.h', 'HAVE_STRING_H', 'c'),
1193 ('strings.h', 'HAVE_STRINGS_H', 'c'),
1194 ('argz.h', 'HAVE_ARGZ_H', 'c'),
1195 ('limits.h', 'HAVE_LIMITS_H', 'c'),
1196 ('alloca.h', 'HAVE_ALLOCA_H', 'c'),
1197 ('stddef.h', 'HAVE_STDDEF_H', 'c'),
1198 ('stdint.h', 'HAVE_STDINT_H', 'c'),
1199 ('sys/param.h', 'HAVE_SYS_PARAM_H', 'c'),
1202 ('getcwd', 'HAVE_GETCWD', None),
1203 ('stpcpy', 'HAVE_STPCPY', None),
1204 ('strcasecmp', 'HAVE_STRCASECMP', None),
1205 ('strdup', 'HAVE_STRDUP', None),
1206 ('strtoul', 'HAVE_STRTOUL', None),
1207 ('alloca', 'HAVE_ALLOCA', None),
1208 ('__fsetlocking', 'HAVE___FSETLOCKING', None),
1209 ('mempcpy', 'HAVE_MEMPCPY', None),
1210 ('__argz_count', 'HAVE___ARGZ_COUNT', None),
1211 ('__argz_next', 'HAVE___ARGZ_NEXT', None),
1212 ('__argz_stringify', 'HAVE___ARGZ_STRINGIFY', None),
1213 ('setlocale', 'HAVE_SETLOCALE', None),
1214 ('tsearch', 'HAVE_TSEARCH', None),
1215 ('getegid', 'HAVE_GETEGID', None),
1216 ('getgid', 'HAVE_GETGID', None),
1217 ('getuid', 'HAVE_GETUID', None),
1218 ('wcslen', 'HAVE_WCSLEN', None),
1219 ('asprintf', 'HAVE_ASPRINTF', None),
1220 ('wprintf', 'HAVE_WPRINTF', None),
1221 ('snprintf', 'HAVE_SNPRINTF', None),
1222 ('printf', 'HAVE_POSIX_PRINTF', None),
1223 ('fcntl', 'HAVE_FCNTL', None),
1226 ('intmax_t', 'HAVE_INTMAX_T', None),
1227 ('long double', 'HAVE_LONG_DOUBLE', None),
1228 ('long long', 'HAVE_LONG_LONG', None),
1229 ('wchar_t', 'HAVE_WCHAR_T', None),
1230 ('wint_t', 'HAVE_WINT_T', None),
1231 ('uintmax_t', 'HAVE_INTTYPES_H_WITH_UINTMAX', '#include <inttypes.h>'),
1232 ('uintmax_t', 'HAVE_STDINT_H_WITH_UINTMAX', '#include <stdint.h>'),
1238 (conf.CheckLC_MESSAGES(),
1240 'Define if your <locale.h> file defines LC_MESSAGES.'
1242 (conf.CheckIconvConst(),
1244 'Define as const if the declaration of iconv() needs const.',
1245 '#define ICONV_CONST const',
1246 '#define ICONV_CONST',
1248 (conf.CheckType('intmax_t', includes='#include <stdint.h>') or \
1249 conf.CheckType('intmax_t', includes='#include <inttypes.h>'),
1251 "Define to 1 if you have the `intmax_t' type."
1253 (env.has_key('nls') and env['nls'],
1255 "Define to 1 if translation of program messages to the user's native anguage is requested.",
1259 ('#define HAVE_ICONV 1', 'Define if iconv or libiconv is found'),
1260 ('#define SIZEOF_WCHAR_T %d' % sizeof_wchar_t,
1261 'Define to be the size of type wchar_t'),
1263 config_post = '#endif'
1266 # these keys are needed in env
1267 for key in ['HAVE_ASPRINTF', 'HAVE_WPRINTF', 'HAVE_SNPRINTF', \
1268 'HAVE_POSIX_PRINTF', 'HAVE_LIBC']:
1269 # USE_ASPELL etc does not go through result
1270 if result.has_key(key):
1271 env[key] = result[key]
1274 # this looks misplaced, but intl/libintl.h is needed by src/message.C
1275 if env['nls'] and included_gettext:
1276 # libgnuintl.h.in => libintl.h
1277 env.Depends('$TOP_SRCDIR/intl/libintl.h', '$BUILDDIR/intl/config.h')
1278 env.substFile('$BUILDDIR/intl/libintl.h', '$TOP_SRCDIR/intl/libgnuintl.h.in')
1279 env.Command('$BUILDDIR/intl/libgnuintl.h', '$BUILDDIR/intl/libintl.h',
1280 [Copy('$TARGET', '$SOURCE')])
1283 # Finish auto-configuration
1286 #----------------------------------------------------------
1287 # Now set up our build process accordingly
1288 #----------------------------------------------------------
1293 # NOTE: Tool('qt') or Tool('qt4') will be loaded later
1294 # in their respective directory and specialized env.
1295 if frontend == 'qt4':
1296 qt_libs = ['QtCore', 'QtGui']
1297 # set the right lib names
1298 if platform_name == 'win32':
1299 if mode == 'debug' and use_vc:
1300 qt_lib_suffix = 'd4'
1305 qt_lib_suffix = '_debug'
1308 frontend_libs = [x + qt_lib_suffix for x in qt_libs]
1309 qtcore_lib = ['QtCore' + qt_lib_suffix]
1312 if env['ICONV_LIB'] is None:
1315 system_libs = [env['ICONV_LIB']]
1316 if platform_name in ['win32', 'cygwin']:
1317 # the final link step needs stdc++ to succeed under mingw
1318 # FIXME: shouldn't g++ automatically link to stdc++?
1320 system_libs += ['ole32', 'shlwapi', 'shell32', 'advapi32', 'zdll']
1322 system_libs += ['shlwapi', 'stdc++', 'z']
1323 elif platform_name == 'cygwin' and env['X11']:
1324 system_libs += ['GL', 'Xmu', 'Xi', 'Xrender', 'Xrandr',
1325 'Xcursor', 'Xft', 'freetype', 'fontconfig', 'Xext', 'X11', 'SM', 'ICE',
1326 'resolv', 'pthread', 'z']
1328 system_libs += ['z']
1331 ('HAVE_LIBGDI32', 'gdi32'),
1332 ('HAVE_LIBAIKSAURUS', env['AIKSAURUS_LIB']),
1333 ('USE_ASPELL', aspell_lib),
1334 ('USE_ISPELL', 'ispell'),
1335 ('USE_PSPELL', 'pspell'),
1340 system_libs.append(lib[1])
1343 # Build parameters CPPPATH etc
1346 env.AppendUnique(LIBPATH = ['/usr/X11R6/lib'])
1349 # boost: for boost header files
1350 # BUILDDIR/common: for config.h
1351 # TOP_SRCDIR/src: for support/* etc
1353 env['CPPPATH'] += ['$BUILDDIR/common', '$TOP_SRCDIR/src']
1355 # Separating boost directories from CPPPATH stops scons from building
1356 # the dependency tree for boost header files, and effectively reduce
1357 # the null build time of lyx from 29s to 16s. Since lyx may tweak local
1358 # boost headers, this is only done for system boost headers.
1360 env.AppendUnique(CPPPATH = ['$BOOST_INC_PATH'])
1363 env.PrependUnique(CCFLAGS = ['/I$BOOST_INC_PATH'])
1365 env.PrependUnique(CCFLAGS = ['-I$BOOST_INC_PATH'])
1367 # for intl/config.h, intl/libintl.h and intl/libgnuintl.h
1368 if env['nls'] and included_gettext:
1369 env['CPPPATH'].append('$BUILDDIR/intl')
1371 # QT_INC_PATH is not needed for *every* source file
1372 env['CPPPATH'].remove(qt_inc_path)
1375 # A Link script for cygwin see
1376 # http://www.cygwin.com/ml/cygwin/2004-09/msg01101.html
1377 # http://www.cygwin.com/ml/cygwin-apps/2004-09/msg00309.html
1380 if platform_name == 'cygwin':
1381 ld_script_path = '/tmp'
1382 ld_script = utils.installCygwinLDScript(ld_script_path)
1383 env.AppendUnique(LINKFLAGS = ['-Wl,--enable-runtime-pseudo-reloc',
1384 '-Wl,--script,%s' % ld_script, '-Wl,-s'])
1389 # fill in the version info
1390 env['VERSION_INFO'] = '''Configuration
1392 Special build flags: %s
1394 C Compiler flags: %s %s
1396 C++ Compiler LyX flags: %s
1397 C++ Compiler flags: %s %s
1399 Linker user flags: %s
1401 Builing directory: %s
1402 Local library directory: %s
1405 Frontend libraries: %s
1406 System libraries: %s
1407 include search path: %s
1413 ''' % (platform_name,
1414 env.subst('$CCFLAGS'), env.subst('$CC'),
1415 env.subst('$CPPFLAGS'), env.subst('$CFLAGS'),
1416 env.subst('$CXX'), env.subst('$CXXFLAGS'),
1417 env.subst('$CPPFLAGS'), env.subst('$CXXFLAGS'),
1418 env.subst('$LINKFLAGS'), env.subst('$LINKFLAGS'),
1419 env.subst('$BUILDDIR'), env.subst('$LOCALLIBPATH'),
1420 str(env['LIBPATH']), str(boost_libraries),
1421 str(frontend_libs), str(system_libs), str(env['CPPPATH']),
1422 frontend, packaging_method,
1423 prefix, env['LYX_DIR'])
1425 if frontend in ['qt4']:
1426 env['VERSION_INFO'] += ''' include dir: %s
1429 ''' % (qt_inc_path, qt_lib_path, env['X11'])
1431 print env['VERSION_INFO']
1434 # Mingw command line may be too short for our link usage,
1435 # Here we use a trick from scons wiki
1436 # http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/LongCmdLinesOnWin32
1438 # I also would like to add logging (commands only) capacity to the
1440 logfile = env.get('logfile', default_log_file)
1441 if logfile != '' or platform_name == 'win32':
1443 utils.setLoggedSpawn(env, logfile, longarg = (platform_name == 'win32'),
1444 info = '''# This is a log of commands used by scons to build lyx
1448 ''' % (time.asctime(), ' '.join(sys.argv),
1449 env['VERSION_INFO'].replace('\n','\n# ')) )
1454 # -h will print out help info
1455 Help(opts.GenerateHelpText(env))
1459 #----------------------------------------------------------
1461 #----------------------------------------------------------
1462 # this has been the source of problems on some platforms...
1463 # I find that I need to supply it with full path name
1464 env.SConsignFile(os.path.join(Dir(env['BUILDDIR']).abspath, '.sconsign'))
1465 # this usage needs further investigation.
1466 #env.CacheDir('%s/Cache/%s' % (env['BUILDDIR'], frontend))
1468 print "Building all targets recursively"
1470 if env.has_key('rebuild'):
1471 rebuild_targets = env['rebuild'].split(',')
1472 if 'none' in rebuild_targets or 'no' in rebuild_targets:
1473 rebuild_targets = []
1474 elif 'all' in rebuild_targets or 'yes' in rebuild_targets:
1475 # None: let scons decide which components to build
1476 # Forcing all components to be rebuilt is in theory not necessary
1477 rebuild_targets = None
1479 rebuild_targets = None
1481 def libExists(libname):
1482 ''' Check whether or not lib $LOCALLIBNAME/libname already exists'''
1483 return os.path.isfile(File(env.subst('$LOCALLIBPATH/${LIBPREFIX}%s$LIBSUFFIX'%libname)).abspath)
1485 def appExists(apppath, appname):
1486 ''' Check whether or not application already exists'''
1487 return os.path.isfile(File(env.subst('$BUILDDIR/common/%s/${PROGPREFIX}%s$PROGSUFFIX' % (apppath, appname))).abspath)
1489 targets = BUILD_TARGETS
1490 # msvc need to pass full target name, so I have to look for path/lyx etc
1491 build_lyx = targets == [] or True in ['lyx' in x for x in targets] \
1492 or 'install' in targets or 'all' in targets
1493 build_boost = (included_boost and not libExists('boost_regex')) or 'boost' in targets
1494 build_intl = (included_gettext and not libExists('included_intl')) or 'intl' in targets
1495 build_support = build_lyx or True in [x in targets for x in ['support', 'client', 'tex2lyx']]
1496 build_mathed = build_lyx or 'mathed' in targets
1497 build_insets = build_lyx or 'insets' in targets
1498 build_frontends = build_lyx or 'frontends' in targets
1499 build_graphics = build_lyx or 'graphics' in targets
1500 build_controllers = build_lyx or 'controllers' in targets
1501 build_client = True in ['client' in x for x in targets] \
1502 or 'install' in targets or 'all' in targets
1503 build_tex2lyx = True in ['tex2lyx' in x for x in targets] \
1504 or 'install' in targets or 'all' in targets
1505 build_lyxbase = build_lyx or 'lyxbase' in targets
1506 build_po = 'po' in targets or 'install' in targets or 'all' in targets
1507 build_qt4 = (build_lyx and frontend == 'qt4') or 'qt4' in targets
1508 build_msvs_projects = use_vc and 'msvs_projects' in targets
1511 # now, if rebuild_targets is specified, do not rebuild some targets
1512 if rebuild_targets is not None:
1514 def ifBuildLib(name, libname, old_value):
1515 # explicitly asked to rebuild
1516 if name in rebuild_targets:
1518 # else if not rebuild, and if the library already exists
1519 elif libExists(libname):
1521 # do not change the original value
1524 build_boost = ifBuildLib('boost', 'included_boost_filesystem', build_boost)
1525 build_intl = ifBuildLib('intl', 'included_intl', build_intl)
1526 build_support = ifBuildLib('support', 'support', build_support)
1527 build_mathed = ifBuildLib('mathed', 'mathed', build_mathed)
1528 build_insets = ifBuildLib('insets', 'insets', build_insets)
1529 build_frontends = ifBuildLib('frontends', 'frontends', build_frontends)
1530 build_graphics = ifBuildLib('graphics', 'graphics', build_graphics)
1531 build_controllers = ifBuildLib('controllers', 'controllers', build_controllers)
1532 build_lyxbase = ifBuildLib('lyxbase', 'lyxbase_pre', build_lyxbase)
1533 build_qt4 = ifBuildLib('qt4', 'qt4', build_qt4)
1535 def ifBuildApp(name, appname, old_value):
1536 # explicitly asked to rebuild
1537 if name in rebuild_targets:
1539 # else if not rebuild, and if the library already exists
1540 elif appExists(name, appname):
1542 # do not change the original value
1545 build_tex2lyx = ifBuildApp('tex2lyx', 'tex2lyx', build_tex2lyx)
1546 build_client = ifBuildApp('client', 'lyxclient', build_client)
1548 # sync frontend and frontend (?)
1558 env.BuildDir('$BUILDDIR/boost', '$TOP_SRCDIR/boost/libs', duplicate = 0)
1560 boostenv = env.Copy()
1562 # boost use its own config.h
1563 boostenv['CPPPATH'] = ['$TOP_SRCDIR/boost', '$BUILDDIR/boost'] + extra_inc_paths
1564 boostenv.AppendUnique(CCFLAGS = ['-DBOOST_USER_CONFIG="<config.h>"'])
1566 for lib in boost_libs:
1567 print 'Processing files in boost/libs/%s/src...' % lib
1568 boostlib = boostenv.StaticLibrary(
1569 target = '$LOCALLIBPATH/included_boost_%s' % lib,
1570 source = ['$BUILDDIR/boost/%s/src/%s' % (lib, x) for x in eval('boost_libs_%s_src_files' % lib)]
1572 Alias('boost', boostlib)
1579 intlenv = env.Copy()
1581 print "Processing files in intl..."
1583 env.BuildDir('$BUILDDIR/intl', '$TOP_SRCDIR/intl', duplicate = 0)
1585 # we need the original C compiler for these files
1586 intlenv['CC'] = C_COMPILER
1587 intlenv['CCFLAGS'] = C_CCFLAGS
1589 intlenv.Append(CCFLAGS=['/Dinline#', '/D__attribute__(x)#', '/Duintmax_t=UINT_MAX'])
1590 # intl does not use global config.h
1591 intlenv['CPPPATH'] = ['$BUILDDIR/intl'] + extra_inc_paths
1593 intlenv.Append(CCFLAGS = [
1594 r'-DLOCALEDIR=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1595 r'-DLOCALE_ALIAS_PATH=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1596 r'-DLIBDIR=\"' + env['TOP_SRCDIR'].replace('\\', '\\\\') + r'/lib\"',
1598 '-DENABLE_RELOCATABLE=1',
1600 r'-DINSTALLDIR=\"' + prefix.replace('\\', '\\\\') + r'/lib\"',
1602 '-Dset_relocation_prefix=libintl_set_relocation_prefix',
1603 '-Drelocate=libintl_relocate',
1604 '-DDEPENDS_ON_LIBICONV=1',
1609 intl = intlenv.StaticLibrary(
1610 target = '$LOCALLIBPATH/included_intl',
1612 source = ['$BUILDDIR/intl/%s' % x for x in intl_files]
1618 # Now, src code under src/
1620 env.BuildDir('$BUILDDIR/common', '$TOP_SRCDIR/src', duplicate = 0)
1627 print "Processing files in src/support..."
1629 env.Depends('$BUILDDIR/common/support/package.C', '$BUILDDIR/common/config.h')
1630 env.substFile('$BUILDDIR/common/support/package.C', '$TOP_SRCDIR/src/support/package.C.in')
1632 support = env.StaticLibrary(
1633 target = '$LOCALLIBPATH/support',
1634 source = ['$BUILDDIR/common/support/%s' % x for x in src_support_files],
1635 CPPPATH = ['$CPPPATH', qt_inc_path, os.path.join(qt_inc_path, 'QtCore')]
1637 Alias('support', support)
1644 print "Processing files in src/mathed..."
1646 mathed = env.StaticLibrary(
1647 target = '$LOCALLIBPATH/mathed',
1648 source = ['$BUILDDIR/common/mathed/%s' % x for x in src_mathed_files]
1650 Alias('mathed', mathed)
1657 print "Processing files in src/insets..."
1659 insets = env.StaticLibrary(
1660 target = '$LOCALLIBPATH/insets',
1661 source = ['$BUILDDIR/common/insets/%s' % x for x in src_insets_files]
1663 Alias('insets', insets)
1670 print "Processing files in src/frontends..."
1672 frontends = env.StaticLibrary(
1673 target = '$LOCALLIBPATH/frontends',
1674 source = ['$BUILDDIR/common/frontends/%s' % x for x in src_frontends_files]
1676 Alias('frontends', frontends)
1683 print "Processing files in src/graphics..."
1685 graphics = env.StaticLibrary(
1686 target = '$LOCALLIBPATH/graphics',
1687 source = ['$BUILDDIR/common/graphics/%s' % x for x in src_graphics_files]
1689 Alias('graphics', graphics)
1692 if build_controllers:
1694 # src/frontends/controllers
1696 print "Processing files in src/frontends/controllers..."
1698 controllers = env.StaticLibrary(
1699 target = '$LOCALLIBPATH/controllers',
1700 source = ['$BUILDDIR/common/frontends/controllers/%s' % x for x in src_frontends_controllers_files]
1702 Alias('controllers', controllers)
1709 env.BuildDir('$BUILDDIR/$frontend', '$TOP_SRCDIR/src/frontend/$frontend', duplicate = 0)
1711 print "Processing files in src/frontends/qt4..."
1714 qt4env['QT_AUTOSCAN'] = 0
1716 # local qt4 toolset from
1717 # http://www.iua.upf.es/~dgarcia/Codders/sconstools.html
1719 # NOTE: I have to patch qt4.py since it does not automatically
1720 # process .C file!!! (add to cxx_suffixes )
1722 qt4env.Tool('qt4', [scons_dir])
1723 qt4env.EnableQt4Modules(qt_libs, debug = (mode == 'debug'))
1724 qt4env['QT4_AUTOSCAN'] = 0
1725 qt4env['QT4_UICDECLFLAGS'] = '-tr lyx::qt_'
1727 qt4env.AppendUnique(CPPPATH = [
1729 '$BUILDDIR/common/images',
1730 '$BUILDDIR/common/frontends',
1731 '$BUILDDIR/common/frontends/qt4',
1732 '$BUILDDIR/common/frontends/controllers',
1737 # FIXME: replace by something from pkg_config
1738 qt4env.Append(CCFLAGS = [
1740 '-DQT_CLEAN_NAMESPACE',
1748 qt4_moc_files = ["$BUILDDIR/common/frontends/qt4/%s" % x for x in src_frontends_qt4_moc_files]
1753 resources = [qt4env.Uic4(x.split('.')[0]) for x in \
1754 ["$BUILDDIR/common/frontends/qt4/ui/%s" % x for x in src_frontends_qt4_ui_files]]
1757 # moc qt4_moc_files, the moced files are included in the original files
1759 qt4_moced_files = [qt4env.Moc4(x.replace('.C', '_moc.cpp'), x.replace('.C', '.h')) for x in qt4_moc_files]
1761 qt4 = qt4env.StaticLibrary(
1762 target = '$LOCALLIBPATH/qt4',
1763 source = ['$BUILDDIR/common/frontends/qt4/%s' % x for x in src_frontends_qt4_files]
1772 env.BuildDir('$BUILDDIR/common', '$TOP_SRCDIR/src', duplicate = 0)
1774 print "Processing files in src/client..."
1776 if env['HAVE_FCNTL']:
1777 client = env.Program(
1778 target = '$BUILDDIR/common/client/lyxclient',
1779 LIBS = ['support'] + intl_libs + system_libs +
1780 socket_libs + boost_libraries + qtcore_lib,
1781 source = ['$BUILDDIR/common/client/%s' % x for x in src_client_files]
1783 Alias('client', env.Command(os.path.join('$BUILDDIR', os.path.split(str(client[0]))[1]),
1784 client, [Copy('$TARGET', '$SOURCE')]))
1787 Alias('client', client)
1789 if env['HAVE_FCNTL']:
1790 # define client even if lyxclient is not built with rebuild=no
1791 client = [env.subst('$BUILDDIR/common/client/${PROGPREFIX}lyxclient$PROGSUFFIX')]
1800 print "Processing files in src/tex2lyx..."
1802 tex2lyx_env = env.Copy()
1804 tex2lyx_env.Prepend(CPPPATH = ['$BUILDDIR/common/tex2lyx'])
1805 tex2lyx_env.AppendUnique(LIBPATH = ['#$LOCALLIBPATH'])
1807 for file in ['FloatList.C', 'Floating.C', 'counters.C', 'lyxlayout.h', 'lyxlayout.C',
1808 'lyxtextclass.h', 'lyxtextclass.C', 'lyxlex.C', 'lyxlex_pimpl.C']:
1809 env.Command('$BUILDDIR/common/tex2lyx/'+file, '$TOP_SRCDIR/src/'+file,
1810 [Copy('$TARGET', '$SOURCE')])
1812 tex2lyx = tex2lyx_env.Program(
1813 target = '$BUILDDIR/common/tex2lyx/tex2lyx',
1814 LIBS = ['support'] + boost_libraries + intl_libs + system_libs + qtcore_lib,
1815 source = ['$BUILDDIR/common/tex2lyx/%s' % x for x in src_tex2lyx_files]
1817 Alias('tex2lyx', env.Command(os.path.join('$BUILDDIR', os.path.split(str(tex2lyx[0]))[1]),
1818 tex2lyx, [Copy('$TARGET', '$SOURCE')]))
1819 Alias('tex2lyx', tex2lyx)
1821 # define tex2lyx even if tex2lyx is not built with rebuild=no
1822 tex2lyx = [env.subst('$BUILDDIR/common/tex2lyx/${PROGPREFIX}tex2lyx$PROGSUFFIX')]
1829 print "Processing files in src..."
1831 env.Depends('$BUILDDIR/common/version.C', '$BUILDDIR/common/config.h')
1832 env.substFile('$BUILDDIR/common/version.C', '$TOP_SRCDIR/src/version.C.in')
1834 if env.has_key('USE_ASPELL') and env['USE_ASPELL']:
1835 src_post_files.append('aspell.C')
1836 elif env.has_key('USE_PSPELL') and env['USE_PSPELL']:
1837 src_post_files.append('pspell.C')
1838 elif env.has_key('USE_ISPELL') and env['USE_ISPELL']:
1839 src_post_files.append('ispell.C')
1841 # msvc requires at least one source file with main()
1842 # so I exclude main.C from lyxbase
1843 lyxbase_pre = env.StaticLibrary(
1844 target = '$LOCALLIBPATH/lyxbase_pre',
1845 source = ['$BUILDDIR/common/%s' % x for x in src_pre_files]
1847 lyxbase_post = env.StaticLibrary(
1848 target = '$LOCALLIBPATH/lyxbase_post',
1849 source = ["$BUILDDIR/common/%s" % x for x in src_post_files]
1851 Alias('lyxbase', lyxbase_pre)
1852 Alias('lyxbase', lyxbase_post)
1857 # Build lyx with given frontend
1860 target = '$BUILDDIR/$frontend/lyx',
1861 source = ['$BUILDDIR/common/main.C'],
1881 # define lyx even if lyx is not built with rebuild=no
1882 lyx = [env.subst('$BUILDDIR/$frontend/${PROGPREFIX}lyx$PROGSUFFIX')]
1885 if build_msvs_projects:
1886 def build_project(target, full_target = None,
1887 src = [], inc = [], res = [], rebuildTargetOnly = True):
1888 ''' build mavs project files
1889 target: alias (correspond to directory name)
1890 full_target: full path/filename of the target
1894 rebuildTargetOnly: whether or not only rebuild this target
1896 For non-debug-able targets like static libraries, target (alias) is
1897 enough to build the target. For executable targets, msvs need to know
1898 the full path to start debug them.
1900 if rebuildTargetOnly:
1901 cmds = 'rebuild='+target
1904 if full_target is None:
1905 build_target = target
1907 build_target = full_target
1909 proj = env.MSVSProject(
1910 target = target + env['MSVSPROJECTSUFFIX'],
1911 # this allows easy access to header files (along with source)
1912 srcs = [env.subst(x) for x in src + inc],
1913 incs = [env.subst('$TOP_SRCDIR/src/config.h')],
1914 localincs = [env.subst(x) for x in inc],
1915 resources = [env.subst(x) for x in res],
1916 buildtarget = build_target,
1920 Alias('msvs_projects', proj)
1923 for lib in boost_libs:
1924 boost_src += ['$TOP_SRCDIR/boost/libs/%s/src/%s' % (lib, x) for x in eval('boost_libs_%s_src_files' % lib)]
1925 build_project('boost', src = boost_src)
1927 build_project('intl', src = ['$TOP_SRCDIR/intl/%s' % x for x in intl_files],
1928 inc = ['$TOP_SRCDIR/intl/%s' % x for x in intl_header_files])
1930 build_project('support', src = ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_files],
1931 inc = ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files])
1933 build_project('mathed', src = ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_files],
1934 inc = ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files])
1936 build_project('insets', src = ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_files],
1937 inc = ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files])
1939 build_project('frontends', src = ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_files],
1940 inc = ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files])
1942 build_project('graphics', src = ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_files],
1943 inc = ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files])
1945 build_project('controllers', src = ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files],
1946 inc = ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files])
1948 build_project('qt4', src = ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_files + src_frontends_qt4_moc_files],
1949 inc = ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_header_files],
1950 res = ['$TOP_SRCDIR/src/frontends/qt4/ui/%s' % x for x in src_frontends_qt4_ui_files])
1952 build_project('client', src = ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_files],
1953 inc = ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_header_files],
1954 rebuildTargetOnly = False,
1955 full_target = File(env.subst('$BUILDDIR/common/client/lyxclient$PROGSUFFIX')).abspath)
1957 build_project('tex2lyx', src = ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_files],
1958 inc = ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_header_files],
1959 rebuildTargetOnly = False,
1960 full_target = File(env.subst('$BUILDDIR/common/tex2lyx/tex2lyx$PROGSUFFIX')).abspath)
1962 build_project('lyxbase', src = ['$TOP_SRCDIR/src/%s' % x for x in src_pre_files + src_post_files],
1963 inc = ['$TOP_SRCDIR/src/%s' % x for x in src_header_files])
1964 build_project('lyx',
1965 src = ['$TOP_SRCDIR/src/%s' % x for x in src_pre_files + src_post_files] + \
1966 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_files] + \
1967 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_files] + \
1968 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_files] + \
1969 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_files] + \
1970 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_files] + \
1971 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files] + \
1972 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_files + src_frontends_qt4_moc_files],
1973 inc = ['$TOP_SRCDIR/src/%s' % x for x in src_header_files] + \
1974 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files] + \
1975 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_header_files] + \
1976 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files] + \
1977 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files] + \
1978 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files] + \
1979 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files] + \
1980 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_header_files],
1981 res = ['$TOP_SRCDIR/src/frontends/qt4/ui/%s' % x for x in src_frontends_qt4_ui_files],
1982 rebuildTargetOnly = False,
1983 full_target = File(env.subst('$BUILDDIR/$frontend/lyx$PROGSUFFIX')).abspath)
1990 print 'Processing files in po...'
1995 # files to translate
1996 transfiles = glob.glob(os.path.join(env.subst('$TOP_SRCDIR'), 'po', '*.po'))
1997 # possibly *only* handle these languages
1999 if env.has_key('languages'):
2000 languages = env.make_list(env['lanauges'])
2001 # use defulat msgfmt
2003 if not env['MSGFMT']:
2004 print 'msgfmt does not exist. Can not process po files'
2007 env['BUILDERS']['Transfiles'] = Builder(action='$MSGFMT $SOURCE -o $TARGET',suffix='.gmo',src_suffix='.po')
2009 for f in transfiles:
2011 fname = os.path.split(f)[1]
2013 country = fname.split('.')[0]
2015 if not languages or country in languages:
2016 gmo_files.extend(env.Transfiles(f))
2019 if 'install' in targets:
2021 # this part is a bit messy right now. Since scons will provide
2022 # --DESTDIR option soon, at least the dest_dir handling can be
2025 # how to join dest_dir and prefix
2026 def joinPaths(path1, path2):
2027 ''' join path1 and path2, do not use os.path.join because
2028 under window, c:\destdir\d:\program is invalid '''
2030 return os.path.normpath(path2)
2031 # separate drive letter
2032 (drive, path) = os.path.splitdrive(os.path.normpath(path2))
2033 # ignore drive letter, so c:\destdir + c:\program = c:\destdir\program
2034 return os.path.join(os.path.normpath(path1), path[1:])
2036 # install to dest_dir/prefix
2037 dest_dir = env.get('DESTDIR', '')
2038 dest_prefix_dir = joinPaths(dest_dir, env.Dir(prefix).abspath)
2039 # create the directory if needed
2040 if not os.path.isdir(dest_prefix_dir):
2042 os.makedirs(dest_prefix_dir)
2045 if not os.path.isdir(dest_prefix_dir):
2046 print 'Can not create directory', dest_prefix_dir
2049 if env.has_key('exec_prefix'):
2050 bin_dest_dir = joinPaths(dest_dir, Dir(env['exec_prefix']).abspath)
2052 bin_dest_dir = os.path.join(dest_prefix_dir, 'bin')
2054 share_dest_dir = os.path.join(dest_prefix_dir, share_dir + program_suffix)
2056 share_dest_dir = os.path.join(dest_prefix_dir, share_dir)
2057 man_dest_dir = os.path.join(dest_prefix_dir, man_dir)
2058 locale_dest_dir = os.path.join(dest_prefix_dir, locale_dir)
2062 # install executables (lyxclient may be None)
2065 version_suffix = program_suffix
2069 # install lyx, if in release mode, try to strip the binary
2070 if env.has_key('STRIP') and env['STRIP'] is not None and mode != 'debug':
2071 # create a builder to strip and install
2072 env['BUILDERS']['StripInstallAs'] = Builder(action='$STRIP $SOURCE -o $TARGET')
2074 # install executables
2075 for (name, obj) in (('lyx', lyx), ('tex2lyx', tex2lyx), ('client', client)):
2078 target_name = os.path.split(str(obj[0]))[1].replace(name, '%s%s' % (name, version_suffix))
2079 target = os.path.join(bin_dest_dir, target_name)
2080 if env['BUILDERS'].has_key('StripInstallAs'):
2081 env.StripInstallAs(target, obj)
2083 env.InstallAs(target, obj)
2084 Alias('install', target)
2088 for (dir,files) in [
2090 ('clipart', lib_clipart_files),
2091 ('examples', lib_examples_files),
2092 ('images', lib_images_files),
2093 ('images/math', lib_images_math_files),
2094 ('bind', lib_bind_files),
2095 ('kbd', lib_kbd_files),
2096 ('layouts', lib_layouts_files),
2097 ('scripts', lib_scripts_files),
2098 ('templates', lib_templates_files),
2099 ('tex', lib_tex_files),
2100 ('ui', lib_ui_files),
2101 ('doc', lib_doc_files),
2102 ('lyx2lyx', lib_lyx2lyx_files)]:
2103 dirs.append(env.Install(os.path.join(share_dest_dir, dir),
2104 [env.subst('$TOP_SRCDIR/lib/%s/%s' % (dir, file)) for file in files]))
2105 Alias('install', dirs)
2107 if platform_name == 'cygwin':
2108 # cygwin packaging requires a file /usr/share/doc/Cygwin/foot-vendor-suffix.README
2109 Cygwin_README = os.path.join(dest_prefix_dir, 'share', 'doc', 'Cygwin',
2110 '%s-%s.README' % (package, package_cygwin_version))
2111 env.InstallAs(Cygwin_README,
2112 os.path.join(env.subst('$TOP_SRCDIR'), 'README.cygwin'))
2113 Alias('install', Cygwin_README)
2114 # also a directory /usr/share/doc/lyx for README etc
2115 Cygwin_Doc = os.path.join(dest_prefix_dir, 'share', 'doc', package)
2116 env.Install(Cygwin_Doc, [os.path.join(env.subst('$TOP_SRCDIR'), x) for x in \
2117 ['INSTALL', 'README', 'README.Cygwin', 'RELEASE-NOTES', 'COPYING', 'ANNOUNCE']])
2118 Alias('install', Cygwin_Doc)
2119 # cygwin fonts also need to be installed
2120 Cygwin_fonts = os.path.join(share_dest_dir, 'fonts')
2121 env.Install(Cygwin_fonts,
2122 [env.subst('$TOP_SRCDIR/development/Win32/packaging/bakoma/%s' % file) \
2123 for file in win32_bakoma_fonts])
2124 Alias('install', Cygwin_fonts)
2125 # we also need a post installation script
2126 tmp_script = utils.installCygwinPostinstallScript('/tmp')
2127 postinstall_path = os.path.join(dest_dir, 'etc', 'postinstall')
2128 env.Install(postinstall_path, tmp_script)
2129 Alias('install', postinstall_path)
2131 # subst and install lyx2lyx_version.py which is not in scons_manifest.py
2132 env.Depends(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py', '$BUILDDIR/common/config.h')
2133 env.substFile(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py',
2134 '$TOP_SRCDIR/lib/lyx2lyx/lyx2lyx_version.py.in')
2135 Alias('install', share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2138 env.InstallAs(os.path.join(man_dest_dir, 'lyx' + version_suffix + '.1'),
2139 env.subst('$TOP_SRCDIR/lyx.man'))
2140 env.InstallAs(os.path.join(man_dest_dir, 'tex2lyx' + version_suffix + '.1'),
2141 env.subst('$TOP_SRCDIR/src/tex2lyx/tex2lyx.man'))
2142 env.InstallAs(os.path.join(man_dest_dir, 'lyxclient' + version_suffix + '.1'),
2143 env.subst('$TOP_SRCDIR/src/client/lyxclient.man'))
2144 Alias('install', [os.path.join(man_dest_dir, x + version_suffix + '.1') for
2145 x in ['lyx', 'tex2lyx', 'lyxclient']])
2147 # ru.gmo ==> ru/LC_MESSAGES/lyxSUFFIX.mo
2148 for gmo in gmo_files:
2149 lan = os.path.split(str(gmo))[1].split('.')[0]
2150 dest_file = os.path.join(locale_dest_dir, lan, 'LC_MESSAGES', 'lyx' + program_suffix + '.mo')
2151 env.InstallAs(dest_file, gmo)
2152 Alias('install', dest_file)
2156 Alias('all', ['lyx', 'client', 'tex2lyx'])