]> git.lyx.org Git - features.git/blob - development/scons/SConstruct
Scons: fix ICONV_LIB caching problem
[features.git] / development / scons / SConstruct
1 # vi:filetype=python:expandtab:tabstop=4:shiftwidth=4
2 #
3 # file SConstruct
4 #
5 # This file is part of LyX, the document processor.
6 # Licence details can be found in the file COPYING.
7 #
8 # \author Bo Peng
9 # Full author contact details are available in file CREDITS.
10 #
11 # This is a scons based building system for lyx, please refer
12 # to INSTALL.scons for detailed instructions.
13 #
14
15 import os, sys, copy, cPickle, glob, 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'] = None
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 if env['ICONV_LIB'] is None:
1379     system_libs = []
1380 else:
1381     system_libs = [env['ICONV_LIB']]
1382 if platform_name in ['win32', 'cygwin']:
1383     # the final link step needs stdc++ to succeed under mingw
1384     # FIXME: shouldn't g++ automatically link to stdc++?
1385     if use_vc:
1386         system_libs += ['ole32', 'shlwapi', 'shell32', 'advapi32', 'zdll']
1387     else:
1388         system_libs += ['shlwapi', 'stdc++', 'z']
1389 elif platform_name == 'cygwin' and env['X11']:
1390     system_libs += ['GL',  'Xmu', 'Xi', 'Xrender', 'Xrandr',
1391         'Xcursor', 'Xft', 'freetype', 'fontconfig', 'Xext', 'X11', 'SM', 'ICE', 
1392         'resolv', 'pthread', 'z']
1393 else:
1394     system_libs += ['z']
1395
1396 libs = [
1397     ('HAVE_LIBGDI32', 'gdi32'),
1398     ('HAVE_LIBAIKSAURUS', env['AIKSAURUS_LIB']),
1399     ('USE_ASPELL', aspell_lib),
1400     ('USE_ISPELL', 'ispell'),
1401     ('USE_PSPELL', 'pspell'),
1402 ]
1403
1404 for lib in libs:
1405     if env[lib[0]]:
1406         system_libs.append(lib[1])
1407
1408 #
1409 # Build parameters CPPPATH etc
1410 #
1411 if env['X11']:
1412     env.AppendUnique(LIBPATH = ['/usr/X11R6/lib'])
1413
1414 #
1415 # boost: for boost header files
1416 # BUILDDIR/common: for config.h
1417 # TOP_SRCDIR/src: for support/* etc
1418 #
1419 env['CPPPATH'] += ['$BUILDDIR/common', '$TOP_SRCDIR/src']
1420 #
1421 # Separating boost directories from CPPPATH stops scons from building
1422 # the dependency tree for boost header files, and effectively reduce
1423 # the null build time of lyx from 29s to 16s. Since lyx may tweak local
1424 # boost headers, this is only done for system boost headers.
1425 if included_boost:
1426     env.AppendUnique(CPPPATH = ['$BOOST_INC_PATH'])
1427 else:
1428     if use_vc:
1429         env.PrependUnique(CCFLAGS = ['/I$BOOST_INC_PATH'])
1430     else:
1431         env.PrependUnique(CCFLAGS = ['-I$BOOST_INC_PATH'])
1432
1433 # for intl/config.h, intl/libintl.h and intl/libgnuintl.h
1434 if env['nls'] and included_gettext:
1435     env['CPPPATH'].append('$BUILDDIR/intl')
1436 #
1437 # QT_INC_PATH is not needed for *every* source file
1438 env['CPPPATH'].remove(qt_inc_path)
1439
1440 #
1441 # A Link script for cygwin see
1442 # http://www.cygwin.com/ml/cygwin/2004-09/msg01101.html
1443 # http://www.cygwin.com/ml/cygwin-apps/2004-09/msg00309.html
1444 # for details
1445 #
1446 if platform_name == 'cygwin':
1447     ld_script_path = '/tmp'
1448     ld_script = utils.installCygwinLDScript(ld_script_path)
1449     env.AppendUnique(LINKFLAGS = ['-Wl,--enable-runtime-pseudo-reloc',
1450         '-Wl,--script,%s' % ld_script, '-Wl,-s'])
1451
1452 #
1453 # Report results
1454 #
1455 # fill in the version info
1456 env['VERSION_INFO'] = '''Configuration
1457   Host type:                      %s
1458   Special build flags:            %s
1459   C   Compiler:                   %s
1460   C   Compiler flags:             %s %s
1461   C++ Compiler:                   %s
1462   C++ Compiler LyX flags:         %s
1463   C++ Compiler flags:             %s %s
1464   Linker flags:                   %s
1465   Linker user flags:              %s
1466 Build info:
1467   Builing directory:              %s
1468   Local library directory:        %s
1469   Libraries paths:                %s
1470   Boost libraries:                %s
1471   Frontend libraries:             %s
1472   System libraries:               %s
1473   include search path:            %s
1474 Frontend:
1475   Frontend:                       %s
1476   Packaging:                      %s
1477   LyX dir:                        %s
1478   LyX files dir:                  %s
1479 ''' % (platform_name,
1480     env.subst('$CCFLAGS'), env.subst('$CC'),
1481     env.subst('$CPPFLAGS'), env.subst('$CFLAGS'),
1482     env.subst('$CXX'), env.subst('$CXXFLAGS'),
1483     env.subst('$CPPFLAGS'), env.subst('$CXXFLAGS'),
1484     env.subst('$LINKFLAGS'), env.subst('$LINKFLAGS'),
1485     env.subst('$BUILDDIR'), env.subst('$LOCALLIBPATH'),
1486     str(env['LIBPATH']), str(boost_libraries),
1487     str(frontend_libs), str(system_libs), str(env['CPPPATH']),
1488     frontend, packaging_method,
1489     prefix, env['LYX_DIR'])
1490
1491 if frontend in ['qt3', 'qt4']:
1492     env['VERSION_INFO'] += '''  include dir:                    %s
1493   library dir:                    %s
1494   X11:                            %s
1495 ''' % (qt_inc_path, qt_lib_path, env['X11'])
1496
1497 if not fast_start:
1498     print env['VERSION_INFO']
1499
1500 #
1501 # Mingw command line may be too short for our link usage,
1502 # Here we use a trick from scons wiki
1503 # http://www.scons.org/cgi-sys/cgiwrap/scons/moin.cgi/LongCmdLinesOnWin32
1504 #
1505 # I also would like to add logging (commands only) capacity to the
1506 # spawn system.
1507 logfile = env.get('logfile', default_log_file)
1508 if logfile != '' or platform_name == 'win32':
1509     import time
1510     utils.setLoggedSpawn(env, logfile, longarg = (platform_name == 'win32'),
1511         info = '''# This is a log of commands used by scons to build lyx
1512 # Time: %s
1513 # Command: %s
1514 # Info: %s
1515 ''' % (time.asctime(), ' '.join(sys.argv),
1516     env['VERSION_INFO'].replace('\n','\n# ')) )
1517
1518
1519 # Cleanup stuff
1520 #
1521 # -h will print out help info
1522 Help(opts.GenerateHelpText(env))
1523
1524 # save environment settings (for fast_start option)
1525 cache_file = open(env_cache_file, 'w')
1526 cPickle.dump(env_cache, cache_file)
1527 cache_file.close()
1528
1529
1530 #----------------------------------------------------------
1531 # Start building
1532 #----------------------------------------------------------
1533 # this has been the source of problems on some platforms...
1534 # I find that I need to supply it with full path name
1535 env.SConsignFile(os.path.join(Dir(env['BUILDDIR']).abspath, '.sconsign'))
1536 # this usage needs further investigation.
1537 #env.CacheDir('%s/Cache/%s' % (env['BUILDDIR'], frontend))
1538
1539 print "Building all targets recursively"
1540
1541 if env.has_key('rebuild'):
1542     rebuild_targets = env['rebuild'].split(',')
1543     if 'none' in rebuild_targets or 'no' in rebuild_targets:
1544         rebuild_targets = []
1545     elif 'all' in rebuild_targets or 'yes' in rebuild_targets:
1546         # None: let scons decide which components to build
1547         # Forcing all components to be rebuilt is in theory not necessary
1548         rebuild_targets = None    
1549 else:
1550     rebuild_targets = None
1551
1552 def libExists(libname):
1553     ''' Check whether or not lib $LOCALLIBNAME/libname already exists'''
1554     return os.path.isfile(File(env.subst('$LOCALLIBPATH/${LIBPREFIX}%s$LIBSUFFIX'%libname)).abspath)
1555
1556 def appExists(apppath, appname):
1557     ''' Check whether or not application already exists'''
1558     return os.path.isfile(File(env.subst('$BUILDDIR/common/%s/${PROGPREFIX}%s$PROGSUFFIX' % (apppath, appname))).abspath)
1559
1560 targets = BUILD_TARGETS
1561 # msvc need to pass full target name, so I have to look for path/lyx etc
1562 build_lyx = targets == [] or True in ['lyx' in x for x in targets] \
1563     or 'install' in targets or 'all' in targets
1564 build_boost = (included_boost and not libExists('boost_regex')) or 'boost' in targets
1565 build_intl = (included_gettext and not libExists('included_intl')) or 'intl' in targets
1566 build_support = build_lyx or True in [x in targets for x in ['support', 'client', 'tex2lyx']]
1567 build_mathed = build_lyx or 'mathed' in targets
1568 build_insets = build_lyx or 'insets' in targets
1569 build_frontends = build_lyx or 'frontends' in targets
1570 build_graphics = build_lyx or 'graphics' in targets
1571 build_controllers = build_lyx or 'controllers' in targets
1572 build_client = True in ['client' in x for x in targets] \
1573     or 'install' in targets or 'all' in targets
1574 build_tex2lyx = True in ['tex2lyx' in x for x in targets] \
1575     or 'install' in targets or 'all' in targets
1576 build_lyxbase = build_lyx or 'lyxbase' in targets
1577 build_po = 'po' in targets or 'install' in targets or 'all' in targets
1578 build_qt3 = (build_lyx and frontend == 'qt3') or 'qt3' in targets
1579 build_qt4 = (build_lyx and frontend == 'qt4') or 'qt4' in targets
1580 build_msvs_projects = use_vc and 'msvs_projects' in targets
1581
1582
1583 # now, if rebuild_targets is specified, do not rebuild some targets
1584 if rebuild_targets is not None:
1585     #
1586     def ifBuildLib(name, libname, old_value):
1587         # explicitly asked to rebuild
1588         if name in rebuild_targets:
1589             return True
1590         # else if not rebuild, and if the library already exists
1591         elif libExists(libname):
1592             return False
1593         # do not change the original value
1594         else:
1595             return old_value
1596     build_boost = ifBuildLib('boost', 'included_boost_filesystem', build_boost)
1597     build_intl = ifBuildLib('intl', 'included_intl', build_intl)
1598     build_support = ifBuildLib('support', 'support', build_support)
1599     build_mathed = ifBuildLib('mathed', 'mathed', build_mathed)
1600     build_insets = ifBuildLib('insets', 'insets', build_insets)
1601     build_frontends = ifBuildLib('frontends', 'frontends', build_frontends)
1602     build_graphics = ifBuildLib('graphics', 'graphics', build_graphics)
1603     build_controllers = ifBuildLib('controllers', 'controllers', build_controllers)
1604     build_lyxbase = ifBuildLib('lyxbase', 'lyxbase_pre', build_lyxbase)
1605     build_qt3 = ifBuildLib('qt3', 'qt3', build_qt3)
1606     build_qt4 = ifBuildLib('qt4', 'qt4', build_qt4)
1607     #
1608     def ifBuildApp(name, appname, old_value):
1609         # explicitly asked to rebuild
1610         if name in rebuild_targets:
1611             return True
1612         # else if not rebuild, and if the library already exists
1613         elif appExists(name, appname):
1614             return False
1615         # do not change the original value
1616         else:
1617             return old_value
1618     build_tex2lyx = ifBuildApp('tex2lyx', 'tex2lyx', build_tex2lyx)
1619     build_client = ifBuildApp('client', 'lyxclient', build_client)
1620
1621 # sync frontend and frontend (maybe build qt4 with frontend=qt3)
1622 if build_qt3:
1623     frontend = 'qt3'
1624 elif build_qt4:
1625     frontend = 'qt4'
1626
1627
1628 if build_boost:
1629     #
1630     # boost libraries
1631     #
1632     # special builddir
1633     env.BuildDir('$BUILDDIR/boost', '$TOP_SRCDIR/boost/libs', duplicate = 0)
1634
1635     boostenv = env.Copy()
1636     #
1637     # boost use its own config.h
1638     boostenv['CPPPATH'] = ['$TOP_SRCDIR/boost', '$BUILDDIR/boost'] + extra_inc_paths
1639     boostenv.AppendUnique(CCFLAGS = ['-DBOOST_USER_CONFIG="<config.h>"'])
1640
1641     for lib in boost_libs:
1642         print 'Processing files in boost/libs/%s/src...' % lib
1643         boostlib = boostenv.StaticLibrary(
1644             target = '$LOCALLIBPATH/included_boost_%s' % lib,
1645             source = ['$BUILDDIR/boost/%s/src/%s' % (lib, x) for x in eval('boost_libs_%s_src_files' % lib)]
1646         )
1647         Alias('boost', boostlib)
1648
1649
1650 if build_intl:
1651     #
1652     # intl
1653     #
1654     intlenv = env.Copy()
1655
1656     print "Processing files in intl..."
1657
1658     env.BuildDir('$BUILDDIR/intl', '$TOP_SRCDIR/intl', duplicate = 0)
1659
1660     # we need the original C compiler for these files
1661     intlenv['CC'] = C_COMPILER
1662     intlenv['CCFLAGS'] = C_CCFLAGS
1663     if use_vc:
1664         intlenv.Append(CCFLAGS=['/Dinline#', '/D__attribute__(x)#', '/Duintmax_t=UINT_MAX'])
1665     # intl does not use global config.h
1666     intlenv['CPPPATH'] = ['$BUILDDIR/intl'] + extra_inc_paths
1667
1668     intlenv.Append(CCFLAGS = [
1669         r'-DLOCALEDIR=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1670         r'-DLOCALE_ALIAS_PATH=\"' + env['LOCALEDIR'].replace('\\', '\\\\') + r'\"',
1671         r'-DLIBDIR=\"' + env['TOP_SRCDIR'].replace('\\', '\\\\') + r'/lib\"',
1672         '-DIN_LIBINTL',
1673         '-DENABLE_RELOCATABLE=1',
1674         '-DIN_LIBRARY',
1675         r'-DINSTALLDIR=\"' + prefix.replace('\\', '\\\\') + r'/lib\"',
1676         '-DNO_XMALLOC',
1677         '-Dset_relocation_prefix=libintl_set_relocation_prefix',
1678         '-Drelocate=libintl_relocate',
1679         '-DDEPENDS_ON_LIBICONV=1',
1680         '-DHAVE_CONFIG_H'
1681         ]
1682     )
1683
1684     intl = intlenv.StaticLibrary(
1685         target = '$LOCALLIBPATH/included_intl',
1686         LIBS = ['c'],
1687         source = ['$BUILDDIR/intl/%s' % x for x in intl_files]
1688     )
1689     Alias('intl', intl)
1690
1691
1692 #
1693 # Now, src code under src/
1694 #
1695 env.BuildDir('$BUILDDIR/common', '$TOP_SRCDIR/src', duplicate = 0)
1696
1697
1698 if build_support:
1699     #
1700     # src/support
1701     #
1702     print "Processing files in src/support..."
1703
1704     env.Depends('$BUILDDIR/common/support/package.C', '$BUILDDIR/common/config.h')
1705     env.substFile('$BUILDDIR/common/support/package.C', '$TOP_SRCDIR/src/support/package.C.in')
1706
1707     support = env.StaticLibrary(
1708         target = '$LOCALLIBPATH/support',
1709         source = ['$BUILDDIR/common/support/%s' % x for x in src_support_files]
1710     )
1711     Alias('support', support)
1712
1713
1714 if build_mathed:
1715     #
1716     # src/mathed
1717     #
1718     print "Processing files in src/mathed..."
1719     #
1720     mathed = env.StaticLibrary(
1721         target = '$LOCALLIBPATH/mathed',
1722         source = ['$BUILDDIR/common/mathed/%s' % x for x in src_mathed_files]
1723     )
1724     Alias('mathed', mathed)
1725
1726
1727 if build_insets:
1728     #
1729     # src/insets
1730     #
1731     print "Processing files in src/insets..."
1732     #
1733     insets = env.StaticLibrary(
1734         target = '$LOCALLIBPATH/insets',
1735         source = ['$BUILDDIR/common/insets/%s' % x for x in src_insets_files]
1736     )
1737     Alias('insets', insets)
1738
1739
1740 if build_frontends:
1741     #
1742     # src/frontends
1743     #
1744     print "Processing files in src/frontends..."
1745
1746     frontends = env.StaticLibrary(
1747         target = '$LOCALLIBPATH/frontends',
1748         source = ['$BUILDDIR/common/frontends/%s' % x for x in src_frontends_files]
1749     )
1750     Alias('frontends', frontends)
1751
1752
1753 if build_graphics:
1754     #
1755     # src/graphics
1756     #
1757     print "Processing files in src/graphics..."
1758
1759     graphics = env.StaticLibrary(
1760         target = '$LOCALLIBPATH/graphics',
1761         source = ['$BUILDDIR/common/graphics/%s' % x for x in src_graphics_files]
1762     )
1763     Alias('graphics', graphics)
1764
1765
1766 if build_controllers:
1767     #
1768     # src/frontends/controllers
1769     #
1770     print "Processing files in src/frontends/controllers..."
1771
1772     controllers = env.StaticLibrary(
1773         target = '$LOCALLIBPATH/controllers',
1774         source = ['$BUILDDIR/common/frontends/controllers/%s' % x for x in src_frontends_controllers_files]
1775     )
1776     Alias('controllers', controllers)
1777
1778
1779 #
1780 # src/frontend/qt3/4
1781 #
1782 if build_qt3 or build_qt4:
1783     env.BuildDir('$BUILDDIR/$frontend', '$TOP_SRCDIR/src/frontend/$frontend', duplicate = 0)
1784
1785 if build_qt3:
1786     print "Processing files in src/frontends/qt3..."
1787
1788     qt3env = env.Copy()
1789     # disable auto scan to speed up non build time
1790     qt3env['QT_AUTOSCAN'] = 0
1791     qt3env['QT_MOCHPREFIX'] = ''
1792
1793     # load qt3 tools
1794     qt3env.Tool('qt')
1795
1796     qt3env.AppendUnique(CPPPATH = [
1797         '$BUILDDIR/common',
1798         '$BUILDDIR/common/images',
1799         '$BUILDDIR/common/frontends',
1800         '$BUILDDIR/common/frontends/qt3',
1801         '$BUILDDIR/common/frontends/controllers',
1802         qt_inc_path]
1803     )
1804
1805     qt3_moc_files = ["$BUILDDIR/common/frontends/qt3/%s" % x for x in src_frontends_qt3_moc_files]
1806     
1807     # manually moc and uic files for better performance
1808     qt3_moced_files = [qt3env.Moc(x.replace('.C', '_moc.cpp'), x.replace('.C', '.h')) for x in qt3_moc_files]
1809
1810     qt3_uiced_files = [qt3env.Uic('$BUILDDIR/common/frontends/qt3/ui/'+x) for x in \
1811         src_frontends_qt3_ui_files]
1812
1813     qt3_uiced_cc_files = []
1814     for x in qt3_uiced_files:
1815         qt3_uiced_cc_files.extend(x[1:])
1816
1817     qt3 = qt3env.StaticLibrary(
1818         target = '$LOCALLIBPATH/qt3',
1819         source = ['$BUILDDIR/common/frontends/qt3/%s' % x for x in src_frontends_qt3_files] \
1820             + qt3_uiced_cc_files
1821     )
1822     Alias('qt3', qt3)
1823
1824
1825 if build_qt4:
1826     print "Processing files in src/frontends/qt4..."
1827
1828     qt4env = env.Copy()
1829     qt4env['QT_AUTOSCAN'] = 0
1830
1831     # local qt4 toolset from
1832     # http://www.iua.upf.es/~dgarcia/Codders/sconstools.html
1833     #
1834     # NOTE: I have to patch qt4.py since it does not automatically
1835     # process .C file!!! (add to cxx_suffixes )
1836     #
1837     qt4env.Tool('qt4', [scons_dir])
1838     qt4env.EnableQt4Modules(qt_libs, debug = (mode == 'debug'))
1839
1840     qt4env.AppendUnique(CPPPATH = [
1841         '$BUILDDIR/common',
1842         '$BUILDDIR/common/images',
1843         '$BUILDDIR/common/frontends',
1844         '$BUILDDIR/common/frontends/qt4',
1845         '$BUILDDIR/common/frontends/controllers',
1846         qt_inc_path
1847         ]
1848     )
1849
1850     # FIXME: replace by something from pkg_config
1851     qt4env.Append(CCFLAGS = [
1852         '-DHAVE_CONFIG_H',
1853         '-DQT_CLEAN_NAMESPACE',
1854         '-DQT_GENUINE_STR',
1855         '-DQT_NO_STL',
1856         '-DQT_NO_KEYWORDS',
1857         ]
1858     )
1859
1860
1861     qt4_moc_files = ["$BUILDDIR/common/frontends/qt4/%s" % x for x in src_frontends_qt4_moc_files]
1862
1863     #
1864     # Compile resources
1865     #
1866     resources = [qt4env.Uic4(x.split('.')[0]) for x in \
1867         ["$BUILDDIR/common/frontends/qt4/ui/%s" % x for x in src_frontends_qt4_ui_files]]
1868
1869     #
1870     # moc qt4_moc_files, the moced files are included in the original files
1871     #
1872     qt4_moced_files = [qt4env.Moc4(x.replace('.C', '_moc.cpp'), x.replace('.C', '.h')) for x in qt4_moc_files]
1873
1874     qt4 = qt4env.StaticLibrary(
1875         target = '$LOCALLIBPATH/qt4',
1876         source = ['$BUILDDIR/common/frontends/qt4/%s' % x for x in src_frontends_qt4_files]
1877     )
1878     Alias('qt4', qt4)
1879
1880
1881 if build_client:
1882     #
1883     # src/client
1884     #
1885     env.BuildDir('$BUILDDIR/common', '$TOP_SRCDIR/src', duplicate = 0)
1886
1887     print "Processing files in src/client..."
1888
1889     if env['HAVE_FCNTL']:
1890         client = env.Program(
1891             target = '$BUILDDIR/common/client/lyxclient',
1892             LIBS = ['support'] + intl_libs + system_libs +
1893                 socket_libs + boost_libraries,
1894             source = ['$BUILDDIR/common/client/%s' % x for x in src_client_files]
1895         )
1896         Alias('client', env.Command(os.path.join('$BUILDDIR', os.path.split(str(client[0]))[1]),
1897             client, [Copy('$TARGET', '$SOURCE')]))
1898     else:
1899         client = None
1900     Alias('client', client)
1901 else:
1902     if env['HAVE_FCNTL']:
1903         # define client even if lyxclient is not built with rebuild=no
1904         client = [env.subst('$BUILDDIR/common/client/${PROGPREFIX}lyxclient$PROGSUFFIX')]
1905     else:
1906         client = None
1907
1908
1909 if build_tex2lyx:
1910     #
1911     # tex2lyx
1912     #
1913     print "Processing files in src/tex2lyx..."
1914
1915     tex2lyx_env = env.Copy()
1916     #
1917     tex2lyx_env.Prepend(CPPPATH = ['$BUILDDIR/common/tex2lyx'])
1918     tex2lyx_env.AppendUnique(LIBPATH = ['#$LOCALLIBPATH'])
1919
1920     for file in ['FloatList.C', 'Floating.C', 'counters.C', 'lyxlayout.h', 'lyxlayout.C',
1921         'lyxtextclass.h', 'lyxtextclass.C', 'lyxlex.C', 'lyxlex_pimpl.C']:
1922         env.Command('$BUILDDIR/common/tex2lyx/'+file, '$TOP_SRCDIR/src/'+file,
1923             [Copy('$TARGET', '$SOURCE')])
1924
1925     tex2lyx = tex2lyx_env.Program(
1926         target = '$BUILDDIR/common/tex2lyx/tex2lyx',
1927         LIBS = ['support'] + boost_libraries + system_libs,
1928         source = ['$BUILDDIR/common/tex2lyx/%s' % x for x in src_tex2lyx_files]
1929     )
1930     Alias('tex2lyx', env.Command(os.path.join('$BUILDDIR', os.path.split(str(tex2lyx[0]))[1]),
1931         tex2lyx, [Copy('$TARGET', '$SOURCE')]))
1932     Alias('tex2lyx', tex2lyx)
1933 else:
1934     # define tex2lyx even if tex2lyx is not built with rebuild=no
1935     tex2lyx = [env.subst('$BUILDDIR/common/tex2lyx/${PROGPREFIX}tex2lyx$PROGSUFFIX')]
1936
1937
1938 if build_lyxbase:
1939     #
1940     # src/
1941     #
1942     print "Processing files in src..."
1943
1944     env.Depends('$BUILDDIR/common/version.C', '$BUILDDIR/common/config.h')
1945     env.substFile('$BUILDDIR/common/version.C', '$TOP_SRCDIR/src/version.C.in')
1946
1947     if env.has_key('USE_ASPELL') and env['USE_ASPELL']:
1948         src_post_files.append('aspell.C')
1949     elif env.has_key('USE_PSPELL') and env['USE_PSPELL']:
1950         src_post_files.append('pspell.C')
1951     elif env.has_key('USE_ISPELL') and env['USE_ISPELL']:
1952         src_post_files.append('ispell.C')
1953
1954     # msvc requires at least one source file with main()
1955     # so I exclude main.C from lyxbase
1956     lyxbase_pre = env.StaticLibrary(
1957         target = '$LOCALLIBPATH/lyxbase_pre',
1958         source = ['$BUILDDIR/common/%s' % x for x in src_pre_files]
1959     )
1960     lyxbase_post = env.StaticLibrary(
1961         target = '$LOCALLIBPATH/lyxbase_post',
1962         source = ["$BUILDDIR/common/%s" % x for x in src_post_files]
1963     )
1964     Alias('lyxbase', lyxbase_pre)
1965     Alias('lyxbase', lyxbase_post)
1966
1967
1968 if build_lyx:
1969     #
1970     # Build lyx with given frontend
1971     #
1972     lyx = env.Program(
1973         target = '$BUILDDIR/$frontend/lyx',
1974         source = ['$BUILDDIR/common/main.C'],
1975         LIBS = [
1976             'lyxbase_pre',
1977             'mathed',
1978             'insets',
1979             'frontends',
1980             frontend,
1981             'controllers',
1982             'graphics',
1983             'support',
1984             'lyxbase_post',
1985             ] +
1986             boost_libraries +
1987             frontend_libs +
1988             intl_libs +
1989             socket_libs +
1990             system_libs
1991     )
1992     # [/path/to/lyx.ext] => lyx-qt3.ext
1993     target_name = os.path.split(str(lyx[0]))[1].replace('lyx', 'lyx-%s' % frontend)
1994     Alias('lyx', env.Command(os.path.join('$BUILDDIR', target_name), lyx,
1995         [Copy('$TARGET', '$SOURCE')]))
1996     Alias('lyx', lyx)
1997 else:
1998     # define lyx even if lyx is not built with rebuild=no
1999     lyx = [env.subst('$BUILDDIR/$frontend/${PROGPREFIX}lyx$PROGSUFFIX')]
2000
2001
2002 if build_msvs_projects:
2003     def build_project(target, full_target = None,
2004         src = [], inc = [], res = [], rebuildTargetOnly = True):
2005         ''' build mavs project files
2006             target:      alias (correspond to directory name)
2007             full_target: full path/filename of the target
2008             src:         source files
2009             inc:         include files
2010             res:         resource files
2011             rebuildTargetOnly:     whether or not only rebuild this target
2012
2013         For non-debug-able targets like static libraries, target (alias) is
2014         enough to build the target. For executable targets, msvs need to know
2015         the full path to start debug them.
2016         '''
2017         if rebuildTargetOnly:
2018             cmds = 'fast_start=yes rebuild='+target
2019         else:
2020             cmds = 'fast_start=yes'
2021         if full_target is None:
2022             build_target = target
2023         else:
2024             build_target = full_target
2025         # project
2026         proj = env.MSVSProject(
2027             target = target + env['MSVSPROJECTSUFFIX'],
2028             # this allows easy access to header files (along with source)
2029             srcs = [env.subst(x) for x in src + inc],
2030             incs = [env.subst('$TOP_SRCDIR/src/config.h')],
2031             localincs = [env.subst(x) for x in inc],
2032             resources = [env.subst(x) for x in res],
2033             buildtarget = build_target,
2034             cmdargs = cmds,
2035             variant = 'Debug'
2036         )
2037         Alias('msvs_projects', proj)
2038     #
2039     boost_src = []
2040     for lib in boost_libs:
2041         boost_src += ['$TOP_SRCDIR/boost/libs/%s/src/%s' % (lib, x) for x in eval('boost_libs_%s_src_files' % lib)]
2042     build_project('boost', src = boost_src)
2043     #
2044     build_project('intl', src = ['$TOP_SRCDIR/intl/%s' % x for x in intl_files], 
2045         inc = ['$TOP_SRCDIR/intl/%s' % x for x in intl_header_files])
2046     #
2047     build_project('support', 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('mathed', src = ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_files], 
2051         inc = ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files])
2052     #
2053     build_project('insets', src = ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_files], 
2054         inc = ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files])
2055     #
2056     build_project('frontends', src = ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_files], 
2057         inc = ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files])
2058     #
2059     build_project('graphics', src = ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_files], 
2060         inc = ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files])
2061     #
2062     build_project('controllers', src = ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files], 
2063         inc = ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files])
2064     #
2065     build_project('qt3', src = ['$TOP_SRCDIR/src/frontends/qt3/%s' % x for x in src_frontends_qt3_files + src_frontends_qt3_moc_files],
2066         inc = ['$TOP_SRCDIR/src/frontends/qt3/%s' % x for x in src_frontends_qt3_header_files],
2067         res = ['$TOP_SRCDIR/src/frontends/qt3/ui/%s' % x for x in src_frontends_qt3_ui_files])
2068     #
2069     build_project('qt4', src = ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_files + src_frontends_qt4_moc_files],
2070         inc = ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_header_files],
2071         res = ['$TOP_SRCDIR/src/frontends/qt4/ui/%s' % x for x in src_frontends_qt4_ui_files])
2072     #
2073     build_project('client', src = ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_files],
2074         inc = ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_header_files],
2075         rebuildTargetOnly = False,
2076         full_target = File(env.subst('$BUILDDIR/common/client/lyxclient$PROGSUFFIX')).abspath)
2077     #
2078     build_project('tex2lyx', src = ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_files],
2079         inc = ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_header_files],
2080         rebuildTargetOnly = False,
2081         full_target = File(env.subst('$BUILDDIR/common/tex2lyx/tex2lyx$PROGSUFFIX')).abspath)
2082     #
2083     build_project('lyxbase', src = ['$TOP_SRCDIR/src/%s' % x for x in src_pre_files + src_post_files],
2084         inc = ['$TOP_SRCDIR/src/%s' % x for x in src_header_files])
2085     #
2086     if frontend == 'qt3':
2087         build_project('lyx', 
2088             src = ['$TOP_SRCDIR/src/%s' % x for x in src_pre_files + src_post_files] + \
2089                 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_files] + \
2090                 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_files] + \
2091                 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_files] + \
2092                 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_files] + \
2093                 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_files] + \
2094                 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files] + \
2095                 ['$TOP_SRCDIR/src/frontends/qt3/%s' % x for x in src_frontends_qt3_files + src_frontends_qt3_moc_files],
2096             inc = ['$TOP_SRCDIR/src/%s' % x for x in src_header_files] + \
2097                 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files] + \
2098                 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_header_files] + \
2099                 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files] + \
2100                 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files] + \
2101                 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files] + \
2102                 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files] + \
2103                 ['$TOP_SRCDIR/src/frontends/qt3/%s' % x for x in src_frontends_qt3_header_files],
2104             res = ['$TOP_SRCDIR/src/frontends/qt3/ui/%s' % x for x in src_frontends_qt3_ui_files],
2105             rebuildTargetOnly = False,
2106             full_target = File(env.subst('$BUILDDIR/$frontend/lyx$PROGSUFFIX')).abspath)
2107     else:
2108         build_project('lyx', 
2109             src = ['$TOP_SRCDIR/src/%s' % x for x in src_pre_files + src_post_files] + \
2110                 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_files] + \
2111                 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_files] + \
2112                 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_files] + \
2113                 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_files] + \
2114                 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_files] + \
2115                 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files] + \
2116                 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_files + src_frontends_qt4_moc_files],
2117             inc = ['$TOP_SRCDIR/src/%s' % x for x in src_header_files] + \
2118                 ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files] + \
2119                 ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_header_files] + \
2120                 ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files] + \
2121                 ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files] + \
2122                 ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files] + \
2123                 ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files] + \
2124                 ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_header_files],
2125             res = ['$TOP_SRCDIR/src/frontends/qt4/ui/%s' % x for x in src_frontends_qt4_ui_files],
2126             rebuildTargetOnly = False,
2127             full_target = File(env.subst('$BUILDDIR/$frontend/lyx$PROGSUFFIX')).abspath)
2128
2129
2130 if build_po:
2131     #
2132     # po/
2133     #
2134     print 'Processing files in po...'
2135
2136     import glob
2137     # handle po files
2138     #
2139     # files to translate
2140     transfiles = glob.glob(os.path.join(env.subst('$TOP_SRCDIR'), 'po', '*.po'))
2141     # possibly *only* handle these languages
2142     languages = None
2143     if env.has_key('languages'):
2144         languages = env.make_list(env['lanauges'])
2145     # use defulat msgfmt
2146     gmo_files = []
2147     if not env['MSGFMT']:
2148         print 'msgfmt does not exist. Can not process po files'
2149     else:
2150         # create a builder
2151         env['BUILDERS']['Transfiles'] = Builder(action='$MSGFMT $SOURCE -o $TARGET',suffix='.gmo',src_suffix='.po')
2152         #
2153         for f in transfiles:
2154             # get filename
2155             fname = os.path.split(f)[1]
2156             # country code
2157             country = fname.split('.')[0]
2158             #
2159             if not languages or country in languages:
2160                 gmo_files.extend(env.Transfiles(f))
2161
2162
2163 if 'install' in targets:
2164     #
2165     # this part is a bit messy right now. Since scons will provide
2166     # --DESTDIR option soon, at least the dest_dir handling can be 
2167     # removed later.
2168     #
2169     # how to join dest_dir and prefix
2170     def joinPaths(path1, path2):
2171         ''' join path1 and path2, do not use os.path.join because
2172             under window, c:\destdir\d:\program is invalid '''
2173         if path1 is None:
2174             return os.path.normpath(path2)
2175         # separate drive letter
2176         (drive, path) = os.path.splitdrive(os.path.normpath(path2))
2177         # ignore drive letter, so c:\destdir + c:\program = c:\destdir\program
2178         return os.path.join(os.path.normpath(path1), path[1:])
2179     #
2180     # install to dest_dir/prefix
2181     dest_dir = env.get('DESTDIR', None)
2182     dest_prefix_dir = joinPaths(dest_dir, env.Dir(prefix).abspath)
2183     # create the directory if needed
2184     if not os.path.isdir(dest_prefix_dir):
2185         try:
2186             os.makedirs(dest_prefix_dir)
2187         except:
2188             pass
2189         if not os.path.isdir(dest_prefix_dir):
2190             print 'Can not create directory', dest_prefix_dir
2191             Exit(3)
2192     #
2193     if env.has_key('exec_prefix'):
2194         bin_dest_dir = joinPaths(dest_dir, Dir(env['exec_prefix']).abspath)
2195     else:
2196         bin_dest_dir = os.path.join(dest_prefix_dir, 'bin')
2197     if add_suffix:
2198         share_dest_dir = os.path.join(dest_prefix_dir, share_dir + program_suffix)
2199     else:
2200         share_dest_dir = os.path.join(dest_prefix_dir, share_dir)
2201     man_dest_dir = os.path.join(dest_prefix_dir, man_dir)
2202     locale_dest_dir = os.path.join(dest_prefix_dir, locale_dir)
2203     #
2204     import glob
2205     #
2206     # install executables (lyxclient may be None)
2207     #
2208     if add_suffix:
2209         version_suffix = program_suffix
2210     else:
2211         version_suffix = ''
2212     #
2213     # install lyx, if in release mode, try to strip the binary
2214     if env.has_key('STRIP') and env['STRIP'] is not None and mode != 'debug':
2215         # create a builder to strip and install
2216         env['BUILDERS']['StripInstallAs'] = Builder(action='$STRIP $SOURCE -o $TARGET')
2217
2218     # install executables
2219     for (name, obj) in (('lyx', lyx), ('tex2lyx', tex2lyx), ('client', client)):
2220         if obj is None:
2221             continue
2222         target_name = os.path.split(str(obj[0]))[1].replace(name, '%s%s' % (name, version_suffix))
2223         target = os.path.join(bin_dest_dir, target_name)
2224         if env['BUILDERS'].has_key('StripInstallAs'):
2225             env.StripInstallAs(target, obj)
2226         else:
2227             env.InstallAs(target, obj)
2228         Alias('install', target)
2229
2230     # share/lyx
2231     dirs = []
2232     for (dir,files) in [
2233             ('.', lib_files),  
2234             ('clipart', lib_clipart_files),
2235             ('examples', lib_examples_files),
2236             ('images', lib_images_files),
2237             ('images/math', lib_images_math_files),
2238             ('bind', lib_bind_files),
2239             ('kbd', lib_kbd_files),
2240             ('layouts', lib_layouts_files),
2241             ('scripts', lib_scripts_files),
2242             ('templates', lib_templates_files),
2243             ('tex', lib_tex_files),
2244             ('ui', lib_ui_files),
2245             ('doc', lib_doc_files),
2246             ('lyx2lyx', lib_lyx2lyx_files)]:
2247         dirs.append(env.Install(os.path.join(share_dest_dir, dir),
2248             [env.subst('$TOP_SRCDIR/lib/%s/%s' % (dir, file)) for file in files]))
2249     Alias('install', dirs)
2250     
2251     if platform_name == 'cygwin':
2252         # cygwin packaging requires a file /usr/share/doc/Cygwin/foot-vendor-suffix.README
2253         Cygwin_README = os.path.join(dest_prefix_dir, 'share', 'doc', 'Cygwin', 
2254             '%s-%s.README' % (package, package_cygwin_version))
2255         env.InstallAs(Cygwin_README,
2256             os.path.join(env.subst('$TOP_SRCDIR'), 'README.cygwin'))
2257         Alias('install', Cygwin_README)
2258         # also a directory /usr/share/doc/lyx for README etc
2259         Cygwin_Doc = os.path.join(dest_prefix_dir, 'share', 'doc', package)
2260         env.Install(Cygwin_Doc, [os.path.join(env.subst('$TOP_SRCDIR'), x) for x in \
2261             ['INSTALL', 'README', 'README.Cygwin', 'RELEASE-NOTES', 'COPYING', 'ANNOUNCE']])
2262         Alias('install', Cygwin_Doc)
2263         # cygwin fonts also need to be installed
2264         Cygwin_fonts = os.path.join(share_dest_dir, 'fonts')
2265         env.Install(Cygwin_fonts, 
2266             [env.subst('$TOP_SRCDIR/development/Win32/packaging/bakoma/%s' % file) \
2267                   for file in win32_bakoma_fonts])
2268         Alias('install', Cygwin_fonts)
2269         # we also need a post installation script
2270         tmp_script = utils.installCygwinPostinstallScript('/tmp')
2271         postinstall_script = os.path.join(dest_dir, 'etc', 'postinstall', 'lyx.sh')
2272         env.Install(postinstall_script, tmp_script)
2273         Alias('install', postinstall_script)
2274
2275     # subst and install lyx2lyx_version.py which is not in scons_manifest.py
2276     env.Depends(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py', '$BUILDDIR/common/config.h')
2277     env.substFile(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py',
2278         '$TOP_SRCDIR/lib/lyx2lyx/lyx2lyx_version.py.in')
2279     Alias('install', share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2280
2281     # man
2282     env.InstallAs(os.path.join(man_dest_dir, 'lyx' + version_suffix + '.1'),
2283         env.subst('$TOP_SRCDIR/lyx.man'))
2284     env.InstallAs(os.path.join(man_dest_dir, 'tex2lyx' + version_suffix + '.1'),
2285         env.subst('$TOP_SRCDIR/src/tex2lyx/tex2lyx.man'))
2286     env.InstallAs(os.path.join(man_dest_dir, 'lyxclient' + version_suffix + '.1'),
2287         env.subst('$TOP_SRCDIR/src/client/lyxclient.man'))
2288     Alias('install', [os.path.join(man_dest_dir, x + version_suffix + '.1') for
2289         x in ['lyx', 'tex2lyx', 'lyxclient']])
2290     # locale files?
2291     # ru.gmo ==> ru/LC_MESSAGES/lyxSUFFIX.mo
2292     for gmo in gmo_files:
2293         lan = os.path.split(str(gmo))[1].split('.')[0]
2294         dest_file = os.path.join(locale_dest_dir, lan, 'LC_MESSAGES', 'lyx' + program_suffix + '.mo')
2295         env.InstallAs(dest_file, gmo)
2296         Alias('install', dest_file)
2297
2298
2299 Default('lyx')
2300 Alias('all', ['lyx', 'client', 'tex2lyx'])