]> git.lyx.org Git - features.git/blob - development/scons/SConstruct
Scons: fix DESTDIR, reloate intl/libintl.h, libgnuintl.h
[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 # This is a scons based building system for lyx, please refer
12 # to INSTALL.scons for detailed instructions.
13 #
14
15 import os, sys, copy, cPickle, glob
16
17 # scons_utils.py defines a few utility function
18 sys.path.append('config')
19 import scons_utils as utils
20
21 #----------------------------------------------------------
22 # Required runtime environment
23 #----------------------------------------------------------
24
25 # scons asks for 1.5.2, lyx requires 2.3
26 EnsurePythonVersion(2, 3)
27 # Please use at least 0.96.91 (not 0.96.1)
28 EnsureSConsVersion(0, 96)
29
30 # determine where I am ...
31 #
32 # called as 'cd development/scons; scons'
33 if os.path.isfile('SConstruct'):
34   top_src_dir = '../..'
35   scons_dir = '.'
36 # called as 'scons -f development/scons/SConstruct'
37 else:
38   top_src_dir = '.'
39   scons_dir = 'development/scons'
40
41
42 #----------------------------------------------------------
43 # Global definitions
44 #----------------------------------------------------------
45
46 # some global settings
47 #
48 # detect version of lyx
49 # only 1.4.x has frontends/qt2
50 if os.path.isdir(os.path.join(top_src_dir, 'src', 'frontends', 'qt2')):
51   package_version = '1.4.2svn'
52 else:
53   package_version = '1.5.0svn'
54
55 devel_version = True
56 default_build_mode = 'debug'
57 lyx_ext = '*.C'
58
59 package = 'lyx'
60 package_bugreport = 'lyx-devel@lists.lyx.org'
61 package_name = 'LyX'
62 package_tarname = 'lyx'
63 package_string = '%s %s' % (package_name, package_version)
64
65 # various cache/log files
66 default_log_file = 'scons_lyx.log'
67 env_cache_file = 'env.cache'
68
69
70 #----------------------------------------------------------
71 # platform dependent settings
72 #----------------------------------------------------------
73
74 if os.name == 'nt':
75   platform_name = 'win32'
76   default_frontend = 'qt4'
77   default_prefix = 'c:/program files/lyx'
78   default_with_x = False
79   default_packaging_method = 'windows'
80 elif os.name == 'posix' and sys.platform != 'cygwin':
81   platform_name = sys.platform
82   default_frontend = 'qt3'
83   default_prefix = '/usr/local'
84   default_with_x = True
85   default_packaging_method = 'posix'
86 elif os.name == 'posix' and sys.platform == 'cygwin':
87   platform_name = 'cygwin'
88   default_frontend = 'qt3'
89   default_prefix = '/usr/local'
90   default_with_x = True
91   default_packaging_method = 'posix'
92 elif os.name == 'darwin':
93   platform_name = 'macosx'
94   default_frontend = 'qt3'
95   # FIXME: macOSX default prefix?
96   default_prefix = '.'
97   default_with_x = False
98   default_packaging_method = 'macosx'
99 else:  # unsupported system, assume posix behavior
100   platform_name = 'others'
101   default_frontend = 'qt3'
102   default_prefix = '.'
103   default_with_x = True
104   default_packaging_method = 'posix'
105
106
107 #---------------------------------------------------------
108 # Handling options
109 #----------------------------------------------------------
110 #
111 # You can set perminant default values in config.py
112 if os.path.isfile('config.py'):
113   print "Getting options from config.py..."
114   print open('config.py').read()
115
116 opts = Options(['config.py'])
117 opts.AddOptions(
118   # frontend
119   EnumOption('frontend', 'Main GUI', default_frontend,
120     allowed_values = ('xform', 'qt2', 'qt3', 'qt4', 'gtk') ),
121   # debug or release build
122   EnumOption('mode', 'Building method', default_build_mode,
123     allowed_values = ('debug', 'release') ),
124   # boost libraries
125   EnumOption('boost',
126     'Use included, system boost library, or try sytem boost first.',
127     'auto', allowed_values = (
128       'auto',       # detect boost, if not found, use included
129       'included',   # always use included boost
130       'system',     # always use system boost, fail if can not find
131       ) ),
132   #
133   EnumOption('gettext',
134     'Use included, system gettext library, or try sytem gettext first',
135     'auto', allowed_values = (
136       'auto',       # detect gettext, if not found, use included
137       'included',   # always use included gettext
138       'system',     # always use system gettext, fail if can not find
139       ) ),
140   #
141   EnumOption('spell', 'Choose spell checker to use.', 'auto',
142     allowed_values = ('aspell', 'pspell', 'ispell', 'auto', 'no') ),
143   # packaging method
144   EnumOption('packaging', 'Packaging method to use.', default_packaging_method,
145     allowed_values = ('windows', 'posix', 'macosx')),
146   #
147   BoolOption('fast_start', 'Whether or not use cached tests and keep current config.h', True),
148   # No precompiled header support (too troublesome to make it work for msvc)
149   # BoolOption('pch', 'Whether or not use pch', False),
150   # enable assertion, (config.h has ENABLE_ASSERTIOS
151   BoolOption('assertions', 'Use assertions', True),
152   # enable warning, (config.h has WITH_WARNINGS)
153   # default to False since MSVC does not have #warning
154   BoolOption('warnings', 'Use warnings', False),
155   # config.h define _GLIBCXX_CONCEPT_CHECKS
156   # Note: for earlier version of gcc (3.3) define _GLIBCPP_CONCEPT_CHECKS
157   BoolOption('concept_checks', 'Enable concept checks', True),
158   #
159   BoolOption('nls', 'Whether or not use native language support', True),
160   #
161   BoolOption('profiling', 'Whether or not enable profiling', False),
162   # config.h define _GLIBCXX_DEBUG and _GLIBCXX_DEBUG_PEDANTIC
163   BoolOption('stdlib_debug', 'Whether or not turn on stdlib debug', False),
164   # using x11?
165   BoolOption('X11', 'Use x11 windows system', default_with_x),
166   # use MS VC++ to build lyx
167   BoolOption('use_vc', 'Use MS VC++ to build lyx (cl.exe will be probed)', None),
168   #
169   PathOption('qt_dir', 'Path to qt directory', None),
170   #
171   PathOption('qt_include_path', 'Path to qt include directory', None),
172   #
173   PathOption('qt_lib_path', 'Path to qt library directory', None),
174   # build directory, will use $mode if not set
175   PathOption('build_dir', 'Build directory', None),
176   # extra include and libpath
177   PathOption('extra_inc_path', 'Extra include path', None),
178   #
179   PathOption('extra_lib_path', 'Extra library path', None),
180   #
181   PathOption('extra_bin_path', 'A convenient way to add a path to $PATH', None),
182   #
183   PathOption('extra_inc_path1', 'Extra include path', None),
184   #
185   PathOption('extra_lib_path1', 'Extra library path', None),
186   # rebuild only specifed, comma separated targets
187   ('rebuild', 'rebuild only specifed, comma separated targets', None),
188   # can be set to a non-existing directory
189   ('prefix', 'install architecture-independent files in PREFIX', default_prefix),
190   # version suffix
191   ('version_suffix', 'install lyx as lyx-suffix', None),
192   # how to load options
193   ('load_option', '''load option from previous scons run. option can be
194     yes (default): load all options
195     no: do not load any option
196     opt1,opt2: load specified options
197     -opt1,opt2: load all options other than specified ones''', 'yes'),
198   #
199   ('optimization', 'optimization CCFLAGS option.', None),
200   #
201   PathOption('exec_prefix', 'install architecture-independent executable files in PREFIX', None),
202   # log file
203   ('logfile', 'save commands (not outputs) to logfile', default_log_file),
204   # provided for backward compatibility
205   ('dest_dir', 'install to DESTDIR. (Provided for backward compatibility only)', None),
206   # environment variable can be set as options.
207   ('DESTDIR', 'install to DESTDIR', None),
208   ('CC', 'replace default $CC', None),
209   ('LINK', 'replace default $LINK', None),
210   ('CPP', 'replace default $CPP', None),
211   ('CXX', 'replace default $CXX', None),
212   ('CXXCPP', 'replace default $CXXCPP', None),
213   ('CCFLAGS', 'replace default $CCFLAGS', None),
214   ('CPPFLAGS', 'replace default $CPPFLAGS', None),
215   ('LINKFLAGS', 'replace default $LINKFLAGS', None),
216 )
217
218 # copied from SCons/Options/BoolOption.py
219 # We need to use them before a boolean ARGUMENTS option is available
220 # in env as bool.
221 true_strings  = ('y', 'yes', 'true', 't', '1', 'on' , 'all' )
222 false_strings = ('n', 'no', 'false', 'f', '0', 'off', 'none')
223
224 # whether or not use current config.h, and cached tests
225 #
226 # if fast_start=yes (default), load variables from env_cache_file
227 if (not ARGUMENTS.has_key('fast_start') or \
228   ARGUMENTS['fast_start'] in true_strings) \
229   and os.path.isfile(env_cache_file):
230   fast_start = True
231   cache_file = open(env_cache_file)
232   env_cache = cPickle.load(cache_file)
233   cache_file.close()
234   print '------------ fast_start mode --------------------'
235   print '  Use cached test results and current config.h'
236   print '  use fast_start=no to override'
237   print
238 else:
239   fast_start = False
240   env_cache = {}
241
242 # if load_option=yes (default), load saved comand line options
243 #
244 # This option can take value yes/no/opt1,opt2/-opt1,opt2
245 # and tries to be clever in choosing options to load
246 if (not ARGUMENTS.has_key('load_option') or \
247   ARGUMENTS['load_option'] not in false_strings) \
248   and os.path.isfile(env_cache_file):
249   cache_file = open(env_cache_file)
250   opt_cache = cPickle.load(cache_file)['arg_cache']
251   cache_file.close()
252   # import cached options, but we should ignore qt_dir when frontend changes
253   if ARGUMENTS.has_key('frontend') and opt_cache.has_key('frontend') \
254     and ARGUMENTS['frontend'] != opt_cache['frontend'] \
255     and opt_cache.has_key('qt_dir'):
256     opt_cache.pop('qt_dir')
257   # some options will require full rebuild
258   # these are in general things that will change config.h
259   for arg in ['version_suffix', 'nls', 'boost', 'spell']:
260     if ARGUMENTS.has_key(arg) and ((not opt_cache.has_key(arg)) or \
261       ARGUMENTS[arg] != opt_cache[arg]):
262       if fast_start:
263         print "  ** fast_start is disabled because of the change of option", arg
264         print
265         fast_start = False
266   # and we do not cache some options
267   for arg in ['fast_start', 'load_option']:
268     if opt_cache.has_key(arg):
269       opt_cache.pop(arg)
270   # now, if load_option=opt1,opt2 or -opt1,opt2
271   if ARGUMENTS.has_key('load_option') and \
272     ARGUMENTS['load_option'] not in true_strings + false_strings:
273     # if -opt1,opt2 is specified, do not load these options
274     if ARGUMENTS['load_option'][0] == '-':
275       for arg in ARGUMENTS['load_option'][1:].split(','):
276         if opt_cache.has_key(arg):
277           opt_cache.pop(arg)
278     # if opt1,opt2 is specified, only load specified options
279     else:
280       args = ARGUMENTS['load_option'].split(',')
281       for arg in opt_cache.keys():
282         if arg not in args:
283           opt_cache.pop(arg)
284   # now restore options as if entered from command line
285   for key in opt_cache.keys():
286     if not ARGUMENTS.has_key(key):
287       ARGUMENTS[key] = opt_cache[key]
288       print "Restoring cached option  %s=%s" % (key, ARGUMENTS[key])
289   print
290
291 # save arguments
292 env_cache['arg_cache'] = ARGUMENTS
293
294
295 #---------------------------------------------------------
296 # Setting up environment
297 #---------------------------------------------------------
298
299 # I do not really like ENV=os.environ, but you may add it
300 # here if you experience some environment related problem
301 env = Environment(options = opts)
302
303 # set individual variables since I do not really like ENV = os.environ
304 env['ENV']['PATH'] = os.environ.get('PATH')
305 env['ENV']['HOME'] = os.environ.get('HOME')
306 # these are defined for MSVC
307 env['ENV']['LIB'] = os.environ.get('LIB')
308 env['ENV']['INCLUDE'] = os.environ.get('INCLUDE')
309
310 # for simplicity, use var instead of env[var]
311 frontend = env['frontend']
312 prefix = env['prefix']
313 mode = env['mode']
314
315 if platform_name == 'win32':
316   if env.has_key('use_vc'):
317     use_vc = env['use_vc']
318     if WhereIs('cl.exe') is None:
319       print "cl.exe is not found. Are you using the MSVC environment?"
320       Exit(2)
321   elif WhereIs('cl.exe') is not None:
322     use_vc = True
323   else:
324     use_vc = False
325 else:
326   use_vc = False
327
328 # lyx will be built to $build/build_dir so it is possible
329 # to build multiple build_dirs using the same source
330 # $mode can be debug or release
331 if env.has_key('build_dir') and env['build_dir'] is not None:
332   env['BUILDDIR'] = env['build_dir']
333 else:
334   # Determine the name of the build $mode
335   env['BUILDDIR'] = '#' + mode
336
337 # all built libraries will go to build_dir/libs
338 # (This is different from the make file approach)
339 env['LOCALLIBPATH'] = '$BUILDDIR/libs'
340 env.AppendUnique(LIBPATH = ['$LOCALLIBPATH'])
341
342
343 # Here is a summary of variables defined in env
344 # 1. defined options
345 # 2. undefined options with a non-None default value
346 # 3. compiler commands and flags like CCFLAGS.
347 #     MSGFMT used to process po files
348 # 4. Variables that will be used to replace variables in some_file.in
349 #     src/support/package.C.in:
350 #       TOP_SRCDIR, LOCALEDIR, LYX_DIR, PROGRAM_SUFFIX
351 #     lib/lyx2lyx/lyx2lyx_version.py.in
352 #       PACKAGE_VERSION
353 #     src/version.C.in
354 #       PACKAGE_VERSION, VERSION_INFO
355 #     src/frontends/xforms/lyx_xpm.h.in
356 #       XPM_H_LOCATION
357 #     src/frontends/xforms/lyx_forms.h.in
358 #       FORMS_H_LOCATION
359
360 # full path name is used to build msvs project files
361 # and to replace TOP_SRCDIR in package.C
362 env['TOP_SRCDIR'] = Dir(top_src_dir).abspath
363 # needed by src/version.C.in => src/version.C
364 env['PACKAGE_VERSION'] = package_version
365
366 # determine share_dir etc
367 packaging_method = env.get('packaging')
368 if packaging_method == 'windows':
369   share_dir = 'Resources'
370   man_dir = 'Resources/man/man1'
371   locale_dir = 'Resources/locale'
372   default_prefix = 'c:/program files/lyx'
373 else:
374   share_dir = 'share/lyx'
375   man_dir = 'man/man1'
376   locale_dir = 'share/locale'
377   default_prefix = '/usr/local/'
378
379 # install to default_prefix by default
380 # program suffix: can be yes, or a string
381 if env.has_key('version_suffix'):
382   if env['version_suffix'] in true_strings:
383     program_suffix = package_version
384   elif env['version_suffix'] in false_strings:
385     program_suffix = ''
386   else:
387     program_suffix = env['version_suffix']
388 else:
389   program_suffix = ''
390 # used by package.C.in
391 env['PROGRAM_SUFFIX'] = program_suffix
392
393 # whether or not add suffix to file and directory names
394 add_suffix = packaging_method != 'windows'
395 # LYX_DIR are different (used in package.C.in)
396 if add_suffix:
397   env['LYX_DIR'] = Dir(os.path.join(prefix, share_dir + program_suffix)).abspath
398 else:
399   env['LYX_DIR'] = Dir(os.path.join(prefix, share_dir)).abspath
400 # we need absolute path for package.C
401 env['LOCALEDIR'] = Dir(os.path.join(prefix, locale_dir)).abspath
402
403
404 #---------------------------------------------------------
405 # Setting building environment (Tools, compiler flags etc)
406 #---------------------------------------------------------
407
408 # Since Tool('mingw') will reset CCFLAGS etc, this should be
409 # done before getEnvVariable
410 if platform_name == 'win32':
411   if use_vc:
412     env.Tool('msvc')
413     env.Tool('mslink')
414   else:
415     env.Tool('mingw')
416     env.AppendUnique(CPPPATH = ['#c:/MinGW/include'])
417
418 # we differentiate between hard-coded options and default options
419 # hard-coded options are required and will always be there
420 # default options can be replaced by enviromental variables or command line options
421 CCFLAGS_required = []
422 LINKFLAGS_required = []
423 CCFLAGS_default = []
424
425 # under windows, scons is confused by .C/.c and uses gcc instead of
426 # g++. I am forcing the use of g++ here. This is expected to change
427 # after lyx renames all .C files to .cpp
428 #
429 # save the old c compiler and CCFLAGS (used by libintl)
430 C_COMPILER = env.subst('$CC')
431 C_CCFLAGS = env.subst('$CCFLAGS').split()
432 # if we use ms vc, the commands are fine (cl.exe and link.exe)
433 if use_vc:
434   # /TP treat all source code as C++
435   # C4819: The file contains a character that cannot be represented
436   #   in the current code page (number)
437   # C4996: foo was decleared deprecated
438   CCFLAGS_required.extend(['/TP', '/EHsc'])
439   CCFLAGS_default.extend(['/wd4819', '/wd4996', '/nologo'])
440 else:
441   if env.has_key('CXX') and env['CXX']:
442     env['CC'] = env.subst('$CXX')
443     env['LINK'] = env.subst('$CXX')
444   else:
445     env['CC'] = 'g++'
446     env['LINK'] = 'g++'
447
448 # for debug/release mode
449 if env.has_key('optimization') and env['optimization'] is not None:
450   # if user supplies optimization flags, use it anyway
451   CCFLAGS_required.extend(env['optimization'].split())
452   # and do not use default
453   set_default_optimization_flags = False
454 else:
455   set_default_optimization_flags = True
456
457 if mode == 'debug':
458   if use_vc:
459     CCFLAGS_required.append('/Zi')
460     LINKFLAGS_required.extend(['/debug', '/map'])
461   else:
462     CCFLAGS_required.append('-g')
463     CCFLAGS_default.append('-O')
464 elif mode == 'release' and set_default_optimization_flags:
465   if use_vc:
466     CCFLAGS_default.append('/O2')
467   else:
468     CCFLAGS_default.append('-O2')
469
470 # msvc uses separate tools for profiling
471 if env.has_key('profiling') and env['profiling']:
472   if use_vc:
473     print 'Visual C++ does not use profiling options'
474   else:
475     CCFLAGS_required.append('-pg')
476     LINKFLAGS_required.append('-pg')
477
478 if env.has_key('warnings') and env['warnings']:
479   if use_vc:
480     CCFLAGS_default.append('/W2')
481   else:
482     # Note: autotools detect gxx version and pass -W for 3.x
483     # and -Wextra for other versions of gcc
484     CCFLAGS_default.append('-Wall')
485
486 # Now, set the variables as follows:
487 # 1. if command line option exists: replace default
488 # 2. then if s envronment variable exists: replace default
489 # 3. set variable to required + default
490 def setEnvVariable(env, name, required = None, default = None, split = True):
491   ''' env: environment to set variable
492       name: variable
493       required: hardcoded options
494       default: default options that can be replaced by command line or
495         environment variables
496       split: whether or not split obtained variable like '-02 -g'
497   '''
498   # first try command line argument (override environment settings)
499   if ARGUMENTS.has_key(name):
500     default = ARGUMENTS[name]
501     if split:
502       default = default.split()
503   # then use environment default
504   elif os.environ.has_key(name):
505     print "Acquiring varaible %s from system environment: %s" % (name, os.environ[name])
506     default = os.environ[name]
507     if split:
508       default = default.split()
509   # set variable
510   if required is not None:
511     env[name] = required
512   if default is not None:
513     if env.has_key(name) and env[name] != default:
514       env[name] += default
515     else:
516       env[name] = default
517
518 setEnvVariable(env, 'DESTDIR', split=False)
519 setEnvVariable(env, 'CC')
520 setEnvVariable(env, 'LINK')
521 setEnvVariable(env, 'CPP')
522 setEnvVariable(env, 'CXX')
523 setEnvVariable(env, 'CXXCPP')
524 setEnvVariable(env, 'CCFLAGS', CCFLAGS_required, CCFLAGS_default)
525 setEnvVariable(env, 'CXXFLAGS')
526 setEnvVariable(env, 'CPPFLAGS')
527 setEnvVariable(env, 'LINKFLAGS', LINKFLAGS_required)
528
529 # if DESTDIR is not set...
530 if env.has_key('dest_dir'):
531   print "This option is obsolete. Please use DESTDIR instead."
532   env['DESTDIR'] = env['dest_dir']
533
534
535 #---------------------------------------------------------
536 # Frontend related variables (QTDIR etc)
537 #---------------------------------------------------------
538
539 if env.has_key('qt_dir') and env['qt_dir']:
540   env['QTDIR'] = env['qt_dir']
541   # add path to the qt tools
542   env.AppendUnique(LIBPATH = [os.path.join(env['qt_dir'], 'lib')])
543   # set environment so that moc etc can be found even if its path is not set properly
544   env.PrependENVPath('PATH', os.path.join(env['qt_dir'], 'bin'))
545 else:
546   env['QTDIR'] = os.environ.get('QTDIR', '/usr/lib/qt-3.3')
547
548 if env.has_key('qt_lib_path') and env['qt_lib_path']:
549   qt_lib_path = env.subst('$qt_lib_path')
550 else:
551   qt_lib_path = env.subst('$QTDIR/lib')
552 env.AppendUnique(LIBPATH = [qt_lib_path])
553 # qt4 seems to be using pkg_config
554 env.PrependENVPath('PKG_CONFIG_PATH', qt_lib_path)
555
556 if env.has_key('qt_inc_path') and env['qt_inc_path']:
557   qt_inc_path = env['qt_inc_path']
558 elif os.path.isdir(os.path.join(env.subst('$QTDIR'), 'include')):
559   qt_inc_path = '$QTDIR/include'
560 # this is the path for cygwin.
561 elif os.path.isdir('/usr/include/' + frontend):
562   qt_inc_path = '/usr/include/$frontend'
563 else:
564   print "Qt include directory not found. Please specify it using qt_inc_path"
565   Exit(1)
566 # Note that this CPPPATH is for testing only
567 # it will be removed before calling SConscript
568 env['CPPPATH'] = [qt_inc_path]
569
570 #
571 # extra_inc_path and extra_lib_path
572 #
573 extra_inc_paths = []
574 if env.has_key('extra_inc_path') and env['extra_inc_path']:
575   extra_inc_paths.append(env['extra_inc_path'])
576 if env.has_key('extra_lib_path') and env['extra_lib_path']:
577   env.AppendUnique(LIBPATH = [env['extra_lib_path']])
578 if env.has_key('extra_inc_path1') and env['extra_inc_path1']:
579   extra_inc_paths.append(env['extra_inc_path1'])
580 if env.has_key('extra_lib_path1') and env['extra_lib_path1']:
581   env.AppendUnique(LIBPATH = [env['extra_lib_path1']])
582 if env.has_key('extra_bin_path') and env['extra_bin_path']:
583   # maybe only one of them is needed
584   os.environ['PATH'] += os.pathsep + env['extra_bin_path']
585   env['ENV']['PATH'] += os.pathsep + env['extra_bin_path']
586 # extra_inc_paths will be used later by intlenv etc
587 env.AppendUnique(CPPPATH = extra_inc_paths)
588
589
590 #----------------------------------------------------------
591 # Autoconf business
592 #----------------------------------------------------------
593
594 conf = Configure(env,
595   custom_tests = {
596     'CheckPkgConfig' : utils.checkPkgConfig,
597     'CheckPackage' : utils.checkPackage,
598     'CheckMkdirOneArg' : utils.checkMkdirOneArg,
599     'CheckSelectArgType' : utils.checkSelectArgType,
600     'CheckBoostLibraries' : utils.checkBoostLibraries,
601     'CheckCommand' : utils.checkCommand,
602     'CheckCXXGlobalCstd' : utils.checkCXXGlobalCstd,
603     'CheckLC_MESSAGES' : utils.checkLC_MESSAGES,
604     'CheckIconvConst' : utils.checkIconvConst,
605   }
606 )
607
608 # pkg-config? (if not, we use hard-coded options)
609 if not fast_start:
610   if conf.CheckPkgConfig('0.15.0'):
611     env['HAS_PKG_CONFIG'] = True
612   else:
613     print 'pkg-config >= 0.1.50 is not found'
614     env['HAS_PKG_CONFIG'] = False
615   env_cache['HAS_PKG_CONFIG'] = env['HAS_PKG_CONFIG']
616 else:
617   env['HAS_PKG_CONFIG'] = env_cache['HAS_PKG_CONFIG']
618
619 # zlib? This is required. (fast_start assumes the existance of zlib)
620 if not fast_start:
621   if (not use_vc and not conf.CheckLibWithHeader('z', 'zlib.h', 'C')) \
622     or (use_vc and not conf.CheckLibWithHeader('zdll', 'zlib.h', 'C')):
623     print 'Did not find zdll.lib or zlib.h, exiting!'
624     Exit(1)
625
626 # qt libraries?
627 if not fast_start:
628   #
629   # qt3 does not use pkg_config
630   if frontend in ['qt2', 'qt3']:
631     if not conf.CheckLibWithHeader('qt-mt', 'qapp.h', 'c++', 'QApplication qapp();'):
632       print 'Did not find qt libraries, exiting!'
633       Exit(1)
634   elif frontend == 'qt4':
635     succ = False
636     # first: try pkg_config
637     if env['HAS_PKG_CONFIG']:
638       succ = conf.CheckPackage('QtCore') or conf.CheckPackage('QtCore4')
639       # FIXME: use pkg_config information?
640       #env['QT4_PKG_CONFIG'] = succ
641     # second: try to link to it
642     if not succ:
643       # Under linux, I can test the following perfectly
644       # Under windows, lib names need to passed as libXXX4.a ...
645       succ = conf.CheckLibWithHeader('QtCore', 'QtGui/QApplication', 'c++', 'QApplication qapp();') or \
646         conf.CheckLibWithHeader('QtCore4', 'QtGui/QApplication', 'c++', 'QApplication qapp();')
647     # third: try to look up the path
648     if not succ:
649       succ = True
650       for lib in ['QtCore', 'QtGui']:
651         # windows version has something like QtGui4 ...
652         if not (os.path.isfile(os.path.join(qt_lib_path, 'lib%s.a' % lib)) or \
653           os.path.isfile(os.path.join(qt_lib_path, 'lib%s4.a' % lib))):
654           succ = False
655           break
656     # still can not find it
657     if succ:
658       print "Qt4 libraries are found."
659     else:
660       print 'Did not find qt libraries, exiting!'
661       Exit(1)
662
663 # now, if msvc2005 is used, we will need that QT_LIB_PATH/QT_LIB.manifest file
664 if use_vc:
665   if mode == 'debug':
666     manifest = os.path.join(qt_lib_path, 'QtGuid4.dll.manifest')
667   else:
668     manifest = os.path.join(qt_lib_path, 'QtGui4.dll.manifest')
669   if os.path.isfile(manifest):
670     env['LINKCOM'] = [env['LINKCOM'], 'mt.exe /MANIFEST %s /outputresource:$TARGET;1' % manifest]
671
672 # check socket libs
673 if not fast_start:
674   socket_libs = []
675   if conf.CheckLib('socket'):
676     socket_libs.append('socket')
677   # nsl is the network services library and provides a
678   # transport-level interface to networking services.
679   if conf.CheckLib('nsl'):
680     socket_libs.append('nsl')
681   env_cache['SOCKET_LIBS'] = socket_libs
682 else:
683   socket_libs = env_cache['SOCKET_LIBS']
684
685 # check available boost libs (since lyx1.4 does not use iostream)
686 boost_libs = []
687 for lib in ['signals', 'regex', 'filesystem', 'iostreams']:
688   if os.path.isdir(os.path.join(top_src_dir, 'boost', 'libs', lib)):
689     boost_libs.append(lib)
690
691 if not fast_start:
692   # check boost libraries
693   boost_opt = ARGUMENTS.get('boost', 'auto')
694   # check for system boost
695   paths = env['LIBPATH'] + ['/usr/lib', '/usr/local/lib']
696   # real libraries (included or system)
697   boost_libraries = []
698   boost_libpath = None
699   # here I assume that all libraries are in the same directory
700   for lib in boost_libs:
701     if boost_opt == 'included':
702       boost_libraries.append('included_boost_%s' % lib)
703       env['INCLUDED_BOOST'] = True
704     elif boost_opt == 'auto':
705       res = conf.CheckBoostLibraries('boost_%s' % lib , paths)
706       # if not found
707       if res[0] == '':
708         boost_libraries.append('included_boost_%s' % lib)
709         env['INCLUDED_BOOST'] = True
710       else:
711         boost_libraries.append(res[1])
712         env['INCLUDED_BOOST'] = False
713         boost_libpath = res[0]
714     elif boost_opt == 'system':
715       res = conf.CheckBoostLibraries('boost_%s' % lib , paths)
716       if res[0] == '':
717         print "Can not find system boost libraries"
718         print "Please supply a path through extra_lib_path and try again."
719         print "Or use boost=included to use included boost libraries."
720         Exit(2)
721       else:
722         boost_libraries.append(res[1])
723         env.AppendUnique(LIBPATH = [res[0]])
724         boost_libpath = res[0]
725   env_cache['BOOST_LIBRARIES'] = boost_libraries
726   env_cache['INCLUDED_BOOST'] = env['INCLUDED_BOOST']
727   env_cache['BOOST_LIBPATH'] = boost_libpath
728 else:
729   boost_libraries = env_cache['BOOST_LIBRARIES']
730   env['INCLUDED_BOOST'] = env_cache['INCLUDED_BOOST']
731   boost_libpath = env_cache['BOOST_LIBPATH']
732
733 if boost_libpath is not None:
734   env.AppendUnique(LIBPATH = [boost_libpath])
735
736
737 env['ENABLE_NLS'] = env['nls']
738
739 if not fast_start:
740   if not env['ENABLE_NLS']:
741     intl_libs = []
742     included_gettext = False
743   else:
744     # check gettext libraries
745     gettext_opt = ARGUMENTS.get('gettext', 'auto')
746     # check for system gettext
747     succ = False
748     if gettext_opt in ['auto', 'system']:
749       if conf.CheckLib('intl'):
750         included_gettext = False
751         intl_libs = ['intl']
752         succ = True
753       else: # no found
754         if gettext_opt == 'system':
755           print "Can not find system gettext library"
756           print "Please supply a path through extra_lib_path and try again."
757           print "Or use gettext=included to use included gettext libraries."
758           Exit(2)
759     # now, auto and succ = false, or gettext=included
760     if not succ:
761       # we do not need to set LIBPATH now.
762       included_gettext = True
763       intl_libs = ['included_intl']
764   env_cache['INCLUDED_GETTEXT'] = included_gettext
765   env_cache['INTL_LIBS'] = intl_libs
766 else:
767   included_gettext = env_cache['INCLUDED_GETTEXT']
768   intl_libs = env_cache['INTL_LIBS']
769
770 #
771 # check for msgfmt command
772 if not fast_start:
773   env['MSGFMT'] = conf.CheckCommand('msgfmt')
774   env_cache['MSGFMT'] = env['MSGFMT']
775 else:
776   env['MSGFMT'] = env_cache['MSGFMT']
777
778 #
779 # Customized builders
780 #
781 # install customized builders
782 env['BUILDERS']['substFile'] = Builder(action = utils.env_subst)
783
784
785 #----------------------------------------------------------
786 # Generating config.h
787 #----------------------------------------------------------
788 aspell_lib = 'aspell'
789 # assume that we use aspell, aspelld compiled for msvc
790 if platform_name == 'win32' and mode == 'debug' and use_vc:
791   aspell_lib = 'aspelld'
792
793 # check the existence of config.h
794 config_h = os.path.join(env.Dir('$BUILDDIR/common').path, 'config.h')
795 boost_config_h = os.path.join(env.Dir('$BUILDDIR/boost').path, 'config.h')
796 if not fast_start or not os.path.isfile(boost_config_h) \
797   or not os.path.isfile(config_h):
798   #
799   print "Creating %s..." % boost_config_h
800   #
801   utils.createConfigFile(conf,
802     config_file = boost_config_h,
803     config_pre = '''/* boost/config.h.  Generated by SCons.  */
804
805 /* -*- C++ -*- */
806 /*
807  * \file config.h
808  * This file is part of LyX, the document processor.
809  * Licence details can be found in the file COPYING.
810  *
811  * This is the compilation configuration file for LyX.
812  * It was generated by scon.
813  * You might want to change some of the defaults if something goes wrong
814  * during the compilation.
815  */
816
817 #ifndef _BOOST_CONFIG_H
818 #define _BOOST_CONFIG_H
819 ''',
820     headers = [
821       ('ostream', 'HAVE_OSTREAM', 'cxx'),
822       ('locale', 'HAVE_LOCALE', 'cxx'),
823       ('sstream', 'HAVE_SSTREAM', 'cxx'),
824       #('newapis.h', 'HAVE_NEWAPIS_H', 'c'),
825     ],
826     custom_tests = [
827       (env.has_key('assertions') and env['assertions'],
828         'ENABLE_ASSERTIONS',
829         'Define if you want assertions to be enabled in the code'
830       ),
831     ],
832     config_post = '''
833
834 #if defined(HAVE_OSTREAM) && defined(HAVE_LOCALE) && defined(HAVE_SSTREAM)
835 #  define USE_BOOST_FORMAT 1
836 #else
837 #  define USE_BOOST_FORMAT 0
838 #endif
839
840 #if !defined(ENABLE_ASSERTIONS)
841 #  define BOOST_DISABLE_ASSERTS 1
842 #endif
843 #define BOOST_ENABLE_ASSERT_HANDLER 1
844
845 #define BOOST_DISABLE_THREADS 1
846 #define BOOST_NO_WREGEX 1
847 #define BOOST_NO_WSTRING 1
848
849 #ifdef __CYGWIN__
850 #  define BOOST_POSIX 1
851 #endif
852
853 #define BOOST_ALL_NO_LIB 1
854
855 #if defined(HAVE_NEWAPIS_H)
856 #  define WANT_GETFILEATTRIBUTESEX_WRAPPER 1
857 #endif
858
859 #endif
860 '''
861   )
862   #
863   print "\nGenerating %s..." % config_h
864
865   # AIKSAURUS_H_LOCATION
866   if (conf.CheckCXXHeader("Aiksaurus.h")):
867     aik_location = '<Aiksaurus.h>'
868   elif (conf.CheckCXXHeader("Aiksaurus/Aiksaurus.h")):
869     aik_location = '<Aiksaurus/Aiksaurus.h>'
870   else:
871     aik_location = ''
872
873   # determine headers to use
874   spell_opt = ARGUMENTS.get('spell', 'auto')
875   env['USE_ASPELL'] = False
876   env['USE_PSPELL'] = False
877   env['USE_ISPELL'] = False
878   if spell_opt in ['auto', 'aspell'] and conf.CheckLib(aspell_lib):
879     spell_engine = 'USE_ASPELL'
880   elif spell_opt in ['auto', 'pspell'] and conf.CheckLib('pspell'):
881     spell_engine = 'USE_PSPELL'
882   elif spell_opt in ['auto', 'ispell'] and conf.CheckLib('ispell'):
883     spell_engine = 'USE_ISPELL'
884   else:
885     spell_engine = None
886
887   if spell_engine is not None:
888     env[spell_engine] = True
889   else:
890     if spell_opt == 'auto':
891       print "Warning: Can not locate any spell checker"
892     elif spell_opt != 'no':
893       print "Warning: Can not locate specified spell checker:", spell_opt
894       Exit(1)
895
896   # check arg types of select function
897   (select_arg1, select_arg234, select_arg5) = conf.CheckSelectArgType()
898
899   #
900   # create config.h
901   result = utils.createConfigFile(conf,
902     config_file = config_h,
903     config_pre = '''/* config.h.  Generated by SCons.  */
904
905 /* -*- C++ -*- */
906 /*
907  * \file config.h
908  * This file is part of LyX, the document processor.
909  * Licence details can be found in the file COPYING.
910  *
911  * This is the compilation configuration file for LyX.
912  * It was generated by scon.
913  * You might want to change some of the defaults if something goes wrong
914  * during the compilation.
915  */
916
917 #ifndef _CONFIG_H
918 #define _CONFIG_H
919 ''',
920     headers = [
921       ('io.h', 'HAVE_IO_H', 'c'),
922       ('limits.h', 'HAVE_LIMITS_H', 'c'),
923       ('locale.h', 'HAVE_LOCALE_H', 'c'),
924       ('process.h', 'HAVE_PROCESS_H', 'c'),
925       ('stdlib.h', 'HAVE_STDLIB_H', 'c'),
926       ('sys/stat.h', 'HAVE_SYS_STAT_H', 'c'),
927       ('sys/time.h', 'HAVE_SYS_TIME_H', 'c'),
928       ('sys/types.h', 'HAVE_SYS_TYPES_H', 'c'),
929       ('sys/utime.h', 'HAVE_SYS_UTIME_H', 'c'),
930       ('sys/socket.h', 'HAVE_SYS_SOCKET_H', 'c'),
931       ('unistd.h', 'HAVE_UNISTD_H', 'c'),
932       ('utime.h', 'HAVE_UTIME_H', 'c'),
933       ('direct.h', 'HAVE_DIRECT_H', 'c'),
934       ('istream', 'HAVE_ISTREAM', 'cxx'),
935       ('ios', 'HAVE_IOS', 'cxx'),
936     ],
937     functions = [
938       ('open', 'HAVE_OPEN', None),
939       ('close', 'HAVE_CLOSE', None),
940       ('popen', 'HAVE_POPEN', None),
941       ('pclose', 'HAVE_PCLOSE', None),
942       ('_open', 'HAVE__OPEN', None),
943       ('_close', 'HAVE__CLOSE', None),
944       ('_popen', 'HAVE__POPEN', None),
945       ('_pclose', 'HAVE__PCLOSE', None),
946       ('getpid', 'HAVE_GETPID', None),
947       ('_getpid', 'HAVE__GETPID', None),
948       ('mkdir', 'HAVE_MKDIR', None),
949       ('_mkdir', 'HAVE__MKDIR', None),
950       ('mktemp', 'HAVE_MKTEMP', None),
951       ('mkstemp', 'HAVE_MKSTEMP', None),
952       ('strerror', 'HAVE_STRERROR', None),
953       ('count', 'HAVE_STD_COUNT', '''
954 #include <algorithm>
955 int count()
956 {
957   char a[] = "hello";
958   return std::count(a, a+5, 'l');
959 }
960 '''),
961       ('getcwd', 'HAVE_GETCWD', None),
962       ('setenv', 'HAVE_SETENV', None),
963       ('putenv', 'HAVE_PUTENV', None),
964       ('fcntl', 'HAVE_FCNTL', None),
965     ],
966     types = [
967       ('std::istreambuf_iterator<std::istream>', 'HAVE_DECL_ISTREAMBUF_ITERATOR',
968         '#include <streambuf>\n#include <istream>')
969     ],
970     libs = [
971       ('gdi32', 'HAVE_LIBGDI32'),
972       (('iconv', 'libiconv'), 'HAVE_ICONV', 'ICONV_LIB'),
973       (('Aiksaurus', 'libAiksaurus'), 'HAVE_LIBAIKSAURUS', 'AIKSAURUS_LIB'),
974     ],
975     custom_tests = [
976       (conf.CheckType('pid_t', includes='#include <sys/types.h>'),
977         'HAVE_PID_T',
978         'Define is sys/types.h does not have pid_t',
979         '',
980         '#define pid_t int',
981       ),
982       (conf.CheckCXXGlobalCstd(),
983         'CXX_GLOBAL_CSTD',
984         'Define if your C++ compiler puts C library functions in the global namespace'
985       ),
986       (conf.CheckMkdirOneArg(),
987         'MKDIR_TAKES_ONE_ARG',
988         'Define if mkdir takes only one argument.'
989       ),
990       (conf.CheckLC_MESSAGES(),
991         'HAVE_LC_MESSAGES',
992         'Define if your <locale.h> file defines LC_MESSAGES.'
993       ),
994       (devel_version, 'DEVEL_VERSION', 'Whether or not a development version'),
995       (env['nls'],
996         'ENABLE_NLS',
997         "Define to 1 if translation of program messages to the user's native anguage is requested.",
998       ),
999       (env['nls'] and not included_gettext,
1000         'HAVE_GETTEXT',
1001         'Define to 1 if using system gettext library'
1002       ),
1003       (env.has_key('warnings') and env['warnings'],
1004         'WITH_WARNINGS',
1005         'Define this if you want to see the warning directives put here and there by the developpers to get attention'
1006       ),
1007       (env.has_key('concept_checks') and env['concept_checks'],
1008         '_GLIBCXX_CONCEPT_CHECKS',
1009         'libstdc++ concept checking'
1010       ),
1011       (env.has_key('stdlib_debug') and env['stdlib_debug'],
1012         '_GLIBCXX_DEBUG',
1013         'libstdc++ debug mode'
1014       ),
1015       (env.has_key('stdlib_debug') and env['stdlib_debug'],
1016         '_GLIBCXX_DEBUG_PEDANTIC',
1017         'libstdc++ pedantic debug mode'
1018       ),
1019       (os.name != 'nt', 'BOOST_POSIX',
1020         'Indicates to boost which API to use (posix or windows).'
1021       ),
1022       (spell_engine is not None, spell_engine,
1023         'Spell engine to use'
1024       ),
1025     ],
1026     extra_items = [
1027       ('#define PACKAGE "%s%s"' % (package, program_suffix),
1028         'Name of package'),
1029       ('#define PACKAGE_BUGREPORT "%s"' % package_bugreport,
1030         'Define to the address where bug reports for this package should be sent.'),
1031       ('#define PACKAGE_NAME "%s"' % package_name,
1032         'Define to the full name of this package.'),
1033       ('#define PACKAGE_STRING "%s"' % package_string,
1034         'Define to the full name and version of this package.'),
1035       ('#define PACKAGE_TARNAME "%s"' % package_tarname,
1036         'Define to the one symbol short name of this package.'),
1037       ('#define PACKAGE_VERSION "%s"' % package_version,
1038         'Define to the version of this package.'),
1039       ('#define BOOST_ALL_NO_LIB 1',
1040         'disable automatic linking of boost libraries.'),
1041       ('#define USE_%s_PACKAGING 1' % packaging_method.upper(),
1042         'Packaging method'),
1043       ('#define AIKSAURUS_H_LOCATION ' + aik_location,
1044         'Aiksaurus include file'),
1045       ('#define SELECT_TYPE_ARG1 %s' % select_arg1,
1046         "Define to the type of arg 1 for `select'."),
1047       ('#define SELECT_TYPE_ARG234 %s' % select_arg234,
1048         "Define to the type of arg 2, 3, 4 for `select'."),
1049       ('#define SELECT_TYPE_ARG5 %s' % select_arg5,
1050         "Define to the type of arg 5 for `select'."),
1051     ],
1052     config_post = '''/************************************************************
1053  ** You should not need to change anything beyond this point */
1054
1055 #ifndef HAVE_STRERROR
1056 #if defined(__cplusplus)
1057 extern "C"
1058 #endif
1059 char * strerror(int n);
1060 #endif
1061
1062 #ifdef HAVE_MKSTEMP
1063 #ifndef HAVE_DECL_MKSTEMP
1064 #if defined(__cplusplus)
1065 extern "C"
1066 #endif
1067 int mkstemp(char*);
1068 #endif
1069 #endif
1070
1071 #include <../boost/config.h>
1072
1073 #endif
1074 '''
1075   )
1076
1077   # these keys are needed in env
1078   for key in ['USE_ASPELL', 'USE_PSPELL', 'USE_ISPELL', 'HAVE_FCNTL',\
1079     'HAVE_ICONV', 'HAVE_LIBGDI32', 'HAVE_LIBAIKSAURUS',
1080     'ICONV_LIB', 'AIKSAURUS_LIB']:
1081     # USE_ASPELL etc does not go through result
1082     if result.has_key(key):
1083       env[key] = result[key]
1084     env_cache[key] = env[key]
1085
1086   #
1087   # if nls=yes and gettext=included, create intl/config.h
1088   # intl/libintl.h etc
1089   #
1090   intl_config_h = os.path.join(env.Dir('$BUILDDIR/intl').path, 'config.h')
1091   if env['nls'] and included_gettext:
1092     #
1093     print "Creating %s..." % intl_config_h
1094     #
1095     # create intl/config.h
1096     result = utils.createConfigFile(conf,
1097       config_file = intl_config_h,
1098       config_pre = '''/* intl/config.h.  Generated by SCons.  */
1099
1100 /* -*- C++ -*- */
1101 /*
1102  * \file config.h
1103  * This file is part of LyX, the document processor.
1104  * Licence details can be found in the file COPYING.
1105  *
1106  * This is the compilation configuration file for LyX.
1107  * It was generated by scon.
1108  * You might want to change some of the defaults if something goes wrong
1109  * during the compilation.
1110  */
1111
1112 #ifndef _CONFIG_H
1113 #define _CONFIG_H
1114 ''',
1115       headers = [
1116         ('unistd.h', 'HAVE_UNISTD_H', 'c'),
1117         ('inttypes.h', 'HAVE_INTTYPES_H', 'c'),
1118         ('string.h', 'HAVE_STRING_H', 'c'),
1119         ('strings.h', 'HAVE_STRINGS_H', 'c'),
1120         ('argz.h', 'HAVE_ARGZ_H', 'c'),
1121         ('limits.h', 'HAVE_LIMITS_H', 'c'),
1122         ('alloca.h', 'HAVE_ALLOCA_H', 'c'),
1123         ('stddef.h', 'HAVE_STDDEF_H', 'c'),
1124         ('stdint.h', 'HAVE_STDINT_H', 'c'),
1125         ('sys/param.h', 'HAVE_SYS_PARAM_H', 'c'),
1126       ],
1127       functions = [
1128         ('getcwd', 'HAVE_GETCWD', None),
1129         ('stpcpy', 'HAVE_STPCPY', None),
1130         ('strcasecmp', 'HAVE_STRCASECMP', None),
1131         ('strdup', 'HAVE_STRDUP', None),
1132         ('strtoul', 'HAVE_STRTOUL', None),
1133         ('alloca', 'HAVE_ALLOCA', None),
1134         ('__fsetlocking', 'HAVE___FSETLOCKING', None),
1135         ('mempcpy', 'HAVE_MEMPCPY', None),
1136         ('__argz_count', 'HAVE___ARGZ_COUNT', None),
1137         ('__argz_next', 'HAVE___ARGZ_NEXT', None),
1138         ('__argz_stringify', 'HAVE___ARGZ_STRINGIFY', None),
1139         ('setlocale', 'HAVE_SETLOCALE', None),
1140         ('tsearch', 'HAVE_TSEARCH', None),
1141         ('getegid', 'HAVE_GETEGID', None),
1142         ('getgid', 'HAVE_GETGID', None),
1143         ('getuid', 'HAVE_GETUID', None),
1144         ('wcslen', 'HAVE_WCSLEN', None),
1145         ('asprintf', 'HAVE_ASPRINTF', None),
1146         ('wprintf', 'HAVE_WPRINTF', None),
1147         ('snprintf', 'HAVE_SNPRINTF', None),
1148         ('printf', 'HAVE_POSIX_PRINTF', None),
1149         ('fcntl', 'HAVE_FCNTL', None),
1150       ],
1151       types = [
1152         ('intmax_t', 'HAVE_INTMAX_T', None),
1153         ('long double', 'HAVE_LONG_DOUBLE', None),
1154         ('long long', 'HAVE_LONG_LONG', None),
1155         ('wchar_t', 'HAVE_WCHAR_T', None),
1156         ('wint_t', 'HAVE_WINT_T', None),
1157         ('uintmax_t', 'HAVE_INTTYPES_H_WITH_UINTMAX', '#include <inttypes.h>'),
1158         ('uintmax_t', 'HAVE_STDINT_H_WITH_UINTMAX', '#include <stdint.h>'),
1159       ],
1160       libs = [
1161         (('iconv', 'libiconv'), 'HAVE_ICONV', 'ICONV_LIB'),
1162         ('c', 'HAVE_LIBC'),
1163       ],
1164       custom_tests = [
1165         (conf.CheckLC_MESSAGES(),
1166           'HAVE_LC_MESSAGES',
1167           'Define if your <locale.h> file defines LC_MESSAGES.'
1168         ),
1169         (conf.CheckIconvConst(),
1170           'ICONV_CONST',
1171           'Define as const if the declaration of iconv() needs const.',
1172           '#define ICONV_CONST',
1173           '#define ICONV_CONST const',
1174         ),
1175         (conf.CheckType('intmax_t', includes='#include <stdint.h>') or \
1176          conf.CheckType('intmax_t', includes='#include <inttypes.h>'),
1177           'HAVE_INTMAX_T',
1178           "Define to 1 if you have the `intmax_t' type."
1179         ),
1180         (env.has_key('nls') and env['nls'],
1181           'ENABLE_NLS',
1182           "Define to 1 if translation of program messages to the user's native anguage is requested.",
1183         ),
1184       ],
1185       config_post = '#endif'
1186     )
1187
1188     # these keys are needed in env
1189     for key in ['HAVE_ASPRINTF', 'HAVE_WPRINTF', 'HAVE_SNPRINTF', \
1190       'HAVE_POSIX_PRINTF', 'HAVE_ICONV', 'HAVE_LIBC']:
1191       # USE_ASPELL etc does not go through result
1192       if result.has_key(key):
1193         env[key] = result[key]
1194       env_cache[key] = env[key]
1195
1196 else:
1197   #
1198   # this comes as a big surprise, without this line
1199   # (doing nothing obvious), adding fast_start=yes
1200   # to a build with fast_start=no will result in a rebuild
1201   # Note that the exact header file to check does not matter
1202   conf.CheckCHeader('io.h')
1203   # only a few variables need to be rescanned
1204   for key in ['USE_ASPELL', 'USE_PSPELL', 'USE_ISPELL', 'HAVE_FCNTL',\
1205     'HAVE_ICONV', 'HAVE_LIBGDI32', 'HAVE_LIBAIKSAURUS',
1206     'ICONV_LIB', 'AIKSAURUS_LIB']:
1207     env[key] = env_cache[key]
1208   #
1209   # nls related keys
1210   if env['nls'] and included_gettext:
1211     # only a few variables need to be rescanned
1212     for key in ['HAVE_ASPRINTF', 'HAVE_WPRINTF', 'HAVE_SNPRINTF', \
1213       'HAVE_POSIX_PRINTF', 'HAVE_ICONV', 'HAVE_LIBC']:
1214       env[key] = env_cache[key]
1215
1216 # this looks misplaced, but intl/libintl.h is needed by src/message.C
1217 if env['nls'] and included_gettext:
1218   # libgnuintl.h.in => libintl.h
1219   env.substFile('$BUILDDIR/intl/libintl.h', '$TOP_SRCDIR/intl/libgnuintl.h.in')
1220   env.Command('$BUILDDIR/intl/libgnuintl.h', '$BUILDDIR/intl/libintl.h',
1221     [Copy('$TARGET', '$SOURCE')])
1222
1223 #
1224 # Finish auto-configuration
1225 env = conf.Finish()
1226
1227 #----------------------------------------------------------
1228 # Now set up our build process accordingly
1229 #----------------------------------------------------------
1230
1231 #
1232 # QT_LIB
1233 #
1234 # NOTE: Tool('qt') or Tool('qt4') will be loaded later
1235 # in their respective directory and specialized env.
1236 try:
1237   if frontend in ['qt2', 'qt3']:
1238     # note: env.Tool('qt') my set QT_LIB to qt
1239     qt_libs = ['qt-mt']
1240     frontend_libs = ['qt-mt']
1241   elif frontend == 'qt4':
1242     qt_libs = ['QtCore', 'QtGui']
1243     # set the right lib names
1244     if platform_name == 'win32':
1245       if mode == 'debug' and use_vc:
1246         qt_lib_suffix = 'd4'
1247       else:
1248         qt_lib_suffix = '4'
1249     else:
1250       if mode == 'debug':
1251         qt_lib_suffix = '_debug'
1252       else:
1253         qt_lib_suffix = ''
1254     frontend_libs = [x + qt_lib_suffix for x in qt_libs]
1255 except:
1256   print "Can not locate qt tools"
1257   print "What I get is "
1258   print "  QTDIR: ", env['QTDIR']
1259
1260
1261 if platform_name in ['win32', 'cygwin']:
1262   # the final link step needs stdc++ to succeed under mingw
1263   # FIXME: shouldn't g++ automatically link to stdc++?
1264   if use_vc:
1265     system_libs = ['shlwapi', 'shell32', 'advapi32', 'zdll']
1266   else:
1267     system_libs = ['shlwapi', 'stdc++', 'z']
1268 elif platform_name == 'cygwin' and env['X11']:
1269   system_libs = ['GL',  'Xmu', 'Xi', 'Xrender', 'Xrandr', 'Xcursor',
1270     'Xft', 'freetype', 'fontconfig', 'Xext', 'X11', 'SM', 'ICE', 'resolv',
1271     'pthread', 'z']
1272 else:
1273   system_libs = ['z']
1274
1275 libs = [
1276   ('HAVE_ICONV', env['ICONV_LIB']),
1277   ('HAVE_LIBGDI32', 'gdi32'),
1278   ('HAVE_LIBAIKSAURUS', env['AIKSAURUS_LIB']),
1279   ('USE_ASPELL', aspell_lib),
1280   ('USE_ISPELL', 'ispell'),
1281   ('USE_PSPELL', 'pspell'),
1282 ]
1283
1284 for lib in libs:
1285   if env[lib[0]]:
1286     system_libs.append(lib[1])
1287
1288 #
1289 # Build parameters CPPPATH etc
1290 #
1291 if env['X11']:
1292   env.AppendUnique(LIBPATH = ['/usr/X11R6/lib'])
1293
1294 #
1295 # boost: for boost header files
1296 # BUILDDIR/common: for config.h
1297 # TOP_SRCDIR/src: for support/* etc
1298 #
1299 env['CPPPATH'] += ['$TOP_SRCDIR/boost', '$BUILDDIR/common', '$TOP_SRCDIR/src']
1300 # for intl/config.h, intl/libintl.h and intl/libgnuintl.h
1301 if env['nls'] and included_gettext:
1302   env['CPPPATH'].append('$BUILDDIR/intl')
1303 #
1304 # QT_INC_PATH is not needed for *every* source file
1305 env['CPPPATH'].remove(qt_inc_path)
1306
1307 #
1308 # A Link script for cygwin see
1309 # http://www.cygwin.com/ml/cygwin/2004-09/msg01101.html
1310 # http://www.cygwin.com/ml/cygwin-apps/2004-09/msg00309.html
1311 # for details
1312 #
1313 if platform_name == 'cygwin':
1314   ld_script_path = '/usr/lib/qt3/mkspecs/cygwin-g++'
1315   ld_script = utils.installCygwinLDScript(ld_script_path)
1316   env.AppendUnique(LINKFLAGS = ['-Wl,--enable-runtime-pseudo-reloc',
1317     '-Wl,--script,%s' % ld_script, '-Wl,-s'])
1318
1319 #
1320 # Report results
1321 #
1322 # fill in the version info
1323 env['VERSION_INFO'] = '''Configuration
1324   Host type:                      %s
1325   Special build flags:            %s
1326   C   Compiler:                   %s
1327   C   Compiler flags:             %s %s
1328   C++ Compiler:                   %s
1329   C++ Compiler LyX flags:         %s
1330   C++ Compiler flags:             %s %s
1331   Linker flags:                   %s
1332   Linker user flags:              %s
1333 Build info:
1334   Builing directory:              %s
1335   Local library directory:        %s
1336   Libraries paths:                %s
1337   Boost libraries:                %s
1338   Frontend libraries:             %s
1339   System libraries:               %s
1340   include search path:            %s
1341 Frontend:
1342   Frontend:                       %s
1343   Packaging:                      %s
1344   LyX dir:                        %s
1345   LyX files dir:                  %s
1346 ''' % (platform_name,
1347   env.subst('$CCFLAGS'), env.subst('$CC'),
1348   env.subst('$CPPFLAGS'), env.subst('$CFLAGS'),
1349   env.subst('$CXX'), env.subst('$CXXFLAGS'),
1350   env.subst('$CPPFLAGS'), env.subst('$CXXFLAGS'),
1351   env.subst('$LINKFLAGS'), env.subst('$LINKFLAGS'),
1352   env.subst('$BUILDDIR'), env.subst('$LOCALLIBPATH'),
1353   str(env['LIBPATH']), str(boost_libraries),
1354   str(frontend_libs), str(system_libs), str(env['CPPPATH']),
1355   frontend, packaging_method,
1356   prefix, env['LYX_DIR'])
1357
1358 if frontend in ['qt2', 'qt3', 'qt4']:
1359   env['VERSION_INFO'] += '''  include dir:                    %s
1360   library dir:                    %s
1361   X11:                            %s
1362 ''' % (qt_inc_path, qt_lib_path, env['X11'])
1363
1364 if not fast_start:
1365   print env['VERSION_INFO']
1366
1367 #
1368 # Mingw command line may be too short for our link usage,
1369 # Here we use a trick from scons wiki
1370 # http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/LongCmdLinesOnWin32
1371 #
1372 # I also would like to add logging (commands only) capacity to the
1373 # spawn system.
1374 logfile = env.get('logfile', default_log_file)
1375 if logfile != '' or platform_name == 'win32':
1376   import time
1377   utils.setLoggedSpawn(env, logfile, longarg = (platform_name == 'win32'),
1378     info = '''# This is a log of commands used by scons to build lyx
1379 # Time: %s
1380 # Command: %s
1381 # Info: %s
1382 ''' % (time.asctime(), ' '.join(sys.argv),
1383   env['VERSION_INFO'].replace('\n','\n# ')) )
1384
1385
1386 # Cleanup stuff
1387 #
1388 # -h will print out help info
1389 Help(opts.GenerateHelpText(env))
1390
1391 # save environment settings (for fast_start option)
1392 cache_file = open(env_cache_file, 'w')
1393 cPickle.dump(env_cache, cache_file)
1394 cache_file.close()
1395
1396
1397 #----------------------------------------------------------
1398 # Start building
1399 #----------------------------------------------------------
1400 # this has been the source of problems on some platforms...
1401 # I find that I need to supply it with full path name
1402 env.SConsignFile(os.path.join(Dir(env['BUILDDIR']).abspath, '.sconsign'))
1403 # this usage needs further investigation.
1404 #env.CacheDir('%s/Cache/%s' % (env['BUILDDIR'], frontend))
1405
1406 print "Building all targets recursively"
1407
1408 if env.has_key('rebuild'):
1409   rebuild_targets = env['rebuild'].split(',')
1410 else:
1411   rebuild_targets = None
1412
1413 def libExists(libname):
1414   ''' Check whether or not lib $LOCALLIBNAME/libname already exists'''
1415   return os.path.isfile(File(env.subst('$LOCALLIBPATH/${LIBPREFIX}%s$LIBSUFFIX'%libname)).abspath)
1416
1417 targets = BUILD_TARGETS
1418 # msvc need to pass full target name, so I have to look for path/lyx etc
1419 build_lyx = targets == [] or True in ['lyx' in x for x in targets] \
1420   or 'install' in targets or 'all' in targets
1421 build_boost = (env['INCLUDED_BOOST'] and not libExists('boost_regex')) or 'boost' in targets
1422 build_intl = (included_gettext and not libExists('included_intl')) or 'intl' in targets
1423 build_support = build_lyx or True in [x in targets for x in ['support', 'client', 'tex2lyx']]
1424 build_mathed = build_lyx or 'mathed' in targets
1425 build_insets = build_lyx or 'insets' in targets
1426 build_frontends = build_lyx or 'frontends' in targets
1427 build_graphics = build_lyx or 'graphics' in targets
1428 build_controllers = build_lyx or 'controllers' in targets
1429 build_client = True in ['client' in x for x in targets] \
1430   or 'install' in targets or 'all' in targets
1431 build_tex2lyx = True in ['tex2lyx' in x for x in targets] \
1432   or 'install' in targets or 'all' in targets
1433 build_lyxbase = build_lyx or 'lyxbase' in targets
1434 build_po = 'po' in targets or 'install' in targets or 'all' in targets
1435 build_qt2 = (build_lyx and frontend == 'qt2') or 'qt2' in targets
1436 build_qt3 = (build_lyx and frontend == 'qt3') or 'qt3' in targets
1437 build_qt4 = (build_lyx and frontend == 'qt4') or 'qt4' in targets
1438 build_msvs_projects = use_vc and 'msvs_projects' in targets
1439
1440
1441 # now, if rebuild_targets is specified, do not rebuild some targets
1442 rebuild_targets = rebuild_targets
1443 if rebuild_targets:
1444   def ifBuildLib(name, libname, old_value):
1445     # explicitly asked to rebuild
1446     if name in rebuild_targets:
1447       return True
1448     # else if not rebuild, and if the library already exists
1449     elif libExists(libname):
1450       return False
1451     # do not change the original value
1452     else:
1453       return old_value
1454   build_boost = ifBuildLib('boost', 'included_boost_filesystem', build_boost)
1455   build_intl = ifBuildLib('intl', 'included_intl', build_intl)
1456   build_support = ifBuildLib('support', 'support', build_support)
1457   build_mathed = ifBuildLib('mathed', 'mathed', build_mathed)
1458   build_insets = ifBuildLib('insets', 'insets', build_insets)
1459   build_frontends = ifBuildLib('frontends', 'frontends', build_frontends)
1460   build_graphics = ifBuildLib('graphics', 'graphics', build_graphics)
1461   build_controllers = ifBuildLib('controllers', 'controllers', build_controllers)
1462   build_lyxbase = ifBuildLib('lyxbase', 'lyxbase_pre', build_lyxbase)
1463   build_qt2 = ifBuildLib('qt2', 'qt2', build_qt2)
1464   build_qt3 = ifBuildLib('qt3', 'qt3', build_qt3)
1465   build_qt4 = ifBuildLib('qt4', 'qt4', build_qt4)
1466
1467 # sync frontend and frontend (maybe build qt4 with frontend=qt3)
1468 if build_qt2:
1469   frontend = 'qt2'
1470 elif build_qt3:
1471   frontend = 'qt3'
1472 elif build_qt4:
1473   frontend = 'qt4'
1474
1475
1476 if build_boost:
1477   #
1478   # boost libraries
1479   #
1480   # special builddir
1481   env.BuildDir('$BUILDDIR/boost', '$TOP_SRCDIR/boost/libs', duplicate = 0)
1482
1483   boostenv = env.Copy()
1484   #
1485   #
1486   # boost use its own config.h
1487   boostenv['CPPPATH'] = ['$TOP_SRCDIR/boost', '$BUILDDIR/boost'] + extra_inc_paths
1488   boostenv.AppendUnique(CCFLAGS = ['-DBOOST_USER_CONFIG="<config.h>"'])
1489
1490   for lib in boost_libs:
1491     print 'Processing files in boost/libs/%s/src...' % lib
1492     boostlib = boostenv.StaticLibrary(
1493       target = '$LOCALLIBPATH/included_boost_%s' % lib,
1494       source = utils.globSource(dir = env.subst('$TOP_SRCDIR/boost/libs/%s/src' % lib),
1495         pattern = '*.cpp', build_dir = '$BUILDDIR/boost/%s/src' % lib)
1496     )
1497     Alias('boost', boostlib)
1498
1499
1500 if build_intl:
1501   #
1502   # intl
1503   #
1504   intlenv = env.Copy()
1505
1506   print "Processing files in intl..."
1507
1508   env.BuildDir('$BUILDDIR/intl', '$TOP_SRCDIR/intl', duplicate = 0)
1509
1510   # we need the original C compiler for these files
1511   intlenv['CC'] = C_COMPILER
1512   intlenv['CCFLAGS'] = C_CCFLAGS
1513   if use_vc:
1514     intlenv.Append(CCFLAGS=['/Dinline#', '/D__attribute__(x)#', '/Duintmax_t=UINT_MAX'])
1515   # intl does not use global config.h
1516   intlenv['CPPPATH'] = ['$BUILDDIR/intl'] + extra_inc_paths
1517
1518   intlenv.Append(CCFLAGS = [
1519     r'-DLOCALEDIR=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1520     r'-DLOCALE_ALIAS_PATH=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1521     r'-DLIBDIR=\"' + env['TOP_SRCDIR'].replace('\\', '\\\\') + r'/lib\"',
1522     '-DIN_LIBINTL',
1523     '-DENABLE_RELOCATABLE=1',
1524     '-DIN_LIBRARY',
1525     r'-DINSTALLDIR=\"' + prefix.replace('\\', '\\\\') + r'/lib\"',
1526     '-DNO_XMALLOC',
1527     '-Dset_relocation_prefix=libintl_set_relocation_prefix',
1528     '-Drelocate=libintl_relocate',
1529     '-DDEPENDS_ON_LIBICONV=1',
1530     '-DHAVE_CONFIG_H'
1531     ]
1532   )
1533
1534   intl = intlenv.StaticLibrary(
1535     target = '$LOCALLIBPATH/included_intl',
1536     LIBS = ['c'],
1537     source = utils.globSource(dir = env.subst('$TOP_SRCDIR/intl'), pattern = '*.c',
1538       exclude = ['vasnprintf.c', 'printf-parse.c', 'printf-args.c', 'os2compat.c'],
1539       build_dir = '$BUILDDIR/intl')
1540   )
1541   Alias('intl', intl)
1542
1543
1544 #
1545 # Now, src code under src/
1546 #
1547 env.BuildDir('$BUILDDIR/common', '$TOP_SRCDIR/src', duplicate = 0)
1548
1549
1550 if build_support:
1551   #
1552   # src/support
1553   #
1554   print "Processing files in src/support..."
1555
1556   env.substFile('$BUILDDIR/common/support/package.C', '$TOP_SRCDIR/src/support/package.C.in')
1557
1558   support = env.StaticLibrary(
1559     target = '$LOCALLIBPATH/support',
1560     source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/support'), pattern = lyx_ext,
1561       exclude = ['os_win32.C', 'os_unix.C', 'os_cygwin.C', 'os_os2.C', 'atexit.c'],
1562       include = ['package.C'], build_dir = '$BUILDDIR/common/support')
1563   )
1564   Alias('support', support)
1565
1566
1567 if build_mathed:
1568   #
1569   # src/mathed
1570   #
1571   print "Processing files in src/mathed..."
1572   #
1573   mathed = env.StaticLibrary(
1574     target = '$LOCALLIBPATH/mathed',
1575     source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/mathed'),
1576       pattern = lyx_ext,
1577       exclude = ['math_xyarrowinset.C', 'math_mboxinset.C', 'formulamacro.C'],
1578       build_dir = '$BUILDDIR/common/mathed')
1579   )
1580   Alias('mathed', mathed)
1581
1582
1583 if build_insets:
1584   #
1585   # src/insets
1586   #
1587   print "Processing files in src/insets..."
1588   #
1589   insets = env.StaticLibrary(
1590     target = '$LOCALLIBPATH/insets',
1591     source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/insets'),
1592       pattern = lyx_ext,
1593       exclude = ['insettheorem.C'], build_dir = '$BUILDDIR/common/insets')
1594   )
1595   Alias('insets', insets)
1596
1597
1598 if build_frontends:
1599   #
1600   # src/frontends
1601   #
1602   print "Processing files in src/frontends..."
1603
1604   frontends = env.StaticLibrary(
1605     target = '$LOCALLIBPATH/frontends',
1606     source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends'), pattern = lyx_ext,
1607       build_dir = '$BUILDDIR/common/frontends')
1608   )
1609   Alias('frontends', frontends)
1610
1611
1612 if build_graphics:
1613   #
1614   # src/graphics
1615   #
1616   print "Processing files in src/graphics..."
1617
1618   graphics = env.StaticLibrary(
1619     target = '$LOCALLIBPATH/graphics',
1620     source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/graphics'), pattern = lyx_ext,
1621       build_dir = '$BUILDDIR/common/graphics')
1622   )
1623   Alias('graphics', graphics)
1624
1625
1626 if build_controllers:
1627   #
1628   # src/frontends/controllers
1629   #
1630   print "Processing files in src/frontends/controllers..."
1631
1632   controllers = env.StaticLibrary(
1633     target = '$LOCALLIBPATH/controllers',
1634     source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/controllers'), pattern = lyx_ext,
1635       build_dir = '$BUILDDIR/common/frontends/controllers')
1636   )
1637   Alias('controllers', controllers)
1638
1639
1640 #
1641 # src/frontend/qt2/3/4
1642 #
1643 if build_qt2 or build_qt3 or build_qt4:
1644   env.BuildDir('$BUILDDIR/$frontend', '$TOP_SRCDIR/src/frontend/$frontend', duplicate = 0)
1645
1646
1647 if build_qt2:
1648   print "Processing files in src/frontends/qt2..."
1649
1650   qt2env = env.Copy()
1651   # disable auto scan to speed up non build time
1652   qt2env['QT_AUTOSCAN'] = 0
1653   qt2env['QT_MOCHPREFIX'] = ''
1654
1655   # load qt2 tools
1656   qt2env.Tool('qt')
1657
1658   qt2env.AppendUnique(CPPPATH = [
1659     '$BUILDDIR/common',
1660     '$BUILDDIR/common/images',
1661     '$BUILDDIR/common/frontends',
1662     '$BUILDDIR/common/frontends/qt2',
1663     '$BUILDDIR/common/frontends/controllers',
1664     qt_inc_path]
1665   )
1666
1667   qt2_moc_files = ["$BUILDDIR/common/frontends/qt2/%s" % x for x in Split('''
1668     BulletsModule.C
1669     emptytable.C
1670     FileDialog_private.C
1671     floatplacement.C
1672     iconpalette.C
1673     lengthcombo.C
1674     panelstack.C
1675     QAboutDialog.C
1676     QBibitemDialog.C
1677     QBibtexDialog.C
1678     QBoxDialog.C
1679     QBranchDialog.C
1680     QBrowseBox.C
1681     QChangesDialog.C
1682     QCharacterDialog.C
1683     QCitationDialog.C
1684     QCommandBuffer.C
1685     QCommandEdit.C
1686     QContentPane.C
1687     QDelimiterDialog.C
1688     QDocumentDialog.C
1689     QErrorListDialog.C
1690     QERTDialog.C
1691     QExternalDialog.C
1692     QFloatDialog.C
1693     QGraphicsDialog.C
1694     QIncludeDialog.C
1695     QIndexDialog.C
1696     QLogDialog.C
1697     QLPopupMenu.C
1698     QLPrintDialog.C
1699     QMathDialog.C
1700     QMathMatrixDialog.C
1701     QNoteDialog.C
1702     QParagraphDialog.C
1703     QPrefsDialog.C
1704     QRefDialog.C
1705     QSearchDialog.C
1706     QSendtoDialog.C
1707     qsetborder.C
1708     QShowFileDialog.C
1709     QSpellcheckerDialog.C
1710     QDialogView.C
1711     QTabularCreateDialog.C
1712     QTabularDialog.C
1713     QTexinfoDialog.C
1714     QThesaurusDialog.C
1715     QTocDialog.C
1716     qttableview.C
1717     QtView.C
1718     QURLDialog.C
1719     QVSpaceDialog.C
1720     QWrapDialog.C
1721     QLToolbar.C
1722     socket_callback.C
1723     validators.C
1724   ''')]
1725
1726   # manually moc and uic files for better performance
1727   qt2_moced_files = [qt2env.Moc(x.replace('.C', '_moc.cpp'), x.replace('.C', '.h')) for x in qt2_moc_files]
1728
1729   qt2_uiced_files = [qt2env.Uic('$BUILDDIR/common/frontends/qt2/ui/'+x) for x in \
1730      utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/qt2/ui'), pattern = '*.ui')]
1731
1732   qt2_uiced_cc_files = []
1733   for x in qt2_uiced_files:
1734     qt2_uiced_cc_files.extend(x[1:])
1735
1736   qt2 = qt2env.StaticLibrary(
1737     target = '$LOCALLIBPATH/qt2',
1738     source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/qt2/'), pattern = lyx_ext,
1739       build_dir = '$BUILDDIR/common/frontends/qt2') + qt2_moced_files + qt2_uiced_cc_files
1740   )
1741   Alias('qt2', qt2)
1742
1743
1744 if build_qt3:
1745   print "Processing files in src/frontends/qt3..."
1746
1747   qt3env = env.Copy()
1748   # disable auto scan to speed up non build time
1749   qt3env['QT_AUTOSCAN'] = 0
1750   qt3env['QT_MOCHPREFIX'] = ''
1751
1752   # load qt3 tools
1753   qt3env.Tool('qt')
1754
1755   qt3env.AppendUnique(CPPPATH = [
1756     '$BUILDDIR/common',
1757     '$BUILDDIR/common/images',
1758     '$BUILDDIR/common/frontends',
1759     '$BUILDDIR/common/frontends/qt3',
1760     '$BUILDDIR/common/frontends/controllers',
1761     qt_inc_path]
1762   )
1763
1764   qt3_moc_files = ["$BUILDDIR/common/frontends/qt3/%s" % x for x in Split('''
1765     BulletsModule.C
1766     emptytable.C
1767     FileDialog_private.C
1768     floatplacement.C
1769     iconpalette.C
1770     lengthcombo.C
1771     panelstack.C
1772     QAboutDialog.C
1773     QBibitemDialog.C
1774     QBibtexDialog.C
1775     QBoxDialog.C
1776     QBranchDialog.C
1777     QBrowseBox.C
1778     QChangesDialog.C
1779     QCharacterDialog.C
1780     QCitationDialog.C
1781     QCommandBuffer.C
1782     QCommandEdit.C
1783     QContentPane.C
1784     QDelimiterDialog.C
1785     QDocumentDialog.C
1786     QErrorListDialog.C
1787     QERTDialog.C
1788     QExternalDialog.C
1789     QFloatDialog.C
1790     QGraphicsDialog.C
1791     QIncludeDialog.C
1792     QIndexDialog.C
1793     QLogDialog.C
1794     QViewSourceDialog.C
1795     QLPopupMenu.C
1796     QLPrintDialog.C
1797     QMathDialog.C
1798     QMathMatrixDialog.C
1799     QNoteDialog.C
1800     QParagraphDialog.C
1801     QPrefsDialog.C
1802     QRefDialog.C
1803     QSearchDialog.C
1804     QSendtoDialog.C
1805     qsetborder.C
1806     QShowFileDialog.C
1807     QSpellcheckerDialog.C
1808     QDialogView.C
1809     QTabularCreateDialog.C
1810     QTabularDialog.C
1811     QTexinfoDialog.C
1812     QThesaurusDialog.C
1813     QTocDialog.C
1814     qttableview.C
1815     QtView.C
1816     QURLDialog.C
1817     QVSpaceDialog.C
1818     QWrapDialog.C
1819     QLToolbar.C
1820     socket_callback.C
1821     validators.C
1822   ''')]
1823
1824   # manually moc and uic files for better performance
1825   qt3_moced_files = [qt3env.Moc(x.replace('.C', '_moc.cpp'), x.replace('.C', '.h')) for x in qt3_moc_files]
1826
1827   qt3_uiced_files = [qt3env.Uic('$BUILDDIR/common/frontends/qt3/ui/'+x) for x in \
1828      utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/qt3/ui'), pattern = '*.ui')]
1829
1830   qt3_uiced_cc_files = []
1831   for x in qt3_uiced_files:
1832     qt3_uiced_cc_files.extend(x[1:])
1833
1834   qt3 = qt3env.StaticLibrary(
1835     target = '$LOCALLIBPATH/qt3',
1836     source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/qt3/'), pattern = lyx_ext,
1837       build_dir = '$BUILDDIR/common/frontends/qt3') + qt3_moced_files + qt3_uiced_cc_files
1838   )
1839   Alias('qt3', qt3)
1840
1841
1842 if build_qt4:
1843   print "Processing files in src/frontends/qt4..."
1844
1845   qt4env = env.Copy()
1846   qt4env['QT_AUTOSCAN'] = 0
1847
1848   # local qt4 toolset from
1849   # http://www.iua.upf.es/~dgarcia/Codders/sconstools.html
1850   #
1851   # NOTE: I have to patch qt4.py since it does not automatically
1852   # process .C file!!! (add to cxx_suffixes )
1853   #
1854   qt4env.Tool('qt4', [scons_dir])
1855   qt4env.EnableQt4Modules(qt_libs, debug = (mode == 'debug'))
1856
1857   qt4env.AppendUnique(CPPPATH = [
1858     '$BUILDDIR/common',
1859     '$BUILDDIR/common/images',
1860     '$BUILDDIR/common/frontends',
1861     '$BUILDDIR/common/frontends/qt4',
1862     '$BUILDDIR/common/frontends/controllers',
1863     qt_inc_path
1864     ]
1865   )
1866
1867   # FIXME: replace by something from pkg_config
1868   qt4env.Append(CCFLAGS = [
1869     '-DHAVE_CONFIG_H',
1870     '-DQT_CLEAN_NAMESPACE',
1871     '-DQT_GENUINE_STR',
1872     '-DQT_NO_STL',
1873     '-DQT3_SUPPORT',
1874     ]
1875   )
1876
1877
1878   qt4_moc_files = ["$BUILDDIR/common/frontends/qt4/%s" % x for x in Split('''
1879     BulletsModule.C
1880     emptytable.C
1881     FileDialog_private.C
1882     floatplacement.C
1883     iconpalette.C
1884     lengthcombo.C
1885     InsertTableWidget.C
1886     panelstack.C
1887     QAboutDialog.C
1888     QBibitemDialog.C
1889     QBibtexDialog.C
1890     QBoxDialog.C
1891     QBranchDialog.C
1892     QBranches.C
1893     QChangesDialog.C
1894     QCharacterDialog.C
1895     QCitationDialog.C
1896     QCommandBuffer.C
1897     QCommandEdit.C
1898     QDelimiterDialog.C
1899     QDocumentDialog.C
1900     QErrorListDialog.C
1901     QERTDialog.C
1902     QExternalDialog.C
1903     QFloatDialog.C
1904     QGraphicsDialog.C
1905     QIncludeDialog.C
1906     QIndexDialog.C
1907     Action.C
1908     QLogDialog.C
1909     QViewSourceDialog.C
1910     QViewSource.C
1911     QLMenubar.C
1912     QLPopupMenu.C
1913     QLPrintDialog.C
1914     QMathDialog.C
1915     QMathMatrixDialog.C
1916     QNoteDialog.C
1917     QParagraphDialog.C
1918     QPrefsDialog.C
1919     QRefDialog.C
1920     QSearchDialog.C
1921     QSendtoDialog.C
1922     qsetborder.C
1923     QShowFileDialog.C
1924     QSpellcheckerDialog.C
1925     QDialogView.C
1926     QTabularCreateDialog.C
1927     QTabularDialog.C
1928     QTexinfoDialog.C
1929     QThesaurusDialog.C
1930     TocModel.C
1931     QTocDialog.C
1932     GuiView.C
1933     QURLDialog.C
1934     QVSpaceDialog.C
1935     GuiWorkArea.C
1936     QWrapDialog.C
1937     QLToolbar.C
1938     socket_callback.C
1939     validators.C
1940   ''') ]
1941
1942   #
1943   # Compile resources
1944   #
1945   resources = [qt4env.Uic4(x.split('.')[0]) for x in \
1946     utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/qt4/ui'), pattern = '*.ui',
1947       build_dir = '$BUILDDIR/common/frontends/qt4/ui')]
1948
1949   #
1950   # moc qt4_moc_files, the moced files are included in the original files
1951   #
1952   qt4_moced_files = [qt4env.Moc4(x.replace('.C', '_moc.cpp'), x.replace('.C', '.h')) for x in qt4_moc_files]
1953
1954   qt4 = qt4env.StaticLibrary(
1955     target = '$LOCALLIBPATH/qt4',
1956     source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/frontends/qt4'), pattern = lyx_ext,
1957       exclude = ['QBrowseBox.C'], build_dir = '$BUILDDIR/common/frontends/qt4')
1958   )
1959   Alias('qt4', qt4)
1960
1961
1962 if build_client:
1963   #
1964   # src/client
1965   #
1966   env.BuildDir('$BUILDDIR/common', '$TOP_SRCDIR/src', duplicate = 0)
1967
1968   print "Processing files in src/client..."
1969
1970   if env['HAVE_FCNTL']:
1971     client = env.Program(
1972       target = '$BUILDDIR/common/client/lyxclient',
1973       LIBS = ['support'] + intl_libs + system_libs +
1974         socket_libs + boost_libraries,
1975       source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/client'), pattern = lyx_ext,
1976         build_dir = '$BUILDDIR/common/client')
1977     )
1978     Alias('client', env.Command(os.path.join('$BUILDDIR', os.path.split(str(client[0]))[1]),
1979       client, [Copy('$TARGET', '$SOURCE')]))
1980   else:
1981     client = None
1982   Alias('client', client)
1983
1984
1985 if build_tex2lyx:
1986   #
1987   # tex2lyx
1988   #
1989   print "Processing files in src/tex2lyx..."
1990
1991   tex2lyx_env = env.Copy()
1992   #
1993   tex2lyx_env.Prepend(CPPPATH = ['$BUILDDIR/common/tex2lyx'])
1994   tex2lyx_env.AppendUnique(LIBPATH = ['#$LOCALLIBPATH'])
1995
1996   for file in ['FloatList.C', 'Floating.C', 'counters.C', 'lyxlayout.h', 'lyxlayout.C',
1997     'lyxtextclass.h', 'lyxtextclass.C', 'lyxlex.C', 'lyxlex_pimpl.C']:
1998     env.Command('$BUILDDIR/common/tex2lyx/'+file, '$TOP_SRCDIR/src/'+file,
1999       [Copy('$TARGET', '$SOURCE')])
2000
2001   tex2lyx = tex2lyx_env.Program(
2002     target = '$BUILDDIR/common/tex2lyx/tex2lyx',
2003     LIBS = ['support'] + boost_libraries + system_libs,
2004     source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src/tex2lyx'), pattern = lyx_ext,
2005       include = ['FloatList.C', 'Floating.C', 'counters.C', 'lyxlayout.C',
2006         'lyxtextclass.C', 'lyxlex.C', 'lyxlex_pimpl.C'],
2007       build_dir = '$BUILDDIR/common/tex2lyx')
2008   )
2009   Alias('tex2lyx', env.Command(os.path.join('$BUILDDIR', os.path.split(str(tex2lyx[0]))[1]),
2010     tex2lyx, [Copy('$TARGET', '$SOURCE')]))
2011   Alias('tex2lyx', tex2lyx)
2012
2013
2014 if build_lyxbase:
2015   #
2016   # src/
2017   #
2018   print "Processing files in src..."
2019
2020   env.substFile('$BUILDDIR/common/version.C', '$TOP_SRCDIR/src/version.C.in')
2021
2022   lyx_post_source = Split('''
2023     tabular.C
2024     dimension.C
2025     PrinterParams.C
2026     box.C
2027     Thesaurus.C
2028     SpellBase.C
2029   ''')
2030
2031   if env.has_key('USE_ASPELL') and env['USE_ASPELL']:
2032     lyx_post_source.append('aspell.C')
2033   elif env.has_key('USE_PSPELL') and env['USE_PSPELL']:
2034     lyx_post_source.append('pspell.C')
2035   elif env.has_key('USE_ISPELL') and env['USE_ISPELL']:
2036     lyx_post_source.append('ispell.C')
2037
2038   # msvc requires at least one source file with main()
2039   # so I exclude main.C from lyxbase
2040   lyxbase_pre = env.StaticLibrary(
2041     target = '$LOCALLIBPATH/lyxbase_pre',
2042     source = utils.globSource(dir = env.subst('$TOP_SRCDIR/src'), pattern = lyx_ext,
2043       exclude = lyx_post_source + ['main.C', 'aspell.C', 'pspell.C',
2044         'ispell.C', 'Variables.C', 'Sectioning.C'],
2045       include = ['version.C'], build_dir = '$BUILDDIR/common')
2046   )
2047   lyxbase_post = env.StaticLibrary(
2048     target = '$LOCALLIBPATH/lyxbase_post',
2049     source = ["$BUILDDIR/common/%s" % x for x in lyx_post_source]
2050   )
2051   Alias('lyxbase', lyxbase_pre)
2052   Alias('lyxbase', lyxbase_post)
2053
2054
2055 if build_lyx:
2056   #
2057   # Build lyx with given frontend
2058   #
2059   lyx = env.Program(
2060     target = '$BUILDDIR/$frontend/lyx',
2061     source = ['$BUILDDIR/common/main.C'],
2062     LIBS = [
2063       'lyxbase_pre',
2064       'mathed',
2065       'insets',
2066       'frontends',
2067       frontend,
2068       'controllers',
2069       'graphics',
2070       'support',
2071       'lyxbase_post',
2072       ] +
2073       boost_libraries +
2074       frontend_libs +
2075       intl_libs +
2076       socket_libs +
2077       system_libs
2078   )
2079   # [/path/to/lyx.ext] => lyx-qt3.ext
2080   target_name = os.path.split(str(lyx[0]))[1].replace('lyx', 'lyx-%s' % frontend)
2081   Alias('lyx', env.Command(os.path.join('$BUILDDIR', target_name), lyx,
2082     [Copy('$TARGET', '$SOURCE')]))
2083   Alias('lyx', lyx)
2084
2085
2086 if build_msvs_projects:
2087   def build_project(target, dir, full_target = None,
2088     src_pattern = lyx_ext, include = [], resource = None, rebuildTargetOnly = True):
2089     ''' build mavs project files
2090       target:      alias (correspond to directory name)
2091       dir:         source directory or directories (a list)
2092       full_target: full path/filename of the target
2093       src_pattern: glob pattern
2094       include:     files to include into source
2095       resource:    directory or directories with resource (.ui) files
2096       rebuildTargetOnly:     whether or not only rebuild this target
2097
2098     For non-debug-able targets like static libraries, target (alias) is
2099     enough to build the target. For executable targets, msvs need to know
2100     the full path to start debug them.
2101     '''
2102     if resource is not None:
2103       res = utils.globSource(dir = env.subst('$TOP_SRCDIR/'+resource), pattern = '*.ui',
2104         build_dir = env.subst('$TOP_SRCDIR/'+resource))
2105     else:
2106       res = []
2107     if rebuildTargetOnly:
2108       cmds = 'faststart=yes rebuild='+target
2109     else:
2110       cmds = 'faststart=yes'
2111     if type(dir) == type([]):
2112       src = []
2113       inc = []
2114       for d in dir:
2115         src.extend(utils.globSource(dir = env.subst('$TOP_SRCDIR/' + d),
2116           pattern = src_pattern, include = include,
2117           build_dir = env.subst('$TOP_SRCDIR/' + d) ))
2118         inc.extend(utils.globSource(dir = env.subst('$TOP_SRCDIR/' + d),
2119           pattern = '*.h',
2120           build_dir = env.subst('$TOP_SRCDIR/' + d) ))
2121     else:
2122       src = utils.globSource(dir = env.subst('$TOP_SRCDIR/' + dir),
2123         pattern = src_pattern, include = include,
2124         build_dir = env.subst('$TOP_SRCDIR/' + dir) )
2125       inc = utils.globSource(dir = env.subst('$TOP_SRCDIR/' + dir),
2126         pattern = '*.h',
2127         build_dir = env.subst('$TOP_SRCDIR/' + dir) )
2128     if full_target is None:
2129       build_target = target
2130     else:
2131       build_target = full_target
2132     # project
2133     proj = env.MSVSProject(
2134       target = target + env['MSVSPROJECTSUFFIX'],
2135       srcs = src,
2136       incs = [env.subst('$TOP_SRCDIR/src/config.h')],
2137       localincs = inc,
2138       resources = res,
2139       buildtarget = build_target,
2140       cmdargs = cmds,
2141       variant = 'Debug'
2142     )
2143     Alias('msvs_projects', proj)
2144   #
2145   build_project('boost', ['boost/libs/%s/src' % x for x in boost_libs],
2146     src_pattern = '*.cpp')
2147   #
2148   build_project('intl', 'intl', src_pattern = '*.c')
2149   #
2150   build_project('support', 'src/support', include=['package.C.in'])
2151   #
2152   build_project('mathed', 'src/mathed')
2153   #
2154   build_project('insets', 'src/insets')
2155   #
2156   build_project('frontends', 'src/frontends')
2157   #
2158   build_project('graphics', 'src/graphics')
2159   #
2160   build_project('controllers', 'src/frontends/controllers')
2161   #
2162   build_project('qt3', 'src/frontends/qt3', resource = 'src/frontends/qt3/ui')
2163   #
2164   build_project('qt4', 'src/frontends/qt4', resource = 'src/frontends/qt4/ui')
2165   #
2166   build_project('client', 'src/client', rebuildTargetOnly = False,
2167     full_target = File(env.subst('$BUILDDIR/common/client/lyxclient$PROGSUFFIX')).abspath)
2168   #
2169   build_project('tex2lyx', 'src/tex2lyx', rebuildTargetOnly = False,
2170     full_target = File(env.subst('$BUILDDIR/common/tex2lyx/tex2lyx$PROGSUFFIX')).abspath)
2171   #
2172   build_project('lyxbase', 'src')
2173   #
2174   if frontend == 'qt3':
2175     build_project('lyx', ['src', 'src/support', 'src/mathed', 'src/insets',
2176       'src/frontends', 'src/graphics', 'src/frontends/controllers',
2177       'src/frontends/qt3'], resource = 'src/frontends/qt3/ui',
2178       rebuildTargetOnly = False,
2179       full_target = File(env.subst('$BUILDDIR/$frontend/lyx$PROGSUFFIX')).abspath)
2180   else:
2181     build_project('lyx', ['src', 'src/support', 'src/mathed', 'src/insets',
2182       'src/frontends', 'src/graphics', 'src/frontends/controllers',
2183       'src/frontends/qt4'], resource = 'src/frontends/qt4/ui',
2184       rebuildTargetOnly = False,
2185       full_target = File(env.subst('$BUILDDIR/$frontend/lyx$PROGSUFFIX')).abspath)
2186
2187
2188 if build_po:
2189   #
2190   # po/
2191   #
2192   print 'Processing files in po...'
2193
2194   import glob
2195   # handle po files
2196   #
2197   # files to translate
2198   transfiles = glob.glob(os.path.join(env.subst('$TOP_SRCDIR'), 'po', '*.po'))
2199   # possibly *only* handle these languages
2200   languages = None
2201   if env.has_key('languages'):
2202     languages = env.make_list(env['lanauges'])
2203   # use defulat msgfmt
2204   if not env['MSGFMT']:
2205     print 'msgfmt does not exist. Can not process po files'
2206   else:
2207     # create a builder
2208     env['BUILDERS']['Transfiles'] = Builder(action='$MSGFMT $SOURCE -o $TARGET',suffix='.gmo',src_suffix='.po')
2209     #
2210     gmo_files = []
2211     for f in transfiles:
2212       # get filename
2213       fname = os.path.split(f)[1]
2214       # country code
2215       country = fname.split('.')[0]
2216       #
2217       if not languages or country in languages:
2218         gmo_files.extend(env.Transfiles(f))
2219
2220
2221 if 'install' in targets:
2222   #
2223   # install to DESTDIR or prefix
2224   dest_dir = env.Dir(env.get('DESTDIR', prefix)).abspath
2225   # if dest_dir is different from prefix.
2226   if env.has_key('exec_prefix'):
2227     bin_dest_dir = Dir(env['exec_prefix']).abspath
2228   else:
2229     bin_dest_dir = os.path.join(dest_dir, 'bin')
2230   if add_suffix:
2231     share_dest_dir = os.path.join(dest_dir, share_dir + program_suffix)
2232   else:
2233     share_dest_dir = os.path.join(dest_dir, share_dir)
2234   man_dest_dir = os.path.join(dest_dir, man_dir)
2235   locale_dest_dir = os.path.join(dest_dir, locale_dir)
2236   # create the directory if needed
2237   if not os.path.isdir(dest_dir):
2238     try:
2239       os.makedirs(dest_dir)
2240     except:
2241       pass
2242     if not os.path.isdir(dest_dir):
2243       print 'Can not create directory', dest_dir
2244       Exit(3)
2245   #
2246   import glob
2247   #
2248   # do not install these files
2249   exclude_list = ['Makefile.am', 'Makefile.in', 'Makefile',
2250     'lyx2lyx_version.py', 'lyx2lyx_version.py.in']
2251
2252   def install(dest, src):
2253     ''' recusive installation of src to dest '''
2254     # separate file and directory
2255     files = filter(lambda x: os.path.isfile(x) and not os.path.split(x)[1] in exclude_list, src)
2256     dirs = filter(os.path.isdir, src)
2257     # install file
2258     env.Install(dest, files)
2259     # install directory
2260     ins_dir = [dest]
2261     for dir in dirs:
2262       ins_dir.extend(install(os.path.join(dest, os.path.basename(dir)),
2263         glob.glob(os.path.join(dir, '*'))) )
2264     return ins_dir
2265   #
2266   # executables (some of them may be none)
2267   #
2268   if add_suffix:
2269     version_suffix = program_suffix
2270   else:
2271     version_suffix = ''
2272   #
2273   # install lyx
2274   target_name = os.path.split(str(lyx[0]))[1].replace('lyx', 'lyx%s' % version_suffix)
2275   target = os.path.join(bin_dest_dir, target_name)
2276   env.InstallAs(target, lyx)
2277   Alias('install', target)
2278   # install lyx as lyx-qt3
2279   target_name = os.path.split(str(lyx[0]))[1].replace('lyx', 'lyx-%s%s' % (frontend, version_suffix))
2280   target = os.path.join(bin_dest_dir, target_name)
2281   env.InstallAs(target, lyx)
2282   Alias('install', target)
2283   #
2284   # install tex2lyx
2285   target_name = os.path.split(str(tex2lyx[0]))[1].replace('tex2lyx', 'tex2lyx%s' % version_suffix)
2286   target = os.path.join(bin_dest_dir, target_name)
2287   env.InstallAs(target, tex2lyx)
2288   Alias('install', target)
2289   #
2290   # install lyxclient, may not exist
2291   if client != None:
2292     target_name = os.path.split(str(client[0]))[1].replace('client', 'client%s' % version_suffix)
2293     target = os.path.join(bin_dest_dir, target_name)
2294     env.InstallAs(target, client)
2295     Alias('install', target)
2296   #
2297   # share/lyx
2298   dirs = install(share_dest_dir,
2299     [env.subst('$TOP_SRCDIR/lib/') + file for file in ['configure.py', 'encodings',
2300      'chkconfig.ltx', 'CREDITS', 'external_templates', 'symbols', 'languages',
2301      'lyxrc.example', 'syntax.default', 'bind', 'images', 'layouts', 'scripts',
2302      'templates', 'examples', 'kbd', 'lyx2lyx', 'tex', 'clipart', 'doc',  'ui']]
2303   )
2304   env.substFile(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py',
2305     '$TOP_SRCDIR/lib/lyx2lyx/lyx2lyx_version.py.in')
2306   Alias('install', dirs)
2307   # man
2308   env.InstallAs(os.path.join(man_dest_dir, 'lyx' + version_suffix + '.1'),
2309     env.subst('$TOP_SRCDIR/lyx.man'))
2310   env.InstallAs(os.path.join(man_dest_dir, 'tex2lyx' + version_suffix + '.1'),
2311     env.subst('$TOP_SRCDIR/src/tex2lyx/tex2lyx.man'))
2312   env.InstallAs(os.path.join(man_dest_dir, 'lyxclient' + version_suffix + '.1'),
2313     env.subst('$TOP_SRCDIR/src/client/lyxclient.man'))
2314   Alias('install', [os.path.join(man_dest_dir, x + version_suffix + '.1') for
2315     x in ['lyx', 'tex2lyx', 'lyxclient']])
2316   # locale files?
2317   # ru.gmo ==> ru/LC_MESSAGES/lyxSUFFIX.mo
2318   for gmo in gmo_files:
2319     lan = os.path.split(str(gmo))[1].split('.')[0]
2320     dest_file = os.path.join(locale_dest_dir, lan, 'LC_MESSAGES', 'lyx' + version_suffix + '.mo')
2321     env.InstallAs(dest_file, gmo)
2322     Alias('install', dest_file)
2323
2324
2325 Default('lyx')
2326 Alias('all', ['lyx', 'client', 'tex2lyx'])