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