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