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