]> git.lyx.org Git - features.git/blob - development/scons/SConstruct
d6e032a79c57e75e42d3fbbc41fc2fa22e75e5c9
[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
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 # FIXME: I remember lyx requires higher version of python?
85 EnsurePythonVersion(1, 5)
86 # Please use at least 0.96.91 (not 0.96.1)
87 EnsureSConsVersion(0, 96)
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
109 PACKAGE = 'lyx'
110 PACKAGE_BUGREPORT = 'lyx-devel@lists.lyx.org'
111 PACKAGE_NAME = 'LyX'
112 PACKAGE_TARNAME = 'lyx'
113 PACKAGE_STRING = '%s %s' % (PACKAGE_NAME, PACKAGE_VERSION)
114 PROGRAM_SUFFIX = ''
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   # FIXME: I do not know how pch is working. Ignore this option now.
240   BoolOption('pch', '(NA) Whether or not use pch', default_pch_opt),
241   # FIXME: Not implemented yet.
242   BoolOption('version_suffix', '(NA) Whether or not add version suffix', False),
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   # FIXME: I do not know what is nls
250   BoolOption('nls', '(NA) Whether or not use native language support', False),
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   # FIXME: not implemented
258   BoolOption('libintl', '(NA) Use libintl library', 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   # can be set to a non-existing directory
276   ('prefix', 'install architecture-independent files in PREFIX', None),
277   #
278   PathOption('exec_prefix', 'install architecture-independent executable files in PREFIX', None),
279   # FIXME: not implemented
280   PathOption('intl_prefix', '(NA) Path to intl library', None),
281   # log file
282   ('logfile', 'save commands (not outputs) to logfile', default_log_file),
283   # Path to aikasurus
284   PathOption('aikasurus_path', 'Path to aikasurus library', None),
285   # environment variable can be set as options. (DO NOT set defaults)
286   ('CC', '$CC', None),
287   ('LINK', '$LINK', None),
288   ('CPP', '$CPP', None),
289   ('CXX', '$CXX', None),
290   ('CXXCPP', '$CXXCPP', None),
291   ('CCFLAGS', '$CCFLAGS', None),
292   ('CPPFLAGS', '$CPPFLAGS', None),
293   ('LDFLAGS', '$LDFLAGS', None),
294 )
295
296
297 #---------------------------------------------------------
298 # Setting up environment
299 #---------------------------------------------------------
300
301 env = Environment(options = opts)
302
303 # Determine the frontend to use, which may be loaded
304 # from option cache
305 frontend = env.get('frontend', default_frontend)
306 # make sure the key exists
307 env['frontend'] = frontend
308 #
309 use_X11 = env.get('X11', default_with_x)
310
311 # whether or not use current config.h, and cached tests
312 if env['fast_start'] and os.path.isfile(env_cache_file):
313   fast_start = True
314   SetOption('implicit_cache', 1)
315   cache_file = open(env_cache_file)
316   env_cache = cPickle.load(cache_file)
317   cache_file.close()
318   print '------------ fast_start mode --------------------'
319   print '  Use cached test results and current config.h'
320   print '  use fast_start=no to override'
321   print '-------------------------------------------------'
322 else:
323   fast_start = False
324   SetOption('implicit_cache', 0)
325   env_cache = {}
326
327 # set individual variables since I do not really like ENV = os.environ
328 env['ENV']['PATH'] = os.environ.get('PATH')
329 env['ENV']['HOME'] = os.environ.get('HOME')
330 env['TOP_SRC_DIR'] = TOP_SRC_DIR
331 env['SCONS_DIR'] = SCONS_DIR
332 # install to default_prefix by default
333 env['PREFIX'] = env.get('prefix', default_prefix)
334 if env.has_key('exec_prefix'):
335   env['BIN_DIR'] = env['exec_prefix']
336 else:
337   env['BIN_DIR'] = os.path.join(env['PREFIX'], 'bin')
338 env['SHARE_DIR'] = os.path.join(env['PREFIX'], share_dir)
339 env['MAN_DIR'] = os.path.join(env['PREFIX'], man_dir)
340 env['LOCALE_DIR'] = os.path.join(env['PREFIX'], locale_dir)
341
342 # speed up source file processing
343 #env['CPPSUFFIXES'] = ['.C', '.cc', '.cpp']
344 #env['CXXSUFFIX'] = ['.C']
345
346 def getEnvVariable(env, name):
347   # first try command line argument (override environment settings)
348   if ARGUMENTS.has_key(name) and ARGUMENTS[name].strip() != '':
349     env[name] = ARGUMENTS[name]
350   # then use environment default
351   elif os.environ.has_key(name) and os.environ[name].strip() != '':
352     env[name] = os.environ[name]
353     print "Acquiring varaible %s from system environment: %s" % (name, env[name])
354   # finally, env['CC'] etc is set to the default values of Options.
355   # and env['CPP'] etc does not exist
356
357 getEnvVariable(env, 'CC')
358 getEnvVariable(env, 'LINK')
359 getEnvVariable(env, 'CPP')
360 getEnvVariable(env, 'CXX')
361 getEnvVariable(env, 'CXXCPP')
362 getEnvVariable(env, 'CCFLAGS')
363 getEnvVariable(env, 'CXXFLAGS')
364 getEnvVariable(env, 'CPPFLAGS')
365 getEnvVariable(env, 'LDFLAGS')
366
367
368 #
369 # frontend, mode, BUILDDIR and LOCALLIBPATH=BUILDDIR/libs
370 #
371 env['mode'] = env.get('mode', default_build_mode)
372 # lyx will be built to $build/build_dir so it is possible
373 # to build multiple build_dirs using the same source
374 # $mode can be debug or release
375 if env.has_key('build_dir') and env['build_dir']:
376   build_dir = env['build_dir']
377   env['BUILDDIR'] = build_dir
378 else:
379   # Determine the name of the build $mode
380   env['BUILDDIR'] = '#' + env['mode']
381 # all built libraries will go to build_dir/libs
382 # (This is different from the make file approach)
383 env['LOCALLIBPATH'] = '$BUILDDIR/libs'
384 env.AppendUnique(LIBPATH = ['$LOCALLIBPATH'])
385
386 #
387 # QTDIR, QT_LIB_PATH, QT_INC_PATH
388 #
389 if env.has_key('qt_dir') and env['qt_dir']:
390   env['QTDIR'] = env['qt_dir']
391   # add path to the qt tools
392   env.AppendUnique(LIBPATH = [os.path.join(env['qt_dir'], 'lib')])
393   # set environment so that moc etc can be found even if its path is not set properly
394   env.PrependENVPath('PATH', os.path.join(env['qt_dir'], 'bin'))
395 else:
396   env['QTDIR'] = os.environ.get('QTDIR', '/usr/lib/qt-3.3')
397
398 if env.has_key('qt_lib_path') and env['qt_lib_path']:
399   env['QT_LIB_PATH'] = env['qt_lib_path']
400 else:
401   env['QT_LIB_PATH'] = '$QTDIR/lib'
402 env.AppendUnique(LIBPATH = ['$QT_LIB_PATH'])
403 # qt4 seems to be using pkg_config
404 env.PrependENVPath('PKG_CONFIG_PATH', env.subst('$QT_LIB_PATH'))
405
406 if env.has_key('qt_inc_path') and env['qt_inc_path']:
407   env['QT_INC_PATH'] = env['qt_inc_path']
408 elif os.path.isdir(os.path.join(env.subst('$QTDIR'), 'include')):
409   env['QT_INC_PATH'] = '$QTDIR/include'
410 else: # have to guess
411   env['QT_INC_PATH'] = '/usr/include/$frontend/'
412 # Note that this CPPPATH is for testing only
413 # it will be removed before calling SConscript
414 env.AppendUnique(CPPPATH = env['QT_INC_PATH'])
415
416 #
417 # extra_inc_path and extra_lib_path
418 #
419 if env.has_key('extra_inc_path') and env['extra_inc_path']:
420   env.AppendUnique(CPPPATH = [env['extra_inc_path']])
421 if env.has_key('extra_lib_path') and env['extra_lib_path']:
422   env.AppendUnique(LIBPATH = [env['extra_lib_path']])
423 if env.has_key('extra_inc_path1') and env['extra_inc_path1']:
424   env.AppendUnique(CPPPATH = [env['extra_inc_path1']])
425 if env.has_key('extra_lib_path1') and env['extra_lib_path1']:
426   env.AppendUnique(LIBPATH = [env['extra_lib_path1']])
427 if env.has_key('aikasurus_path') and env['aikasurus_path']:
428   env.AppendUnique(LIBPATH = [env['aikasurus_path']])
429
430 #
431 # this is a bit out of place (after auto-configration)
432 # but it is required to do the tests.
433 if platform_name == 'win32':
434   env.AppendUnique(CPPPATH = ['#c:/MinGW/include'])
435   env.Tool('mingw')
436
437 # under windows, scons is confused by .C/.c and uses gcc instead of
438 # g++. I am forcing the use of g++ here. This is expected to change
439 # after lyx renames all .C files to .cpp
440 #
441 # Note that this step has to be after env.Tool('mingw') step
442 # since env.Tool('mingw') will set env['CC'] etc.
443 #
444 if env.has_key('CXX') and env['CXX']:
445   env['CC'] = env['CXX']
446   env['LINK'] = env['CXX']
447 else:
448   env['CC'] = 'g++'
449   env['LINK'] = 'g++'
450
451
452 #----------------------------------------------------------
453 # Autoconf business
454 #----------------------------------------------------------
455
456 conf = Configure(env,
457   custom_tests = {
458     'CheckPkgConfig' : utils.checkPkgConfig,
459     'CheckPackage' : utils.checkPackage,
460     'CheckPutenv' : utils.checkPutenv,
461     'CheckIstreambufIterator' : utils.checkIstreambufIterator,
462     'CheckMkdirOneArg' : utils.checkMkdirOneArg,
463     'CheckStdCount' : utils.checkStdCount,
464     'CheckSelectArgType' : utils.checkSelectArgType,
465     'CheckBoostLibraries' : utils.checkBoostLibraries,
466     'CheckMsgFmt' : utils.checkMsgFmt,
467   }
468 )
469
470 # pkg-config? (if not, we use hard-coded options)
471 if not fast_start:
472   if conf.CheckPkgConfig('0.15.0'):
473     env['HAS_PKG_CONFIG'] = True
474   else:
475     print 'pkg-config >= 0.1.50 is not found'
476     env['HAS_PKG_CONFIG'] = False
477   env_cache['HAS_PKG_CONFIG'] = env['HAS_PKG_CONFIG']
478 else:
479   env['HAS_PKG_CONFIG'] = env_cache['HAS_PKG_CONFIG']
480
481 # zlib? This is required. (fast_start assumes the existance of zlib)
482 if not fast_start and not conf.CheckLibWithHeader('z', 'zlib.h', 'C'):
483     print 'Did not find libz or zlib.h, exiting!'
484     Exit(1)
485
486 # qt libraries?
487 if not fast_start:
488   #
489   # qt3 does not use pkg_config
490   if frontend == 'qt3':
491     if not conf.CheckLibWithHeader('qt-mt', 'qapp.h', 'c++', 'QApplication qapp();'):
492       print 'Did not find qt libraries, exiting!'
493       Exit(1)
494   elif frontend == 'qt4':
495     succ = False
496     # first: try pkg_config
497     if env['HAS_PKG_CONFIG']:
498       succ = conf.CheckPackage('QtCore') or conf.CheckPackage('QtCore4')
499       env['QT4_PKG_CONFIG'] = succ
500     # second: try to link to it
501     if not succ:
502       # FIXME: under linux, I can test the following perfectly
503       # However, under windows, lib names need to passed as libXXX4.a ...
504       succ = conf.CheckLibWithHeader('QtCore', 'QtGui/QApplication', 'c++', 'QApplication qapp();') or \
505         conf.CheckLibWithHeader('QtCore4', 'QtGui/QApplication', 'c++', 'QApplication qapp();')
506     # third: try to look up the path
507     if not succ:
508       succ = True
509       for lib in ['QtCore', 'QtGui']:
510         # windows version has something like QtGui4 ...
511         if not (os.path.isfile(os.path.join(env.subst('$QT_LIB_PATH'), 'lib%s.a' % lib)) or \
512           os.path.isfile(os.path.join(env.subst('$QT_LIB_PATH'), 'lib%s4.a' % lib))):
513           succ = False
514           break
515     # still can not find it
516     if succ:
517       print "Qt4 libraries are found."
518     else:
519       print 'Did not find qt libraries, exiting!'
520       Exit(1)
521
522
523 # check socket libs
524 if not fast_start:
525   env['SOCKET_LIBS'] = []
526   if conf.CheckLib('socket'):
527     env['SOCKET_LIBS'].append('socket')
528
529   # nsl is the network services library and provides a
530   # transport-level interface to networking services.
531   if conf.CheckLib('nsl'):
532     env['SOCKET_LIBS'].append('nsl')
533
534   env_cache['SOCKET_LIBS'] = env['SOCKET_LIBS']
535 else:
536   env['SOCKET_LIBS'] = env_cache['SOCKET_LIBS']
537
538 if not fast_start:
539   # check boost libraries
540   boost_opt = ARGUMENTS.get('boost', default_boost_opt)
541   # check for system boost
542   succ = False
543   if boost_opt in ['auto', 'system']:
544     pathes = env['LIBPATH'] + ['/usr/lib', '/usr/local/lib']
545     sig = conf.CheckBoostLibraries('boost_signals', pathes)
546     reg = conf.CheckBoostLibraries('boost_regex', pathes)
547     fil = conf.CheckBoostLibraries('boost_filesystem', pathes)
548     ios = conf.CheckBoostLibraries('boost_iostreams', pathes)
549     # if any of them is not found
550     if ('' in [sig[0], reg[0], fil[0], ios[0]]):
551       if boost_opt == 'system':
552         print "Can not find system boost libraries"
553         print "Please supply a path through extra_lib_path and try again."
554         print "Or use boost=included to use included boost libraries."
555         Exit(2)
556     else:
557       env['BOOST_LIBRARIES'] = [sig[1], reg[1], fil[1], ios[1]]
558       # assume all boost libraries are in the same path...
559       env.AppendUnique(LIBPATH = [sig[0]])
560       env['INCLUDED_BOOST'] = False
561       succ = True
562   # now, auto and succ = false, or boost=included
563   if not succ:
564     # we do not need to set LIBPATH now.
565     env['BOOST_LIBRARIES'] = ['boost_signals', 'boost_regex',
566       'boost_filesystem', 'boost_iostreams']
567     env['INCLUDED_BOOST'] = True
568   env_cache['BOOST_LIBRARIES'] = env['BOOST_LIBRARIES']
569   env_cache['INCLUDED_BOOST'] = env['INCLUDED_BOOST']
570 else:
571   env['BOOST_LIBRARIES'] = env_cache['BOOST_LIBRARIES']
572   env['INCLUDED_BOOST'] = env_cache['INCLUDED_BOOST']
573
574 #
575 # check for msgfmt command
576 if not fast_start:
577   env['MSGFMT'] = conf.CheckMsgFmt()
578   env_cache['MSGFMT'] = env['MSGFMT']
579 else:
580   env['MSGFMT'] = env_cache['MSGFMT']
581
582
583 #----------------------------------------------------------
584 # Generating config.h
585 #----------------------------------------------------------
586 if not fast_start:
587   print "Generating ", utils.config_h, "..."
588
589   # I do not handle all macros in src/config.h.in, rather I am following a list
590   # of *used-by-lyx* macros compiled by Abdelrazak Younes <younes.a@free.fr>
591   #
592   # Note: addToConfig etc are defined in scons_util
593   utils.startConfigH(TOP_SRC_DIR)
594
595   # HAVE_IO_H
596   # HAVE_LIMITS_H
597   # HAVE_LOCALE_H
598   # HAVE_LOCALE
599   # HAVE_PROCESS_H
600   # HAVE_STDLIB_H
601   # HAVE_SYS_STAT_H
602   # HAVE_SYS_TIME_H
603   # HAVE_SYS_TYPES_H
604   # HAVE_SYS_UTIME_H
605   # HAVE_UNISTD_H
606   # HAVE_UTIME_H
607   # HAVE_ISTREAM
608   # HAVE_OSTREAM
609   # HAVE_IOS
610
611   # Check header files
612   headers = [
613     ('io.h', 'HAVE_IO_H', 'c'),
614     ('limits.h', 'HAVE_LIMITS_H', 'c'),
615     ('locale.h', 'HAVE_LOCALE_H', 'c'),
616     ('locale', 'HAVE_LOCALE', 'cxx'),
617     ('process.h', 'HAVE_PROCESS_H', 'c'),
618     ('stdlib.h', 'HAVE_STDLIB_H', 'c'),
619     ('sys/stat.h', 'HAVE_SYS_STAT_H', 'c'),
620     ('sys/time.h', 'HAVE_SYS_TIME_H', 'c'),
621     ('sys/types.h', 'HAVE_SYS_TYPES_H', 'c'),
622     ('sys/utime.h', 'HAVE_SYS_UTIME_H', 'c'),
623     ('sys/socket.h', 'HAVE_SYS_SOCKET_H', 'c'),
624     ('unistd.h', 'HAVE_UNISTD_H', 'c'),
625     ('utime.h', 'HAVE_UTIME_H', 'c'),
626     ('istream', 'HAVE_ISTREAM', 'cxx'),
627     ('ostream', 'HAVE_OSTREAM', 'cxx'),
628     ('ios', 'HAVE_IOS', 'cxx')
629   ]
630
631   for header in headers:
632     if (header[2] == 'c' and conf.CheckCHeader(header[0])) or \
633       (header[2] == 'cxx' and conf.CheckCXXHeader(header[0])):
634       utils.addToConfig('#define %s 1' % header[1], TOP_SRC_DIR)
635     else:
636       utils.addToConfig('/* #undef %s */' % header[1], TOP_SRC_DIR)
637
638   # HAVE_OPEN
639   # HAVE_CLOSE
640   # HAVE_POPEN
641   # HAVE_PCLOSE
642   # HAVE__OPEN
643   # HAVE__CLOSE
644   # HAVE__POPEN
645   # HAVE__PCLOSE
646   # HAVE_GETPID
647   # HAVE__GETPID
648   # HAVE_MKDIR
649   # HAVE__MKDIR
650   # HAVE_MKTEMP
651   # HAVE_MKSTEMP
652   # HAVE_STRERROR
653   # HAVE_FCNTL
654
655   # Check functions
656   functions = [
657     ('open', 'HAVE_OPEN'),
658     ('close', 'HAVE_CLOSE'),
659     ('popen', 'HAVE_POPEN'),
660     ('pclose', 'HAVE_PCLOSE'),
661     ('_open', 'HAVE__OPEN'),
662     ('_close', 'HAVE__CLOSE'),
663     ('_popen', 'HAVE__POPEN'),
664     ('_pclose', 'HAVE__PCLOSE'),
665     ('getpid', 'HAVE_GETPID'),
666     ('_getpid', 'HAVE__GETPID'),
667     ('mkdir', 'HAVE_MKDIR'),
668     ('_mkdir', 'HAVE__MKDIR'),
669     ('mktemp', 'HAVE_MKTEMP'),
670     ('mkstemp', 'HAVE_MKSTEMP'),
671     ('strerror', 'HAVE_STRERROR'),
672     ('fcntl', 'HAVE_FCNTL')
673   ]
674
675   for func in functions:
676     if conf.CheckFunc(func[0]):
677       utils.addToConfig('#define %s 1' % func[1], TOP_SRC_DIR)
678     else:
679       utils.addToConfig('/* #undef %s */' % func[1], TOP_SRC_DIR)
680
681   # PACKAGE
682   # PACKAGE_VERSION
683   # DEVEL_VERSION
684   utils.addToConfig('#define PACKAGE "%s"' % PACKAGE, TOP_SRC_DIR)
685   utils.addToConfig('#define PACKAGE_VERSION "%s"' % PACKAGE_VERSION, TOP_SRC_DIR)
686   if DEVEL_VERSION:
687     utils.addToConfig('#define DEVEL_VERSION 1', TOP_SRC_DIR)
688
689   # ENABLE_ASSERTIONS
690   # ENABLE_NLS
691   # WITH_WARNINGS
692   # _GLIBCXX_CONCEPT_CHECKS
693
694   # items are (ENV, ARGUMENTS)
695   values = [
696     ('ENABLE_ASSERTIONS', 'assertions'),
697     ('ENABLE_NLS', 'nls'),
698     ('WITH_WARNINGS', 'warnings'),
699     ('_GLIBCXX_CONCEPT_CHECKS', 'concept_checks'),
700   ]
701
702   for val in values:
703     if (env.has_key(val[0]) and env[val[0]]) or \
704         ARGUMENTS.get(val[1]):
705       utils.addToConfig('#define %s 1' % val[0], TOP_SRC_DIR)
706     else:
707       utils.addToConfig('/* #undef %s */' % val[0], TOP_SRC_DIR)
708
709
710   env['EXTRA_LIBS'] = []
711   # HAVE_LIBAIKSAURUS
712   # AIKSAURUS_H_LOCATION
713   if conf.CheckLib('Aiksaurus'):
714     utils.addToConfig("#define HAVE_LIBAIKSAURUS 1", TOP_SRC_DIR)
715     if (conf.CheckCXXHeader("Aiksaurus.h")):
716       utils.addToConfig("#define AIKSAURUS_H_LOCATION <Aiksaurus.h>", TOP_SRC_DIR)
717     elif (conf.CheckCXXHeader("Aiksaurus/Aiksaurus.h")):
718       utils.addToConfig("#define AIKSAURUS_H_LOCATION <Aiksaurus/Aiksaurus.h>", TOP_SRC_DIR)
719     else:
720       utils.addToConfig("#define AIKSAURUS_H_LOCATION", TOP_SRC_DIR)
721     env['EXTRA_LIBS'].append('Aiksaurus')
722
723   # USE_ASPELL
724   # USE_PSPELL
725   # USE_ISPELL
726
727   # determine headers to use
728   spell_engine = ARGUMENTS.get('spell', 'auto')
729   spell_detected = False
730   if spell_engine in ['auto', 'aspell'] and \
731     conf.CheckLib('aspell'):
732     utils.addToConfig('#define USE_ASPELL 1', TOP_SRC_DIR)
733     env['USE_ASPELL'] = True
734     env['USE_PSPELL'] = False
735     env['USE_ISPELL'] = False
736     env['EXTRA_LIBS'].append('aspell')
737     spell_detected = True
738   elif spell_engine in ['auto', 'pspell'] and \
739     conf.CheckLib('pspell'):
740     utils.addToConfig('#define USE_PSPELL 1', TOP_SRC_DIR)
741     env['USE_ASPELL'] = False
742     env['USE_PSPELL'] = True
743     env['USE_ISPELL'] = False
744     env['EXTRA_LIBS'].append('pspell')
745     spell_detected = True
746   elif spell_engine in ['auto', 'ispell'] and \
747     conf.CheckLib('ispell'):
748     utils.addToConfig('#define USE_ISPELL 1', TOP_SRC_DIR)
749     env['USE_ASPELL'] = False
750     env['USE_PSPELL'] = False
751     env['USE_ISPELL'] = True
752     env['EXTRA_LIBS'].append('ispell')
753     spell_detected = True
754
755   if not spell_detected:
756     env['USE_ASPELL'] = False
757     env['USE_PSPELL'] = False
758     env['USE_ISPELL'] = False
759     # FIXME: can lyx work without an spell engine
760     if spell_engine == 'auto':
761       print "Warning: Can not locate any spell checker"
762     else:
763       print "Warning: Can not locate specified spell checker:", spell_engine
764
765   # env['EXTRA_LIBS'] will be modified later, so a unique copy is needed
766   # NOTE that we do *not* save qt_libs in environment.
767   env_cache['EXTRA_LIBS'] = copy.copy(env['EXTRA_LIBS'])
768   env_cache['USE_ASPELL'] = env['USE_ASPELL']
769   env_cache['USE_PSPELL'] = env['USE_PSPELL']
770   env_cache['USE_ISPELL'] = env['USE_ISPELL']
771
772   # USE_POSIX_PACKAGING
773   # USE_MACOSX_PACKAGING
774   # USE_WINDOWS_PACKAGING
775   if packaging_method == 'windows':
776     utils.addToConfig('#define USE_WINDOWS_PACKAGING 1', TOP_SRC_DIR)
777   elif packaging_method == 'posix':
778     utils.addToConfig('#define USE_POSIX_PACKAGING 1', TOP_SRC_DIR)
779   elif packaging_method == 'mac':
780     utils.addToConfig('#define USE_MACOSX_PACKAGING 1', TOP_SRC_DIR)
781
782   # BOOST_POSIX
783   if boost_posix:
784     utils.addToConfig('#define BOOST_POSIX 1', TOP_SRC_DIR)
785   else:
786     utils.addToConfig('/* #undef BOOST_POSIX */', TOP_SRC_DIR)
787
788   # HAVE_PUTENV
789   if conf.CheckPutenv():
790     utils.addToConfig('#define HAVE_PUTENV 1', TOP_SRC_DIR)
791   else:
792     utils.addToConfig('/* #undef HAVE_PUTENV */', TOP_SRC_DIR)
793
794   # HAVE_DECL_ISTREAMBUF_ITERATOR
795   if conf.CheckIstreambufIterator():
796     utils.addToConfig('#define HAVE_DECL_ISTREAMBUF_ITERATOR 1', TOP_SRC_DIR)
797   else:
798     utils.addToConfig('/* #undef HAVE_DECL_ISTREAMBUF_ITERATOR */', TOP_SRC_DIR)
799
800   # MKDIR_TAKES_ONE_ARG
801   if conf.CheckMkdirOneArg():
802     utils.addToConfig('#define MKDIR_TAKES_ONE_ARG 1', TOP_SRC_DIR)
803   else:
804     utils.addToConfig('/* #undef MKDIR_TAKES_ONE_ARG */', TOP_SRC_DIR)
805
806   # HAVE_STD_COUNT
807   if conf.CheckStdCount():
808     utils.addToConfig('#define HAVE_STD_COUNT 1', TOP_SRC_DIR)
809   else:
810     utils.addToConfig('/* #undef HAVE_STD_COUNT */', TOP_SRC_DIR)
811
812   # SELECT_TYPE_ARG1
813   # SELECT_TYPE_ARG234
814   # SELECT_TYPE_ARG5
815   (arg1, arg234, arg5) = conf.CheckSelectArgType()
816   utils.addToConfig('#define SELECT_TYPE_ARG1 %s' % arg1, TOP_SRC_DIR)
817   utils.addToConfig('#define SELECT_TYPE_ARG234 %s' % arg234, TOP_SRC_DIR)
818   utils.addToConfig('#define SELECT_TYPE_ARG5 %s' % arg5, TOP_SRC_DIR)
819
820   # mkstemp
821   # USE_BOOST_FORMAT
822   # WANT_GETFILEATTRIBUTESEX_WRAPPER
823   utils.endConfigH(TOP_SRC_DIR)
824
825 else:
826   # only a few variables need to be rescanned
827   env['EXTRA_LIBS'] = copy.copy(env_cache['EXTRA_LIBS'])
828   env['USE_ASPELL'] = env_cache['USE_ASPELL']
829   env['USE_PSPELL'] = env_cache['USE_PSPELL']
830   env['USE_ISPELL'] = env_cache['USE_ISPELL']
831
832 #
833 # Finish auto-configuration
834 env = conf.Finish()
835
836 #----------------------------------------------------------
837 # Now set up our build process accordingly
838 #----------------------------------------------------------
839
840 #
841 # QT_LIB etc (EXTRA_LIBS holds lib for each frontend)
842 #
843 # NOTE: Tool('qt') or Tool('qt4') will be loaded later
844 # in their respective directory and specialized env.
845 try:
846   if frontend == 'qt3':
847     # note: env.Tool('qt') my set QT_LIB to qt
848     env['QT_LIB'] = 'qt-mt'
849     env['EXTRA_LIBS'].append('qt-mt')
850     if platform_name == 'cygwin' and use_X11:
851       env['EXTRA_LIBS'].extend(['GL',  'Xmu', 'Xi', 'Xrender', 'Xrandr', 'Xcursor',
852         'Xft', 'freetype', 'fontconfig', 'Xext', 'X11', 'SM', 'ICE', 'resolv',
853         'pthread'])
854       env.AppendUnique(LIBPATH = ['/usr/X11R6/lib'])
855   elif frontend == 'qt4':
856     if platform_name == "win32":
857       env['QT_LIB'] = ['QtCore4', 'QtGui4']
858     else:
859       env['QT_LIB'] = ['QtCore', 'QtGui']
860     env['EXTRA_LIBS'] += env['QT_LIB']
861 except:
862   print "Can not locate qt tools"
863   print "What I get is "
864   print "  QTDIR: ", env['QTDIR']
865
866
867 if platform_name in ['win32', 'cygwin']:
868   # the final link step needs stdc++ to succeed under mingw
869   # FIXME: shouldn't g++ automatically link to stdc++?
870   env['SYSTEM_LIBS'] = ['shlwapi', 'z', 'stdc++']
871 else:
872   env['SYSTEM_LIBS'] = ['z']
873
874 #
875 # Build parameters CPPPATH etc
876 #
877 # boost is always in, src is needed for config.h
878
879 # Note that previously added QT_DIR/include etc is removed
880 # they will be added when processing for example src/qt3
881 env['CPPPATH'] = ['$TOP_SRC_DIR/boost', '$TOP_SRC_DIR/src']
882
883 # TODO: add (more) appropriate compiling options (-DNDEBUG etc)
884 # for debug/release mode
885 if ARGUMENTS.get('mode', default_build_mode) == 'debug':
886   env.AppendUnique(CCFLAGS = [])
887 else:
888   env.AppendUnique(CCFLAGS = [])
889
890 #
891 # Customized builders
892 #
893 # install customized builders
894 env['BUILDERS']['substFile'] = Builder(action = utils.env_subst)
895 # FIXME: there must be a better way.
896 env['BUILDERS']['fileCopy'] = Builder(action = utils.env_filecopy)
897
898 #
899 # A Link script for cygwin see
900 # http://www.cygwin.com/ml/cygwin/2004-09/msg01101.html
901 # http://www.cygwin.com/ml/cygwin-apps/2004-09/msg00309.html
902 # for details
903 #
904 if platform_name == 'cygwin':
905   ld_script_path = '/usr/lib/qt3/mkspecs/cygwin-g++'
906   ld_script = utils.installCygwinLDScript(ld_script_path)
907   env.AppendUnique(LINKFLAGS = ['-Wl,--enable-runtime-pseudo-reloc',
908     '-Wl,--script,%s' % ld_script, '-Wl,-s'])
909
910 #
911 # Report results
912 #
913 # src/support/package.C.in needs the following to replace
914 #  LYX_ABS_INSTALLED_DATADIR (e.g. /usr/local/lyx/share/lyx)
915 env['LYX_DIR'] = env['SHARE_DIR']
916 #  LYX_ABS_INSTALLED_LOCALEDIR
917 env['LOCALEDIR'] = env['LOCALE_DIR']
918 env['TOP_SRCDIR'] = env['TOP_SRC_DIR']
919 env['PROGRAM_SUFFIX'] = PROGRAM_SUFFIX
920 # needed by src/version.C.in => src/version.C
921 env['PACKAGE_VERSION'] = PACKAGE_VERSION
922 # fill in the version info
923 env['VERSION_INFO'] = '''Configuration
924   Host type:                      %s
925   Special build flags:            %s
926   C   Compiler:                   %s
927   C   Compiler flags:             %s %s
928   C++ Compiler:                   %s
929   C++ Compiler LyX flags:         %s
930   C++ Compiler flags:             %s %s
931   Linker flags:                   %s
932   Linker user flags:              %s
933 Build info:
934   Builing directory:              %s
935   Local library directory:        %s
936   Libraries pathes:               %s
937   Boost libraries:                %s
938   Extra libraries:                %s
939   System libraries:               %s
940 Frontend:
941   Frontend:                       %s
942   Packaging:                      %s
943   LyX binary dir:                 FIXME
944   LyX files dir:                  FIXME
945 ''' % (platform_name,
946   env.subst('$CCFLAGS'), env.subst('$CC'),
947   env.subst('$CPPFLAGS'), env.subst('$CFLAGS'),
948   env.subst('$CXX'), env.subst('$CXXFLAGS'),
949   env.subst('$CPPFLAGS'), env.subst('$CXXFLAGS'),
950   env.subst('$LINKFLAGS'), env.subst('$LINKFLAGS'),
951   env.subst('$BUILDDIR'), env.subst('$LOCALLIBPATH'),
952   str(env['LIBPATH']), str(env['BOOST_LIBRARIES']),
953   str(env['EXTRA_LIBS']), str(env['SYSTEM_LIBS']),
954   env['frontend'], packaging_method)
955
956 if env['frontend'] in ['qt3', 'qt4']:
957   env['VERSION_INFO'] += '''  include dir:                    %s
958   library dir:                    %s
959   X11:                            %s
960 ''' % (env.subst('$QT_INC_PATH'), env.subst('$QT_LIB_PATH'), use_X11)
961
962 if not fast_start:
963   print env['VERSION_INFO']
964
965 #
966 # Mingw command line may be too short for our link usage,
967 # Here we use a trick from scons wiki
968 # http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/LongCmdLinesOnWin32
969 #
970 # I also would like to add logging (commands only) capacity to the
971 # spawn system.
972 logfile = env.get('logfile', default_log_file)
973 if logfile != '' or platform_name == 'win32':
974   import time
975   utils.setLoggedSpawn(env, logfile, longarg = (platform_name == 'win32'),
976     info = '''# This is a log of commands used by scons to build lyx
977 # Time: %s
978 # Command: %s
979 # Info: %s
980 ''' % (time.asctime(), ' '.join(sys.argv),
981   env['VERSION_INFO'].replace('\n','\n# ')) )
982
983
984 #
985 # Cleanup stuff
986 #
987 # -h will print out help info
988 Help(opts.GenerateHelpText(env))
989 # save environment settings (for fast_start option)
990 cache_file = open(env_cache_file, 'w')
991 cPickle.dump(env_cache, cache_file)
992 cache_file.close()
993
994 #----------------------------------------------------------
995 # Start building
996 #----------------------------------------------------------
997 Export('env')
998
999 # this has been the source of problem on some platforms...
1000 # needs more testing
1001 env.SConsignFile('%s/.sconsign' % env['BUILDDIR'][1:])
1002 # this usage needs further investigation.
1003 #env.CacheDir('%s/Cache/%s' % (env['BUILDDIR'], frontend))
1004
1005 env['BUILD_TARGETS'] = BUILD_TARGETS
1006
1007 print "Building all targets recursively"
1008
1009 env.SConscript('$SCONS_DIR/SConscript', duplicate = 0)
1010
1011