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