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