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