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