]> git.lyx.org Git - lyx.git/blob - development/scons/SConstruct
Scons: Better MSVS Projects support (now with debug)
[lyx.git] / development / scons / SConstruct
1 # vi:filetype=python:expandtab:tabstop=2:shiftwidth=2
2 #
3 # file SConstruct
4 #
5 # This file is part of LyX, the document processor.
6 # Licence details can be found in the file COPYING.
7 #
8 # \author Bo Peng
9 # Full author contact details are available in file CREDITS.
10 #
11 #
12 # This is a scons based building system for lyx, you can use it as follows:
13 #
14 #   $ cd development/scons
15 #   $ scons [options] [targets]
16 # or:
17 #   $ scons -f development/scons/SConstruct [options] [targets]
18 # and:
19 #   $ scons [prefix=.] install
20 #
21 # Where:
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 
24 #     for install
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
29 #
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/
38 #
39 # Hints:
40 #   * scons fast_start=yes
41 #     If env.cache exists, bypass all tests and use existing src/config.h
42 #
43 #   * scons --config=force
44 #     force re-configuration (use scons -H for details)
45 #
46 #   * check config.log to see why config has failed
47 #
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.
52 #
53 #   * executed commands will be logged in scons_lyx.log. You can use logfile=
54 #     option to save log to another file.
55 #
56 # Notes:
57 #
58 #   * scons dist etc may be added later. Interested contributors can follow
59 #       http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/AccumulateBuilder
60 #     or
61 #       http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/DistTarBuilder
62 #     Please also see the commented out code in scons_utils.py
63 #   
64 #   * NSIS support can be found here.
65 #     http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/NsisSconsTool
66 #
67 #   * rpm support?
68 #     http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/RpmHonchoTemp
69 #
70 #   However, I decide to wait since scons seems to be standardizing these
71 #   features.
72 #
73
74 import os, sys, copy, cPickle, glob
75
76 # config/scons_utils.py defines a few utility function
77 sys.path.append('config')
78 import scons_utils as utils
79
80 #----------------------------------------------------------
81 # Required runtime environment
82 #----------------------------------------------------------
83
84 # scons asks for 1.5.2, lyx requires 2.2
85 EnsurePythonVersion(2, 2)
86 # Please use at least 0.96.91 (not 0.96.1)
87 EnsureSConsVersion(0, 96)
88
89 # determine where I am ...
90 #
91 # called as 'scons -f development/scons/SConstruct'
92 if os.path.isfile('SConstruct'):
93   TOP_SRC_DIR = '../..'
94   SCONS_DIR = '.'
95 # called as 'cd development/scons; scons'
96 else:
97   TOP_SRC_DIR = '.'
98   SCONS_DIR = 'development/scons'
99
100 #----------------------------------------------------------
101 # Global definitions
102 #----------------------------------------------------------
103
104 # some global settings
105 PACKAGE_VERSION = '1.5.0svn'
106 DEVEL_VERSION = True
107 default_build_mode = 'debug'
108 lyx_ext = '*.C'
109
110 PACKAGE = 'lyx'
111 PACKAGE_BUGREPORT = 'lyx-devel@lists.lyx.org'
112 PACKAGE_NAME = 'LyX'
113 PACKAGE_TARNAME = 'lyx'
114 PACKAGE_STRING = '%s %s' % (PACKAGE_NAME, PACKAGE_VERSION)
115
116 # various cache/log files
117 default_log_file = 'scons_lyx.log'
118 env_cache_file = 'env.cache'
119
120
121 #----------------------------------------------------------
122 # platform dependent settings
123 #----------------------------------------------------------
124 if os.name == 'nt':
125   platform_name = 'win32'
126   default_frontend = 'qt4'
127   # boost and gettext are unlikely to be installed already
128   default_boost_opt = 'included'
129   default_gettext_opt = 'included'
130   default_pch_opt = False
131   default_with_x = False
132   spell_checker = 'auto'
133   # boost_posix indicates to boost which API to use (posix or windows).
134   # If not specified, boost tries to figure out by itself, but it may fail.
135   boost_posix = False
136   packaging_method = 'windows'
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
149   boost_posix = True
150   packaging_method = 'posix'
151   default_prefix = '/usr/local/'
152   share_dir = 'share/lyx'
153   man_dir = 'man/man1'
154   locale_dir = 'share/locale'
155 elif os.name == 'posix' and sys.platform == 'cygwin':
156   platform_name = 'cygwin'
157   default_frontend = 'qt3'
158   # force the use of cygwin/boost/gettext
159   default_boost_opt = 'system'
160   default_gettext_opt = 'system'
161   default_pch_opt = False
162   default_with_x = True
163   boost_posix = True
164   packaging_method = 'posix'
165   default_prefix = '/usr/local/'
166   share_dir = 'share/lyx'
167   man_dir = 'man/man1'
168   locale_dir = 'share/locale'
169 elif os.name == 'darwin':
170   platform_name = 'mac'
171   default_frontend = 'qt3'
172   # to be safe
173   default_boost_opt = 'included'
174   default_gettext_opt = 'included'
175   default_pch_opt = False
176   default_with_x = False
177   boost_posix = True
178   packaging_method = 'mac'
179   # FIXME: where to install?
180   default_prefix = '/usr/local/'
181   share_dir = 'Resources'
182   man_dir = 'Resources/man/man1'
183   locale_dir = 'Resources/locale'
184 else:  # unsupported system
185   platform_name = 'others'
186   default_frontend = 'qt3'
187   # to be safe
188   default_boost_opt = 'included'
189   default_gettext_opt = 'included'
190   default_pch_opt = False
191   default_with_x = True
192   boost_posix = False
193   packaging_method = 'posix'
194   default_prefix = '/usr/local/'
195   share_dir = 'share/lyx'
196   man_dir = 'man/man1'
197   locale_dir = 'share/locale'
198
199
200 #---------------------------------------------------------
201 # Handling options
202 #----------------------------------------------------------
203 #
204 if os.path.isfile('config.py'):
205   print "Getting options from config.py..."
206   print open('config.py').read()
207
208 opts = Options(['config.py'])
209 opts.AddOptions(
210   # frontend,
211   EnumOption('frontend', 'Main GUI', default_frontend,
212     allowed_values = ('xform', 'qt3', 'qt4', 'gtk') ),
213   # debug or release build
214   EnumOption('mode', 'Building method', default_build_mode,
215     allowed_values = ('debug', 'release') ),
216   # boost libraries
217   EnumOption('boost',
218     'Use included, system boost library, or try sytem boost first.',
219     default_boost_opt,
220     allowed_values = (
221       'auto',       # detect boost, if not found, use included
222       'included',   # always use included boost
223       'system',     # always use system boost, fail if can not find
224       ) ),
225   # FIXME: not implemented yet.
226   EnumOption('gettext',
227     'Use included, system gettext library, or try sytem gettext first',
228     default_gettext_opt,
229     allowed_values = (
230       'auto',       # detect gettext, if not found, use included
231       'included',   # always use included gettext
232       'system',     # always use system gettext, fail if can not find
233       ) ),
234   #
235   EnumOption('spell', 'Choose spell checker to use.', 'auto',
236     allowed_values = ('aspell', 'pspell', 'ispell', 'auto') ),
237   #
238   BoolOption('fast_start', 'Whether or not use cached tests and keep current config.h', True),
239   #
240   BoolOption('load_option', 'load option from previous scons run', True),
241   # FIXME: I do not know how pch is working. Ignore this option now.
242   BoolOption('pch', '(NA) Whether or not use pch', default_pch_opt),
243   # enable assertion, (config.h has ENABLE_ASSERTIOS
244   BoolOption('assertions', 'Use assertions', True),
245   # enable warning, (config.h has WITH_WARNINGS)
246   BoolOption('warnings', 'Use warnings', True),
247   # enable glib, (config.h has _GLIBCXX_CONCEPT_CHECKS)
248   BoolOption('concept_checks', 'Enable concept checks', True),
249   # 
250   BoolOption('nls', 'Whether or not use native language support', True),
251   # FIXME: not implemented
252   BoolOption('profile', '(NA) Whether or not enable profiling', False),
253   # FIXME: not implemented
254   BoolOption('std_debug', '(NA) Whether or not turn on stdlib debug', False),
255   # using x11?
256   BoolOption('X11', 'Use x11 windows system', default_with_x),
257   # use MS VC++ to build lyx
258   BoolOption('use_vc', 'Use MS VC++ to build lyx', False),
259   #
260   PathOption('qt_dir', 'Path to qt directory', None),
261   #
262   PathOption('qt_include_path', 'Path to qt include directory', None),
263   #
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),
269   #
270   PathOption('extra_lib_path', 'Extra library path', None),
271   #
272   PathOption('extra_bin_path', 'A convenient way to add a path to $PATH', None),
273   #
274   PathOption('extra_inc_path1', 'Extra include path', None),
275   #
276   PathOption('extra_lib_path1', 'Extra library path', None),
277   # rebuild only specifed, comma separated targets
278   ('rebuild', 'rebuild only specifed, comma separated targets', None),
279   # can be set to a non-existing directory
280   ('prefix', 'install architecture-independent files in PREFIX', None),
281   # will install to dest_dir if defined. Otherwise, prefix will be used.
282   ('dest_dir', 'install to dest_dir', None),
283   # version suffix
284   ('version_suffix', 'install lyx as lyx-suffix', ''),
285   #
286   PathOption('exec_prefix', 'install architecture-independent executable files in PREFIX', None),
287   # log file
288   ('logfile', 'save commands (not outputs) to logfile', default_log_file),
289   # Path to aikasurus
290   PathOption('aikasurus_path', 'Path to aikasurus library', None),
291   # environment variable can be set as options. (DO NOT set defaults)
292   ('CC', '$CC', None),
293   ('LINK', '$LINK', None),
294   ('CPP', '$CPP', None),
295   ('CXX', '$CXX', None),
296   ('CXXCPP', '$CXXCPP', None),
297   ('CCFLAGS', '$CCFLAGS', None),
298   ('CPPFLAGS', '$CPPFLAGS', None),
299   ('LDFLAGS', '$LDFLAGS', None),
300 )
301
302 # whether or not use current config.h, and cached tests
303 if (not ARGUMENTS.has_key('fast_start') or \
304   ARGUMENTS['fast_start'] in ['y', 'yes', 't', 'true', '1', 'all']) \
305   and os.path.isfile(env_cache_file):
306   fast_start = True
307   cache_file = open(env_cache_file)
308   env_cache = cPickle.load(cache_file)
309   cache_file.close()
310   print '------------ fast_start mode --------------------'
311   print '  Use cached test results and current config.h'
312   print '  use fast_start=no to override'
313   print
314 else:
315   fast_start = False
316   env_cache = {}
317
318 if (not ARGUMENTS.has_key('load_option') or \
319   ARGUMENTS['load_option'] in ['y', 'yes', 't', 'true', '1', 'all']) \
320   and os.path.isfile(env_cache_file):
321   cache_file = open(env_cache_file)
322   opt_cache = cPickle.load(cache_file)['arg_cache']
323   cache_file.close()
324   # import cached options, but we should ignore qt_dir when frontend changes
325   if ARGUMENTS.has_key('frontend') and opt_cache.has_key('frontend') \
326     and ARGUMENTS['frontend'] != opt_cache['frontend'] \
327     and opt_cache.has_key('qt_dir'):
328     opt_cache.pop('qt_dir')
329   # some options will require full rebuild
330   # these are in general things that will change src/config.h
331   for arg in ['version_suffix', 'nls']:
332     if ARGUMENTS.has_key(arg) and ((not opt_cache.has_key(arg)) or \
333       ARGUMENTS[arg] != opt_cache[arg]):
334       if fast_start:
335         print "  ** fast_start is disabled because of the change of option", arg
336         print
337         fast_start = False
338   # and we do not cache some options
339   for arg in ['fast_start']:
340     if opt_cache.has_key(arg):
341       opt_cache.pop(arg)
342   for key in opt_cache.keys():
343     if not ARGUMENTS.has_key(key):
344       ARGUMENTS[key] = opt_cache[key]
345       print "Restoring cached option  %s=%s" % (key, ARGUMENTS[key])
346   print
347
348 # save arguments
349 env_cache['arg_cache'] = ARGUMENTS
350
351
352 #---------------------------------------------------------
353 # Setting up environment
354 #---------------------------------------------------------
355
356 # I do not really like ENV=os.environ, but you may 
357 # add it here if you experience some environment related problem
358 env = Environment(options = opts)
359
360 # Determine the frontend to use, which may be loaded
361 # from option cache
362 frontend = env.get('frontend', default_frontend)
363 # make sure the key exists
364 env['frontend'] = frontend
365 env['LYX_EXT'] = lyx_ext
366 #
367 use_X11 = env.get('X11', default_with_x)
368 use_vc = env.get('use_vc', False)
369 # use it only once for s scons-bug, will remove it later.
370 env['USE_VC'] = use_vc
371
372
373 # set individual variables since I do not really like ENV = os.environ
374 env['ENV']['PATH'] = os.environ.get('PATH')
375 env['ENV']['HOME'] = os.environ.get('HOME')
376 # these are defined for MSVC
377 env['ENV']['LIB'] = os.environ.get('LIB')
378 env['ENV']['INCLUDE'] = os.environ.get('INCLUDE')
379 if use_vc:
380   # full path name is used to build msvs project files
381   env['TOP_SRC_DIR'] = Dir(TOP_SRC_DIR).abspath
382 else:
383   env['TOP_SRC_DIR'] = TOP_SRC_DIR
384 env['SCONS_DIR'] = SCONS_DIR
385 # install to default_prefix by default
386 env['PREFIX'] = env.get('prefix', default_prefix)
387 # program suffix
388 if env.has_key('version_suffix'):
389   if env['version_suffix'] in ['y', 'yes', 't', 'true', '1', 'all']:
390     env['PROGRAM_SUFFIX'] = PACKAGE_VERSION
391   else:
392     env['PROGRAM_SUFFIX'] = env['version_suffix']
393 else:
394   env['PROGRAM_SUFFIX'] = ''
395
396 # whether or not add suffix to file and directory names
397 env['ADD_SUFFIX'] = packaging_method != 'windows'
398 if env['ADD_SUFFIX']:
399   env['SHARE_DIR'] = os.path.join(env['PREFIX'], share_dir + env['PROGRAM_SUFFIX'])
400 else:  
401   env['SHARE_DIR'] = os.path.join(env['PREFIX'], share_dir)
402 env['LOCALE_DIR'] = os.path.join(env['PREFIX'], locale_dir)
403 #
404 # if dest_dir is different from prefix.
405 env['DEST_DIR'] = env.get('dest_dir', env['PREFIX'])
406 if env.has_key('exec_prefix'):
407   env['BIN_DEST_DIR'] = env['exec_prefix']
408 else:
409   env['BIN_DEST_DIR'] = os.path.join(env['DEST_DIR'], 'bin')
410 if env['ADD_SUFFIX']:
411   env['SHARE_DEST_DIR'] = os.path.join(env['DEST_DIR'], share_dir + env['PROGRAM_SUFFIX'])
412 else:
413   env['SHARE_DEST_DIR'] = os.path.join(env['DEST_DIR'], share_dir)
414 env['MAN_DEST_DIR'] = os.path.join(env['DEST_DIR'], man_dir)
415 env['LOCALE_DEST_DIR'] = os.path.join(env['DEST_DIR'], locale_dir)
416
417 #
418 # this is a bit out of place (after auto-configration) but 
419 # it is required to do the tests. Since Tool('mingw') will 
420 # reset CCFLAGS etc, this should be done before getEnvVariable
421 if platform_name == 'win32' and not use_vc:
422   env.Tool('mingw')
423   env.AppendUnique(CPPPATH = ['#c:/MinGW/include'])
424 elif use_vc:
425   env.Tool('msvc')
426   env.Tool('mslink')
427
428
429 # speed up source file processing
430 #env['CPPSUFFIXES'] = ['.C', '.cc', '.cpp']
431 #env['CXXSUFFIX'] = ['.C']
432
433 def getEnvVariable(env, name):
434   # first try command line argument (override environment settings)
435   if ARGUMENTS.has_key(name) and ARGUMENTS[name].strip() != '':
436     # multiple options may be passed like "-02 -g"
437     env[name] = ARGUMENTS[name].split()
438     # it does not seem necessary, but it is safer to change ['a'] back to 'a'
439     if len(env[name]) == 1:
440       env[name] = env[name][0]
441   # then use environment default
442   elif os.environ.has_key(name) and os.environ[name].strip() != '':
443     print "Acquiring varaible %s from system environment: %s" % (name, env[name])
444     env[name] = os.environ[name].split()
445     if len(env[name]) == 1:
446       env[name] = env[name][0]
447   # finally, env['CC'] etc is set to the default values of Options.
448   # and env['CPP'] etc does not exist
449
450 getEnvVariable(env, 'CC')
451 getEnvVariable(env, 'LINK')
452 getEnvVariable(env, 'CPP')
453 getEnvVariable(env, 'CXX')
454 getEnvVariable(env, 'CXXCPP')
455 getEnvVariable(env, 'CCFLAGS')
456 getEnvVariable(env, 'CXXFLAGS')
457 getEnvVariable(env, 'CPPFLAGS')
458 getEnvVariable(env, 'LDFLAGS')
459
460
461 #
462 # frontend, mode, BUILDDIR and LOCALLIBPATH=BUILDDIR/libs
463 #
464 env['mode'] = env.get('mode', default_build_mode)
465 # lyx will be built to $build/build_dir so it is possible
466 # to build multiple build_dirs using the same source
467 # $mode can be debug or release
468 if env.has_key('build_dir') and env['build_dir']:
469   build_dir = env['build_dir']
470   env['BUILDDIR'] = build_dir
471 else:
472   # Determine the name of the build $mode
473   env['BUILDDIR'] = '#' + env['mode']
474 # all built libraries will go to build_dir/libs
475 # (This is different from the make file approach)
476 env['LOCALLIBPATH'] = '$BUILDDIR/libs'
477 # to make use of local cached parameters, this one has to be '.'
478 env['MSVSPATH'] = '.'
479 env.AppendUnique(LIBPATH = ['$LOCALLIBPATH'])
480
481 #
482 # QTDIR, QT_LIB_PATH, QT_INC_PATH
483 #
484 if env.has_key('qt_dir') and env['qt_dir']:
485   env['QTDIR'] = env['qt_dir']
486   # add path to the qt tools
487   env.AppendUnique(LIBPATH = [os.path.join(env['qt_dir'], 'lib')])
488   # set environment so that moc etc can be found even if its path is not set properly
489   env.PrependENVPath('PATH', os.path.join(env['qt_dir'], 'bin'))
490 else:
491   env['QTDIR'] = os.environ.get('QTDIR', '/usr/lib/qt-3.3')
492
493 if env.has_key('qt_lib_path') and env['qt_lib_path']:
494   env['QT_LIB_PATH'] = env['qt_lib_path']
495 else:
496   env['QT_LIB_PATH'] = '$QTDIR/lib'
497 env.AppendUnique(LIBPATH = ['$QT_LIB_PATH'])
498 # qt4 seems to be using pkg_config
499 env.PrependENVPath('PKG_CONFIG_PATH', env.subst('$QT_LIB_PATH'))
500
501 if env.has_key('qt_inc_path') and env['qt_inc_path']:
502   env['QT_INC_PATH'] = env['qt_inc_path']
503 elif os.path.isdir(os.path.join(env.subst('$QTDIR'), 'include')):
504   env['QT_INC_PATH'] = '$QTDIR/include'
505 else: # have to guess
506   env['QT_INC_PATH'] = '/usr/include/$frontend/'
507 # Note that this CPPPATH is for testing only
508 # it will be removed before calling SConscript
509 env['CPPPATH'] = [env['QT_INC_PATH']]
510
511 #
512 # extra_inc_path and extra_lib_path
513 #
514 if env.has_key('extra_inc_path') and env['extra_inc_path']:
515   env.AppendUnique(CPPPATH = [env['extra_inc_path']])
516 if env.has_key('extra_lib_path') and env['extra_lib_path']:
517   env.AppendUnique(LIBPATH = [env['extra_lib_path']])
518 if env.has_key('extra_inc_path1') and env['extra_inc_path1']:
519   env.AppendUnique(CPPPATH = [env['extra_inc_path1']])
520 if env.has_key('extra_lib_path1') and env['extra_lib_path1']:
521   env.AppendUnique(LIBPATH = [env['extra_lib_path1']])
522 if env.has_key('extra_bin_path') and env['extra_bin_path']:
523   # maybe only one of them is needed
524   os.environ['PATH'] += os.pathsep + env['extra_bin_path']
525   env['ENV']['PATH'] += os.pathsep + env['extra_bin_path']
526 if env.has_key('aikasurus_path') and env['aikasurus_path']:
527   env.AppendUnique(LIBPATH = [env['aikasurus_path']])
528
529
530 # under windows, scons is confused by .C/.c and uses gcc instead of
531 # g++. I am forcing the use of g++ here. This is expected to change
532 # after lyx renames all .C files to .cpp
533 #
534 # Note that this step has to be after env.Tool('mingw') step
535 # since env.Tool('mingw') will set env['CC'] etc.
536 #
537 # save the old c compiler and CCFLAGS (used by libintl)
538 env['C_COMPILER'] = env.subst('$CC')
539 env['C_CCFLAGS'] = env.subst('$CCFLAGS').split()
540 # if we use ms vc, the commands are fine (cl.exe and link.exe)
541 if not use_vc:
542   if env.has_key('CXX') and env['CXX']:
543     env['CC'] = env.subst('$CXX')
544     env['LINK'] = env.subst('$CXX')
545   else:
546     env['CC'] = 'g++'
547     env['LINK'] = 'g++'
548 else: 
549   # /TP treat all source code as C++
550   # C4819: The file contains a character that cannot be represented 
551   #   in the current code page (number)
552   # C4996: foo was decleared deprecated
553   env.Append(CCFLAGS=['/TP', '/EHsc', '/wd4819', '/wd4996'])
554   env.Append(C_CCFLAGS=['/Dinline#', '/D__attribute__(x)#', '/Duintmax_t=UINT_MAX'])
555
556
557 #----------------------------------------------------------
558 # Autoconf business
559 #----------------------------------------------------------
560
561 conf = Configure(env,
562   custom_tests = {
563     'CheckPkgConfig' : utils.checkPkgConfig,
564     'CheckPackage' : utils.checkPackage,
565     'CheckMkdirOneArg' : utils.checkMkdirOneArg,
566     'CheckSelectArgType' : utils.checkSelectArgType,
567     'CheckBoostLibraries' : utils.checkBoostLibraries,
568     'CheckCommand' : utils.checkCommand,
569     'CheckCXXGlobalCstd' : utils.checkCXXGlobalCstd,
570     'CheckLC_MESSAGES' : utils.checkLC_MESSAGES,
571     'CheckIconvConst' : utils.checkIconvConst,
572   }
573 )
574
575
576 # pkg-config? (if not, we use hard-coded options)
577 if not fast_start:
578   if conf.CheckPkgConfig('0.15.0'):
579     env['HAS_PKG_CONFIG'] = True
580   else:
581     print 'pkg-config >= 0.1.50 is not found'
582     env['HAS_PKG_CONFIG'] = False
583   env_cache['HAS_PKG_CONFIG'] = env['HAS_PKG_CONFIG']
584 else:
585   env['HAS_PKG_CONFIG'] = env_cache['HAS_PKG_CONFIG']
586
587 # zlib? This is required. (fast_start assumes the existance of zlib)
588 if not fast_start:
589   if (not use_vc and not conf.CheckLibWithHeader('z', 'zlib.h', 'C')) \
590     or (use_vc and not conf.CheckLibWithHeader('zdll', 'zlib.h', 'C')):
591     print 'Did not find zdll.lib or zlib.h, exiting!'
592     Exit(1)
593
594 # qt libraries?
595 if not fast_start:
596   #
597   # qt3 does not use pkg_config
598   if frontend == 'qt3':
599     if not conf.CheckLibWithHeader('qt-mt', 'qapp.h', 'c++', 'QApplication qapp();'):
600       print 'Did not find qt libraries, exiting!'
601       Exit(1)
602   elif frontend == 'qt4':
603     succ = False
604     # first: try pkg_config
605     if env['HAS_PKG_CONFIG']:
606       succ = conf.CheckPackage('QtCore') or conf.CheckPackage('QtCore4')
607       env['QT4_PKG_CONFIG'] = succ
608     # second: try to link to it
609     if not succ:
610       # FIXME: under linux, I can test the following perfectly
611       # However, under windows, lib names need to passed as libXXX4.a ...
612       succ = conf.CheckLibWithHeader('QtCore', 'QtGui/QApplication', 'c++', 'QApplication qapp();') or \
613         conf.CheckLibWithHeader('QtCore4', 'QtGui/QApplication', 'c++', 'QApplication qapp();')
614     # third: try to look up the path
615     if not succ:
616       succ = True
617       for lib in ['QtCore', 'QtGui']:
618         # windows version has something like QtGui4 ...
619         if not (os.path.isfile(os.path.join(env.subst('$QT_LIB_PATH'), 'lib%s.a' % lib)) or \
620           os.path.isfile(os.path.join(env.subst('$QT_LIB_PATH'), 'lib%s4.a' % lib))):
621           succ = False
622           break
623     # still can not find it
624     if succ:
625       print "Qt4 libraries are found."
626     else:
627       print 'Did not find qt libraries, exiting!'
628       Exit(1)
629
630 # now, if msvc2005 is used, we will need that QT_LIB_PATH/QT_LIB.manifest file
631 if use_vc:
632   # glob file xxx.dll.manifest (msvc 2003 may not have it)
633   manifests = glob.glob(os.path.join(env.subst('$QT_LIB_PATH'), '*.dll.manifest'))
634   if manifests != []:
635     env['LINKCOM'] = [env['LINKCOM'], 'mt.exe /MANIFEST %s /outputresource:$TARGET;1' % manifests[0]]
636
637 # check socket libs
638 if not fast_start:
639   env['SOCKET_LIBS'] = []
640   if conf.CheckLib('socket'):
641     env['SOCKET_LIBS'].append('socket')
642
643   # nsl is the network services library and provides a
644   # transport-level interface to networking services.
645   if conf.CheckLib('nsl'):
646     env['SOCKET_LIBS'].append('nsl')
647
648   env_cache['SOCKET_LIBS'] = env['SOCKET_LIBS']
649 else:
650   env['SOCKET_LIBS'] = env_cache['SOCKET_LIBS']
651
652 if not fast_start:
653   # check boost libraries
654   boost_opt = ARGUMENTS.get('boost', default_boost_opt)
655   # check for system boost
656   succ = False
657   if boost_opt in ['auto', 'system']:
658     pathes = env['LIBPATH'] + ['/usr/lib', '/usr/local/lib']
659     sig = conf.CheckBoostLibraries('boost_signals', pathes)
660     reg = conf.CheckBoostLibraries('boost_regex', pathes)
661     fil = conf.CheckBoostLibraries('boost_filesystem', pathes)
662     ios = conf.CheckBoostLibraries('boost_iostreams', pathes)
663     # if any of them is not found
664     if ('' in [sig[0], reg[0], fil[0], ios[0]]):
665       if boost_opt == 'system':
666         print "Can not find system boost libraries"
667         print "Please supply a path through extra_lib_path and try again."
668         print "Or use boost=included to use included boost libraries."
669         Exit(2)
670     else:
671       env['BOOST_LIBRARIES'] = [sig[1], reg[1], fil[1], ios[1]]
672       # assume all boost libraries are in the same path...
673       env.AppendUnique(LIBPATH = [sig[0]])
674       env['INCLUDED_BOOST'] = False
675       succ = True
676   # now, auto and succ = false, or boost=included
677   if not succ:
678     # we do not need to set LIBPATH now.
679     env['BOOST_LIBRARIES'] = ['included_boost_signals', 'included_boost_regex',
680       'included_boost_filesystem', 'included_boost_iostreams']
681     env['INCLUDED_BOOST'] = True
682   env_cache['BOOST_LIBRARIES'] = env['BOOST_LIBRARIES']
683   env_cache['INCLUDED_BOOST'] = env['INCLUDED_BOOST']
684 else:
685   env['BOOST_LIBRARIES'] = env_cache['BOOST_LIBRARIES']
686   env['INCLUDED_BOOST'] = env_cache['INCLUDED_BOOST']
687
688
689 env['ENABLE_NLS'] = not env.has_key('nls') or env['nls']
690
691 if not fast_start:
692   if not env['ENABLE_NLS']:
693     env['INTL_LIBS'] = []
694     env['INCLUDED_GETTEXT'] = False
695   else:
696     # check gettext libraries
697     gettext_opt = ARGUMENTS.get('gettext', default_gettext_opt)
698     # check for system gettext
699     succ = False
700     if gettext_opt in ['auto', 'system']:
701       if conf.CheckLib('intl'):
702         env['INCLUDED_GETTEXT'] = False
703         env['INTL_LIBS'] = ['intl']
704         succ = True
705       else: # no found
706         if gettext_opt == 'system':
707           print "Can not find system gettext library"
708           print "Please supply a path through extra_lib_path and try again."
709           print "Or use gettext=included to use included gettext libraries."
710           Exit(2)
711     # now, auto and succ = false, or gettext=included
712     if not succ:
713       # we do not need to set LIBPATH now.
714       env['INCLUDED_GETTEXT'] = True
715       env['INTL_LIBS'] = ['included_intl']
716   env_cache['INCLUDED_GETTEXT'] = env['INCLUDED_GETTEXT']
717   env_cache['INTL_LIBS'] = env['INTL_LIBS']
718 else:
719   env['INTL_LIBS'] = env_cache['INTL_LIBS']
720   env['INCLUDED_GETTEXT'] = env_cache['INCLUDED_GETTEXT']
721
722 #
723 # check for msgfmt command
724 if not fast_start:
725   env['MSGFMT'] = conf.CheckCommand('msgfmt')
726   env_cache['MSGFMT'] = env['MSGFMT']
727 else:
728   env['MSGFMT'] = env_cache['MSGFMT']
729
730
731 #----------------------------------------------------------
732 # Generating config.h
733 #----------------------------------------------------------
734 if not fast_start:
735   print "Generating ", utils.config_h, "..."
736
737   # I do not handle all macros in src/config.h.in, rather I am following a list
738   # of *used-by-lyx* macros compiled by Abdelrazak Younes <younes.a@free.fr>
739   #
740   # Note: addToConfig etc are defined in scons_util
741   utils.startConfigH()
742
743   # HAVE_IO_H
744   # HAVE_LIMITS_H
745   # HAVE_LOCALE_H
746   # HAVE_LOCALE
747   # HAVE_PROCESS_H
748   # HAVE_STDLIB_H
749   # HAVE_SYS_STAT_H
750   # HAVE_SYS_TIME_H
751   # HAVE_SYS_TYPES_H
752   # HAVE_SYS_UTIME_H
753   # HAVE_UNISTD_H
754   # HAVE_UTIME_H
755   # HAVE_STRINGS_H
756   # HAVE_DIRECT_H
757   # HAVE_ISTREAM
758   # HAVE_OSTREAM
759   # HAVE_IOS
760
761   # for libintl % grep HAVE * | grep _H | cut -d: -f2 | sort -u
762   
763   # 
764   # HAVE_INTTYPES_H
765   # HAVE_STDINT_H
766   # HAVE_ALLOCA_H
767   # HAVE_STDLIB_H
768   # HAVE_STRING_H
769   # HAVE_STDDEF_H
770   # HAVE_LIMITS_H
771   # HAVE_ARGZ_H
772   # HAVE_UNISTD_H
773   # HAVE_SYS_PARAM_H
774
775   # Check header files
776   headers = [
777     ('io.h', 'HAVE_IO_H', 'c'),
778     ('limits.h', 'HAVE_LIMITS_H', 'c'),
779     ('locale.h', 'HAVE_LOCALE_H', 'c'),
780     ('locale', 'HAVE_LOCALE', 'cxx'),
781     ('process.h', 'HAVE_PROCESS_H', 'c'),
782     ('stdlib.h', 'HAVE_STDLIB_H', 'c'),
783     ('sys/stat.h', 'HAVE_SYS_STAT_H', 'c'),
784     ('sys/time.h', 'HAVE_SYS_TIME_H', 'c'),
785     ('sys/types.h', 'HAVE_SYS_TYPES_H', 'c'),
786     ('sys/utime.h', 'HAVE_SYS_UTIME_H', 'c'),
787     ('sys/socket.h', 'HAVE_SYS_SOCKET_H', 'c'),
788     ('unistd.h', 'HAVE_UNISTD_H', 'c'),
789     ('inttypes.h', 'HAVE_INTTYPES_H', 'c'),
790     ('utime.h', 'HAVE_UTIME_H', 'c'),
791     ('string.h', 'HAVE_STRING_H', 'c'),
792     ('strings.h', 'HAVE_STRINGS_H', 'c'),
793     ('direct.h', 'HAVE_DIRECT_H', 'c'),
794     ('istream', 'HAVE_ISTREAM', 'cxx'),
795     ('ostream', 'HAVE_OSTREAM', 'cxx'),
796     ('ios', 'HAVE_IOS', 'cxx'),
797     ('argz.h', 'HAVE_ARGZ_H', 'c'),
798     ('limits.h', 'HAVE_LIMITS_H', 'c'),
799     ('alloca.h', 'HAVE_ALLOCA_H', 'c'),
800     ('stddef.h', 'HAVE_STDDEF_H', 'c'),
801     ('stdint.h', 'HAVE_STDINT_H', 'c'),
802     ('sys/param.h', 'HAVE_SYS_PARAM_H', 'c')
803   ]
804
805   for header in headers:
806     description = "Define to 1 if you have the <%s> header file." % header[0]
807     if (header[2] == 'c' and conf.CheckCHeader(header[0])) or \
808       (header[2] == 'cxx' and conf.CheckCXXHeader(header[0])):
809       utils.addToConfig('#define %s 1' % header[1], desc = description)
810     else:
811       utils.addToConfig('/* #undef %s */' % header[1], desc = description)
812
813   # HAVE_OPEN
814   # HAVE_CLOSE
815   # HAVE_POPEN
816   # HAVE_PCLOSE
817   # HAVE__OPEN
818   # HAVE__CLOSE
819   # HAVE__POPEN
820   # HAVE__PCLOSE
821   # HAVE_GETPID
822   # HAVE__GETPID
823   # HAVE_MKDIR
824   # HAVE__MKDIR
825   # HAVE_PUTENV
826   # HAVE_MKTEMP
827   # HAVE_MKSTEMP
828   # HAVE_STRERROR
829   # HAVE_STD_COUNT
830   # HAVE_GETCWD
831   # HAVE_STRCPY
832   # HAVE_STRCASECMP 
833   # HAVE_STRDUP
834   # HAVE_STRTOUL
835   # HAVE_WCSLEN
836   # HAVE_MMAP ?
837   # HAVE_ALLOCA
838   # HAVE___FSETLOCKING
839   # HAVE_MEMPCPY
840   # HAVE_STRCASECMP
841   # HAVE___ARGZ_COUNT
842   # HAVE___ARGZ_NEXT
843   # HAVE___ARGZ_STRINGIFY
844   # HAVE___FSETLOCKING
845   # HAVE_GETCWD 
846   # HAVE_STRTOUL  
847   # HAVE_STRCASECMP
848   # HAVE_STRDUP
849   # HAVE_TSEARCH 
850
851   # Check functions
852   functions = [
853     ('open', 'HAVE_OPEN', None),
854     ('close', 'HAVE_CLOSE', None),
855     ('popen', 'HAVE_POPEN', None),
856     ('pclose', 'HAVE_PCLOSE', None),
857     ('_open', 'HAVE__OPEN', None),
858     ('_close', 'HAVE__CLOSE', None),
859     ('_popen', 'HAVE__POPEN', None),
860     ('_pclose', 'HAVE__PCLOSE', None),
861     ('getpid', 'HAVE_GETPID', None),
862     ('_getpid', 'HAVE__GETPID', None),
863     ('mkdir', 'HAVE_MKDIR', None),
864     ('_mkdir', 'HAVE__MKDIR', None),
865     ('putenv', 'HAVE_PUTENV', None),
866     ('mktemp', 'HAVE_MKTEMP', None),
867     ('mkstemp', 'HAVE_MKSTEMP', None),
868     ('strerror', 'HAVE_STRERROR', None),
869     ('count', 'HAVE_STD_COUNT', '''
870 #include <algorithm>
871 int count()
872 {
873   char a[] = "hello";
874   return std::count(a, a+5, 'l');
875 }
876 '''),
877     ('getcwd', 'HAVE_GETCWD', None),
878     ('stpcpy', 'HAVE_STPCPY', None),
879     ('strcasecmp', 'HAVE_STRCASECMP', None),
880     ('strdup', 'HAVE_STRDUP', None),
881     ('strtoul', 'HAVE_STRTOUL', None),
882     ('alloca', 'HAVE_ALLOCA', None),
883     ('__fsetlocking', 'HAVE___FSETLOCKING', None),
884     ('mempcpy', 'HAVE_MEMPCPY', None),
885     ('__argz_count', 'HAVE___ARGZ_COUNT', None),
886     ('__argz_next', 'HAVE___ARGZ_NEXT', None),
887     ('__argz_stringify', 'HAVE___ARGZ_STRINGIFY', None),
888     ('setlocale', 'HAVE_SETLOCALE', None),
889     ('tsearch', 'HAVE_TSEARCH', None),
890     ('getegid', 'HAVE_GETEGID', None),
891     ('getgid', 'HAVE_GETGID', None),
892     ('getuid', 'HAVE_GETUID', None),
893     ('wcslen', 'HAVE_WCSLEN', None)
894   ]
895
896   for func in functions:
897     description = "Define to 1 if you have the `%s' function." % func[0]
898     if conf.CheckFunc(func[0], header=func[2]):
899       utils.addToConfig('#define %s 1' % func[1], desc = description)
900     else:
901       utils.addToConfig('/* #undef %s */' % func[1], desc = description)
902
903
904   # HAVE_ASPRINTF
905   # HAVE_WPRINTF
906   # HAVE_SNPRINTF
907   # HAVE_POSIX_PRINTF
908   # HAVE_FCNTL
909
910   env_functions = [
911     ('asprintf', 'HAVE_ASPRINTF'),
912     ('wprintf', 'HAVE_WPRINTF'),
913     ('snprintf', 'HAVE_SNPRINTF'),
914     ('printf', 'HAVE_POSIX_PRINTF'),
915     ('fcntl', 'HAVE_FCNTL')
916   ]
917
918   for func in env_functions:
919     description = "Define to 1 if you have the `%s' function." % func[0]
920     if conf.CheckFunc(func[0]):
921       utils.addToConfig('#define %s 1' % func[1], desc = description)
922       env[func[1]] = 1
923     else:
924       utils.addToConfig('/* #undef %s */' % func[1], desc = description)
925       env[func[1]] = 0
926
927   # HAVE_INTMAX_T
928   # HAVE_DECL_ISTREAMBUF_ITERATOR
929   description = "Define to 1 if you have the `intmax_t' type."
930   if conf.CheckType('intmax_t', includes='#include <stdint.h>') or \
931     conf.CheckType('intmax_t', includes='#include <inttypes.h>'):
932     utils.addToConfig('#define HAVE_INTMAX_T 1', desc = description)
933   else:
934     utils.addToConfig('/* #undef HAVE_INTMAX_T */',desc = description)
935
936   # HAVE_INTMAX_T
937   # HAVE_LONG_DOUBLE
938   # HAVE_LONG_LONG
939   # HAVE_WCHAR_T
940   # HAVE_WINT_T
941   # HAVE_INTTYPES_H_WITH_UINTMAX 
942   # HAVE_STDINT_H_WITH_UINTMAX
943
944   types = [
945     ('intmax_t', 'HAVE_INTMAX_T', None),
946     ('long double', 'HAVE_LONG_DOUBLE', None),
947     ('long long', 'HAVE_LONG_LONG', None),
948     ('wchar_t', 'HAVE_WCHAR_T', None),
949     ('wint_t', 'HAVE_WINT_T', None),
950     ('uintmax_t', 'HAVE_INTTYPES_H_WITH_UINTMAX', '#include <inttypes.h>'),
951     ('uintmax_t', 'HAVE_STDINT_H_WITH_UINTMAX', '#include <stdint.h>'),
952     ('std::istreambuf_iterator<std::istream>', 'HAVE_DECL_ISTREAMBUF_ITERATOR',
953       '#include <streambuf>\n#include <istream>')
954   ]
955   for t in types: 
956     description = "Define to 1 if you have the `%s' type." % t[0]
957     if conf.CheckType(t[0], includes=t[2]):
958       utils.addToConfig('#define %s 1' % t[1], desc = description)
959     else:
960       utils.addToConfig('/* #undef %s */' % t[1],  desc = description)
961
962   # windows/msvc sys/types.h does not have pid_t
963   # FIXME: #include <windows.h> is the right way?
964   if not conf.CheckType('pid_t', includes='#include <sys/types.h>'):
965     utils.addToConfig('#define pid_t int', desc = 'Define is sys/types.h does not have pid_t')
966
967   # determine the use of std::tolower or tolower
968   description = 'Define if your C++ compiler puts C library functions in the global namespace'
969   if conf.CheckCXXGlobalCstd():
970     utils.addToConfig('#define CXX_GLOBAL_CSTD 1', desc = description)
971   else:
972     utils.addToConfig('/* #undef CXX_GLOBAL_CSTD */', desc = description)
973
974   # HAVE_LIBGDI32
975   # HAVE_ICONV
976   # HAVE_LIBC
977   # HAVE_LIBAIKSAURUS
978   libs = [
979     ('gdi32', 'HAVE_LIBGDI32'),
980     ('iconv', 'HAVE_ICONV'),
981     ('c', 'HAVE_LIBC'),
982     ('Aiksaurus', 'HAVE_LIBAIKSAURUS'),
983   ]
984   for lib in libs:
985     description = "Define to 1 if you have the `%s' library (-l%s)." % (lib[0], lib[0])
986     if conf.CheckLib(lib[0]):
987       utils.addToConfig('#define %s 1' % lib[1], desc = description)
988       env[lib[1]] = True
989     else:
990       utils.addToConfig('/* #undef %s */' % lib[1], desc = description)
991       env[lib[1]] = False
992
993   # HAVE_LC_MESSAGES
994   description = 'Define if your <locale.h> file defines LC_MESSAGES.'
995   if conf.CheckLC_MESSAGES():
996     utils.addToConfig('#define HAVE_LC_MESSAGES 1', desc = description)
997   else:
998     utils.addToConfig('/* #undef HAVE_LC_MESSAGES */', desc = description)
999
1000   # ICONV_CONST
1001   description = 'Define as const if the declaration of iconv() needs const.'
1002   if conf.CheckIconvConst():
1003     utils.addToConfig('#define ICONV_CONST', desc = description)
1004   else:
1005     utils.addToConfig('/* #undef ICONV_CONST */', desc = description)
1006
1007   # PACKAGE
1008   # PACKAGE_VERSION
1009   # PACKAGE_BUGREPORT
1010   # PACKAGE_NAME
1011   # PACKAGE_STRING
1012   # DEVEL_VERSION
1013   utils.addToConfig('#define PACKAGE "%s%s"' % (PACKAGE, env['PROGRAM_SUFFIX']),
1014     desc = "Name of package")
1015
1016   utils.addToConfig('#define PACKAGE_BUGREPORT "%s"' % PACKAGE_BUGREPORT,
1017     desc = 'Define to the address where bug reports for this package should be sent.')
1018
1019   utils.addToConfig('#define PACKAGE_NAME "%s"' % PACKAGE_NAME,
1020       desc = 'Define to the full name of this package.')
1021
1022   utils.addToConfig('#define PACKAGE_STRING "%s"' % PACKAGE_STRING,
1023       desc = "Define to the full name and version of this package.")
1024
1025   utils.addToConfig('#define PACKAGE_TARNAME "%s"' % PACKAGE_TARNAME,
1026       desc = "Define to the one symbol short name of this package.")
1027
1028   utils.addToConfig('#define PACKAGE_VERSION "%s"' % PACKAGE_VERSION,
1029     desc = "Define to the version of this package.")
1030
1031   if DEVEL_VERSION:
1032     utils.addToConfig('#define DEVEL_VERSION 1')
1033
1034   # ENABLE_ASSERTIONS
1035   # ENABLE_NLS
1036   # WITH_WARNINGS
1037   # _GLIBCXX_CONCEPT_CHECKS
1038
1039   # items are (ENV, ARGUMENTS)
1040   values = [
1041     ('ENABLE_ASSERTIONS', 'assertions', 'Define if you want assertions to be enabled in the code'),
1042     ('ENABLE_NLS', 'nls', "Define to 1 if translation of program messages to the user's native anguage is requested."),
1043     ('WITH_WARNINGS', 'warnings', 'Define this if you want to see the warning directives put here and there by the developpers to get attention'),
1044     ('_GLIBCXX_CONCEPT_CHECKS', 'concept_checks', 'libstdc++ concept checking'),
1045   ]
1046
1047   for val in values:
1048     if (env.has_key(val[0]) and env[val[0]]) or \
1049        (env.has_key(val[1]) and env[val[1]]):
1050       utils.addToConfig('#define %s 1' % val[0], desc = val[2])
1051     else:
1052       utils.addToConfig('/* #undef %s */' % val[0], desc = val[2])
1053
1054   # disable automatic linking of boost libraries.
1055   # This is an interesting feature that is supposed to be useful under
1056   # windows but since I can not find a way to use it on all platforms, 
1057   # I disable it for now.
1058   utils.addToConfig('#define BOOST_ALL_NO_LIB 1')
1059
1060   # AIKSAURUS_H_LOCATION
1061   if (conf.CheckCXXHeader("Aiksaurus.h")):
1062     utils.addToConfig("#define AIKSAURUS_H_LOCATION <Aiksaurus.h>")
1063   elif (conf.CheckCXXHeader("Aiksaurus/Aiksaurus.h")):
1064     utils.addToConfig("#define AIKSAURUS_H_LOCATION <Aiksaurus/Aiksaurus.h>")
1065   else:
1066     utils.addToConfig("#define AIKSAURUS_H_LOCATION")
1067
1068   # USE_ASPELL
1069   # USE_PSPELL
1070   # USE_ISPELL
1071
1072   # determine headers to use
1073   spell_engine = ARGUMENTS.get('spell', 'auto')
1074   spell_detected = False
1075   if spell_engine in ['auto', 'aspell'] and \
1076     conf.CheckLib('aspell'):
1077     utils.addToConfig('#define USE_ASPELL 1', desc = 'Define as 1 to use the aspell library')
1078     env['USE_ASPELL'] = True
1079     env['USE_PSPELL'] = False
1080     env['USE_ISPELL'] = False
1081     spell_detected = True
1082   elif spell_engine in ['auto', 'pspell'] and \
1083     conf.CheckLib('pspell'):
1084     utils.addToConfig('#define USE_PSPELL 1', desc = 'Define as 1 to use the pspell library')
1085     env['USE_ASPELL'] = False
1086     env['USE_PSPELL'] = True
1087     env['USE_ISPELL'] = False
1088     spell_detected = True
1089   elif spell_engine in ['auto', 'ispell'] and \
1090     conf.CheckLib('ispell'):
1091     utils.addToConfig('#define USE_ISPELL 1', desc = 'Define as 1 to use the ispell library')
1092     env['USE_ASPELL'] = False
1093     env['USE_PSPELL'] = False
1094     env['USE_ISPELL'] = True
1095     spell_detected = True
1096
1097   if not spell_detected:
1098     env['USE_ASPELL'] = False
1099     env['USE_PSPELL'] = False
1100     env['USE_ISPELL'] = False
1101     # FIXME: can lyx work without an spell engine
1102     if spell_engine == 'auto':
1103       print "Warning: Can not locate any spell checker"
1104     else:
1105       print "Warning: Can not locate specified spell checker:", spell_engine
1106
1107   # USE_POSIX_PACKAGING
1108   # USE_MACOSX_PACKAGING
1109   # USE_WINDOWS_PACKAGING
1110   if packaging_method == 'windows':
1111     utils.addToConfig('#define USE_WINDOWS_PACKAGING 1')
1112   elif packaging_method == 'posix':
1113     utils.addToConfig('#define USE_POSIX_PACKAGING 1')
1114   elif packaging_method == 'mac':
1115     utils.addToConfig('#define USE_MACOSX_PACKAGING 1')
1116
1117   # BOOST_POSIX
1118   if boost_posix:
1119     utils.addToConfig('#define BOOST_POSIX 1')
1120   else:
1121     utils.addToConfig('/* #undef BOOST_POSIX */')
1122
1123   # MKDIR_TAKES_ONE_ARG
1124   description = 'Define if mkdir takes only one argument.'
1125   if conf.CheckMkdirOneArg():
1126     utils.addToConfig('#define MKDIR_TAKES_ONE_ARG 1', desc = description)
1127   else:
1128     utils.addToConfig('/* #undef MKDIR_TAKES_ONE_ARG */', desc = description)
1129
1130   # SELECT_TYPE_ARG1
1131   # SELECT_TYPE_ARG234
1132   # SELECT_TYPE_ARG5
1133   (arg1, arg234, arg5) = conf.CheckSelectArgType()
1134   utils.addToConfig('#define SELECT_TYPE_ARG1 %s' % arg1,
1135     desc = "Define to the type of arg 1 for `select'.")
1136   utils.addToConfig('#define SELECT_TYPE_ARG234 %s' % arg234,
1137     desc = "Define to the type of arg 2, 3, 4 for `select'.")
1138   utils.addToConfig('#define SELECT_TYPE_ARG5 %s' % arg5,
1139     desc = "Define to the type of arg 5 for `select'.")
1140
1141   # mkstemp
1142   # USE_BOOST_FORMAT
1143   # WANT_GETFILEATTRIBUTESEX_WRAPPER
1144   utils.endConfigH(TOP_SRC_DIR)
1145
1146   for key in ['USE_ASPELL', 'USE_PSPELL', 'USE_ISPELL', 'HAVE_ASPRINTF', \
1147     'HAVE_WPRINTF', 'HAVE_SNPRINTF', 'HAVE_POSIX_PRINTF', 'HAVE_FCNTL', \
1148     'HAVE_ICONV', 'HAVE_LIBGDI32', 'HAVE_LIBC', 'HAVE_LIBAIKSAURUS']:
1149     env_cache[key] = env[key]
1150 else:
1151   #
1152   # this comes as a big surprise, without this line 
1153   # (doing nothing obvious), adding fast_start=yes
1154   # to a build with fast_start=no will result in a rebuild
1155   # Note that the exact header file to check does not matter
1156   conf.CheckCHeader('io.h')
1157   # only a few variables need to be rescanned
1158   for key in ['USE_ASPELL', 'USE_PSPELL', 'USE_ISPELL', 'HAVE_ASPRINTF', \
1159     'HAVE_WPRINTF', 'HAVE_SNPRINTF', 'HAVE_POSIX_PRINTF', 'HAVE_FCNTL', \
1160     'HAVE_ICONV', 'HAVE_LIBGDI32', 'HAVE_LIBC', 'HAVE_LIBAIKSAURUS']:
1161     env[key] = env_cache[key]
1162
1163
1164 #
1165 # Finish auto-configuration
1166 env = conf.Finish()
1167
1168 #----------------------------------------------------------
1169 # Now set up our build process accordingly
1170 #----------------------------------------------------------
1171
1172 #
1173 # QT_LIB
1174 #
1175 # NOTE: Tool('qt') or Tool('qt4') will be loaded later
1176 # in their respective directory and specialized env.
1177 try:
1178   if frontend == 'qt3':
1179     # note: env.Tool('qt') my set QT_LIB to qt
1180     env['QT_LIB'] = 'qt-mt'
1181     env['FRONTEND_LIBS'] = ['qt-mt']
1182     if platform_name == 'cygwin' and use_X11:
1183       env.AppendUnique(LIBPATH = ['/usr/X11R6/lib'])
1184   elif frontend == 'qt4':
1185     if platform_name == "win32":
1186       env['QT_LIB'] = ['QtCore4', 'QtGui4']
1187     else:
1188       env['QT_LIB'] = ['QtCore', 'QtGui']
1189     env['FRONTEND_LIBS'] = env['QT_LIB']
1190 except:
1191   print "Can not locate qt tools"
1192   print "What I get is "
1193   print "  QTDIR: ", env['QTDIR']
1194
1195
1196 if platform_name in ['win32', 'cygwin']:
1197   # the final link step needs stdc++ to succeed under mingw
1198   # FIXME: shouldn't g++ automatically link to stdc++?
1199   if use_vc:
1200     env['SYSTEM_LIBS'] = ['shlwapi', 'shell32', 'advapi32', 'zdll']
1201   else:
1202     env['SYSTEM_LIBS'] = ['shlwapi', 'stdc++', 'z']
1203 elif platform_name == 'cygwin' and use_X11:
1204   env['SYSTEM_LIBS'] = ['GL',  'Xmu', 'Xi', 'Xrender', 'Xrandr', 'Xcursor',
1205     'Xft', 'freetype', 'fontconfig', 'Xext', 'X11', 'SM', 'ICE', 'resolv',
1206     'pthread', 'z']
1207 else:
1208   env['SYSTEM_LIBS'] = ['z']
1209
1210 libs = [
1211   ('HAVE_ICONV', 'iconv'),
1212   ('HAVE_LIBGDI32', 'gdi32'),
1213   ('HAVE_LIBAIKSAURUS', 'Aiksaurus'),
1214   ('USE_ASPELL', 'aspell'),
1215   ('USE_ISPELL', 'ispell'),
1216   ('USE_PSPELL', 'pspell'),
1217 ]
1218
1219 for lib in libs:
1220   if env[lib[0]]:
1221     env['SYSTEM_LIBS'].append(lib[1])
1222
1223 #
1224 # Build parameters CPPPATH etc
1225 #
1226 # boost is always in, src is needed for config.h
1227
1228 # QT_INC_PATH is not needed for *every* source file
1229 env['CPPPATH'].remove(env['QT_INC_PATH'])
1230 env['CPPPATH'] += ['$TOP_SRC_DIR/boost', '$TOP_SRC_DIR/src']
1231
1232 # add appropriate compiling options (-DNDEBUG etc)
1233 # for debug/release mode
1234 # /Zi: debug info
1235 if ARGUMENTS.get('mode', default_build_mode) == 'debug':
1236   if use_vc:
1237     env.AppendUnique(CCFLAGS = ['/Zi'])
1238     env.AppendUnique(LINKFLAGS = ['/debug', '/map'])
1239   else:
1240     env.AppendUnique(CCFLAGS = ['-Wall', '-g'])
1241 else:
1242   if use_vc:
1243     env.AppendUnique(CCFLAGS = ['/O2'])
1244   else:
1245     env.AppendUnique(CCFLAGS = ['-Wall', '-O2'])
1246
1247 #
1248 # Customized builders
1249 #
1250 # install customized builders
1251 env['BUILDERS']['substFile'] = Builder(action = utils.env_subst)
1252
1253 #
1254 # A Link script for cygwin see
1255 # http://www.cygwin.com/ml/cygwin/2004-09/msg01101.html
1256 # http://www.cygwin.com/ml/cygwin-apps/2004-09/msg00309.html
1257 # for details
1258 #
1259 if platform_name == 'cygwin':
1260   ld_script_path = '/usr/lib/qt3/mkspecs/cygwin-g++'
1261   ld_script = utils.installCygwinLDScript(ld_script_path)
1262   env.AppendUnique(LINKFLAGS = ['-Wl,--enable-runtime-pseudo-reloc',
1263     '-Wl,--script,%s' % ld_script, '-Wl,-s'])
1264
1265 #
1266 # Report results
1267 #
1268 # src/support/package.C.in needs the following to replace
1269 #  LYX_ABS_INSTALLED_DATADIR (e.g. /usr/local/lyx/share/lyx)
1270 env['LYX_DIR'] = Dir(env['SHARE_DIR']).abspath
1271 #  LYX_ABS_INSTALLED_LOCALEDIR
1272 env['LOCALEDIR'] = Dir(env['LOCALE_DIR']).abspath
1273 # during variable substitution, absolute path is needed.
1274 env['TOP_SRCDIR'] = Dir(env['TOP_SRC_DIR']).abspath
1275 # needed by src/version.C.in => src/version.C
1276 env['PACKAGE_VERSION'] = PACKAGE_VERSION
1277 # fill in the version info
1278 env['VERSION_INFO'] = '''Configuration
1279   Host type:                      %s
1280   Special build flags:            %s
1281   C   Compiler:                   %s
1282   C   Compiler flags:             %s %s
1283   C++ Compiler:                   %s
1284   C++ Compiler LyX flags:         %s
1285   C++ Compiler flags:             %s %s
1286   Linker flags:                   %s
1287   Linker user flags:              %s
1288 Build info:
1289   Builing directory:              %s
1290   Local library directory:        %s
1291   Libraries pathes:               %s
1292   Boost libraries:                %s
1293   Frontend libraries:             %s
1294   System libraries:               %s
1295   include search path:            %s
1296 Frontend:
1297   Frontend:                       %s
1298   Packaging:                      %s
1299   LyX dir:                        %s
1300   LyX binary dir:                 %s
1301   LyX files dir:                  %s
1302 ''' % (platform_name,
1303   env.subst('$CCFLAGS'), env.subst('$CC'),
1304   env.subst('$CPPFLAGS'), env.subst('$CFLAGS'),
1305   env.subst('$CXX'), env.subst('$CXXFLAGS'),
1306   env.subst('$CPPFLAGS'), env.subst('$CXXFLAGS'),
1307   env.subst('$LINKFLAGS'), env.subst('$LINKFLAGS'),
1308   env.subst('$BUILDDIR'), env.subst('$LOCALLIBPATH'),
1309   str(env['LIBPATH']), str(env['BOOST_LIBRARIES']),
1310   str(env['FRONTEND_LIBS']), str(env['SYSTEM_LIBS']), str(env['CPPPATH']),
1311   env['frontend'], packaging_method,
1312   env['PREFIX'], env['BIN_DEST_DIR'], env['SHARE_DIR'])
1313
1314 if env['frontend'] in ['qt3', 'qt4']:
1315   env['VERSION_INFO'] += '''  include dir:                    %s
1316   library dir:                    %s
1317   X11:                            %s
1318 ''' % (env.subst('$QT_INC_PATH'), env.subst('$QT_LIB_PATH'), use_X11)
1319
1320 if not fast_start:
1321   print env['VERSION_INFO']
1322
1323 #
1324 # Mingw command line may be too short for our link usage,
1325 # Here we use a trick from scons wiki
1326 # http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/LongCmdLinesOnWin32
1327 #
1328 # I also would like to add logging (commands only) capacity to the
1329 # spawn system.
1330 logfile = env.get('logfile', default_log_file)
1331 if logfile != '' or platform_name == 'win32':
1332   import time
1333   utils.setLoggedSpawn(env, logfile, longarg = (platform_name == 'win32'),
1334     info = '''# This is a log of commands used by scons to build lyx
1335 # Time: %s
1336 # Command: %s
1337 # Info: %s
1338 ''' % (time.asctime(), ' '.join(sys.argv),
1339   env['VERSION_INFO'].replace('\n','\n# ')) )
1340
1341
1342 #
1343 # Cleanup stuff
1344 #
1345 # -h will print out help info
1346 Help(opts.GenerateHelpText(env))
1347 # save environment settings (for fast_start option)
1348 cache_file = open(env_cache_file, 'w')
1349 cPickle.dump(env_cache, cache_file)
1350 cache_file.close()
1351
1352 #----------------------------------------------------------
1353 # Start building
1354 #----------------------------------------------------------
1355 Export('env')
1356
1357 # this has been the source of problems on some platforms...
1358 # I find that I need to supply it with full path name
1359 env.SConsignFile(os.path.join(Dir(env['BUILDDIR']).abspath, '.sconsign'))
1360 # this usage needs further investigation.
1361 #env.CacheDir('%s/Cache/%s' % (env['BUILDDIR'], frontend))
1362
1363 env['BUILD_TARGETS'] = BUILD_TARGETS
1364 if env.has_key('rebuild'):
1365   env['REBUILD_TARGETS'] = env['rebuild'].split(',')
1366 else:
1367   env['REBUILD_TARGETS'] = None
1368
1369 print "Building all targets recursively"
1370
1371 env.SConscript('$SCONS_DIR/SConscript', duplicate = 0)
1372
1373