]> git.lyx.org Git - lyx.git/blob - development/scons/SConstruct
Scons cleanup 5: config.h typo, do not have to make builddir by myself
[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         ['$BUILDDIR/src/support/minizip/%s' % x for x in src_support_minizip_windows_files if platform_name == 'win32'],
1521     CCFLAGS =  [
1522         '$CCFLAGS',
1523         '-DHAVE_CONFIG_H',
1524         '-DQT_CLEAN_NAMESPACE',
1525         '-DQT_GENUINE_STR',
1526         '-DQT_NO_STL',
1527         '-DQT_NO_KEYWORDS',
1528     ],
1529     CPPPATH = ['$CPPPATH', '$TOP_SRCDIR/src/support/minizip']
1530 )
1531 Alias('support', support)
1532
1533
1534 #
1535 # src/mathed
1536 #
1537 mathed = env.StaticLibrary(
1538     target = '$LOCALLIBPATH/mathed',
1539     source = ['$BUILDDIR/src/mathed/%s' % x for x in src_mathed_files]
1540 )
1541 Alias('mathed', mathed)
1542
1543
1544 #
1545 # src/insets
1546 #
1547 insets = env.StaticLibrary(
1548     target = '$LOCALLIBPATH/insets',
1549     source = ['$BUILDDIR/src/insets/%s' % x for x in src_insets_files]
1550 )
1551 Alias('insets', insets)
1552
1553
1554 #
1555 # src/frontends
1556 #
1557 frontends = env.StaticLibrary(
1558     target = '$LOCALLIBPATH/frontends',
1559     source = ['$BUILDDIR/src/frontends/%s' % x for x in src_frontends_files]
1560 )
1561 Alias('frontends', frontends)
1562
1563
1564 #
1565 # src/graphics
1566 #
1567 graphics = env.StaticLibrary(
1568     target = '$LOCALLIBPATH/graphics',
1569     source = ['$BUILDDIR/src/graphics/%s' % x for x in src_graphics_files]
1570 )
1571 Alias('graphics', graphics)
1572
1573
1574 #
1575 # src/frontends/controllers
1576 #
1577 controllers = env.StaticLibrary(
1578     target = '$LOCALLIBPATH/controllers',
1579     source = ['$BUILDDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files]
1580 )
1581 Alias('controllers', controllers)
1582
1583
1584 #
1585 # src/frontend/qt4
1586 #
1587 frontend_env['QT4_MOCHPREFIX'] = ''
1588 frontend_env['QT4_MOCHSUFFIX'] = '_moc.cpp'
1589
1590 # tells scons how to get these moced files, although not all moced files are needed
1591 # (or are actually generated).
1592 qt4_moced_files = [frontend_env.Moc4('$BUILDDIR/src/frontends/qt4/%s' % x)
1593     for x in src_frontends_qt4_header_files ]
1594 resources = [frontend_env.Uic4('$BUILDDIR/src/frontends/qt4/ui/%s' % x.split('.')[0])
1595     for x in src_frontends_qt4_ui_files]
1596
1597 #
1598 # moc qt4_moc_files, the moced files are included in the original files
1599 #
1600 qt4 = frontend_env.StaticLibrary(
1601     target = '$LOCALLIBPATH/qt4',
1602     source = ['$BUILDDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_files],
1603     CPPPATH = [
1604         '$CPPPATH',
1605         '$BUILDDIR/src',
1606         '$BUILDDIR/src/images',
1607         '$BUILDDIR/src/frontends',
1608         '$BUILDDIR/src/frontends/qt4',
1609         '$BUILDDIR/src/frontends/qt4/ui',
1610         '$BUILDDIR/src/frontends/controllers'
1611     ],
1612     CCFLAGS =  [
1613         '$CCFLAGS',
1614         '-DHAVE_CONFIG_H',
1615         '-DQT_CLEAN_NAMESPACE',
1616         '-DQT_GENUINE_STR',
1617         '-DQT_NO_STL',
1618         '-DQT_NO_KEYWORDS',
1619     ]
1620 )
1621 Alias('qt4', qt4)
1622
1623
1624 #
1625 # src/client
1626 #
1627 if env['HAVE_FCNTL']:
1628     client = frontend_env.Program(
1629         target = '$BUILDDIR/src/client/lyxclient',
1630         LIBS = ['support'] + intl_libs + system_libs +
1631             socket_libs + boost_libraries + qtcore_lib,
1632         source = ['$BUILDDIR/src/client/%s' % x for x in src_client_files] + \
1633             utils.createResFromIcon(frontend_env, 'lyx_32x32.ico', '$LOCALLIBPATH/client.rc')
1634     )
1635     Alias('client', frontend_env.Command(os.path.join('$BUILDDIR', os.path.split(str(client[0]))[1]),
1636         client, [Copy('$TARGET', '$SOURCE')]))
1637 else:
1638     client = None
1639 Alias('client', client)
1640
1641
1642 #
1643 # tex2lyx
1644 #
1645 for file in src_tex2lyx_copied_files + src_tex2lyx_copied_header_files:
1646     frontend_env.Command('$BUILDDIR/src/tex2lyx/'+file, '$TOP_SRCDIR/src/'+file,
1647         [Copy('$TARGET', '$SOURCE')])
1648
1649 tex2lyx = frontend_env.Program(
1650     target = '$BUILDDIR/src/tex2lyx/tex2lyx',
1651     LIBS = ['support'] + boost_libraries + intl_libs + system_libs + qtcore_lib,
1652     source = ['$BUILDDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_files + src_tex2lyx_copied_files] + \
1653         utils.createResFromIcon(frontend_env, 'lyx_32x32.ico', '$LOCALLIBPATH/tex2lyx.rc'),
1654     CPPPATH = ['$BUILDDIR/src/tex2lyx', '$CPPPATH'],
1655     LIBPATH = ['#$LOCALLIBPATH', '$LIBPATH'],
1656 )
1657 Alias('tex2lyx', frontend_env.Command(os.path.join('$BUILDDIR', os.path.split(str(tex2lyx[0]))[1]),
1658     tex2lyx, [Copy('$TARGET', '$SOURCE')]))
1659 Alias('tex2lyx', tex2lyx)
1660
1661
1662 #
1663 # src/
1664 #
1665 if env.has_key('USE_ASPELL') and env['USE_ASPELL']:
1666     src_post_files.append('ASpell.cpp')
1667 elif env.has_key('USE_PSPELL') and env['USE_PSPELL']:
1668     src_post_files.append('PSpell.cpp')
1669 elif env.has_key('USE_ISPELL') and env['USE_ISPELL']:
1670     src_post_files.append('ISpell.cpp')
1671
1672 # msvc requires at least one source file with main()
1673 # so I exclude main.cpp from lyxbase
1674 lyxbase_pre = env.StaticLibrary(
1675     target = '$LOCALLIBPATH/lyxbase_pre',
1676     source = ['$BUILDDIR/src/%s' % x for x in src_pre_files]
1677 )
1678 lyxbase_post = env.StaticLibrary(
1679     target = '$LOCALLIBPATH/lyxbase_post',
1680     source = ["$BUILDDIR/src/%s" % x for x in src_post_files]
1681 )
1682 Alias('lyxbase', lyxbase_pre)
1683 Alias('lyxbase', lyxbase_post)
1684
1685
1686 #
1687 # Build lyx with given frontend
1688 #
1689 lyx = frontend_env.Program(
1690     target = '$BUILDDIR/lyx',
1691     source = ['$BUILDDIR/src/main.cpp'] + \
1692         utils.createResFromIcon(frontend_env, 'lyx_32x32.ico', '$LOCALLIBPATH/lyx.rc'),
1693     LIBS = [
1694         'lyxbase_pre',
1695         'mathed',
1696         'insets',
1697         'frontends',
1698         frontend,
1699         'controllers',
1700         'graphics',
1701         'support',
1702         'lyxbase_post',
1703         ] +
1704         boost_libraries +
1705         frontend_libs +
1706         intl_libs +
1707         socket_libs +
1708         system_libs
1709 )
1710 Alias('lyx', lyx)
1711
1712
1713 if use_vc and 'msvs_projects' in BUILD_TARGETS:
1714     def build_project(target, full_target = None,
1715         src = [], inc = [], res = []):
1716         ''' build mavs project files
1717             target:      alias (correspond to directory name)
1718             full_target: full path/filename of the target
1719             src:         source files
1720             inc:         include files
1721             res:         resource files
1722
1723         For non-debug-able targets like static libraries, target (alias) is
1724         enough to build the target. For executable targets, msvs need to know
1725         the full path to start debug them.
1726         '''
1727         cmds = ''
1728         if full_target is None:
1729             build_target = target
1730         else:
1731             build_target = full_target
1732         # project
1733         proj = env.MSVSProject(
1734             target = target + env['MSVSPROJECTSUFFIX'],
1735             # this allows easy access to header files (along with source)
1736             srcs = [env.subst(x) for x in src + inc],
1737             incs = [env.subst('$TOP_SRCDIR/src/config.h')],
1738             localincs = [env.subst(x) for x in inc],
1739             resources = [env.subst(x) for x in res],
1740             buildtarget = build_target,
1741             cmdargs = cmds,
1742             variant = 'Debug'
1743         )
1744         Alias('msvs_projects', proj)
1745     #
1746     build_project('client', src = ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_files],
1747         inc = ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_header_files],
1748         full_target = File(env.subst('$BUILDDIR/src/client/lyxclient$PROGSUFFIX')).abspath)
1749     #
1750     build_project('tex2lyx', src = ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_files],
1751         inc = ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_header_files],
1752         full_target = File(env.subst('$BUILDDIR/src/tex2lyx/tex2lyx$PROGSUFFIX')).abspath)
1753     #
1754     build_project('lyx', 
1755         src = ['$TOP_SRCDIR/src/%s' % x for x in src_pre_files + src_post_files + ['version.cpp']] + \
1756             ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_files + ['Package.cpp'] ] + \
1757             ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_files] + \
1758             ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_files] + \
1759             ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_files] + \
1760             ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_files] + \
1761             ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_files] + \
1762             ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_files + src_frontends_qt4_moc_files],
1763         inc = ['$TOP_SRCDIR/src/%s' % x for x in src_header_files] + \
1764             ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files] + \
1765             ['$TOP_SRCDIR/src/mathed/%s' % x for x in src_mathed_header_files] + \
1766             ['$TOP_SRCDIR/src/insets/%s' % x for x in src_insets_header_files] + \
1767             ['$TOP_SRCDIR/src/frontends/%s' % x for x in src_frontends_header_files] + \
1768             ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files] + \
1769             ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files] + \
1770             ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_header_files],
1771         res = ['$TOP_SRCDIR/src/frontends/qt4/ui/%s' % x for x in src_frontends_qt4_ui_files],
1772         full_target = File(env.subst('$BUILDDIR/lyx$PROGSUFFIX')).abspath)
1773
1774
1775 if 'update_po' in BUILD_TARGETS:
1776     #
1777     # update po files
1778     #
1779     print 'Updating po/*.po files...'
1780
1781     # whether or not update po files
1782     if not env['XGETTEXT'] or not env['MSGMERGE'] or not env['MSGUNIQ']:
1783         print 'xgettext or msgmerge does not exist. Cannot merge po files'
1784         Exit(1)
1785     # rebuild POTFILES.in
1786     POTFILES_in = env.potfiles('$TOP_SRCDIR/po/POTFILES.in', 
1787         ['$TOP_SRCDIR/src/%s' % x for x in  src_header_files + src_pre_files + src_post_files + \
1788             src_extra_src_files] + \
1789         ['$TOP_SRCDIR/src/support/%s' % x for x in src_support_header_files + src_support_files + \
1790             src_support_extra_header_files + src_support_extra_src_files] + \
1791         ['$TOP_SRCDIR/src/mathed/%s' % x for x in  src_mathed_header_files + src_mathed_files] + \
1792         ['$TOP_SRCDIR/src/insets/%s' % x for x in  src_insets_header_files + src_insets_files] + \
1793         ['$TOP_SRCDIR/src/frontends/%s' % x for x in  src_frontends_header_files + src_frontends_files] + \
1794         ['$TOP_SRCDIR/src/graphics/%s' % x for x in src_graphics_header_files + src_graphics_files] + \
1795         ['$TOP_SRCDIR/src/frontends/controllers/%s' % x for x in src_frontends_controllers_header_files + src_frontends_controllers_files] + \
1796         ['$TOP_SRCDIR/src/frontends/qt4/%s' % x for x in src_frontends_qt4_header_files + src_frontends_qt4_files + src_frontends_qt4_moc_files] + \
1797         ['$TOP_SRCDIR/src/client/%s' % x for x in src_client_header_files + src_client_files ]  + \
1798         ['$TOP_SRCDIR/src/tex2lyx/%s' % x for x in src_tex2lyx_header_files + src_tex2lyx_files ]
1799     )
1800     Alias('update_po', POTFILES_in)
1801     # build language_l10n.pot, ui_l10n.pot, layouts_l10n.pot, qt4_l10n.pot, external_l10n
1802     # and combine them to lyx.po
1803     env['LYX_POT'] = 'python $TOP_SRCDIR/po/lyx_pot.py'
1804     lyx_po = env.Command('$BUILDDIR/po/lyx.po',
1805         env.Command('$BUILDDIR/po/all.po',
1806             [env.Command('$BUILDDIR/po/qt4_l10n.pot', 
1807                 ['$TOP_SRCDIR/src/frontends/qt4/ui/%s' % x for x in src_frontends_qt4_ui_files],
1808                 '$LYX_POT -b $TOP_SRCDIR -t qt4 -o $TARGET $SOURCES'),
1809              env.Command('$BUILDDIR/po/layouts_l10n.pot', 
1810                 ['$TOP_SRCDIR/lib/layouts/%s' % x for x in lib_layouts_files + lib_layouts_inc_files],
1811                 '$LYX_POT -b $TOP_SRCDIR -t layouts -o $TARGET $SOURCES'),
1812              env.Command('$BUILDDIR/po/languages_l10n.pot', '$TOP_SRCDIR/lib/languages',
1813                 '$LYX_POT -b $TOP_SRCDIR -t languages -o $TARGET $SOURCES'),
1814              env.Command('$BUILDDIR/po/ui_l10n.pot', 
1815                 ['$TOP_SRCDIR/lib/ui/%s' % x for x in lib_ui_files],
1816                 '$LYX_POT -b $TOP_SRCDIR -t ui -o $TARGET $SOURCES'),
1817              env.Command('$BUILDDIR/po/external_l10n.pot', '$TOP_SRCDIR/lib/external_templates',
1818                 '$LYX_POT -b $TOP_SRCDIR -t external -o $TARGET $SOURCES'),
1819              ], utils.env_cat),
1820             ['$MSGUNIQ -o $TARGET $SOURCE',
1821              '''$XGETTEXT --default-domain=${TARGET.base} \
1822                 --directory=$TOP_SRCDIR --add-comments=TRANSLATORS: \
1823                 --language=C++ --join-existing \
1824                 --keyword=_ --keyword=N_ --keyword=B_ --keyword=qt_ \
1825                 --files-from=$TOP_SRCDIR/po/POTFILES.in \
1826                 --copyright-holder="LyX Developers" \
1827                 --msgid-bugs-address="lyx-devel@lists.lyx.org" ''']
1828         )
1829     env.Depends(lyx_po, POTFILES_in)
1830     # copy lyx.po to lyx.pot
1831     lyx_pot = env.Command('$BUILDDIR/po/lyx.pot', lyx_po,
1832         Copy('$TARGET', '$SOURCE'))
1833     #
1834     import glob
1835     # files to translate
1836     transfiles = glob.glob(os.path.join(env.Dir('$TOP_SRCDIR/po').abspath, '*.po'))
1837     # possibly *only* handle these languages
1838     languages = None
1839     if env.has_key('languages'):
1840         languages = env.make_list(env['languages'])
1841     # merge. if I use lan.po as $TARGET, it will be removed
1842     # before it is merged. In this builder,
1843     # $BUILDDIR/po/lang.po is merged from po/lang.po and $BUILDDIR/po/lyx.pot
1844     # and is copied to po/lang.po
1845     env['BUILDERS']['msgmerge'] = Builder(action=[
1846         '$MSGMERGE $TOP_SRCDIR/po/${TARGET.filebase}.po $SOURCE -o $TARGET',
1847         Copy('$TOP_SRCDIR/po/${TARGET.filebase}.po', '$TARGET')]
1848         )
1849     # for each po file, generate pot
1850     for po_file in transfiles:
1851         # get filename
1852         fname = os.path.split(po_file)[1]
1853         # country code
1854         country = fname.split('.')[0]
1855         #
1856         if not languages or country in languages:
1857             # merge po files, the generated lan.po_new file is copied to lan.po file.
1858             po = env.msgmerge('$BUILDDIR/po/%s.po' % country, lyx_pot)
1859             env.Depends(po, POTFILES_in)
1860             Alias('update_po', po)
1861
1862
1863 # if 'install' is not in the target, do not process this
1864 if 'install' in BUILD_TARGETS or 'installer' in BUILD_TARGETS:
1865     #
1866     # this part is a bit messy right now. Since scons will provide
1867     # --DESTDIR option soon, at least the dest_dir handling can be 
1868     # removed later.
1869     #
1870     #
1871     # po/
1872     #
1873     import glob
1874     # handle po files
1875     #
1876     # files to translate
1877     transfiles = glob.glob(os.path.join(env.subst('$TOP_SRCDIR'), 'po', '*.po'))
1878     # possibly *only* handle these languages
1879     languages = None
1880     if env.has_key('languages'):
1881         languages = env.make_list(env['lanauges'])
1882     # use defulat msgfmt
1883     gmo_files = []
1884     if not env['MSGFMT']:
1885         print 'msgfmt does not exist. Can not process po files'
1886     else:
1887         # create a builder
1888         env['BUILDERS']['Transfiles'] = Builder(action='$MSGFMT $SOURCE -c --statistics -o $TARGET',suffix='.gmo',src_suffix='.po')
1889         #
1890         for f in transfiles:
1891             # get filename
1892             fname = os.path.split(f)[1]
1893             # country code
1894             country = fname.split('.')[0]
1895             #
1896             if not languages or country in languages:
1897                 gmo_files.extend(env.Transfiles(f))
1898     # how to join dest_dir and prefix
1899     def joinPaths(path1, path2):
1900         ''' join path1 and path2, do not use os.path.join because
1901             under window, c:\destdir\d:\program is invalid '''
1902         if path1 == '':
1903             return os.path.normpath(path2)
1904         # separate drive letter
1905         (drive, path) = os.path.splitdrive(os.path.normpath(path2))
1906         # ignore drive letter, so c:\destdir + c:\program = c:\destdir\program
1907         return os.path.join(os.path.normpath(path1), path[1:])
1908     #
1909     # install to dest_dir/prefix
1910     dest_dir = env.get('DESTDIR', '')
1911     dest_prefix_dir = joinPaths(dest_dir, env.Dir(prefix).abspath)
1912     # create the directory if needed
1913     if not os.path.isdir(dest_prefix_dir):
1914         try:
1915             os.makedirs(dest_prefix_dir)
1916         except:
1917             pass
1918         if not os.path.isdir(dest_prefix_dir):
1919             print 'Can not create directory', dest_prefix_dir
1920             Exit(3)
1921     #
1922     if env.has_key('exec_prefix'):
1923         bin_dest_dir = joinPaths(dest_dir, Dir(env['exec_prefix']).abspath)
1924     else:
1925         bin_dest_dir = os.path.join(dest_prefix_dir, 'bin')
1926     if add_suffix:
1927         share_dest_dir = os.path.join(dest_prefix_dir, share_dir + program_suffix)
1928     else:
1929         share_dest_dir = os.path.join(dest_prefix_dir, share_dir)
1930     man_dest_dir = os.path.join(dest_prefix_dir, man_dir)
1931     locale_dest_dir = os.path.join(dest_prefix_dir, locale_dir)
1932     env['LYX2LYX_DEST'] = os.path.join(share_dest_dir, 'lyx2lyx')
1933     #
1934     import glob
1935     #
1936     # install executables (lyxclient may be None)
1937     #
1938     if add_suffix:
1939         version_suffix = program_suffix
1940     else:
1941         version_suffix = ''
1942     #
1943     # install lyx, if in release mode, try to strip the binary
1944     if env.has_key('STRIP') and env['STRIP'] is not None and mode != 'debug':
1945         # create a builder to strip and install
1946         env['BUILDERS']['StripInstallAs'] = Builder(action='$STRIP $SOURCE -o $TARGET')
1947
1948     # install executables
1949     for (name, obj) in (('lyx', lyx), ('tex2lyx', tex2lyx), ('client', client)):
1950         if obj is None:
1951             continue
1952         target_name = os.path.split(str(obj[0]))[1].replace(name, '%s%s' % (name, version_suffix))
1953         target = os.path.join(bin_dest_dir, target_name)
1954         if env['BUILDERS'].has_key('StripInstallAs'):
1955             env.StripInstallAs(target, obj)
1956         else:
1957             env.InstallAs(target, obj)
1958         Alias('install', target)
1959
1960     # share/lyx
1961     dirs = []
1962     for (dir,files) in [
1963             ('.', lib_files),  
1964             ('bind', lib_bind_files),
1965             ('bind/de', lib_bind_de_files),
1966             ('bind/fi', lib_bind_fi_files),
1967             ('bind/pt', lib_bind_pt_files),
1968             ('bind/sv', lib_bind_sv_files),
1969             ('doc', lib_doc_files),
1970             ('doc/biblio', lib_doc_biblio_files),
1971             ('doc/clipart', lib_doc_clipart_files),
1972             ('doc/cs', lib_doc_cs_files),
1973             ('doc/da', lib_doc_da_files),
1974             ('doc/de', lib_doc_de_files),
1975             ('doc/de/clipart', lib_doc_de_clipart_files),
1976             ('doc/es', lib_doc_es_files),
1977             ('doc/es/clipart', lib_doc_es_clipart_files),
1978             ('doc/eu', lib_doc_eu_files),
1979             ('doc/fr', lib_doc_fr_files),
1980             ('doc/he', lib_doc_he_files),
1981             ('doc/hu', lib_doc_hu_files),
1982             ('doc/it', lib_doc_it_files),
1983             ('doc/nl', lib_doc_nl_files),
1984             ('doc/nb', lib_doc_nb_files),
1985             ('doc/pl', lib_doc_pl_files),
1986             ('doc/pt', lib_doc_pt_files),
1987             ('doc/ro', lib_doc_ro_files),
1988             ('doc/ru', lib_doc_ru_files),
1989             ('doc/sk', lib_doc_sk_files),
1990             ('doc/sl', lib_doc_sl_files),
1991             ('doc/sv', lib_doc_sv_files),
1992             ('examples', lib_examples_files),
1993             ('examples/ca', lib_examples_ca_files),
1994             ('examples/cs', lib_examples_cs_files),
1995             ('examples/da', lib_examples_da_files),
1996             ('examples/de', lib_examples_de_files),
1997             ('examples/es', lib_examples_es_files),
1998             ('examples/eu', lib_examples_eu_files),
1999             ('examples/fa', lib_examples_fa_files),
2000             ('examples/fr', lib_examples_fr_files),
2001             ('examples/he', lib_examples_he_files),
2002             ('examples/hu', lib_examples_hu_files),
2003             ('examples/it', lib_examples_it_files),
2004             ('examples/nl', lib_examples_nl_files),
2005             ('examples/pl', lib_examples_pl_files),
2006             ('examples/pt', lib_examples_pt_files),
2007             ('examples/ru', lib_examples_ru_files),
2008             ('examples/sl', lib_examples_sl_files),
2009             ('examples/ro', lib_examples_ro_files),
2010             ('fonts', lib_fonts_files),
2011             ('images', lib_images_files),
2012             ('images/math', lib_images_math_files),
2013             ('kbd', lib_kbd_files),
2014             ('layouts', lib_layouts_files + lib_layouts_inc_files),
2015             ('lyx2lyx', lib_lyx2lyx_files),
2016             ('scripts', lib_scripts_files),
2017             ('templates', lib_templates_files),
2018             ('tex', lib_tex_files),
2019             ('ui', lib_ui_files)]:
2020         dirs.append(env.Install(os.path.join(share_dest_dir, dir),
2021             [env.subst('$TOP_SRCDIR/lib/%s/%s' % (dir, file)) for file in files]))
2022     Alias('install', dirs)
2023
2024     # subst and install lyx2lyx_version.py which is not in scons_manifest.py
2025     env.Depends(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py', '$BUILDDIR/src/config.h')
2026     env.substFile(share_dest_dir + '/lyx2lyx/lyx2lyx_version.py',
2027         '$TOP_SRCDIR/lib/lyx2lyx/lyx2lyx_version.py.in')
2028     Alias('install', share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2029     sys.path.append(share_dest_dir + '/lyx2lyx')
2030     
2031     # generate TOC files for each doc
2032     languages = depend.all_documents(env.Dir('$TOP_SRCDIR/lib/doc').abspath)
2033     tocs = []
2034     for lang in languages.keys():
2035         if os.path.isdir(os.path.join(env.Dir('$TOP_SRCDIR/lib/doc').abspath, lang)):
2036             toc = env.installTOC(os.path.join(share_dest_dir, 'doc', lang, 'TOC.lyx'),
2037                 languages[lang])
2038             tocs.append(toc)
2039             # doc_toc.build_toc needs a installed version of lyx2lyx to execute
2040             env.Depends(toc, share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2041         else:
2042             # this is for English
2043             toc = env.installTOC(os.path.join(share_dest_dir, 'doc', 'TOC.lyx'),
2044                 languages[lang])
2045             tocs.append(toc)
2046             env.Depends(toc, share_dest_dir + '/lyx2lyx/lyx2lyx_version.py')
2047     Alias('install', tocs)
2048     
2049     if platform_name == 'cygwin':
2050         # cygwin packaging requires a file /usr/share/doc/Cygwin/foot-vendor-suffix.README
2051         Cygwin_README = os.path.join(dest_prefix_dir, 'share', 'doc', 'Cygwin', 
2052             '%s-%s.README' % (package, package_cygwin_version))
2053         env.InstallAs(Cygwin_README,
2054             os.path.join(env.subst('$TOP_SRCDIR'), 'README.cygwin'))
2055         Alias('install', Cygwin_README)
2056         # also a directory /usr/share/doc/lyx for README etc
2057         Cygwin_Doc = os.path.join(dest_prefix_dir, 'share', 'doc', package)
2058         env.Install(Cygwin_Doc, [os.path.join(env.subst('$TOP_SRCDIR'), x) for x in \
2059             ['INSTALL', 'README', 'README.Cygwin', 'RELEASE-NOTES', 'COPYING', 'ANNOUNCE']])
2060         Alias('install', Cygwin_Doc)
2061         # cygwin fonts also need to be installed
2062         Cygwin_fonts = os.path.join(share_dest_dir, 'fonts')
2063         env.Install(Cygwin_fonts, 
2064             [env.subst('$TOP_SRCDIR/development/Win32/packaging/bakoma/%s' % file) \
2065                   for file in win32_bakoma_fonts])
2066         Alias('install', Cygwin_fonts)
2067         # we also need a post installation script
2068         tmp_script = utils.installCygwinPostinstallScript('/tmp')
2069         postinstall_path = os.path.join(dest_dir, 'etc', 'postinstall')
2070         env.Install(postinstall_path, tmp_script)
2071         Alias('install', postinstall_path)
2072
2073
2074     # man
2075     env.InstallAs(os.path.join(man_dest_dir, 'lyx' + version_suffix + '.1'),
2076         env.subst('$TOP_SRCDIR/lyx.man'))
2077     env.InstallAs(os.path.join(man_dest_dir, 'tex2lyx' + version_suffix + '.1'),
2078         env.subst('$TOP_SRCDIR/src/tex2lyx/tex2lyx.man'))
2079     env.InstallAs(os.path.join(man_dest_dir, 'lyxclient' + version_suffix + '.1'),
2080         env.subst('$TOP_SRCDIR/src/client/lyxclient.man'))
2081     Alias('install', [os.path.join(man_dest_dir, x + version_suffix + '.1') for
2082         x in ['lyx', 'tex2lyx', 'lyxclient']])
2083     # locale files?
2084     # ru.gmo ==> ru/LC_MESSAGES/lyxSUFFIX.mo
2085     for gmo in gmo_files:
2086         lan = os.path.split(str(gmo))[1].split('.')[0]
2087         dest_file = os.path.join(locale_dest_dir, lan, 'LC_MESSAGES', 'lyx' + program_suffix + '.mo')
2088         env.InstallAs(dest_file, gmo)
2089         Alias('install', dest_file)
2090
2091
2092 if 'install' in BUILD_TARGETS or 'installer' in BUILD_TARGETS:
2093     #
2094     # build windows installer using NSIS
2095     #
2096     # NOTE:
2097     # There is a nsis builder on scons wiki but it does not work with
2098     # our lyx.nsi because it does not dig through all the include directives
2099     # and find the dependencies automatically. Also, it can not parse
2100     # OutFile in lyx.nsi since it is defined as SETUP_EXE which is in turn
2101     # something rely on date.
2102     # Because of this, I am doing a simple nsis builder here.
2103     if platform_name != 'win32':
2104         print 'installer target is only available for windows platform'
2105         Exit(1)
2106     if mode != 'release':
2107         print 'installer has to be built in release mode (use option mode=release)'
2108         Exit(1)
2109     installer_files = ['$TOP_SRCDIR/development/Win32/packaging/installer/%s' \
2110             % x for x in development_Win32_packaging_installer] + \
2111         ['$TOP_SRCDIR/development/Win32/packaging/installer/components/%s' \
2112             % x for x in development_Win32_packaging_installer_components] + \
2113         ['$TOP_SRCDIR/development/Win32/packaging/installer/dialogs/%s' \
2114             % x for x in development_Win32_packaging_installer_dialogs] + \
2115         ['$TOP_SRCDIR/development/Win32/packaging/installer/graphics/%s' \
2116             % x for x in development_Win32_packaging_installer_graphics] + \
2117         ['$TOP_SRCDIR/development/Win32/packaging/installer/include/%s' \
2118             % x for x in development_Win32_packaging_installer_include] + \
2119         ['$TOP_SRCDIR/development/Win32/packaging/installer/lang/%s' \
2120             % x for x in development_Win32_packaging_installer_lang]
2121     if env.has_key('NSIS') and env['NSIS'] is not None:
2122         # create a builder to strip and install
2123         env['BUILDERS']['installer'] = Builder(generator=utils.env_nsis)
2124     else:
2125         print 'No nsis compiler is found. Existing...'
2126         Exit(2)
2127     if not env.has_key('win_installer') or env['win_installer'] is None:
2128         if devel_version:
2129             env['win_installer'] = '%s-%s-%s-Installer.exe' % (package_name, package_version, time.strftime('%Y-%m-%d'))
2130         else:
2131             env['win_installer'] = '%s-%s-Installer.exe' % (package_name, package_version)
2132     # provide default setting            
2133     if not env.has_key('deps_dir') or env['deps_dir'] is None:
2134         env['deps_dir'] = os.path.join(env.Dir('$TOP_SRCDIR').abspath, 'lyx-windows-deps-msvc-qt4')
2135     if not os.path.isdir(env.Dir('$deps_dir').abspath):
2136         print 'Development dependency package is not found.'
2137         Exit(1)    
2138     else:
2139         env['deps_dir'] = env.Dir('$deps_dir').abspath
2140     # build bundle?
2141     if env.has_key('bundle_dir') and os.path.isdir(env.Dir('$bundle_dir').abspath):
2142         env['bundle_dir'] = env.Dir('$bundle_dir').abspath
2143     elif os.path.isdir(os.path.join(env.Dir('$TOP_SRCDIR').abspath, 'lyx-windows-bundle-deps')):
2144         env['bundle_dir'] = os.path.join(env.Dir('$TOP_SRCDIR').abspath, 'lyx-windows-bundle-deps')
2145     else:
2146         env['bundle_dir'] = None
2147     # if absolute path is given, use it, otherwise, write to current directory
2148     if not (':' in env['win_installer'] or '/' in env['win_installer'] or '\\' in env['win_installer']):
2149         env['win_installer'] = os.path.join(env.Dir('$BUILDDIR').abspath, env['win_installer'])
2150     env.Append(NSISDEFINES={
2151         'ExeFile':env['win_installer'],
2152         'BundleExeFile':env['win_installer'].replace('.exe', '-bundle.exe'),
2153         'FilesLyx':env.Dir(dest_prefix_dir).abspath,
2154         'FilesDeps':env['deps_dir'],
2155         'FilesBundle':env['bundle_dir'],
2156         })
2157     installer = env.installer(env['win_installer'],
2158         '$TOP_SRCDIR/development/Win32/packaging/installer/lyx.nsi')
2159     # since I can not use a scanner, explicit dependent is required
2160     env.Depends(installer, 'install')
2161     env.Depends(installer, installer_files)
2162     env.Alias('installer', installer)
2163     # also generate bundle?
2164     if env.has_key('bundle') and env['bundle']:
2165         if env['bundle_dir'] is None or not os.path.isdir(env['bundle_dir']):
2166             print 'Bundle directory does not exist (default to %s\lyx-windows-bundle-deps.' % env.Dir('$TOP_SRCDIR').abspath
2167             print 'Use bundle_dir option to specify'
2168             Exit(1)
2169         # generator of the builder will add bundle stuff depending on output name
2170         bundle_installer = env.installer(env['win_installer'].replace('.exe', '-bundle.exe'),
2171             '$TOP_SRCDIR/development/Win32/packaging/installer/lyx.nsi')
2172         env.Depends(bundle_installer, 'install')
2173         env.Depends(bundle_installer, installer_files)
2174         env.Alias('installer', bundle_installer)
2175
2176 Default('lyx')
2177 Alias('all', ['lyx', 'client', 'tex2lyx'])