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