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 default_prefix = 'c:/program files/lyx'
137 share_dir = 'Resources'
138 man_dir = 'Resources/man/man1'
139 locale_dir = 'Resources/locale'
140 elif os.name == 'posix' and sys.platform != 'cygwin':
141 platform_name = sys.platform
142 default_frontend = 'qt3'
143 # try to use system boost/gettext libraries
144 default_boost_opt = 'auto'
145 default_gettext_opt = 'auto'
146 default_pch_opt = False
147 default_with_x = True
149 packaging_method = 'posix'
150 default_prefix = '/usr/local/'
151 share_dir = 'share/lyx'
153 locale_dir = 'share/locale'
154 elif os.name == 'posix' and sys.platform == 'cygwin':
155 platform_name = 'cygwin'
156 default_frontend = 'qt3'
157 # force the use of cygwin/boost/gettext
158 default_boost_opt = 'system'
159 default_gettext_opt = 'system'
160 default_pch_opt = False
161 default_with_x = True
163 packaging_method = 'posix'
164 default_prefix = '/usr/local/'
165 share_dir = 'share/lyx'
167 locale_dir = 'share/locale'
168 elif os.name == 'darwin':
169 platform_name = 'mac'
170 default_frontend = 'qt3'
172 default_boost_opt = 'included'
173 default_gettext_opt = 'included'
174 default_pch_opt = False
175 default_with_x = False
177 packaging_method = 'mac'
178 # FIXME: where to install?
179 default_prefix = '/usr/local/'
180 share_dir = 'Resources'
181 man_dir = 'Resources/man/man1'
182 locale_dir = 'Resources/locale'
183 else: # unsupported system
184 platform_name = 'others'
185 default_frontend = 'qt3'
187 default_boost_opt = 'included'
188 default_gettext_opt = 'included'
189 default_pch_opt = False
190 default_with_x = True
192 packaging_method = 'posix'
193 default_prefix = '/usr/local/'
194 share_dir = 'share/lyx'
196 locale_dir = 'share/locale'
199 #---------------------------------------------------------
201 #----------------------------------------------------------
203 if os.path.isfile('config.py'):
204 print "Getting options from config.py..."
205 print open('config.py').read()
207 opts = Options(['config.py'])
210 EnumOption('frontend', 'Main GUI', default_frontend,
211 allowed_values = ('xform', 'qt3', 'qt4', 'gtk') ),
212 # debug or release build
213 EnumOption('mode', 'Building method', default_build_mode,
214 allowed_values = ('debug', 'release') ),
217 'Use included, system boost library, or try sytem boost first.',
220 'auto', # detect boost, if not found, use included
221 'included', # always use included boost
222 'system', # always use system boost, fail if can not find
224 # FIXME: not implemented yet.
225 EnumOption('gettext',
226 'Use included, system gettext library, or try sytem gettext first',
229 'auto', # detect gettext, if not found, use included
230 'included', # always use included gettext
231 'system', # always use system gettext, fail if can not find
234 EnumOption('spell', 'Choose spell checker to use.', 'auto',
235 allowed_values = ('aspell', 'pspell', 'ispell', 'auto') ),
237 BoolOption('fast_start', 'Whether or not use cached tests and keep current config.h', True),
238 # FIXME: I do not know how pch is working. Ignore this option now.
239 BoolOption('pch', '(NA) Whether or not use pch', default_pch_opt),
240 # enable assertion, (config.h has ENABLE_ASSERTIOS
241 BoolOption('assertions', 'Use assertions', True),
242 # enable warning, (config.h has WITH_WARNINGS)
243 BoolOption('warnings', 'Use warnings', True),
244 # enable glib, (config.h has _GLIBCXX_CONCEPT_CHECKS)
245 BoolOption('concept_checks', 'Enable concept checks', True),
246 # FIXME: I do not know what is nls
247 BoolOption('nls', '(NA) Whether or not use native language support', False),
248 # FIXME: not implemented
249 BoolOption('profile', '(NA) Whether or not enable profiling', False),
250 # FIXME: not implemented
251 BoolOption('std_debug', '(NA) Whether or not turn on stdlib debug', False),
253 BoolOption('X11', 'Use x11 windows system', default_with_x),
254 # FIXME: not implemented
255 BoolOption('libintl', '(NA) Use libintl library', False),
257 PathOption('qt_dir', 'Path to qt directory', None),
259 PathOption('qt_include_path', 'Path to qt include directory', None),
261 PathOption('qt_lib_path', 'Path to qt library directory', None),
262 # build directory, will use $mode if not set
263 PathOption('build_dir', 'Build directory', None),
264 # extra include and libpath
265 PathOption('extra_inc_path', 'Extra include path', None),
267 PathOption('extra_lib_path', 'Extra library path', None),
269 PathOption('extra_inc_path1', 'Extra include path', None),
271 PathOption('extra_lib_path1', 'Extra library path', None),
272 # can be set to a non-existing directory
273 ('prefix', 'install architecture-independent files in PREFIX', None),
275 ('version_suffix', 'install lyx as lyx-suffix', ''),
277 PathOption('exec_prefix', 'install architecture-independent executable files in PREFIX', None),
278 # FIXME: not implemented
279 PathOption('intl_prefix', '(NA) Path to intl library', None),
281 ('logfile', 'save commands (not outputs) to logfile', default_log_file),
283 PathOption('aikasurus_path', 'Path to aikasurus library', None),
284 # environment variable can be set as options. (DO NOT set defaults)
286 ('LINK', '$LINK', None),
287 ('CPP', '$CPP', None),
288 ('CXX', '$CXX', None),
289 ('CXXCPP', '$CXXCPP', None),
290 ('CCFLAGS', '$CCFLAGS', None),
291 ('CPPFLAGS', '$CPPFLAGS', None),
292 ('LDFLAGS', '$LDFLAGS', None),
296 #---------------------------------------------------------
297 # Setting up environment
298 #---------------------------------------------------------
300 env = Environment(options = opts)
302 # Determine the frontend to use, which may be loaded
304 frontend = env.get('frontend', default_frontend)
305 # make sure the key exists
306 env['frontend'] = frontend
308 use_X11 = env.get('X11', default_with_x)
310 # whether or not use current config.h, and cached tests
311 if env['fast_start'] and os.path.isfile(env_cache_file):
313 SetOption('implicit_cache', 1)
314 cache_file = open(env_cache_file)
315 env_cache = cPickle.load(cache_file)
317 print '------------ fast_start mode --------------------'
318 print ' Use cached test results and current config.h'
319 print ' use fast_start=no to override'
320 print '-------------------------------------------------'
323 SetOption('implicit_cache', 0)
326 # set individual variables since I do not really like ENV = os.environ
327 env['ENV']['PATH'] = os.environ.get('PATH')
328 env['ENV']['HOME'] = os.environ.get('HOME')
329 env['TOP_SRC_DIR'] = TOP_SRC_DIR
330 env['SCONS_DIR'] = SCONS_DIR
331 # install to default_prefix by default
332 env['PREFIX'] = env.get('prefix', default_prefix)
333 if env.has_key('exec_prefix'):
334 env['BIN_DIR'] = env['exec_prefix']
336 env['BIN_DIR'] = os.path.join(env['PREFIX'], 'bin')
337 env['SHARE_DIR'] = os.path.join(env['PREFIX'], share_dir)
338 env['MAN_DIR'] = os.path.join(env['PREFIX'], man_dir)
339 env['LOCALE_DIR'] = os.path.join(env['PREFIX'], locale_dir)
341 # speed up source file processing
342 #env['CPPSUFFIXES'] = ['.C', '.cc', '.cpp']
343 #env['CXXSUFFIX'] = ['.C']
345 def getEnvVariable(env, name):
346 # first try command line argument (override environment settings)
347 if ARGUMENTS.has_key(name) and ARGUMENTS[name].strip() != '':
348 env[name] = ARGUMENTS[name]
349 # then use environment default
350 elif os.environ.has_key(name) and os.environ[name].strip() != '':
351 env[name] = os.environ[name]
352 print "Acquiring varaible %s from system environment: %s" % (name, env[name])
353 # finally, env['CC'] etc is set to the default values of Options.
354 # and env['CPP'] etc does not exist
356 getEnvVariable(env, 'CC')
357 getEnvVariable(env, 'LINK')
358 getEnvVariable(env, 'CPP')
359 getEnvVariable(env, 'CXX')
360 getEnvVariable(env, 'CXXCPP')
361 getEnvVariable(env, 'CCFLAGS')
362 getEnvVariable(env, 'CXXFLAGS')
363 getEnvVariable(env, 'CPPFLAGS')
364 getEnvVariable(env, 'LDFLAGS')
368 # frontend, mode, BUILDDIR and LOCALLIBPATH=BUILDDIR/libs
370 env['mode'] = env.get('mode', default_build_mode)
371 # lyx will be built to $build/build_dir so it is possible
372 # to build multiple build_dirs using the same source
373 # $mode can be debug or release
374 if env.has_key('build_dir') and env['build_dir']:
375 build_dir = env['build_dir']
376 env['BUILDDIR'] = build_dir
378 # Determine the name of the build $mode
379 env['BUILDDIR'] = '#' + env['mode']
380 # all built libraries will go to build_dir/libs
381 # (This is different from the make file approach)
382 env['LOCALLIBPATH'] = '$BUILDDIR/libs'
383 env.AppendUnique(LIBPATH = ['$LOCALLIBPATH'])
386 # QTDIR, QT_LIB_PATH, QT_INC_PATH
388 if env.has_key('qt_dir') and env['qt_dir']:
389 env['QTDIR'] = env['qt_dir']
390 # add path to the qt tools
391 env.AppendUnique(LIBPATH = [os.path.join(env['qt_dir'], 'lib')])
392 # set environment so that moc etc can be found even if its path is not set properly
393 env.PrependENVPath('PATH', os.path.join(env['qt_dir'], 'bin'))
395 env['QTDIR'] = os.environ.get('QTDIR', '/usr/lib/qt-3.3')
397 if env.has_key('qt_lib_path') and env['qt_lib_path']:
398 env['QT_LIB_PATH'] = env['qt_lib_path']
400 env['QT_LIB_PATH'] = '$QTDIR/lib'
401 env.AppendUnique(LIBPATH = ['$QT_LIB_PATH'])
402 # qt4 seems to be using pkg_config
403 env.PrependENVPath('PKG_CONFIG_PATH', env.subst('$QT_LIB_PATH'))
405 if env.has_key('qt_inc_path') and env['qt_inc_path']:
406 env['QT_INC_PATH'] = env['qt_inc_path']
407 elif os.path.isdir(os.path.join(env.subst('$QTDIR'), 'include')):
408 env['QT_INC_PATH'] = '$QTDIR/include'
409 else: # have to guess
410 env['QT_INC_PATH'] = '/usr/include/$frontend/'
411 # Note that this CPPPATH is for testing only
412 # it will be removed before calling SConscript
413 env['CPPPATH'] = [env['QT_INC_PATH']]
416 # extra_inc_path and extra_lib_path
418 if env.has_key('extra_inc_path') and env['extra_inc_path']:
419 env.AppendUnique(CPPPATH = [env['extra_inc_path']])
420 if env.has_key('extra_lib_path') and env['extra_lib_path']:
421 env.AppendUnique(LIBPATH = [env['extra_lib_path']])
422 if env.has_key('extra_inc_path1') and env['extra_inc_path1']:
423 env.AppendUnique(CPPPATH = [env['extra_inc_path1']])
424 if env.has_key('extra_lib_path1') and env['extra_lib_path1']:
425 env.AppendUnique(LIBPATH = [env['extra_lib_path1']])
426 if env.has_key('aikasurus_path') and env['aikasurus_path']:
427 env.AppendUnique(LIBPATH = [env['aikasurus_path']])
430 # this is a bit out of place (after auto-configration)
431 # but it is required to do the tests.
432 if platform_name == 'win32':
433 env.AppendUnique(CPPPATH = ['#c:/MinGW/include'])
436 # under windows, scons is confused by .C/.c and uses gcc instead of
437 # g++. I am forcing the use of g++ here. This is expected to change
438 # after lyx renames all .C files to .cpp
440 # Note that this step has to be after env.Tool('mingw') step
441 # since env.Tool('mingw') will set env['CC'] etc.
443 if env.has_key('CXX') and env['CXX']:
444 env['CC'] = env['CXX']
445 env['LINK'] = env['CXX']
451 #----------------------------------------------------------
453 #----------------------------------------------------------
455 conf = Configure(env,
457 'CheckPkgConfig' : utils.checkPkgConfig,
458 'CheckPackage' : utils.checkPackage,
459 'CheckPutenv' : utils.checkPutenv,
460 'CheckIstreambufIterator' : utils.checkIstreambufIterator,
461 'CheckMkdirOneArg' : utils.checkMkdirOneArg,
462 'CheckStdCount' : utils.checkStdCount,
463 'CheckSelectArgType' : utils.checkSelectArgType,
464 'CheckBoostLibraries' : utils.checkBoostLibraries,
465 'CheckMsgFmt' : utils.checkMsgFmt,
469 # pkg-config? (if not, we use hard-coded options)
471 if conf.CheckPkgConfig('0.15.0'):
472 env['HAS_PKG_CONFIG'] = True
474 print 'pkg-config >= 0.1.50 is not found'
475 env['HAS_PKG_CONFIG'] = False
476 env_cache['HAS_PKG_CONFIG'] = env['HAS_PKG_CONFIG']
478 env['HAS_PKG_CONFIG'] = env_cache['HAS_PKG_CONFIG']
480 # zlib? This is required. (fast_start assumes the existance of zlib)
481 if not fast_start and not conf.CheckLibWithHeader('z', 'zlib.h', 'C'):
482 print 'Did not find libz or zlib.h, exiting!'
488 # qt3 does not use pkg_config
489 if frontend == 'qt3':
490 if not conf.CheckLibWithHeader('qt-mt', 'qapp.h', 'c++', 'QApplication qapp();'):
491 print 'Did not find qt libraries, exiting!'
493 elif frontend == 'qt4':
495 # first: try pkg_config
496 if env['HAS_PKG_CONFIG']:
497 succ = conf.CheckPackage('QtCore') or conf.CheckPackage('QtCore4')
498 env['QT4_PKG_CONFIG'] = succ
499 # second: try to link to it
501 # FIXME: under linux, I can test the following perfectly
502 # However, under windows, lib names need to passed as libXXX4.a ...
503 succ = conf.CheckLibWithHeader('QtCore', 'QtGui/QApplication', 'c++', 'QApplication qapp();') or \
504 conf.CheckLibWithHeader('QtCore4', 'QtGui/QApplication', 'c++', 'QApplication qapp();')
505 # third: try to look up the path
508 for lib in ['QtCore', 'QtGui']:
509 # windows version has something like QtGui4 ...
510 if not (os.path.isfile(os.path.join(env.subst('$QT_LIB_PATH'), 'lib%s.a' % lib)) or \
511 os.path.isfile(os.path.join(env.subst('$QT_LIB_PATH'), 'lib%s4.a' % lib))):
514 # still can not find it
516 print "Qt4 libraries are found."
518 print 'Did not find qt libraries, exiting!'
524 env['SOCKET_LIBS'] = []
525 if conf.CheckLib('socket'):
526 env['SOCKET_LIBS'].append('socket')
528 # nsl is the network services library and provides a
529 # transport-level interface to networking services.
530 if conf.CheckLib('nsl'):
531 env['SOCKET_LIBS'].append('nsl')
533 env_cache['SOCKET_LIBS'] = env['SOCKET_LIBS']
535 env['SOCKET_LIBS'] = env_cache['SOCKET_LIBS']
538 # check boost libraries
539 boost_opt = ARGUMENTS.get('boost', default_boost_opt)
540 # check for system boost
542 if boost_opt in ['auto', 'system']:
543 pathes = env['LIBPATH'] + ['/usr/lib', '/usr/local/lib']
544 sig = conf.CheckBoostLibraries('boost_signals', pathes)
545 reg = conf.CheckBoostLibraries('boost_regex', pathes)
546 fil = conf.CheckBoostLibraries('boost_filesystem', pathes)
547 ios = conf.CheckBoostLibraries('boost_iostreams', pathes)
548 # if any of them is not found
549 if ('' in [sig[0], reg[0], fil[0], ios[0]]):
550 if boost_opt == 'system':
551 print "Can not find system boost libraries"
552 print "Please supply a path through extra_lib_path and try again."
553 print "Or use boost=included to use included boost libraries."
556 env['BOOST_LIBRARIES'] = [sig[1], reg[1], fil[1], ios[1]]
557 # assume all boost libraries are in the same path...
558 env.AppendUnique(LIBPATH = [sig[0]])
559 env['INCLUDED_BOOST'] = False
561 # now, auto and succ = false, or boost=included
563 # we do not need to set LIBPATH now.
564 env['BOOST_LIBRARIES'] = ['boost_signals', 'boost_regex',
565 'boost_filesystem', 'boost_iostreams']
566 env['INCLUDED_BOOST'] = True
567 env_cache['BOOST_LIBRARIES'] = env['BOOST_LIBRARIES']
568 env_cache['INCLUDED_BOOST'] = env['INCLUDED_BOOST']
570 env['BOOST_LIBRARIES'] = env_cache['BOOST_LIBRARIES']
571 env['INCLUDED_BOOST'] = env_cache['INCLUDED_BOOST']
574 # check for msgfmt command
576 env['MSGFMT'] = conf.CheckMsgFmt()
577 env_cache['MSGFMT'] = env['MSGFMT']
579 env['MSGFMT'] = env_cache['MSGFMT']
582 #----------------------------------------------------------
583 # Generating config.h
584 #----------------------------------------------------------
586 print "Generating ", utils.config_h, "..."
588 # I do not handle all macros in src/config.h.in, rather I am following a list
589 # of *used-by-lyx* macros compiled by Abdelrazak Younes <younes.a@free.fr>
591 # Note: addToConfig etc are defined in scons_util
592 utils.startConfigH(TOP_SRC_DIR)
612 ('io.h', 'HAVE_IO_H', 'c'),
613 ('limits.h', 'HAVE_LIMITS_H', 'c'),
614 ('locale.h', 'HAVE_LOCALE_H', 'c'),
615 ('locale', 'HAVE_LOCALE', 'cxx'),
616 ('process.h', 'HAVE_PROCESS_H', 'c'),
617 ('stdlib.h', 'HAVE_STDLIB_H', 'c'),
618 ('sys/stat.h', 'HAVE_SYS_STAT_H', 'c'),
619 ('sys/time.h', 'HAVE_SYS_TIME_H', 'c'),
620 ('sys/types.h', 'HAVE_SYS_TYPES_H', 'c'),
621 ('sys/utime.h', 'HAVE_SYS_UTIME_H', 'c'),
622 ('sys/socket.h', 'HAVE_SYS_SOCKET_H', 'c'),
623 ('unistd.h', 'HAVE_UNISTD_H', 'c'),
624 ('utime.h', 'HAVE_UTIME_H', 'c'),
625 ('istream', 'HAVE_ISTREAM', 'cxx'),
626 ('ostream', 'HAVE_OSTREAM', 'cxx'),
627 ('ios', 'HAVE_IOS', 'cxx')
630 for header in headers:
631 if (header[2] == 'c' and conf.CheckCHeader(header[0])) or \
632 (header[2] == 'cxx' and conf.CheckCXXHeader(header[0])):
633 utils.addToConfig('#define %s 1' % header[1], TOP_SRC_DIR)
635 utils.addToConfig('/* #undef %s */' % header[1], TOP_SRC_DIR)
656 ('open', 'HAVE_OPEN'),
657 ('close', 'HAVE_CLOSE'),
658 ('popen', 'HAVE_POPEN'),
659 ('pclose', 'HAVE_PCLOSE'),
660 ('_open', 'HAVE__OPEN'),
661 ('_close', 'HAVE__CLOSE'),
662 ('_popen', 'HAVE__POPEN'),
663 ('_pclose', 'HAVE__PCLOSE'),
664 ('getpid', 'HAVE_GETPID'),
665 ('_getpid', 'HAVE__GETPID'),
666 ('mkdir', 'HAVE_MKDIR'),
667 ('_mkdir', 'HAVE__MKDIR'),
668 ('mktemp', 'HAVE_MKTEMP'),
669 ('mkstemp', 'HAVE_MKSTEMP'),
670 ('strerror', 'HAVE_STRERROR'),
673 for func in functions:
674 if conf.CheckFunc(func[0]):
675 utils.addToConfig('#define %s 1' % func[1], TOP_SRC_DIR)
677 utils.addToConfig('/* #undef %s */' % func[1], TOP_SRC_DIR)
679 if conf.CheckFunc('fcntl'):
680 utils.addToConfig('#define HAVE_FCNTL 1', TOP_SRC_DIR)
681 env['HAVE_FCNTL'] = True
683 utils.addToConfig('/* #undef HAVE_FCNTL */', TOP_SRC_DIR)
684 env['HAVE_FCNTL'] = False
689 utils.addToConfig('#define PACKAGE "%s"' % PACKAGE, TOP_SRC_DIR)
690 utils.addToConfig('#define PACKAGE_VERSION "%s"' % PACKAGE_VERSION, TOP_SRC_DIR)
692 utils.addToConfig('#define DEVEL_VERSION 1', TOP_SRC_DIR)
697 # _GLIBCXX_CONCEPT_CHECKS
699 # items are (ENV, ARGUMENTS)
701 ('ENABLE_ASSERTIONS', 'assertions'),
702 ('ENABLE_NLS', 'nls'),
703 ('WITH_WARNINGS', 'warnings'),
704 ('_GLIBCXX_CONCEPT_CHECKS', 'concept_checks'),
708 if (env.has_key(val[0]) and env[val[0]]) or \
709 ARGUMENTS.get(val[1]):
710 utils.addToConfig('#define %s 1' % val[0], TOP_SRC_DIR)
712 utils.addToConfig('/* #undef %s */' % val[0], TOP_SRC_DIR)
715 env['EXTRA_LIBS'] = []
717 # AIKSAURUS_H_LOCATION
718 if conf.CheckLib('Aiksaurus'):
719 utils.addToConfig("#define HAVE_LIBAIKSAURUS 1", TOP_SRC_DIR)
720 if (conf.CheckCXXHeader("Aiksaurus.h")):
721 utils.addToConfig("#define AIKSAURUS_H_LOCATION <Aiksaurus.h>", TOP_SRC_DIR)
722 elif (conf.CheckCXXHeader("Aiksaurus/Aiksaurus.h")):
723 utils.addToConfig("#define AIKSAURUS_H_LOCATION <Aiksaurus/Aiksaurus.h>", TOP_SRC_DIR)
725 utils.addToConfig("#define AIKSAURUS_H_LOCATION", TOP_SRC_DIR)
726 env['EXTRA_LIBS'].append('Aiksaurus')
732 # determine headers to use
733 spell_engine = ARGUMENTS.get('spell', 'auto')
734 spell_detected = False
735 if spell_engine in ['auto', 'aspell'] and \
736 conf.CheckLib('aspell'):
737 utils.addToConfig('#define USE_ASPELL 1', TOP_SRC_DIR)
738 env['USE_ASPELL'] = True
739 env['USE_PSPELL'] = False
740 env['USE_ISPELL'] = False
741 env['EXTRA_LIBS'].append('aspell')
742 spell_detected = True
743 elif spell_engine in ['auto', 'pspell'] and \
744 conf.CheckLib('pspell'):
745 utils.addToConfig('#define USE_PSPELL 1', TOP_SRC_DIR)
746 env['USE_ASPELL'] = False
747 env['USE_PSPELL'] = True
748 env['USE_ISPELL'] = False
749 env['EXTRA_LIBS'].append('pspell')
750 spell_detected = True
751 elif spell_engine in ['auto', 'ispell'] and \
752 conf.CheckLib('ispell'):
753 utils.addToConfig('#define USE_ISPELL 1', TOP_SRC_DIR)
754 env['USE_ASPELL'] = False
755 env['USE_PSPELL'] = False
756 env['USE_ISPELL'] = True
757 env['EXTRA_LIBS'].append('ispell')
758 spell_detected = True
760 if not spell_detected:
761 env['USE_ASPELL'] = False
762 env['USE_PSPELL'] = False
763 env['USE_ISPELL'] = False
764 # FIXME: can lyx work without an spell engine
765 if spell_engine == 'auto':
766 print "Warning: Can not locate any spell checker"
768 print "Warning: Can not locate specified spell checker:", spell_engine
770 # USE_POSIX_PACKAGING
771 # USE_MACOSX_PACKAGING
772 # USE_WINDOWS_PACKAGING
773 if packaging_method == 'windows':
774 utils.addToConfig('#define USE_WINDOWS_PACKAGING 1', TOP_SRC_DIR)
775 elif packaging_method == 'posix':
776 utils.addToConfig('#define USE_POSIX_PACKAGING 1', TOP_SRC_DIR)
777 elif packaging_method == 'mac':
778 utils.addToConfig('#define USE_MACOSX_PACKAGING 1', TOP_SRC_DIR)
782 utils.addToConfig('#define BOOST_POSIX 1', TOP_SRC_DIR)
784 utils.addToConfig('/* #undef BOOST_POSIX */', TOP_SRC_DIR)
787 if conf.CheckPutenv():
788 utils.addToConfig('#define HAVE_PUTENV 1', TOP_SRC_DIR)
790 utils.addToConfig('/* #undef HAVE_PUTENV */', TOP_SRC_DIR)
792 # HAVE_DECL_ISTREAMBUF_ITERATOR
793 if conf.CheckIstreambufIterator():
794 utils.addToConfig('#define HAVE_DECL_ISTREAMBUF_ITERATOR 1', TOP_SRC_DIR)
796 utils.addToConfig('/* #undef HAVE_DECL_ISTREAMBUF_ITERATOR */', TOP_SRC_DIR)
798 # MKDIR_TAKES_ONE_ARG
799 if conf.CheckMkdirOneArg():
800 utils.addToConfig('#define MKDIR_TAKES_ONE_ARG 1', TOP_SRC_DIR)
802 utils.addToConfig('/* #undef MKDIR_TAKES_ONE_ARG */', TOP_SRC_DIR)
805 if conf.CheckStdCount():
806 utils.addToConfig('#define HAVE_STD_COUNT 1', TOP_SRC_DIR)
808 utils.addToConfig('/* #undef HAVE_STD_COUNT */', TOP_SRC_DIR)
813 (arg1, arg234, arg5) = conf.CheckSelectArgType()
814 utils.addToConfig('#define SELECT_TYPE_ARG1 %s' % arg1, TOP_SRC_DIR)
815 utils.addToConfig('#define SELECT_TYPE_ARG234 %s' % arg234, TOP_SRC_DIR)
816 utils.addToConfig('#define SELECT_TYPE_ARG5 %s' % arg5, TOP_SRC_DIR)
820 # WANT_GETFILEATTRIBUTESEX_WRAPPER
821 utils.endConfigH(TOP_SRC_DIR)
823 # env['EXTRA_LIBS'] will be modified later, so a unique copy is needed
824 # NOTE that we do *not* save qt_libs in environment.
825 env_cache['EXTRA_LIBS'] = copy.copy(env['EXTRA_LIBS'])
826 env_cache['USE_ASPELL'] = env['USE_ASPELL']
827 env_cache['USE_PSPELL'] = env['USE_PSPELL']
828 env_cache['USE_ISPELL'] = env['USE_ISPELL']
829 env_cache['HAVE_FCNTL'] = env['HAVE_FCNTL']
833 # this comes as a big surprise, without this line
834 # (doing nothing obvious), adding fast_start=yes
835 # to a build with fast_start=no will result in a rebuild
836 # Note that the exact header file to check does not matter
837 conf.CheckCHeader('io.h')
838 # only a few variables need to be rescanned
839 env['EXTRA_LIBS'] = copy.copy(env_cache['EXTRA_LIBS'])
840 env['USE_ASPELL'] = env_cache['USE_ASPELL']
841 env['USE_PSPELL'] = env_cache['USE_PSPELL']
842 env['USE_ISPELL'] = env_cache['USE_ISPELL']
843 env['HAVE_FCNTL'] = env_cache['HAVE_FCNTL']
846 # Finish auto-configuration
849 #----------------------------------------------------------
850 # Now set up our build process accordingly
851 #----------------------------------------------------------
854 # QT_LIB etc (EXTRA_LIBS holds lib for each frontend)
856 # NOTE: Tool('qt') or Tool('qt4') will be loaded later
857 # in their respective directory and specialized env.
859 if frontend == 'qt3':
860 # note: env.Tool('qt') my set QT_LIB to qt
861 env['QT_LIB'] = 'qt-mt'
862 env['EXTRA_LIBS'].append('qt-mt')
863 if platform_name == 'cygwin' and use_X11:
864 env['EXTRA_LIBS'].extend(['GL', 'Xmu', 'Xi', 'Xrender', 'Xrandr', 'Xcursor',
865 'Xft', 'freetype', 'fontconfig', 'Xext', 'X11', 'SM', 'ICE', 'resolv',
867 env.AppendUnique(LIBPATH = ['/usr/X11R6/lib'])
868 elif frontend == 'qt4':
869 if platform_name == "win32":
870 env['QT_LIB'] = ['QtCore4', 'QtGui4']
872 env['QT_LIB'] = ['QtCore', 'QtGui']
873 env['EXTRA_LIBS'] += env['QT_LIB']
875 print "Can not locate qt tools"
876 print "What I get is "
877 print " QTDIR: ", env['QTDIR']
880 if platform_name in ['win32', 'cygwin']:
881 # the final link step needs stdc++ to succeed under mingw
882 # FIXME: shouldn't g++ automatically link to stdc++?
883 env['SYSTEM_LIBS'] = ['shlwapi', 'z', 'stdc++']
885 env['SYSTEM_LIBS'] = ['z']
888 # Build parameters CPPPATH etc
890 # boost is always in, src is needed for config.h
892 # QT_INC_PATH is not needed for *every* source file
893 env['CPPPATH'].remove(env['QT_INC_PATH'])
894 env['CPPPATH'] += ['$TOP_SRC_DIR/boost', '$TOP_SRC_DIR/src']
896 # TODO: add (more) appropriate compiling options (-DNDEBUG etc)
897 # for debug/release mode
898 if ARGUMENTS.get('mode', default_build_mode) == 'debug':
899 env.AppendUnique(CCFLAGS = [])
901 env.AppendUnique(CCFLAGS = [])
904 # Customized builders
906 # install customized builders
907 env['BUILDERS']['substFile'] = Builder(action = utils.env_subst)
908 # FIXME: there must be a better way.
909 env['BUILDERS']['fileCopy'] = Builder(action = utils.env_filecopy)
912 # A Link script for cygwin see
913 # http://www.cygwin.com/ml/cygwin/2004-09/msg01101.html
914 # http://www.cygwin.com/ml/cygwin-apps/2004-09/msg00309.html
917 if platform_name == 'cygwin':
918 ld_script_path = '/usr/lib/qt3/mkspecs/cygwin-g++'
919 ld_script = utils.installCygwinLDScript(ld_script_path)
920 env.AppendUnique(LINKFLAGS = ['-Wl,--enable-runtime-pseudo-reloc',
921 '-Wl,--script,%s' % ld_script, '-Wl,-s'])
926 # src/support/package.C.in needs the following to replace
927 # LYX_ABS_INSTALLED_DATADIR (e.g. /usr/local/lyx/share/lyx)
928 env['LYX_DIR'] = env['SHARE_DIR']
929 # LYX_ABS_INSTALLED_LOCALEDIR
930 env['LOCALEDIR'] = env['LOCALE_DIR']
931 env['TOP_SRCDIR'] = env['TOP_SRC_DIR']
933 if env.has_key('version_suffix'):
934 env['PROGRAM_SUFFIX'] = env['version_suffix']
936 env['PROGRAM_SUFFIX'] = ''
937 # needed by src/version.C.in => src/version.C
938 env['PACKAGE_VERSION'] = PACKAGE_VERSION
939 # fill in the version info
940 env['VERSION_INFO'] = '''Configuration
942 Special build flags: %s
944 C Compiler flags: %s %s
946 C++ Compiler LyX flags: %s
947 C++ Compiler flags: %s %s
949 Linker user flags: %s
951 Builing directory: %s
952 Local library directory: %s
957 include search path: %s
964 ''' % (platform_name,
965 env.subst('$CCFLAGS'), env.subst('$CC'),
966 env.subst('$CPPFLAGS'), env.subst('$CFLAGS'),
967 env.subst('$CXX'), env.subst('$CXXFLAGS'),
968 env.subst('$CPPFLAGS'), env.subst('$CXXFLAGS'),
969 env.subst('$LINKFLAGS'), env.subst('$LINKFLAGS'),
970 env.subst('$BUILDDIR'), env.subst('$LOCALLIBPATH'),
971 str(env['LIBPATH']), str(env['BOOST_LIBRARIES']),
972 str(env['EXTRA_LIBS']), str(env['SYSTEM_LIBS']), str(env['CPPPATH']),
973 env['frontend'], packaging_method,
974 env['PREFIX'], env['BIN_DIR'], env['SHARE_DIR'])
976 if env['frontend'] in ['qt3', 'qt4']:
977 env['VERSION_INFO'] += ''' include dir: %s
980 ''' % (env.subst('$QT_INC_PATH'), env.subst('$QT_LIB_PATH'), use_X11)
983 print env['VERSION_INFO']
986 # Mingw command line may be too short for our link usage,
987 # Here we use a trick from scons wiki
988 # http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/LongCmdLinesOnWin32
990 # I also would like to add logging (commands only) capacity to the
992 logfile = env.get('logfile', default_log_file)
993 if logfile != '' or platform_name == 'win32':
995 utils.setLoggedSpawn(env, logfile, longarg = (platform_name == 'win32'),
996 info = '''# This is a log of commands used by scons to build lyx
1000 ''' % (time.asctime(), ' '.join(sys.argv),
1001 env['VERSION_INFO'].replace('\n','\n# ')) )
1007 # -h will print out help info
1008 Help(opts.GenerateHelpText(env))
1009 # save environment settings (for fast_start option)
1010 cache_file = open(env_cache_file, 'w')
1011 cPickle.dump(env_cache, cache_file)
1014 #----------------------------------------------------------
1016 #----------------------------------------------------------
1019 # this has been the source of problems on some platforms...
1020 # I find that I need to supply it with full path name
1021 env.SConsignFile(os.path.join(Dir(env['BUILDDIR']).abspath, '.sconsign'))
1022 # this usage needs further investigation.
1023 #env.CacheDir('%s/Cache/%s' % (env['BUILDDIR'], frontend))
1025 env['BUILD_TARGETS'] = BUILD_TARGETS
1027 print "Building all targets recursively"
1029 env.SConscript('$SCONS_DIR/SConscript', duplicate = 0)