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