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