1 # vi:filetype=python:expandtab:tabstop=2:shiftwidth=2
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.
12 # This is a scons based building system for lyx, you can use it as follows:
14 # $ cd development/scons
15 # $ scons [options] [targets]
17 # $ scons -f development/scons/SConstruct [options] [targets]
19 # $ scons [prefix=.] install
22 # * targets can be one or more of lyx, tex2lyx, client, po, install.
23 # default to lyx, you can use 'scons all' to build all targets except
25 # * options: use scons -h for details about options, the most important
26 # one is frontend=qt3|qt4.
27 # - qt3 is used by default on linux, cygwin and mac
28 # - qt4 is used by default on win32/mingw
30 # File layouts (Important):
31 # * Unless you specify builddir=dir, building will happen
32 # in $BUILDDIR = $mode, which can be debug or release
33 # * $BUILDDIR has subdirectories
34 # libs: all intermediate libraries
35 # boost: boost libraries, if boost=included is used
36 # qt3/4: frontend-specific objects
37 # * executables will be copied to $BUILDDIR/
40 # * scons fast_start=yes
41 # If env.cache exists, bypass all tests and use existing src/config.h
43 # * scons --config=force
44 # force re-configuration (use scons -H for details)
46 # * check config.log to see why config has failed
48 # * use extra_inc_path, extra_lib_path, qt_dir, qt_inc_path
49 # qt_lib_path to help locate qt and other libraries.
50 # There are also extra_inc_path1, extra_lib_path1 if you need to spacify
51 # more than one extra paths.
53 # * executed commands will be logged in scons_lyx.log. You can use logfile=
54 # option to save log to another file.
58 # * scons dist etc may be added later. Interested contributors can follow
59 # http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/AccumulateBuilder
61 # http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/DistTarBuilder
62 # Please also see the commented out code in scons_utils.py
64 # * NSIS support can be found here.
65 # http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/NsisSconsTool
68 # http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/RpmHonchoTemp
70 # However, I decide to wait since scons seems to be standardizing these
74 import os, sys, copy, cPickle
76 # config/scons_utils.py defines a few utility function
77 sys.path.append('config')
78 import scons_utils as utils
80 #----------------------------------------------------------
81 # Required runtime environment
82 #----------------------------------------------------------
84 # FIXME: I remember lyx requires higher version of python?
85 EnsurePythonVersion(1, 5)
86 # Please use at least 0.96.91 (not 0.96.1)
87 EnsureSConsVersion(0, 96)
89 # determine where I am ...
91 # called as 'scons -f development/scons/SConstruct'
92 if os.path.isfile('SConstruct'):
95 # called as 'cd development/scons; scons'
98 SCONS_DIR = 'development/scons'
100 #----------------------------------------------------------
102 #----------------------------------------------------------
104 # some global settings
105 PACKAGE_VERSION = '1.5.0svn'
107 default_build_mode = 'debug'
110 PACKAGE_BUGREPORT = 'lyx-devel@lists.lyx.org'
112 PACKAGE_TARNAME = 'lyx'
113 PACKAGE_STRING = '%s %s' % (PACKAGE_NAME, PACKAGE_VERSION)
115 # various cache/log files
116 default_log_file = 'scons_lyx.log'
117 env_cache_file = 'env.cache'
120 #----------------------------------------------------------
121 # platform dependent settings
122 #----------------------------------------------------------
124 platform_name = 'win32'
125 default_frontend = 'qt4'
126 # boost and gettext are unlikely to be installed already
127 default_boost_opt = 'included'
128 default_gettext_opt = 'included'
129 default_pch_opt = False
130 default_with_x = False
131 spell_checker = 'auto'
132 # boost_posix indicates to boost which API to use (posix or windows).
133 # If not specified, boost tries to figure out by itself, but it may fail.
135 packaging_method = 'windows'
136 add_suffix_to_executables = False
137 default_prefix = 'c:/program files/lyx'
138 share_dir = 'Resources'
139 man_dir = 'Resources/man/man1'
140 locale_dir = 'Resources/locale'
141 elif os.name == 'posix' and sys.platform != 'cygwin':
142 platform_name = sys.platform
143 default_frontend = 'qt3'
144 # try to use system boost/gettext libraries
145 default_boost_opt = 'auto'
146 default_gettext_opt = 'auto'
147 default_pch_opt = False
148 default_with_x = True
150 packaging_method = 'posix'
151 add_suffix_to_executables = True
152 default_prefix = '/usr/local/'
153 share_dir = 'share/lyx'
155 locale_dir = 'share/locale'
156 elif os.name == 'posix' and sys.platform == 'cygwin':
157 platform_name = 'cygwin'
158 default_frontend = 'qt3'
159 # force the use of cygwin/boost/gettext
160 default_boost_opt = 'system'
161 default_gettext_opt = 'system'
162 default_pch_opt = False
163 default_with_x = True
165 packaging_method = 'posix'
166 add_suffix_to_executables = True
167 default_prefix = '/usr/local/'
168 share_dir = 'share/lyx'
170 locale_dir = 'share/locale'
171 elif os.name == 'darwin':
172 platform_name = 'mac'
173 default_frontend = 'qt3'
175 default_boost_opt = 'included'
176 default_gettext_opt = 'included'
177 default_pch_opt = False
178 default_with_x = False
180 packaging_method = 'mac'
181 add_suffix_to_executables = True
182 # FIXME: where to install?
183 default_prefix = '/usr/local/'
184 share_dir = 'Resources'
185 man_dir = 'Resources/man/man1'
186 locale_dir = 'Resources/locale'
187 else: # unsupported system
188 platform_name = 'others'
189 default_frontend = 'qt3'
191 default_boost_opt = 'included'
192 default_gettext_opt = 'included'
193 default_pch_opt = False
194 default_with_x = True
196 packaging_method = 'posix'
197 add_suffix_to_executables = True
198 default_prefix = '/usr/local/'
199 share_dir = 'share/lyx'
201 locale_dir = 'share/locale'
204 #---------------------------------------------------------
206 #----------------------------------------------------------
208 if os.path.isfile('config.py'):
209 print "Getting options from config.py..."
210 print open('config.py').read()
212 opts = Options(['config.py'])
215 EnumOption('frontend', 'Main GUI', default_frontend,
216 allowed_values = ('xform', 'qt3', 'qt4', 'gtk') ),
217 # debug or release build
218 EnumOption('mode', 'Building method', default_build_mode,
219 allowed_values = ('debug', 'release') ),
222 'Use included, system boost library, or try sytem boost first.',
225 'auto', # detect boost, if not found, use included
226 'included', # always use included boost
227 'system', # always use system boost, fail if can not find
229 # FIXME: not implemented yet.
230 EnumOption('gettext',
231 'Use included, system gettext library, or try sytem gettext first',
234 'auto', # detect gettext, if not found, use included
235 'included', # always use included gettext
236 'system', # always use system gettext, fail if can not find
239 EnumOption('spell', 'Choose spell checker to use.', 'auto',
240 allowed_values = ('aspell', 'pspell', 'ispell', 'auto') ),
242 BoolOption('fast_start', 'Whether or not use cached tests and keep current config.h', True),
243 # FIXME: I do not know how pch is working. Ignore this option now.
244 BoolOption('pch', '(NA) Whether or not use pch', default_pch_opt),
245 # enable assertion, (config.h has ENABLE_ASSERTIOS
246 BoolOption('assertions', 'Use assertions', True),
247 # enable warning, (config.h has WITH_WARNINGS)
248 BoolOption('warnings', 'Use warnings', True),
249 # enable glib, (config.h has _GLIBCXX_CONCEPT_CHECKS)
250 BoolOption('concept_checks', 'Enable concept checks', True),
252 BoolOption('nls', 'Whether or not use native language support', True),
253 # FIXME: not implemented
254 BoolOption('profile', '(NA) Whether or not enable profiling', False),
255 # FIXME: not implemented
256 BoolOption('std_debug', '(NA) Whether or not turn on stdlib debug', False),
258 BoolOption('X11', 'Use x11 windows system', default_with_x),
260 PathOption('qt_dir', 'Path to qt directory', None),
262 PathOption('qt_include_path', 'Path to qt include directory', None),
264 PathOption('qt_lib_path', 'Path to qt library directory', None),
265 # build directory, will use $mode if not set
266 PathOption('build_dir', 'Build directory', None),
267 # extra include and libpath
268 PathOption('extra_inc_path', 'Extra include path', None),
270 PathOption('extra_lib_path', 'Extra library path', None),
272 PathOption('extra_inc_path1', 'Extra include path', None),
274 PathOption('extra_lib_path1', 'Extra library path', None),
275 # rebuild only specifed, comma separated targets
276 ('rebuild', 'rebuild only specifed, comma separated targets', None),
277 # can be set to a non-existing directory
278 ('prefix', 'install architecture-independent files in PREFIX', None),
279 # will install to dest_dir if defined. Otherwise, prefix will be used.
280 ('dest_dir', 'install to dest_dir', None),
282 ('version_suffix', 'install lyx as lyx-suffix', ''),
284 PathOption('exec_prefix', 'install architecture-independent executable files in PREFIX', None),
286 ('logfile', 'save commands (not outputs) to logfile', default_log_file),
288 PathOption('aikasurus_path', 'Path to aikasurus library', None),
289 # environment variable can be set as options. (DO NOT set defaults)
291 ('LINK', '$LINK', None),
292 ('CPP', '$CPP', None),
293 ('CXX', '$CXX', None),
294 ('CXXCPP', '$CXXCPP', None),
295 ('CCFLAGS', '$CCFLAGS', None),
296 ('CPPFLAGS', '$CPPFLAGS', None),
297 ('LDFLAGS', '$LDFLAGS', None),
300 # whether or not use current config.h, and cached tests
301 if (not ARGUMENTS.has_key('fast_start') or \
302 ARGUMENTS['fast_start'] in ['y', 'yes', 't', 'true', '1', 'all']) \
303 and os.path.isfile(env_cache_file):
305 cache_file = open(env_cache_file)
306 env_cache = cPickle.load(cache_file)
308 # import cached options, but we should ignore qt_dir when frontend changes
309 if ARGUMENTS.has_key('frontend') and env_cache['arg_cache'].has_key('frontend') \
310 and ARGUMENTS['frontend'] != env_cache['arg_cache']['frontend'] \
311 and env_cache['arg_cache'].has_key('qt_dir'):
312 env_cache['arg_cache'].pop('qt_dir')
313 # and we do not cache fast_start
314 if env_cache['arg_cache'].has_key('fast_start'):
315 env_cache['arg_cache'].pop('fast_start')
316 print '------------ fast_start mode --------------------'
317 print ' Use cached test results and current config.h'
318 print ' use fast_start=no to override'
320 for key in env_cache['arg_cache'].keys():
321 if not ARGUMENTS.has_key(key):
322 ARGUMENTS[key] = env_cache['arg_cache'][key]
323 print "Restoring cached option %s=%s" % (key, ARGUMENTS[key])
324 print '-------------------------------------------------'
330 env_cache['arg_cache'] = ARGUMENTS
333 #---------------------------------------------------------
334 # Setting up environment
335 #---------------------------------------------------------
337 env = Environment(options = opts)
339 # Determine the frontend to use, which may be loaded
341 frontend = env.get('frontend', default_frontend)
342 # make sure the key exists
343 env['frontend'] = frontend
345 use_X11 = env.get('X11', default_with_x)
348 # set individual variables since I do not really like ENV = os.environ
349 env['ENV']['PATH'] = os.environ.get('PATH')
350 env['ENV']['HOME'] = os.environ.get('HOME')
351 env['TOP_SRC_DIR'] = TOP_SRC_DIR
352 env['SCONS_DIR'] = SCONS_DIR
353 # install to default_prefix by default
354 env['PREFIX'] = env.get('prefix', default_prefix)
356 if env.has_key('version_suffix'):
357 env['PROGRAM_SUFFIX'] = env['version_suffix']
359 env['PROGRAM_SUFFIX'] = ''
360 env['ADD_SUFFIX_TO_EXECUTABLES'] = add_suffix_to_executables
361 env['SHARE_DIR'] = os.path.join(env['PREFIX'], share_dir + env['PROGRAM_SUFFIX'])
362 env['LOCALE_DIR'] = os.path.join(env['PREFIX'], locale_dir)
364 # if dest_dir is different from prefix.
365 env['DEST_DIR'] = env.get('dest_dir', env['PREFIX'])
366 if env.has_key('exec_prefix'):
367 env['BIN_DEST_DIR'] = env['exec_prefix']
369 env['BIN_DEST_DIR'] = os.path.join(env['DEST_DIR'], 'bin')
370 env['SHARE_DEST_DIR'] = os.path.join(env['DEST_DIR'], share_dir + env['PROGRAM_SUFFIX'])
371 env['MAN_DEST_DIR'] = os.path.join(env['DEST_DIR'], man_dir)
372 env['LOCALE_DEST_DIR'] = os.path.join(env['DEST_DIR'], locale_dir)
375 # this is a bit out of place (after auto-configration) but
376 # it is required to do the tests. Since Tool('mingw') will
377 # reset CCFLAGS etc, this should be before getEnvVariable
378 if platform_name == 'win32':
380 env.AppendUnique(CPPPATH = ['#c:/MinGW/include'])
383 # speed up source file processing
384 #env['CPPSUFFIXES'] = ['.C', '.cc', '.cpp']
385 #env['CXXSUFFIX'] = ['.C']
387 def getEnvVariable(env, name):
388 # first try command line argument (override environment settings)
389 if ARGUMENTS.has_key(name) and ARGUMENTS[name].strip() != '':
390 # multiple options may be passed like "-02 -g"
391 env[name] = ARGUMENTS[name].split()
392 # it does not seem necessary, but it is safer to change ['a'] back to 'a'
393 if len(env[name]) == 1:
394 env[name] = env[name][0]
395 # then use environment default
396 elif os.environ.has_key(name) and os.environ[name].strip() != '':
397 print "Acquiring varaible %s from system environment: %s" % (name, env[name])
398 env[name] = os.environ[name].split()
399 if len(env[name]) == 1:
400 env[name] = env[name][0]
401 # finally, env['CC'] etc is set to the default values of Options.
402 # and env['CPP'] etc does not exist
404 getEnvVariable(env, 'CC')
405 getEnvVariable(env, 'LINK')
406 getEnvVariable(env, 'CPP')
407 getEnvVariable(env, 'CXX')
408 getEnvVariable(env, 'CXXCPP')
409 getEnvVariable(env, 'CCFLAGS')
410 getEnvVariable(env, 'CXXFLAGS')
411 getEnvVariable(env, 'CPPFLAGS')
412 getEnvVariable(env, 'LDFLAGS')
416 # frontend, mode, BUILDDIR and LOCALLIBPATH=BUILDDIR/libs
418 env['mode'] = env.get('mode', default_build_mode)
419 # lyx will be built to $build/build_dir so it is possible
420 # to build multiple build_dirs using the same source
421 # $mode can be debug or release
422 if env.has_key('build_dir') and env['build_dir']:
423 build_dir = env['build_dir']
424 env['BUILDDIR'] = build_dir
426 # Determine the name of the build $mode
427 env['BUILDDIR'] = '#' + env['mode']
428 # all built libraries will go to build_dir/libs
429 # (This is different from the make file approach)
430 env['LOCALLIBPATH'] = '$BUILDDIR/libs'
431 env.AppendUnique(LIBPATH = ['$LOCALLIBPATH'])
434 # QTDIR, QT_LIB_PATH, QT_INC_PATH
436 if env.has_key('qt_dir') and env['qt_dir']:
437 env['QTDIR'] = env['qt_dir']
438 # add path to the qt tools
439 env.AppendUnique(LIBPATH = [os.path.join(env['qt_dir'], 'lib')])
440 # set environment so that moc etc can be found even if its path is not set properly
441 env.PrependENVPath('PATH', os.path.join(env['qt_dir'], 'bin'))
443 env['QTDIR'] = os.environ.get('QTDIR', '/usr/lib/qt-3.3')
445 if env.has_key('qt_lib_path') and env['qt_lib_path']:
446 env['QT_LIB_PATH'] = env['qt_lib_path']
448 env['QT_LIB_PATH'] = '$QTDIR/lib'
449 env.AppendUnique(LIBPATH = ['$QT_LIB_PATH'])
450 # qt4 seems to be using pkg_config
451 env.PrependENVPath('PKG_CONFIG_PATH', env.subst('$QT_LIB_PATH'))
453 if env.has_key('qt_inc_path') and env['qt_inc_path']:
454 env['QT_INC_PATH'] = env['qt_inc_path']
455 elif os.path.isdir(os.path.join(env.subst('$QTDIR'), 'include')):
456 env['QT_INC_PATH'] = '$QTDIR/include'
457 else: # have to guess
458 env['QT_INC_PATH'] = '/usr/include/$frontend/'
459 # Note that this CPPPATH is for testing only
460 # it will be removed before calling SConscript
461 env['CPPPATH'] = [env['QT_INC_PATH']]
464 # extra_inc_path and extra_lib_path
466 if env.has_key('extra_inc_path') and env['extra_inc_path']:
467 env.AppendUnique(CPPPATH = [env['extra_inc_path']])
468 if env.has_key('extra_lib_path') and env['extra_lib_path']:
469 env.AppendUnique(LIBPATH = [env['extra_lib_path']])
470 if env.has_key('extra_inc_path1') and env['extra_inc_path1']:
471 env.AppendUnique(CPPPATH = [env['extra_inc_path1']])
472 if env.has_key('extra_lib_path1') and env['extra_lib_path1']:
473 env.AppendUnique(LIBPATH = [env['extra_lib_path1']])
474 if env.has_key('aikasurus_path') and env['aikasurus_path']:
475 env.AppendUnique(LIBPATH = [env['aikasurus_path']])
478 # under windows, scons is confused by .C/.c and uses gcc instead of
479 # g++. I am forcing the use of g++ here. This is expected to change
480 # after lyx renames all .C files to .cpp
482 # Note that this step has to be after env.Tool('mingw') step
483 # since env.Tool('mingw') will set env['CC'] etc.
485 # save the old c compiler
486 env['C_COMPILER'] = env['CC']
487 if env.has_key('CXX') and env['CXX']:
488 env['CC'] = env['CXX']
489 env['LINK'] = env['CXX']
495 #----------------------------------------------------------
497 #----------------------------------------------------------
499 conf = Configure(env,
501 'CheckPkgConfig' : utils.checkPkgConfig,
502 'CheckPackage' : utils.checkPackage,
503 'CheckMkdirOneArg' : utils.checkMkdirOneArg,
504 'CheckSelectArgType' : utils.checkSelectArgType,
505 'CheckBoostLibraries' : utils.checkBoostLibraries,
506 'CheckCommand' : utils.checkCommand,
510 # pkg-config? (if not, we use hard-coded options)
512 if conf.CheckPkgConfig('0.15.0'):
513 env['HAS_PKG_CONFIG'] = True
515 print 'pkg-config >= 0.1.50 is not found'
516 env['HAS_PKG_CONFIG'] = False
517 env_cache['HAS_PKG_CONFIG'] = env['HAS_PKG_CONFIG']
519 env['HAS_PKG_CONFIG'] = env_cache['HAS_PKG_CONFIG']
521 # zlib? This is required. (fast_start assumes the existance of zlib)
522 if not fast_start and not conf.CheckLibWithHeader('z', 'zlib.h', 'C'):
523 print 'Did not find libz or zlib.h, exiting!'
529 # qt3 does not use pkg_config
530 if frontend == 'qt3':
531 if not conf.CheckLibWithHeader('qt-mt', 'qapp.h', 'c++', 'QApplication qapp();'):
532 print 'Did not find qt libraries, exiting!'
534 elif frontend == 'qt4':
536 # first: try pkg_config
537 if env['HAS_PKG_CONFIG']:
538 succ = conf.CheckPackage('QtCore') or conf.CheckPackage('QtCore4')
539 env['QT4_PKG_CONFIG'] = succ
540 # second: try to link to it
542 # FIXME: under linux, I can test the following perfectly
543 # However, under windows, lib names need to passed as libXXX4.a ...
544 succ = conf.CheckLibWithHeader('QtCore', 'QtGui/QApplication', 'c++', 'QApplication qapp();') or \
545 conf.CheckLibWithHeader('QtCore4', 'QtGui/QApplication', 'c++', 'QApplication qapp();')
546 # third: try to look up the path
549 for lib in ['QtCore', 'QtGui']:
550 # windows version has something like QtGui4 ...
551 if not (os.path.isfile(os.path.join(env.subst('$QT_LIB_PATH'), 'lib%s.a' % lib)) or \
552 os.path.isfile(os.path.join(env.subst('$QT_LIB_PATH'), 'lib%s4.a' % lib))):
555 # still can not find it
557 print "Qt4 libraries are found."
559 print 'Did not find qt libraries, exiting!'
565 env['SOCKET_LIBS'] = []
566 if conf.CheckLib('socket'):
567 env['SOCKET_LIBS'].append('socket')
569 # nsl is the network services library and provides a
570 # transport-level interface to networking services.
571 if conf.CheckLib('nsl'):
572 env['SOCKET_LIBS'].append('nsl')
574 env_cache['SOCKET_LIBS'] = env['SOCKET_LIBS']
576 env['SOCKET_LIBS'] = env_cache['SOCKET_LIBS']
579 # check boost libraries
580 boost_opt = ARGUMENTS.get('boost', default_boost_opt)
581 # check for system boost
583 if boost_opt in ['auto', 'system']:
584 pathes = env['LIBPATH'] + ['/usr/lib', '/usr/local/lib']
585 sig = conf.CheckBoostLibraries('boost_signals', pathes)
586 reg = conf.CheckBoostLibraries('boost_regex', pathes)
587 fil = conf.CheckBoostLibraries('boost_filesystem', pathes)
588 ios = conf.CheckBoostLibraries('boost_iostreams', pathes)
589 # if any of them is not found
590 if ('' in [sig[0], reg[0], fil[0], ios[0]]):
591 if boost_opt == 'system':
592 print "Can not find system boost libraries"
593 print "Please supply a path through extra_lib_path and try again."
594 print "Or use boost=included to use included boost libraries."
597 env['BOOST_LIBRARIES'] = [sig[1], reg[1], fil[1], ios[1]]
598 # assume all boost libraries are in the same path...
599 env.AppendUnique(LIBPATH = [sig[0]])
600 env['INCLUDED_BOOST'] = False
602 # now, auto and succ = false, or boost=included
604 # we do not need to set LIBPATH now.
605 env['BOOST_LIBRARIES'] = ['included_boost_signals', 'included_boost_regex',
606 'included_boost_filesystem', 'included_boost_iostreams']
607 env['INCLUDED_BOOST'] = True
608 env_cache['BOOST_LIBRARIES'] = env['BOOST_LIBRARIES']
609 env_cache['INCLUDED_BOOST'] = env['INCLUDED_BOOST']
611 env['BOOST_LIBRARIES'] = env_cache['BOOST_LIBRARIES']
612 env['INCLUDED_BOOST'] = env_cache['INCLUDED_BOOST']
615 env['ENABLE_NLS'] = not env.has_key('nls') or env['nls']
618 if not env['ENABLE_NLS']:
619 env['INTL_LIBS'] = []
620 env['INCLUDED_GETTEXT'] = False
622 # check gettext libraries
623 gettext_opt = ARGUMENTS.get('gettext', default_gettext_opt)
624 # check for system gettext
626 if gettext_opt in ['auto', 'system']:
627 if conf.CheckLib('intl'):
628 env['INCLUDED_GETTEXT'] = False
629 env['INTL_LIBS'] = ['intl']
632 if gettext_opt == 'system':
633 print "Can not find system gettext library"
634 print "Please supply a path through extra_lib_path and try again."
635 print "Or use gettext=included to use included gettext libraries."
637 # now, auto and succ = false, or gettext=included
639 # we do not need to set LIBPATH now.
640 env['INCLUDED_GETTEXT'] = True
641 env['INTL_LIBS'] = ['included_intl']
642 if platform_name == 'win32':
643 # for functions AddFontResouceA, RemoveFontResourceA
644 env['INTL_LIBS'].append('gdi32')
645 env_cache['INCLUDED_GETTEXT'] = env['INCLUDED_GETTEXT']
646 env_cache['INTL_LIBS'] = env['INTL_LIBS']
648 env['INTL_LIBS'] = env_cache['INTL_LIBS']
649 env['INCLUDED_GETTEXT'] = env_cache['INCLUDED_GETTEXT']
652 # check for msgfmt command
654 env['MSGFMT'] = conf.CheckCommand('msgfmt')
655 env_cache['MSGFMT'] = env['MSGFMT']
657 env['MSGFMT'] = env_cache['MSGFMT']
660 #----------------------------------------------------------
661 # Generating config.h
662 #----------------------------------------------------------
664 print "Generating ", utils.config_h, "..."
666 # I do not handle all macros in src/config.h.in, rather I am following a list
667 # of *used-by-lyx* macros compiled by Abdelrazak Younes <younes.a@free.fr>
669 # Note: addToConfig etc are defined in scons_util
689 # for libintl % grep HAVE * | grep _H | cut -d: -f2 | sort -u
691 # HAVE_STDINT_H_WITH_UINTMAX
692 # HAVE_INTTYPES_H_WITH_UINTMAX
707 ('io.h', 'HAVE_IO_H', 'c'),
708 ('limits.h', 'HAVE_LIMITS_H', 'c'),
709 ('locale.h', 'HAVE_LOCALE_H', 'c'),
710 ('locale', 'HAVE_LOCALE', 'cxx'),
711 ('process.h', 'HAVE_PROCESS_H', 'c'),
712 ('stdlib.h', 'HAVE_STDLIB_H', 'c'),
713 ('sys/stat.h', 'HAVE_SYS_STAT_H', 'c'),
714 ('sys/time.h', 'HAVE_SYS_TIME_H', 'c'),
715 ('sys/types.h', 'HAVE_SYS_TYPES_H', 'c'),
716 ('sys/utime.h', 'HAVE_SYS_UTIME_H', 'c'),
717 ('sys/socket.h', 'HAVE_SYS_SOCKET_H', 'c'),
718 ('unistd.h', 'HAVE_UNISTD_H', 'c'),
719 ('inttypes.h', 'HAVE_INTTYPES_H', 'c'),
720 ('utime.h', 'HAVE_UTIME_H', 'c'),
721 ('string.h', 'HAVE_STRING_H', 'c'),
722 ('strings.h', 'HAVE_STRINGS_H', 'c'),
723 ('istream', 'HAVE_ISTREAM', 'cxx'),
724 ('ostream', 'HAVE_OSTREAM', 'cxx'),
725 ('ios', 'HAVE_IOS', 'cxx'),
726 ('argz.h', 'HAVE_ARGZ_H', 'c'),
727 ('limits.h', 'HAVE_LIMITS_H', 'c'),
728 ('alloca.h', 'HAVE_ALLOCA_H', 'c'),
729 ('stddef.h', 'HAVE_STDDEF_H', 'c'),
730 ('stdint.h', 'HAVE_STDINT_H', 'c'),
731 ('sys/param.h', 'HAVE_SYS_PARAM_H', 'c')
734 for header in headers:
735 utils.addToConfig("/* Define to 1 if you have the <%s> header file. */" % header[0], newline=1)
736 if (header[2] == 'c' and conf.CheckCHeader(header[0])) or \
737 (header[2] == 'cxx' and conf.CheckCXXHeader(header[0])):
738 utils.addToConfig('#define %s 1' % header[1])
740 utils.addToConfig('/* #undef %s */' % header[1])
772 # HAVE___ARGZ_STRINGIFY
782 ('open', 'HAVE_OPEN', None),
783 ('close', 'HAVE_CLOSE', None),
784 ('popen', 'HAVE_POPEN', None),
785 ('pclose', 'HAVE_PCLOSE', None),
786 ('_open', 'HAVE__OPEN', None),
787 ('_close', 'HAVE__CLOSE', None),
788 ('_popen', 'HAVE__POPEN', None),
789 ('_pclose', 'HAVE__PCLOSE', None),
790 ('getpid', 'HAVE_GETPID', None),
791 ('_getpid', 'HAVE__GETPID', None),
792 ('mkdir', 'HAVE_MKDIR', None),
793 ('_mkdir', 'HAVE__MKDIR', None),
794 ('putenv', 'HAVE_PUTENV', None),
795 ('mktemp', 'HAVE_MKTEMP', None),
796 ('mkstemp', 'HAVE_MKSTEMP', None),
797 ('strerror', 'HAVE_STRERROR', None),
798 ('count', 'HAVE_STD_COUNT', '''
803 return std::count(a, a+5, 'l');
806 ('getcwd', 'HAVE_GETCWD', None),
807 ('stpcpy', 'HAVE_STPCPY', None),
808 ('strcasecmp', 'HAVE_STRCASECMP', None),
809 ('strdup', 'HAVE_STRDUP', None),
810 ('strtoul', 'HAVE_STRTOUL', None),
811 ('alloca', 'HAVE_ALLOCA', None),
812 ('__fsetlocking', 'HAVE___FSETLOCKING', None),
813 ('mempcpy', 'HAVE_MEMPCPY', None),
814 ('__argz_count', 'HAVE___ARGZ_COUNT', None),
815 ('__argz_next', 'HAVE___ARGZ_NEXT', None),
816 ('__argz_stringify', 'HAVE___ARGZ_STRINGIFY', None),
817 ('setlocale', 'HAVE_SETLOCALE', None),
818 ('tsearch', 'HAVE_TSEARCH', None),
819 ('getegid', 'HAVE_GETEGID', None),
820 ('getgid', 'HAVE_GETGID', None),
821 ('getuid', 'HAVE_GETUID', None),
822 ('wcslen', 'HAVE_WCSLEN', None)
831 for func in functions:
832 utils.addToConfig("/* Define to 1 if you have the `%s' function. */" % func[0], newline=1)
833 if conf.CheckFunc(func[0], header=func[2]):
834 utils.addToConfig('#define %s 1' % func[1])
836 utils.addToConfig('/* #undef %s */' % func[1])
839 ('asprintf', 'HAVE_ASPRINTF'),
840 ('wprintf', 'HAVE_WPRINTF'),
841 ('snprintf', 'HAVE_SNPRINTF'),
842 ('printf', 'HAVE_POSIX_PRINTF'),
843 ('fcntl', 'HAVE_FCNTL')
846 for func in env_functions:
847 utils.addToConfig("/* Define to 1 if you have the `%s' function. */" % func[0], newline=1)
848 if conf.CheckFunc(func[0]):
849 utils.addToConfig('#define %s 1' % func[1])
852 utils.addToConfig('/* #undef %s */' % func[1])
856 # HAVE_INTTYPES_H_WITH_UINTMAX
857 # HAVE_DECL_ISTREAMBUF_ITERATOR
858 utils.addToConfig("/* Define to 1 if you have the `intmax_t' type. */", newline=1)
859 if conf.CheckType('intmax_t', includes='#include <stdint.h>') or \
860 conf.CheckType('intmax_t', includes='#include <inttypes.h>'):
861 utils.addToConfig('#define HAVE_INTMAX_T 1')
863 utils.addToConfig('/* #undef HAVE_INTMAX_T */')
870 # HAVE_INTTYPES_H_WITH_UINTMAX
873 ('intmax_t', 'HAVE_INTMAX_T', None),
874 ('long double', 'HAVE_LONG_DOUBLE', None),
875 ('long long', 'HAVE_LONG_LONG', None),
876 ('wchar_t', 'HAVE_WCHAR_T', None),
877 ('wint_t', 'HAVE_WINT_T', None),
878 ('uintmax_t', 'HAVE_INTTYPES_H_WITH_UINTMAX', '#include <inttypes.h>'),
879 ('std::istreambuf_iterator<std::istream>', 'HAVE_DECL_ISTREAMBUF_ITERATOR',
880 '#include <streambuf>\n#include <istream>')
883 utils.addToConfig("/* Define to 1 if you have the `%s' type. */" % t[0], newline=1)
884 if conf.CheckType(t[0], includes=t[2]):
885 utils.addToConfig('#define %s 1' % t[1])
887 utils.addToConfig('/* #undef %s */' % t[1])
892 utils.addToConfig('#define PACKAGE "%s%s"' % (PACKAGE, env['PROGRAM_SUFFIX']))
893 utils.addToConfig('#define PACKAGE_VERSION "%s"' % PACKAGE_VERSION)
895 utils.addToConfig('#define DEVEL_VERSION 1')
900 # _GLIBCXX_CONCEPT_CHECKS
902 # items are (ENV, ARGUMENTS)
904 ('ENABLE_ASSERTIONS', 'assertions'),
905 ('ENABLE_NLS', 'nls'),
906 ('WITH_WARNINGS', 'warnings'),
907 ('_GLIBCXX_CONCEPT_CHECKS', 'concept_checks'),
911 if (env.has_key(val[0]) and env[val[0]]) or \
912 ARGUMENTS.get(val[1]):
913 utils.addToConfig('#define %s 1' % val[0])
915 utils.addToConfig('/* #undef %s */' % val[0])
918 env['EXTRA_LIBS'] = []
920 # AIKSAURUS_H_LOCATION
921 if conf.CheckLib('Aiksaurus'):
922 utils.addToConfig("#define HAVE_LIBAIKSAURUS 1")
923 if (conf.CheckCXXHeader("Aiksaurus.h")):
924 utils.addToConfig("#define AIKSAURUS_H_LOCATION <Aiksaurus.h>")
925 elif (conf.CheckCXXHeader("Aiksaurus/Aiksaurus.h")):
926 utils.addToConfig("#define AIKSAURUS_H_LOCATION <Aiksaurus/Aiksaurus.h>")
928 utils.addToConfig("#define AIKSAURUS_H_LOCATION")
929 env['EXTRA_LIBS'].append('Aiksaurus')
935 # determine headers to use
936 spell_engine = ARGUMENTS.get('spell', 'auto')
937 spell_detected = False
938 if spell_engine in ['auto', 'aspell'] and \
939 conf.CheckLib('aspell'):
940 utils.addToConfig('#define USE_ASPELL 1')
941 env['USE_ASPELL'] = True
942 env['USE_PSPELL'] = False
943 env['USE_ISPELL'] = False
944 env['EXTRA_LIBS'].append('aspell')
945 spell_detected = True
946 elif spell_engine in ['auto', 'pspell'] and \
947 conf.CheckLib('pspell'):
948 utils.addToConfig('#define USE_PSPELL 1')
949 env['USE_ASPELL'] = False
950 env['USE_PSPELL'] = True
951 env['USE_ISPELL'] = False
952 env['EXTRA_LIBS'].append('pspell')
953 spell_detected = True
954 elif spell_engine in ['auto', 'ispell'] and \
955 conf.CheckLib('ispell'):
956 utils.addToConfig('#define USE_ISPELL 1')
957 env['USE_ASPELL'] = False
958 env['USE_PSPELL'] = False
959 env['USE_ISPELL'] = True
960 env['EXTRA_LIBS'].append('ispell')
961 spell_detected = True
963 if not spell_detected:
964 env['USE_ASPELL'] = False
965 env['USE_PSPELL'] = False
966 env['USE_ISPELL'] = False
967 # FIXME: can lyx work without an spell engine
968 if spell_engine == 'auto':
969 print "Warning: Can not locate any spell checker"
971 print "Warning: Can not locate specified spell checker:", spell_engine
973 # USE_POSIX_PACKAGING
974 # USE_MACOSX_PACKAGING
975 # USE_WINDOWS_PACKAGING
976 if packaging_method == 'windows':
977 utils.addToConfig('#define USE_WINDOWS_PACKAGING 1')
978 elif packaging_method == 'posix':
979 utils.addToConfig('#define USE_POSIX_PACKAGING 1')
980 elif packaging_method == 'mac':
981 utils.addToConfig('#define USE_MACOSX_PACKAGING 1')
985 utils.addToConfig('#define BOOST_POSIX 1')
987 utils.addToConfig('/* #undef BOOST_POSIX */')
989 # MKDIR_TAKES_ONE_ARG
990 if conf.CheckMkdirOneArg():
991 utils.addToConfig('#define MKDIR_TAKES_ONE_ARG 1')
993 utils.addToConfig('/* #undef MKDIR_TAKES_ONE_ARG */')
998 (arg1, arg234, arg5) = conf.CheckSelectArgType()
999 utils.addToConfig('#define SELECT_TYPE_ARG1 %s' % arg1)
1000 utils.addToConfig('#define SELECT_TYPE_ARG234 %s' % arg234)
1001 utils.addToConfig('#define SELECT_TYPE_ARG5 %s' % arg5)
1005 # WANT_GETFILEATTRIBUTESEX_WRAPPER
1006 utils.endConfigH(TOP_SRC_DIR)
1008 # env['EXTRA_LIBS'] will be modified later, so a unique copy is needed
1009 # NOTE that we do *not* save qt_libs in environment.
1010 env_cache['EXTRA_LIBS'] = copy.copy(env['EXTRA_LIBS'])
1011 env_cache['USE_ASPELL'] = env['USE_ASPELL']
1012 env_cache['USE_PSPELL'] = env['USE_PSPELL']
1013 env_cache['USE_ISPELL'] = env['USE_ISPELL']
1014 env_cache['HAVE_ASPRINTF'] = env['HAVE_ASPRINTF']
1015 env_cache['HAVE_WPRINTF'] = env['HAVE_WPRINTF']
1016 env_cache['HAVE_SNPRINTF'] = env['HAVE_SNPRINTF']
1017 env_cache['HAVE_POSIX_PRINTF'] = env['HAVE_POSIX_PRINTF']
1018 env_cache['HAVE_FCNTL'] = env['HAVE_FCNTL']
1022 # this comes as a big surprise, without this line
1023 # (doing nothing obvious), adding fast_start=yes
1024 # to a build with fast_start=no will result in a rebuild
1025 # Note that the exact header file to check does not matter
1026 conf.CheckCHeader('io.h')
1027 # only a few variables need to be rescanned
1028 env['EXTRA_LIBS'] = copy.copy(env_cache['EXTRA_LIBS'])
1029 env['USE_ASPELL'] = env_cache['USE_ASPELL']
1030 env['USE_PSPELL'] = env_cache['USE_PSPELL']
1031 env['USE_ISPELL'] = env_cache['USE_ISPELL']
1032 env['HAVE_ASPRINTF'] = env_cache['HAVE_ASPRINTF']
1033 env['HAVE_WPRINTF'] = env_cache['HAVE_WPRINTF']
1034 env['HAVE_SNPRINTF'] = env_cache['HAVE_SNPRINTF']
1035 env['HAVE_POSIX_PRINTF'] = env_cache['HAVE_POSIX_PRINTF']
1036 env['HAVE_FCNTL'] = env_cache['HAVE_FCNTL']
1039 # Finish auto-configuration
1042 #----------------------------------------------------------
1043 # Now set up our build process accordingly
1044 #----------------------------------------------------------
1047 # QT_LIB etc (EXTRA_LIBS holds lib for each frontend)
1049 # NOTE: Tool('qt') or Tool('qt4') will be loaded later
1050 # in their respective directory and specialized env.
1052 if frontend == 'qt3':
1053 # note: env.Tool('qt') my set QT_LIB to qt
1054 env['QT_LIB'] = 'qt-mt'
1055 env['EXTRA_LIBS'].append('qt-mt')
1056 if platform_name == 'cygwin' and use_X11:
1057 env['EXTRA_LIBS'].extend(['GL', 'Xmu', 'Xi', 'Xrender', 'Xrandr', 'Xcursor',
1058 'Xft', 'freetype', 'fontconfig', 'Xext', 'X11', 'SM', 'ICE', 'resolv',
1060 env.AppendUnique(LIBPATH = ['/usr/X11R6/lib'])
1061 elif frontend == 'qt4':
1062 if platform_name == "win32":
1063 env['QT_LIB'] = ['QtCore4', 'QtGui4']
1065 env['QT_LIB'] = ['QtCore', 'QtGui']
1066 env['EXTRA_LIBS'] += env['QT_LIB']
1068 print "Can not locate qt tools"
1069 print "What I get is "
1070 print " QTDIR: ", env['QTDIR']
1073 if platform_name in ['win32', 'cygwin']:
1074 # the final link step needs stdc++ to succeed under mingw
1075 # FIXME: shouldn't g++ automatically link to stdc++?
1076 env['SYSTEM_LIBS'] = ['shlwapi', 'z', 'stdc++']
1078 env['SYSTEM_LIBS'] = ['z']
1081 # Build parameters CPPPATH etc
1083 # boost is always in, src is needed for config.h
1085 # QT_INC_PATH is not needed for *every* source file
1086 env['CPPPATH'].remove(env['QT_INC_PATH'])
1087 env['CPPPATH'] += ['$TOP_SRC_DIR/boost', '$TOP_SRC_DIR/src']
1089 # TODO: add (more) appropriate compiling options (-DNDEBUG etc)
1090 # for debug/release mode
1091 if ARGUMENTS.get('mode', default_build_mode) == 'debug':
1092 env.AppendUnique(CCFLAGS = [])
1094 env.AppendUnique(CCFLAGS = [])
1097 # Customized builders
1099 # install customized builders
1100 env['BUILDERS']['substFile'] = Builder(action = utils.env_subst)
1103 # A Link script for cygwin see
1104 # http://www.cygwin.com/ml/cygwin/2004-09/msg01101.html
1105 # http://www.cygwin.com/ml/cygwin-apps/2004-09/msg00309.html
1108 if platform_name == 'cygwin':
1109 ld_script_path = '/usr/lib/qt3/mkspecs/cygwin-g++'
1110 ld_script = utils.installCygwinLDScript(ld_script_path)
1111 env.AppendUnique(LINKFLAGS = ['-Wl,--enable-runtime-pseudo-reloc',
1112 '-Wl,--script,%s' % ld_script, '-Wl,-s'])
1117 # src/support/package.C.in needs the following to replace
1118 # LYX_ABS_INSTALLED_DATADIR (e.g. /usr/local/lyx/share/lyx)
1119 env['LYX_DIR'] = env['SHARE_DIR']
1120 # LYX_ABS_INSTALLED_LOCALEDIR
1121 env['LOCALEDIR'] = env['LOCALE_DIR']
1122 env['TOP_SRCDIR'] = env['TOP_SRC_DIR']
1123 # needed by src/version.C.in => src/version.C
1124 env['PACKAGE_VERSION'] = PACKAGE_VERSION
1125 # fill in the version info
1126 env['VERSION_INFO'] = '''Configuration
1128 Special build flags: %s
1130 C Compiler flags: %s %s
1132 C++ Compiler LyX flags: %s
1133 C++ Compiler flags: %s %s
1135 Linker user flags: %s
1137 Builing directory: %s
1138 Local library directory: %s
1139 Libraries pathes: %s
1142 System libraries: %s
1143 include search path: %s
1150 ''' % (platform_name,
1151 env.subst('$CCFLAGS'), env.subst('$CC'),
1152 env.subst('$CPPFLAGS'), env.subst('$CFLAGS'),
1153 env.subst('$CXX'), env.subst('$CXXFLAGS'),
1154 env.subst('$CPPFLAGS'), env.subst('$CXXFLAGS'),
1155 env.subst('$LINKFLAGS'), env.subst('$LINKFLAGS'),
1156 env.subst('$BUILDDIR'), env.subst('$LOCALLIBPATH'),
1157 str(env['LIBPATH']), str(env['BOOST_LIBRARIES']),
1158 str(env['EXTRA_LIBS']), str(env['SYSTEM_LIBS']), str(env['CPPPATH']),
1159 env['frontend'], packaging_method,
1160 env['PREFIX'], env['BIN_DEST_DIR'], env['SHARE_DIR'])
1162 if env['frontend'] in ['qt3', 'qt4']:
1163 env['VERSION_INFO'] += ''' include dir: %s
1166 ''' % (env.subst('$QT_INC_PATH'), env.subst('$QT_LIB_PATH'), use_X11)
1169 print env['VERSION_INFO']
1172 # Mingw command line may be too short for our link usage,
1173 # Here we use a trick from scons wiki
1174 # http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/LongCmdLinesOnWin32
1176 # I also would like to add logging (commands only) capacity to the
1178 logfile = env.get('logfile', default_log_file)
1179 if logfile != '' or platform_name == 'win32':
1181 utils.setLoggedSpawn(env, logfile, longarg = (platform_name == 'win32'),
1182 info = '''# This is a log of commands used by scons to build lyx
1186 ''' % (time.asctime(), ' '.join(sys.argv),
1187 env['VERSION_INFO'].replace('\n','\n# ')) )
1193 # -h will print out help info
1194 Help(opts.GenerateHelpText(env))
1195 # save environment settings (for fast_start option)
1196 cache_file = open(env_cache_file, 'w')
1197 cPickle.dump(env_cache, cache_file)
1200 #----------------------------------------------------------
1202 #----------------------------------------------------------
1205 # this has been the source of problems on some platforms...
1206 # I find that I need to supply it with full path name
1207 env.SConsignFile(os.path.join(Dir(env['BUILDDIR']).abspath, '.sconsign'))
1208 # this usage needs further investigation.
1209 #env.CacheDir('%s/Cache/%s' % (env['BUILDDIR'], frontend))
1211 env['BUILD_TARGETS'] = BUILD_TARGETS
1212 if env.has_key('rebuild'):
1213 env['REBUILD_TARGETS'] = env['rebuild'].split(',')
1215 env['REBUILD_TARGETS'] = None
1217 print "Building all targets recursively"
1219 env.SConscript('$SCONS_DIR/SConscript', duplicate = 0)