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