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