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