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