]> git.lyx.org Git - lyx.git/blob - development/scons/SConstruct
Scons: fix typos and minor bugs
[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 aiksaurus
290   PathOption('aiksaurus_path', 'Path to aiksaurus 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('aiksaurus_path') and env['aiksaurus_path']:
527   env.AppendUnique(LIBPATH = [env['aiksaurus_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   boost_libpath = None
658   if boost_opt in ['auto', 'system']:
659     paths = env['LIBPATH'] + ['/usr/lib', '/usr/local/lib']
660     sig = conf.CheckBoostLibraries('boost_signals', paths)
661     reg = conf.CheckBoostLibraries('boost_regex', paths)
662     fil = conf.CheckBoostLibraries('boost_filesystem', paths)
663     ios = conf.CheckBoostLibraries('boost_iostreams', paths)
664     # if any of them is not found
665     if ('' in [sig[0], reg[0], fil[0], ios[0]]):
666       if boost_opt == 'system':
667         print "Can not find system boost libraries"
668         print "Please supply a path through extra_lib_path and try again."
669         print "Or use boost=included to use included boost libraries."
670         Exit(2)
671     else:
672       env['BOOST_LIBRARIES'] = [sig[1], reg[1], fil[1], ios[1]]
673       # assume all boost libraries are in the same path...
674       boost_libpath = sig[0]
675       env.AppendUnique(LIBPATH = [sig[0]])
676       env['INCLUDED_BOOST'] = False
677       succ = True
678   # now, auto and succ = false, or boost=included
679   if not succ:
680     # we do not need to set LIBPATH now.
681     env['BOOST_LIBRARIES'] = ['included_boost_signals', 'included_boost_regex',
682       'included_boost_filesystem', 'included_boost_iostreams']
683     env['INCLUDED_BOOST'] = True
684   env_cache['BOOST_LIBRARIES'] = env['BOOST_LIBRARIES']
685   env_cache['INCLUDED_BOOST'] = env['INCLUDED_BOOST']
686   env_cache['BOOST_LIBPATH'] = boost_libpath
687 else:
688   env['BOOST_LIBRARIES'] = env_cache['BOOST_LIBRARIES']
689   if env_cache['BOOST_LIBPATH'] is not None:
690     env.AppendUnique(LIBPATH = [env_cache['BOOST_LIBPATH']])
691   env['INCLUDED_BOOST'] = env_cache['INCLUDED_BOOST']
692
693
694 env['ENABLE_NLS'] = not env.has_key('nls') or env['nls']
695
696 if not fast_start:
697   if not env['ENABLE_NLS']:
698     env['INTL_LIBS'] = []
699     env['INCLUDED_GETTEXT'] = False
700   else:
701     # check gettext libraries
702     gettext_opt = ARGUMENTS.get('gettext', default_gettext_opt)
703     # check for system gettext
704     succ = False
705     if gettext_opt in ['auto', 'system']:
706       if conf.CheckLib('intl'):
707         env['INCLUDED_GETTEXT'] = False
708         env['INTL_LIBS'] = ['intl']
709         succ = True
710       else: # no found
711         if gettext_opt == 'system':
712           print "Can not find system gettext library"
713           print "Please supply a path through extra_lib_path and try again."
714           print "Or use gettext=included to use included gettext libraries."
715           Exit(2)
716     # now, auto and succ = false, or gettext=included
717     if not succ:
718       # we do not need to set LIBPATH now.
719       env['INCLUDED_GETTEXT'] = True
720       env['INTL_LIBS'] = ['included_intl']
721   env_cache['INCLUDED_GETTEXT'] = env['INCLUDED_GETTEXT']
722   env_cache['INTL_LIBS'] = env['INTL_LIBS']
723 else:
724   env['INTL_LIBS'] = env_cache['INTL_LIBS']
725   env['INCLUDED_GETTEXT'] = env_cache['INCLUDED_GETTEXT']
726
727 #
728 # check for msgfmt command
729 if not fast_start:
730   env['MSGFMT'] = conf.CheckCommand('msgfmt')
731   env_cache['MSGFMT'] = env['MSGFMT']
732 else:
733   env['MSGFMT'] = env_cache['MSGFMT']
734
735
736 #----------------------------------------------------------
737 # Generating config.h
738 #----------------------------------------------------------
739 if not fast_start:
740   print "Generating ", utils.config_h, "..."
741
742   # I do not handle all macros in src/config.h.in, rather I am following a list
743   # of *used-by-lyx* macros compiled by Abdelrazak Younes <younes.a@free.fr>
744   #
745   # Note: addToConfig etc are defined in scons_util
746   utils.startConfigH()
747
748   # HAVE_IO_H
749   # HAVE_LIMITS_H
750   # HAVE_LOCALE_H
751   # HAVE_LOCALE
752   # HAVE_PROCESS_H
753   # HAVE_STDLIB_H
754   # HAVE_SYS_STAT_H
755   # HAVE_SYS_TIME_H
756   # HAVE_SYS_TYPES_H
757   # HAVE_SYS_UTIME_H
758   # HAVE_UNISTD_H
759   # HAVE_UTIME_H
760   # HAVE_STRINGS_H
761   # HAVE_DIRECT_H
762   # HAVE_ISTREAM
763   # HAVE_OSTREAM
764   # HAVE_IOS
765
766   # for libintl % grep HAVE * | grep _H | cut -d: -f2 | sort -u
767   
768   # 
769   # HAVE_INTTYPES_H
770   # HAVE_STDINT_H
771   # HAVE_ALLOCA_H
772   # HAVE_STDLIB_H
773   # HAVE_STRING_H
774   # HAVE_STDDEF_H
775   # HAVE_LIMITS_H
776   # HAVE_ARGZ_H
777   # HAVE_UNISTD_H
778   # HAVE_SYS_PARAM_H
779
780   # Check header files
781   headers = [
782     ('io.h', 'HAVE_IO_H', 'c'),
783     ('limits.h', 'HAVE_LIMITS_H', 'c'),
784     ('locale.h', 'HAVE_LOCALE_H', 'c'),
785     ('locale', 'HAVE_LOCALE', 'cxx'),
786     ('process.h', 'HAVE_PROCESS_H', 'c'),
787     ('stdlib.h', 'HAVE_STDLIB_H', 'c'),
788     ('sys/stat.h', 'HAVE_SYS_STAT_H', 'c'),
789     ('sys/time.h', 'HAVE_SYS_TIME_H', 'c'),
790     ('sys/types.h', 'HAVE_SYS_TYPES_H', 'c'),
791     ('sys/utime.h', 'HAVE_SYS_UTIME_H', 'c'),
792     ('sys/socket.h', 'HAVE_SYS_SOCKET_H', 'c'),
793     ('unistd.h', 'HAVE_UNISTD_H', 'c'),
794     ('inttypes.h', 'HAVE_INTTYPES_H', 'c'),
795     ('utime.h', 'HAVE_UTIME_H', 'c'),
796     ('string.h', 'HAVE_STRING_H', 'c'),
797     ('strings.h', 'HAVE_STRINGS_H', 'c'),
798     ('direct.h', 'HAVE_DIRECT_H', 'c'),
799     ('istream', 'HAVE_ISTREAM', 'cxx'),
800     ('ostream', 'HAVE_OSTREAM', 'cxx'),
801     ('ios', 'HAVE_IOS', 'cxx'),
802     ('argz.h', 'HAVE_ARGZ_H', 'c'),
803     ('limits.h', 'HAVE_LIMITS_H', 'c'),
804     ('alloca.h', 'HAVE_ALLOCA_H', 'c'),
805     ('stddef.h', 'HAVE_STDDEF_H', 'c'),
806     ('stdint.h', 'HAVE_STDINT_H', 'c'),
807     ('sys/param.h', 'HAVE_SYS_PARAM_H', 'c')
808   ]
809
810   for header in headers:
811     description = "Define to 1 if you have the <%s> header file." % header[0]
812     if (header[2] == 'c' and conf.CheckCHeader(header[0])) or \
813       (header[2] == 'cxx' and conf.CheckCXXHeader(header[0])):
814       utils.addToConfig('#define %s 1' % header[1], desc = description)
815     else:
816       utils.addToConfig('/* #undef %s */' % header[1], desc = description)
817
818   # HAVE_OPEN
819   # HAVE_CLOSE
820   # HAVE_POPEN
821   # HAVE_PCLOSE
822   # HAVE__OPEN
823   # HAVE__CLOSE
824   # HAVE__POPEN
825   # HAVE__PCLOSE
826   # HAVE_GETPID
827   # HAVE__GETPID
828   # HAVE_MKDIR
829   # HAVE__MKDIR
830   # HAVE_PUTENV
831   # HAVE_MKTEMP
832   # HAVE_MKSTEMP
833   # HAVE_STRERROR
834   # HAVE_STD_COUNT
835   # HAVE_GETCWD
836   # HAVE_STRCPY
837   # HAVE_STRCASECMP 
838   # HAVE_STRDUP
839   # HAVE_STRTOUL
840   # HAVE_WCSLEN
841   # HAVE_MMAP ?
842   # HAVE_ALLOCA
843   # HAVE___FSETLOCKING
844   # HAVE_MEMPCPY
845   # HAVE_STRCASECMP
846   # HAVE___ARGZ_COUNT
847   # HAVE___ARGZ_NEXT
848   # HAVE___ARGZ_STRINGIFY
849   # HAVE___FSETLOCKING
850   # HAVE_GETCWD 
851   # HAVE_STRTOUL  
852   # HAVE_STRCASECMP
853   # HAVE_STRDUP
854   # HAVE_TSEARCH 
855
856   # Check functions
857   functions = [
858     ('open', 'HAVE_OPEN', None),
859     ('close', 'HAVE_CLOSE', None),
860     ('popen', 'HAVE_POPEN', None),
861     ('pclose', 'HAVE_PCLOSE', None),
862     ('_open', 'HAVE__OPEN', None),
863     ('_close', 'HAVE__CLOSE', None),
864     ('_popen', 'HAVE__POPEN', None),
865     ('_pclose', 'HAVE__PCLOSE', None),
866     ('getpid', 'HAVE_GETPID', None),
867     ('_getpid', 'HAVE__GETPID', None),
868     ('mkdir', 'HAVE_MKDIR', None),
869     ('_mkdir', 'HAVE__MKDIR', None),
870     ('putenv', 'HAVE_PUTENV', None),
871     ('mktemp', 'HAVE_MKTEMP', None),
872     ('mkstemp', 'HAVE_MKSTEMP', None),
873     ('strerror', 'HAVE_STRERROR', None),
874     ('count', 'HAVE_STD_COUNT', '''
875 #include <algorithm>
876 int count()
877 {
878   char a[] = "hello";
879   return std::count(a, a+5, 'l');
880 }
881 '''),
882     ('getcwd', 'HAVE_GETCWD', None),
883     ('stpcpy', 'HAVE_STPCPY', None),
884     ('strcasecmp', 'HAVE_STRCASECMP', None),
885     ('strdup', 'HAVE_STRDUP', None),
886     ('strtoul', 'HAVE_STRTOUL', None),
887     ('alloca', 'HAVE_ALLOCA', None),
888     ('__fsetlocking', 'HAVE___FSETLOCKING', None),
889     ('mempcpy', 'HAVE_MEMPCPY', None),
890     ('__argz_count', 'HAVE___ARGZ_COUNT', None),
891     ('__argz_next', 'HAVE___ARGZ_NEXT', None),
892     ('__argz_stringify', 'HAVE___ARGZ_STRINGIFY', None),
893     ('setlocale', 'HAVE_SETLOCALE', None),
894     ('tsearch', 'HAVE_TSEARCH', None),
895     ('getegid', 'HAVE_GETEGID', None),
896     ('getgid', 'HAVE_GETGID', None),
897     ('getuid', 'HAVE_GETUID', None),
898     ('wcslen', 'HAVE_WCSLEN', None)
899   ]
900
901   for func in functions:
902     description = "Define to 1 if you have the `%s' function." % func[0]
903     if conf.CheckFunc(func[0], header=func[2]):
904       utils.addToConfig('#define %s 1' % func[1], desc = description)
905     else:
906       utils.addToConfig('/* #undef %s */' % func[1], desc = description)
907
908
909   # HAVE_ASPRINTF
910   # HAVE_WPRINTF
911   # HAVE_SNPRINTF
912   # HAVE_POSIX_PRINTF
913   # HAVE_FCNTL
914
915   env_functions = [
916     ('asprintf', 'HAVE_ASPRINTF'),
917     ('wprintf', 'HAVE_WPRINTF'),
918     ('snprintf', 'HAVE_SNPRINTF'),
919     ('printf', 'HAVE_POSIX_PRINTF'),
920     ('fcntl', 'HAVE_FCNTL')
921   ]
922
923   for func in env_functions:
924     description = "Define to 1 if you have the `%s' function." % func[0]
925     if conf.CheckFunc(func[0]):
926       utils.addToConfig('#define %s 1' % func[1], desc = description)
927       env[func[1]] = 1
928     else:
929       utils.addToConfig('/* #undef %s */' % func[1], desc = description)
930       env[func[1]] = 0
931
932   # HAVE_INTMAX_T
933   # HAVE_DECL_ISTREAMBUF_ITERATOR
934   description = "Define to 1 if you have the `intmax_t' type."
935   if conf.CheckType('intmax_t', includes='#include <stdint.h>') or \
936     conf.CheckType('intmax_t', includes='#include <inttypes.h>'):
937     utils.addToConfig('#define HAVE_INTMAX_T 1', desc = description)
938   else:
939     utils.addToConfig('/* #undef HAVE_INTMAX_T */',desc = description)
940
941   # HAVE_INTMAX_T
942   # HAVE_LONG_DOUBLE
943   # HAVE_LONG_LONG
944   # HAVE_WCHAR_T
945   # HAVE_WINT_T
946   # HAVE_INTTYPES_H_WITH_UINTMAX 
947   # HAVE_STDINT_H_WITH_UINTMAX
948
949   types = [
950     ('intmax_t', 'HAVE_INTMAX_T', None),
951     ('long double', 'HAVE_LONG_DOUBLE', None),
952     ('long long', 'HAVE_LONG_LONG', None),
953     ('wchar_t', 'HAVE_WCHAR_T', None),
954     ('wint_t', 'HAVE_WINT_T', None),
955     ('uintmax_t', 'HAVE_INTTYPES_H_WITH_UINTMAX', '#include <inttypes.h>'),
956     ('uintmax_t', 'HAVE_STDINT_H_WITH_UINTMAX', '#include <stdint.h>'),
957     ('std::istreambuf_iterator<std::istream>', 'HAVE_DECL_ISTREAMBUF_ITERATOR',
958       '#include <streambuf>\n#include <istream>')
959   ]
960   for t in types: 
961     description = "Define to 1 if you have the `%s' type." % t[0]
962     if conf.CheckType(t[0], includes=t[2]):
963       utils.addToConfig('#define %s 1' % t[1], desc = description)
964     else:
965       utils.addToConfig('/* #undef %s */' % t[1],  desc = description)
966
967   # windows/msvc sys/types.h does not have pid_t
968   # FIXME: #include <windows.h> is the right way?
969   if not conf.CheckType('pid_t', includes='#include <sys/types.h>'):
970     utils.addToConfig('#define pid_t int', desc = 'Define is sys/types.h does not have pid_t')
971
972   # determine the use of std::tolower or tolower
973   description = 'Define if your C++ compiler puts C library functions in the global namespace'
974   if conf.CheckCXXGlobalCstd():
975     utils.addToConfig('#define CXX_GLOBAL_CSTD 1', desc = description)
976   else:
977     utils.addToConfig('/* #undef CXX_GLOBAL_CSTD */', desc = description)
978
979   # HAVE_LIBGDI32
980   # HAVE_ICONV
981   # HAVE_LIBC
982   # HAVE_LIBAIKSAURUS
983   libs = [
984     ('gdi32', 'HAVE_LIBGDI32'),
985     ('iconv', 'HAVE_ICONV'),
986     ('c', 'HAVE_LIBC'),
987     ('Aiksaurus', 'HAVE_LIBAIKSAURUS'),
988   ]
989   for lib in libs:
990     description = "Define to 1 if you have the `%s' library (-l%s)." % (lib[0], lib[0])
991     if conf.CheckLib(lib[0]):
992       utils.addToConfig('#define %s 1' % lib[1], desc = description)
993       env[lib[1]] = True
994     else:
995       utils.addToConfig('/* #undef %s */' % lib[1], desc = description)
996       env[lib[1]] = False
997
998   # HAVE_LC_MESSAGES
999   description = 'Define if your <locale.h> file defines LC_MESSAGES.'
1000   if conf.CheckLC_MESSAGES():
1001     utils.addToConfig('#define HAVE_LC_MESSAGES 1', desc = description)
1002   else:
1003     utils.addToConfig('/* #undef HAVE_LC_MESSAGES */', desc = description)
1004
1005   # ICONV_CONST
1006   description = 'Define as const if the declaration of iconv() needs const.'
1007   if conf.CheckIconvConst():
1008     utils.addToConfig('#define ICONV_CONST', desc = description)
1009   else:
1010     utils.addToConfig('/* #undef ICONV_CONST */', desc = description)
1011
1012   # PACKAGE
1013   # PACKAGE_VERSION
1014   # PACKAGE_BUGREPORT
1015   # PACKAGE_NAME
1016   # PACKAGE_STRING
1017   # DEVEL_VERSION
1018   utils.addToConfig('#define PACKAGE "%s%s"' % (PACKAGE, env['PROGRAM_SUFFIX']),
1019     desc = "Name of package")
1020
1021   utils.addToConfig('#define PACKAGE_BUGREPORT "%s"' % PACKAGE_BUGREPORT,
1022     desc = 'Define to the address where bug reports for this package should be sent.')
1023
1024   utils.addToConfig('#define PACKAGE_NAME "%s"' % PACKAGE_NAME,
1025       desc = 'Define to the full name of this package.')
1026
1027   utils.addToConfig('#define PACKAGE_STRING "%s"' % PACKAGE_STRING,
1028       desc = "Define to the full name and version of this package.")
1029
1030   utils.addToConfig('#define PACKAGE_TARNAME "%s"' % PACKAGE_TARNAME,
1031       desc = "Define to the one symbol short name of this package.")
1032
1033   utils.addToConfig('#define PACKAGE_VERSION "%s"' % PACKAGE_VERSION,
1034     desc = "Define to the version of this package.")
1035
1036   if DEVEL_VERSION:
1037     utils.addToConfig('#define DEVEL_VERSION 1')
1038
1039   # ENABLE_ASSERTIONS
1040   # ENABLE_NLS
1041   # WITH_WARNINGS
1042   # _GLIBCXX_CONCEPT_CHECKS
1043
1044   # items are (ENV, ARGUMENTS)
1045   values = [
1046     ('ENABLE_ASSERTIONS', 'assertions', 'Define if you want assertions to be enabled in the code'),
1047     ('ENABLE_NLS', 'nls', "Define to 1 if translation of program messages to the user's native anguage is requested."),
1048     ('WITH_WARNINGS', 'warnings', 'Define this if you want to see the warning directives put here and there by the developpers to get attention'),
1049     ('_GLIBCXX_CONCEPT_CHECKS', 'concept_checks', 'libstdc++ concept checking'),
1050   ]
1051
1052   for val in values:
1053     if (env.has_key(val[0]) and env[val[0]]) or \
1054        (env.has_key(val[1]) and env[val[1]]):
1055       utils.addToConfig('#define %s 1' % val[0], desc = val[2])
1056     else:
1057       utils.addToConfig('/* #undef %s */' % val[0], desc = val[2])
1058
1059   # disable automatic linking of boost libraries.
1060   # This is an interesting feature that is supposed to be useful under
1061   # windows but since I can not find a way to use it on all platforms, 
1062   # I disable it for now.
1063   utils.addToConfig('#define BOOST_ALL_NO_LIB 1')
1064
1065   # AIKSAURUS_H_LOCATION
1066   if (conf.CheckCXXHeader("Aiksaurus.h")):
1067     utils.addToConfig("#define AIKSAURUS_H_LOCATION <Aiksaurus.h>")
1068   elif (conf.CheckCXXHeader("Aiksaurus/Aiksaurus.h")):
1069     utils.addToConfig("#define AIKSAURUS_H_LOCATION <Aiksaurus/Aiksaurus.h>")
1070   else:
1071     utils.addToConfig("#define AIKSAURUS_H_LOCATION")
1072
1073   # USE_ASPELL
1074   # USE_PSPELL
1075   # USE_ISPELL
1076
1077   # determine headers to use
1078   spell_engine = ARGUMENTS.get('spell', 'auto')
1079   spell_detected = False
1080   if spell_engine in ['auto', 'aspell'] and \
1081     conf.CheckLib('aspell'):
1082     utils.addToConfig('#define USE_ASPELL 1', desc = 'Define as 1 to use the aspell library')
1083     env['USE_ASPELL'] = True
1084     env['USE_PSPELL'] = False
1085     env['USE_ISPELL'] = False
1086     spell_detected = True
1087   elif spell_engine in ['auto', 'pspell'] and \
1088     conf.CheckLib('pspell'):
1089     utils.addToConfig('#define USE_PSPELL 1', desc = 'Define as 1 to use the pspell library')
1090     env['USE_ASPELL'] = False
1091     env['USE_PSPELL'] = True
1092     env['USE_ISPELL'] = False
1093     spell_detected = True
1094   elif spell_engine in ['auto', 'ispell'] and \
1095     conf.CheckLib('ispell'):
1096     utils.addToConfig('#define USE_ISPELL 1', desc = 'Define as 1 to use the ispell library')
1097     env['USE_ASPELL'] = False
1098     env['USE_PSPELL'] = False
1099     env['USE_ISPELL'] = True
1100     spell_detected = True
1101
1102   if not spell_detected:
1103     env['USE_ASPELL'] = False
1104     env['USE_PSPELL'] = False
1105     env['USE_ISPELL'] = False
1106     # FIXME: can lyx work without an spell engine
1107     if spell_engine == 'auto':
1108       print "Warning: Can not locate any spell checker"
1109     else:
1110       print "Warning: Can not locate specified spell checker:", spell_engine
1111
1112   # USE_POSIX_PACKAGING
1113   # USE_MACOSX_PACKAGING
1114   # USE_WINDOWS_PACKAGING
1115   if packaging_method == 'windows':
1116     utils.addToConfig('#define USE_WINDOWS_PACKAGING 1')
1117   elif packaging_method == 'posix':
1118     utils.addToConfig('#define USE_POSIX_PACKAGING 1')
1119   elif packaging_method == 'mac':
1120     utils.addToConfig('#define USE_MACOSX_PACKAGING 1')
1121
1122   # BOOST_POSIX
1123   if boost_posix:
1124     utils.addToConfig('#define BOOST_POSIX 1')
1125   else:
1126     utils.addToConfig('/* #undef BOOST_POSIX */')
1127
1128   # MKDIR_TAKES_ONE_ARG
1129   description = 'Define if mkdir takes only one argument.'
1130   if conf.CheckMkdirOneArg():
1131     utils.addToConfig('#define MKDIR_TAKES_ONE_ARG 1', desc = description)
1132   else:
1133     utils.addToConfig('/* #undef MKDIR_TAKES_ONE_ARG */', desc = description)
1134
1135   # SELECT_TYPE_ARG1
1136   # SELECT_TYPE_ARG234
1137   # SELECT_TYPE_ARG5
1138   (arg1, arg234, arg5) = conf.CheckSelectArgType()
1139   utils.addToConfig('#define SELECT_TYPE_ARG1 %s' % arg1,
1140     desc = "Define to the type of arg 1 for `select'.")
1141   utils.addToConfig('#define SELECT_TYPE_ARG234 %s' % arg234,
1142     desc = "Define to the type of arg 2, 3, 4 for `select'.")
1143   utils.addToConfig('#define SELECT_TYPE_ARG5 %s' % arg5,
1144     desc = "Define to the type of arg 5 for `select'.")
1145
1146   # mkstemp
1147   # USE_BOOST_FORMAT
1148   # WANT_GETFILEATTRIBUTESEX_WRAPPER
1149   utils.endConfigH(TOP_SRC_DIR)
1150
1151   for key in ['USE_ASPELL', 'USE_PSPELL', 'USE_ISPELL', 'HAVE_ASPRINTF', \
1152     'HAVE_WPRINTF', 'HAVE_SNPRINTF', 'HAVE_POSIX_PRINTF', 'HAVE_FCNTL', \
1153     'HAVE_ICONV', 'HAVE_LIBGDI32', 'HAVE_LIBC', 'HAVE_LIBAIKSAURUS']:
1154     env_cache[key] = env[key]
1155 else:
1156   #
1157   # this comes as a big surprise, without this line 
1158   # (doing nothing obvious), adding fast_start=yes
1159   # to a build with fast_start=no will result in a rebuild
1160   # Note that the exact header file to check does not matter
1161   conf.CheckCHeader('io.h')
1162   # only a few variables need to be rescanned
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[key] = env_cache[key]
1167
1168
1169 #
1170 # Finish auto-configuration
1171 env = conf.Finish()
1172
1173 #----------------------------------------------------------
1174 # Now set up our build process accordingly
1175 #----------------------------------------------------------
1176
1177 #
1178 # QT_LIB
1179 #
1180 # NOTE: Tool('qt') or Tool('qt4') will be loaded later
1181 # in their respective directory and specialized env.
1182 try:
1183   if frontend == 'qt3':
1184     # note: env.Tool('qt') my set QT_LIB to qt
1185     env['QT_LIB'] = 'qt-mt'
1186     env['FRONTEND_LIBS'] = ['qt-mt']
1187     if platform_name == 'cygwin' and use_X11:
1188       env.AppendUnique(LIBPATH = ['/usr/X11R6/lib'])
1189   elif frontend == 'qt4':
1190     if platform_name == "win32":
1191       env['QT_LIB'] = ['QtCore4', 'QtGui4']
1192     else:
1193       env['QT_LIB'] = ['QtCore', 'QtGui']
1194     env['FRONTEND_LIBS'] = env['QT_LIB']
1195 except:
1196   print "Can not locate qt tools"
1197   print "What I get is "
1198   print "  QTDIR: ", env['QTDIR']
1199
1200
1201 if platform_name in ['win32', 'cygwin']:
1202   # the final link step needs stdc++ to succeed under mingw
1203   # FIXME: shouldn't g++ automatically link to stdc++?
1204   if use_vc:
1205     env['SYSTEM_LIBS'] = ['shlwapi', 'shell32', 'advapi32', 'zdll']
1206   else:
1207     env['SYSTEM_LIBS'] = ['shlwapi', 'stdc++', 'z']
1208 elif platform_name == 'cygwin' and use_X11:
1209   env['SYSTEM_LIBS'] = ['GL',  'Xmu', 'Xi', 'Xrender', 'Xrandr', 'Xcursor',
1210     'Xft', 'freetype', 'fontconfig', 'Xext', 'X11', 'SM', 'ICE', 'resolv',
1211     'pthread', 'z']
1212 else:
1213   env['SYSTEM_LIBS'] = ['z']
1214
1215 libs = [
1216   ('HAVE_ICONV', 'iconv'),
1217   ('HAVE_LIBGDI32', 'gdi32'),
1218   ('HAVE_LIBAIKSAURUS', 'Aiksaurus'),
1219   ('USE_ASPELL', 'aspell'),
1220   ('USE_ISPELL', 'ispell'),
1221   ('USE_PSPELL', 'pspell'),
1222 ]
1223
1224 for lib in libs:
1225   if env[lib[0]]:
1226     env['SYSTEM_LIBS'].append(lib[1])
1227
1228 #
1229 # Build parameters CPPPATH etc
1230 #
1231 # boost is always in, src is needed for config.h
1232
1233 # QT_INC_PATH is not needed for *every* source file
1234 env['CPPPATH'].remove(env['QT_INC_PATH'])
1235 env['CPPPATH'] += ['$TOP_SRC_DIR/boost', '$TOP_SRC_DIR/src']
1236
1237 # add appropriate compiling options (-DNDEBUG etc)
1238 # for debug/release mode
1239 # /Zi: debug info
1240 if ARGUMENTS.get('mode', default_build_mode) == 'debug':
1241   if use_vc:
1242     env.AppendUnique(CCFLAGS = ['/Zi'])
1243     env.AppendUnique(LINKFLAGS = ['/debug', '/map'])
1244   else:
1245     env.AppendUnique(CCFLAGS = ['-Wall', '-g'])
1246 else:
1247   if use_vc:
1248     env.AppendUnique(CCFLAGS = ['/O2'])
1249   else:
1250     env.AppendUnique(CCFLAGS = ['-Wall', '-O2'])
1251
1252 #
1253 # Customized builders
1254 #
1255 # install customized builders
1256 env['BUILDERS']['substFile'] = Builder(action = utils.env_subst)
1257
1258 #
1259 # A Link script for cygwin see
1260 # http://www.cygwin.com/ml/cygwin/2004-09/msg01101.html
1261 # http://www.cygwin.com/ml/cygwin-apps/2004-09/msg00309.html
1262 # for details
1263 #
1264 if platform_name == 'cygwin':
1265   ld_script_path = '/usr/lib/qt3/mkspecs/cygwin-g++'
1266   ld_script = utils.installCygwinLDScript(ld_script_path)
1267   env.AppendUnique(LINKFLAGS = ['-Wl,--enable-runtime-pseudo-reloc',
1268     '-Wl,--script,%s' % ld_script, '-Wl,-s'])
1269
1270 #
1271 # Report results
1272 #
1273 # src/support/package.C.in needs the following to replace
1274 #  LYX_ABS_INSTALLED_DATADIR (e.g. /usr/local/lyx/share/lyx)
1275 env['LYX_DIR'] = Dir(env['SHARE_DIR']).abspath
1276 #  LYX_ABS_INSTALLED_LOCALEDIR
1277 env['LOCALEDIR'] = Dir(env['LOCALE_DIR']).abspath
1278 # during variable substitution, absolute path is needed.
1279 env['TOP_SRCDIR'] = Dir(env['TOP_SRC_DIR']).abspath
1280 # needed by src/version.C.in => src/version.C
1281 env['PACKAGE_VERSION'] = PACKAGE_VERSION
1282 # fill in the version info
1283 env['VERSION_INFO'] = '''Configuration
1284   Host type:                      %s
1285   Special build flags:            %s
1286   C   Compiler:                   %s
1287   C   Compiler flags:             %s %s
1288   C++ Compiler:                   %s
1289   C++ Compiler LyX flags:         %s
1290   C++ Compiler flags:             %s %s
1291   Linker flags:                   %s
1292   Linker user flags:              %s
1293 Build info:
1294   Builing directory:              %s
1295   Local library directory:        %s
1296   Libraries paths:                %s
1297   Boost libraries:                %s
1298   Frontend libraries:             %s
1299   System libraries:               %s
1300   include search path:            %s
1301 Frontend:
1302   Frontend:                       %s
1303   Packaging:                      %s
1304   LyX dir:                        %s
1305   LyX binary dir:                 %s
1306   LyX files dir:                  %s
1307 ''' % (platform_name,
1308   env.subst('$CCFLAGS'), env.subst('$CC'),
1309   env.subst('$CPPFLAGS'), env.subst('$CFLAGS'),
1310   env.subst('$CXX'), env.subst('$CXXFLAGS'),
1311   env.subst('$CPPFLAGS'), env.subst('$CXXFLAGS'),
1312   env.subst('$LINKFLAGS'), env.subst('$LINKFLAGS'),
1313   env.subst('$BUILDDIR'), env.subst('$LOCALLIBPATH'),
1314   str(env['LIBPATH']), str(env['BOOST_LIBRARIES']),
1315   str(env['FRONTEND_LIBS']), str(env['SYSTEM_LIBS']), str(env['CPPPATH']),
1316   env['frontend'], packaging_method,
1317   env['PREFIX'], env['BIN_DEST_DIR'], env['SHARE_DIR'])
1318
1319 if env['frontend'] in ['qt3', 'qt4']:
1320   env['VERSION_INFO'] += '''  include dir:                    %s
1321   library dir:                    %s
1322   X11:                            %s
1323 ''' % (env.subst('$QT_INC_PATH'), env.subst('$QT_LIB_PATH'), use_X11)
1324
1325 if not fast_start:
1326   print env['VERSION_INFO']
1327
1328 #
1329 # Mingw command line may be too short for our link usage,
1330 # Here we use a trick from scons wiki
1331 # http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/LongCmdLinesOnWin32
1332 #
1333 # I also would like to add logging (commands only) capacity to the
1334 # spawn system.
1335 logfile = env.get('logfile', default_log_file)
1336 if logfile != '' or platform_name == 'win32':
1337   import time
1338   utils.setLoggedSpawn(env, logfile, longarg = (platform_name == 'win32'),
1339     info = '''# This is a log of commands used by scons to build lyx
1340 # Time: %s
1341 # Command: %s
1342 # Info: %s
1343 ''' % (time.asctime(), ' '.join(sys.argv),
1344   env['VERSION_INFO'].replace('\n','\n# ')) )
1345
1346
1347 #
1348 # Cleanup stuff
1349 #
1350 # -h will print out help info
1351 Help(opts.GenerateHelpText(env))
1352 # save environment settings (for fast_start option)
1353 cache_file = open(env_cache_file, 'w')
1354 cPickle.dump(env_cache, cache_file)
1355 cache_file.close()
1356
1357 #----------------------------------------------------------
1358 # Start building
1359 #----------------------------------------------------------
1360 Export('env')
1361
1362 # this has been the source of problems on some platforms...
1363 # I find that I need to supply it with full path name
1364 env.SConsignFile(os.path.join(Dir(env['BUILDDIR']).abspath, '.sconsign'))
1365 # this usage needs further investigation.
1366 #env.CacheDir('%s/Cache/%s' % (env['BUILDDIR'], frontend))
1367
1368 env['BUILD_TARGETS'] = BUILD_TARGETS
1369 if env.has_key('rebuild'):
1370   env['REBUILD_TARGETS'] = env['rebuild'].split(',')
1371 else:
1372   env['REBUILD_TARGETS'] = None
1373
1374 print "Building all targets recursively"
1375
1376 env.SConscript('$SCONS_DIR/SConscript', duplicate = 0)
1377
1378