root/trunk/SConstruct

Revision 1372, 40.3 kB (checked in by patrick, 2 weeks ago)

For some reason, SCons is using the wrong compile flag to create shared
libraries on Mac OS X. Force the use of -dynamiclib until this gets resolved
in a more correct manner.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1 #!python
2 #
3 # SCons build script for OpenSG
4 import os, string, sys, re, glob, copy, types, traceback, pprint, tempfile, shutil
5 pj = os.path.join
6
7 # If we have wingide, try loading the debugging extenstions
8 try:
9    import wing.wingdbstub
10    print "Loaded wingdb stub for debugging..."
11 except:
12    pass
13
14 # Extend paths for scons-addons and scons-build if needed
15 # - this allows a development version of scons-addons to be
16 #   in the standard python path and used instead.
17 try:
18    import SConsAddons.Util
19    print "Using SConsAddons from: ", os.path.dirname(SConsAddons.Util.__file__)
20 except:
21    sys.path.insert(0,pj('Tools','scons-addons','src'))
22    print "Using SConsAddons from: Tools/scons-addons/src"
23
24 sys.path.insert(0,pj('Tools','scons-build'))
25
26 print "-------------------------------------------------"
27 print "WARNING: The build is currently in development.  "
28 print "            - It needs the svn version of scons-addons"
29 print "WARNING:"
30
31 import SCons.Environment
32 import SCons
33 import SConsAddons.Util as sca_util
34 import SConsAddons.Options as sca_opts
35 import SConsAddons.Variants as sca_variants
36 import SConsAddons.Builders
37 import SConsAddons.Options.Boost
38 import SConsAddons.Options.VTK
39 from SConsAddons.EnvironmentBuilder import EnvironmentBuilder
40 from LibraryUtils import *
41 from sets import Set
42 from socket import gethostname
43
44 import OpenSG.AddOnHacks
45 import OpenSG.ColladaOption
46
47 from BuildInfoScanner import BuildInfoScanner
48 from RevisionTagWriter import RevisionTagWriter
49
50 # If we have pysvn, load it
51 try:
52    import pysvn
53    have_pysvn = True
54 except:
55    have_pysvn = False
56
57 # Aliases
58 GetPlatform = sca_util.GetPlatform
59 Export('GetPlatform')
60 verbose_build = False
61
62 # Build TODO
63 # - Support selection of WS/ES
64 # - Support selection of compiler to build with
65 # - QT support
66 # - Contrib libraries
67 # - Library specific defines (if needed)
68 # - Build on windows
69 # - Project files for windows
70
71 # ---------------------------------------------------------------------------- #
72 # ------------------------------ HELPER METHODS ------------------------------ #
73 # ---------------------------------------------------------------------------- #
74
75 # ---------------- #
76 # --- BUILDERS --- #
77 # ---------------- #
78
79 # fcd2code builder
80 # - Custom builder for fcd2code
81 def registerfcd2codeBuilder(env, required=True):
82    print "Setting up fcd2code builder...",
83    
84    fcd2code_cmd = pj("Tools", "fcd2code","fcd2code")
85    fcd2code_cmd = os.path.abspath(fcd2code_cmd)
86    if not os.path.isfile(fcd2code_cmd):
87       print " Warning: fcd2code not found at: ", fcd2code_cmd
88       if required:
89          sys.exit(1)
90       return
91    
92    template_files = glob.glob(pj("Tools",
93                                  "fcd2code",
94                                  "*TemplateFieldContainer*Base*.txt"))
95
96    template_files.append(glob.glob(pj("Tools",
97                                       "fcd2code",
98                                       "*TemplateFieldContainer*Field*.txt")))
99
100    template_files.append(glob.glob(pj("Tools",
101                                       "fcd2code",
102                                       "*.py")))
103
104
105    
106    def prop_emitter(target,source,env, template_files=template_files):
107       """ Returns a list of files including all output forms and
108           The input templates as sources.
109       """
110       assert str(source[0]).endswith(".fcd")
111       assert len(source) == 1
112
113       base_name = os.path.splitext(str(source[0]))[0]
114
115       # Targets are all the files that we build
116       target = []
117       for ext in ["Base.cpp","Base.h","Base.inl","Fields.h"]:
118          target.append(base_name+ext)
119      
120       # Sources are the fcd file and all the template files
121       source.extend(template_files)
122
123       return (target, source)
124    
125    
126    fcd2code_builder = Builder(action = " ".join([sys.executable, fcd2code_cmd]) + ' -c -b -d $SOURCE -p ${TARGET.dir}',
127                               src_suffix = '.fcd',
128                               suffix = 'unused.h',
129                               emitter = prop_emitter)
130    env.Append(BUILDERS = {'fcd2code' : fcd2code_builder})
131    print "[OK]"
132
133
134 # fbd2code builder
135 # - Custom builder for fbd2code
136 def registerfbd2codeBuilder(env, required=True):
137    print "Setting up fbd2code builder...",
138    
139    fbd2code_cmd = pj("Tools", "fcd2code","fcd2code")
140    fbd2code_cmd = os.path.abspath(fbd2code_cmd)
141    if not os.path.isfile(fbd2code_cmd):
142       print " Warning: fcd2code not found at: ", fbd2code_cmd
143       if required:
144          sys.exit(1)
145       return
146    
147    template_files = glob.glob(pj("Tools",
148                                  "fcd2code",
149                                  "*TemplateFieldBundle*Base*.txt"))
150
151    template_files.append(glob.glob(pj("Tools",
152                                       "fcd2code",
153                                       "*TemplateFieldBundle*Field*.txt")))
154
155    template_files.append(glob.glob(pj("Tools",
156                                       "fcd2code",
157                                       "*Template*.py")))
158    
159    def prop_emitter(target,source,env, template_files=template_files):
160       """ Returns a list of files including all output forms and
161           The input templates as sources.
162       """
163       assert str(source[0]).endswith(".fbd")
164       assert len(source) == 1
165
166       base_name = os.path.splitext(str(source[0]))[0]
167
168       # Targets are all the files that we build
169       target = []
170       for ext in ["Base.cpp","Base.h","Base.inl","Fields.h"]:
171          target.append(base_name+ext)
172      
173       # Sources are the fbd file and all the template files
174       source.extend(template_files)
175
176       return (target, source)
177    
178    
179    fbd2code_builder = Builder(action = " ".join([sys.executable,
180                               fbd2code_cmd]) + ' -c -b -B -d $SOURCE -p ${TARGET.dir}',
181                               src_suffix = '.fbd',
182                               suffix = 'unused.h',
183                               emitter = prop_emitter)
184    env.Append(BUILDERS = {'fbd2code' : fbd2code_builder})
185    print "[OK]"
186
187
188 def addScanParseSkel(common_env):
189    """ This is an ugly hack to add the lex/yacc support into the build.  It is ugly because of a couple of things.
190       - We use some very custom flags
191       - We need to post process the scanner to include a different file then normal.
192       - We are forcing this to be done in the source tree in a subdir without actually going there.
193       - Dependency management seems to be a little messed up right now in the code or scons.
194       - BUGS: Scons does not seem to recognize that the files we are building here are source
195               files for the libraries.  This makes it so we have to run the build twice if the files change.
196               Scons cannot recognize whether the existing files are current or not, if they come out of
197                svn. This can result in spurious regens, which break the code if the wrong versions of
198                flex/bison are present.
199    """
200    # Hack to handle the generation of the parser from .y
201    # This pretty hacky to allow using a version of the file from the repository if yacc is not installed
202    # 1. Call bison: OSGScanParseSkelParser.yy -> OSGScanParseSkelParser.hpp .cpp .output (we don't need the last one)
203    if "yacc" in common_env["TOOLS"]:
204       if common_env["enable_scanparse_regen"]:
205          parser_env = common_env.Copy()
206          parser_env.Append(YACCFLAGS = ["-d","-v","-pOSGScanParseSkel_","-bOSGScanParseSkel_"])
207          source_file = "Source/System/FileIO/ScanParseSkel/OSGScanParseSkelParser.yy"
208          target_file = "Source/System/FileIO/ScanParseSkel/OSGScanParseSkelParser.cpp"
209          yfiles = parser_env.CXXFile(target=target_file,source=source_file)
210          NoClean(yfiles)
211          #print "yfiles: ", yfiles
212
213          # Make sure the parser files have been found for OSGFileIO
214          y_cpp_file = str(yfiles[0]).replace("Source/","",1)
215          y_hpp_file = str(yfiles[1]).replace("Source/","",1)
216          #if not y_cpp_file in lib_map["OSGSystem"].source_files:
217          #   lib_map["OSGSystem"].source_files.append(y_cpp_file)
218          #if not y_hpp_file in lib_map["OSGSystem"].header_files:
219          #   lib_map["OSGSystem"].header_files.append(y_hpp_file)
220          #print " yy source: %s \n header: %s"%(lib_map["OSGSystem"].source_files, lib_map["OSGSystem"].header_files)
221       else:
222          print "WARNING: enable_scanparse_regen disabled. If you change .yy files they will not be rebuilt."
223          common_env["TOOLS"].remove('yacc')
224    else:
225       print "WARNING: bison not available.  If you change .yy files they cannot be rebuilt."
226    
227    # Hack to handle the generation of the scanner from .lpp
228    # This pretty hacky to allow using a version of the file from the repository if lex is not installed
229    # 2. Call flex: OSGScanParseSkelScanner.lpp -> OSGScanParseSkelScanner.cpp (this one needs to be filtered to change the include)
230    if "lex" in common_env["TOOLS"]:
231       def filter_header(target, source, env):
232          """ Custom filter to change the include file for the flexlexer.h"""
233          fname = str(target[0])
234          contents = open(fname).readlines()
235          for i in range(len(contents)):
236             if contents[i] == "#include <FlexLexer.h>\n":
237                contents[i] = "#include \"%s\"\n" % os.path.split(OSG_flexlexer_h)[1]
238                break
239          open(fname,'w').writelines(contents)
240          #print "filter_header: Created ", fname
241
242       if common_env["enable_scanparse_regen"]:
243          lexer_env = common_env.Copy()
244          lexer_env.Append(LEXFLAGS = ["-+","-POSGScanParseSkel_"])
245
246          lexer_dir       = pj('Source','System','FileIO','ScanParseSkel')
247          sys_flexlexer_h = "/usr/include/FlexLexer.h"
248          OSG_flexlexer_h = pj(lexer_dir,"OSGScanParseSkelScanner_FlexLexer.h")
249          source_file     = pj(lexer_dir,"OSGScanParseSkelScanner.ll")
250          target_file     = pj(lexer_dir,"OSGScanParseSkelScanner.cpp")
251
252          # Replace lex builder with new action that calls flex and then filters
253          std_lex_action = Action("$LEXCOM", "$LEXCOMSTR")
254          filter_action = Action(filter_header, lambda t,s,e: "Filtering header: %s %s"%(str(t),str(s)))
255          cxx_file_builder = lexer_env['BUILDERS']['CXXFile']
256          cxx_file_builder.add_action('.ll', Action([std_lex_action, filter_action]))
257          lfiles = lexer_env.CXXFile(target=target_file,source=source_file)
258          NoClean(lfiles)
259          #print "lfiles: ", lfiles
260
261          # If available, copy the system FlexLexer.h file to local source dir
262          if os.path.exists(sys_flexlexer_h):
263             flexlex_cp = lexer_env.Command(OSG_flexlexer_h, sys_flexlexer_h,[Copy('$TARGET','$SOURCE'),])
264             Depends(lfiles, flexlex_cp)
265
266          #Depends(lfiles, "Source/System/FileIO/ScanParseSkel/OSGScanParseSkelParser.hpp") # the scanner includes the token header from the parser...
267          if vars().has_key('yfiles'):
268             Depends(lfiles, yfiles)
269
270          # Strip off "Source/" since this will be in the build dir
271          scanner_src = target_file.replace("Source/","",1)
272          #if not scanner_src in lib_map["OSGSystem"].source_files:
273          #   lib_map["OSGSystem"].source_files.append(scanner_src)
274          #print "FileIO source files: ", lib_map["OSGSystem"].source_files
275       else:
276          print "WARNING: enable_scanparse_regen disabled. If you change .ll files they will not be rebuilt."
277          common_env["TOOLS"].remove('lex')
278    else:
279       print "WARNING: flex not available.  If you change .ll files they cannot be rebuilt."
280
281 # -------------------- #
282 # --- OPTION TYPES --- #
283 # -------------------- #
284
285 class SimpleAppendOption(sca_opts.SimpleOption):
286    """
287    Variant of the simple option wrapper that appends a value to the environment instead
288    of replacing it.
289    """
290    def __init__(self, name, key, help):
291       """
292       Create an option
293       name - the name of the commandline option
294       key - the name of the key in the environment to append to
295       help - Help text about the option object
296       """
297       sca_opts.SimpleOption.__init__(self, name, name, help + " (Use ':' to separate multiple)", \
298                                      None, None, None, None)
299       self.key = key
300
301    """
302    We want these options to be applied before all others, to have them have effect on e.g.
303    StandardPackageOption tests, so override completeProcess instead of apply.
304    """
305    def completeProcess(self, env):
306       if self.value:
307          for i in self.value.split(os.pathsep):
308             exec("env.Append(%s = [i])" % self.key)
309
310 # ---------------------------------------------------------------------------- #
311 # ----------------------------- Main build setup ----------------------------- #
312 # ---------------------------------------------------------------------------- #
313
314 EnsureSConsVersion(0,96,92)
315 SourceSignatures('MD5')
316 #SourceSignatures('timestamp')
317 opensg_version_string = file("VERSION").readline().strip()
318
319 print "Building OpenSG ", opensg_version_string
320
321 OpenSG.AddOnHacks.apply()
322
323 # Allow user to pass an options file on the command line, with the
324 # option_file=myOptFile syntax
325
326 platform = sca_util.GetPlatform()
327 unspecified_prefix = "use-instlinks"
328
329
330 # Create base environment to use for option processing
331 if GetPlatform() == "win32":
332    # XXX: Temp hack to get msvs version setting
333    if ARGUMENTS.has_key("MSVS_VERSION"):
334       common_env = Environment(MSVS_VERSION=ARGUMENTS["MSVS_VERSION"],
335                                 tools = ['default', 'doxygen'],
336                                 toolpath = '.')
337    else:
338       common_env = Environment(tools = ['default', 'doxygen'], toolpath = '.')
339 else:
340    if ARGUMENTS.has_key("icc"):
341       use_cxxlib_icc = False
342
343       if ARGUMENTS.has_key("cxxlib-icc"):
344          use_cxxlib_icc = True
345
346       common_env = Environment(ENV = os.environ,
347                                tools=['gnulink', 'intelicc', 'intelicpc', 'doxygen'],
348                                cxxlib_icc=use_cxxlib_icc,
349                                toolpath = ['.', 'Tools/scons-build/OpenSG/Tools'])
350    else:
351       common_env = Environment(ENV = os.environ,
352                                toolpath = ['.', 'Tools/scons-build/OpenSG/Tools'],
353                                tools = ['g++', 'gcc', 'gnulink', 'osg_yacc',
354                                         'osg_lex', 'doxygen'])
355
356 SConsignFile('.sconsign.'+GetPlatform()+common_env.subst('$CXX'))
357 buildDir = "build." + platform + '.' + common_env.subst('$CXX')
358
359 option_filename = "option.cache." + platform + '.' + common_env.subst('$CXX')
360
361 if ARGUMENTS.has_key("options_file"):
362    opt_file = ARGUMENTS["options_file"]
363    if os.path.exists(opt_file):
364       print "Reading options from: %s" % str(opt_file)
365       option_filename = opt_file
366    else:
367       print "Options file '%s' not found.. will continue with default '%s'" % \
368       (opt_file, option_filename)
369
370 # Check if the GL subdir should be used - can not be done with the regular options
371 # stuff as sca_opts.StandardPackageOption for glut depends on this value
372 if ARGUMENTS.has_key("disable_glut_glsubdir") and ARGUMENTS["disable_glut_glsubdir"]:
373     glsubdir = ""
374 else:
375     glsubdir = "GL/"
376
377 # Setup the directories used for sconf processing
378 common_env["CONFIGUREDIR"] = '.sconf_temp_'+platform+'_'+common_env.subst('$CXX')
379 common_env["CONFIGURELOG"] = 'sconf.log_'+platform+'_'+common_env.subst('$CXX')
380 if common_env.has_key("MSVS"):
381    common_env["CONFIGUREDIR"] += "." + common_env["MSVS"]["VERSION"]
382    common_env["CONFIGURELOG"] += "." + common_env["MSVS"]["VERSION"]
383
384 SConsAddons.Builders.registerDefineBuilder(common_env)
385 SConsAddons.Builders.registerSubstBuilder(common_env)
386
387 # Create variant helper and builder
388 variant_helper = sca_variants.VariantsHelper(variantKeys=["type", "arch"])
389 base_bldr = EnvironmentBuilder()
390
391 # ----------------- #
392 # --- CONFIGURE --- #
393 # ----------------- #
394
395 # There is nothing to do ATM - sca_opts.StandardPackageOption can handle
396 # everything so far.
397
398 # --------------- #
399 # --- OPTIONS --- #
400 # --------------- #
401
402 # Options are stored in one of these groups:
403 # - required_libs_options:  Libraries needed to build OpenSG
404 # - optional_libs_options:  Libraries needed for/providing additional functionality
405 # - build_options:          Options to select build/install directories and
406 #                           special build steps.
407 # - feature_options:        Options to enable/disable or tweak certain features
408 #                           of OpenSG.
409 # - misc_options:           Options that do not fit anywhere else.
410 # - extra_libs_options:     Should not be changed - it's only to allow building
411 #                           with additional libraries that are not integrated into
412 #                           the build
413 #
414 # There is special handling for image formats, because some are directly
415 # supported and others require external libs, they may end up in different
416 # option groups, but in the help message they should show up together - see below.
417
418 #
419 # 1) Setup options
420 #    Create Option objects and store them in their group.
421
422 opts = sca_opts.Options(files = [option_filename, 'options.custom'],
423                                    args= ARGUMENTS)
424
425 # Handle library name differences between platforms
426 if "win32" == platform:
427     glut_libname = "glut32"
428     tiff_libname = "tif32"
429     zlib_libname = "zlib"
430     jpeg_libname = "libjpeg"
431     png_libname = "libpng"
432 else:
433     glut_libname = "glut"
434     tiff_libname = "tiff"
435     zlib_libname = "z"
436     jpeg_libname = "jpeg"
437     png_libname = "png"
438
439
440 # Build options - source and destination directories etc.
441 build_options = {}
442 build_options["install_prefix"] = sca_opts.SimpleOption(
443     "prefix", "prefix", "Installation prefix", unspecified_prefix, None, None, None)
444 build_options["build_suffix"] = sca_opts.SimpleOption(
445     "build_suffix", "build_suffix",
446     "Suffix to append to build directory.  Useful for compiling multiple variations on the same platform",
447     "", None, None, None)
448 build_options["enable_fcd2code"] = sca_opts.BoolOption(
449     "enable_fcd2code", "Enable code generation pass (from .fcd files) during build", False)
450 build_options["enable_fbd2code"] = sca_opts.BoolOption(
451     "enable_fbd2code", "Enable code generation pass (from .fbd files) during build", False)
452 build_options["enable_distcc"] = sca_opts.BoolOption(
453     "enable_distcc", "Enable use of distcc during build. (distcc must be in your path)", False)
454 build_options["enable_unittests"] = sca_opts.BoolOption(
455     "enable_unittests", "Enable building and running of the unit tests after build", True)
456 build_options["enable_revision_tags"] = sca_opts.BoolOption(
457     "enable_revision_tags", "Enable updating of OSG*Def.cpp files with current svn revision numbers", False)
458 build_options["enable_gv_beta"] = sca_opts.BoolOption(
459     "enable_gv_beta", "Enable gv testing stuff", False)
460
461 # Options for required external libraries
462 required_libs_options = {}
463 if "win32" == platform:
464
465     toolset = "auto"
466
467     if common_env.has_key("MSVS"):
468        toolset = 'vc' + common_env["MSVS"]["VERSION"].replace('.', '')
469
470     required_libs_options["boost"] = sca_opts.Boost.Boost(
471         "boost", "1.31.0", libs = ["filesystem"], required = True,
472         useVersion = True, allowLibNameFallbacks=True, toolset = toolset);
473 else:
474     required_libs_options["boost"] = sca_opts.Boost.Boost(
475         "boost", "1.31.0", libs = ["filesystem"], required = True, useVersion = True, allowLibNameFallbacks=True);
476
477 # Options for optional external libraries
478 optional_libs_options = {}
479 optional_libs_options["jpeg"] = sca_opts.StandardPackageOption(
480     "jpeg", "Location of the JPEG library", library = jpeg_libname, required = False)
481
482 optional_libs_options["tiff"] = sca_opts.StandardPackageOption(
483     "tiff", "Location of the TIFF library", library = tiff_libname, required = False)
484
485 optional_libs_options["png"] = sca_opts.StandardPackageOption(
486     "png", "Location of the PNG library", library = png_libname, required = False)
487
488 optional_libs_options["glut"] = sca_opts.StandardPackageOption(
489     "glut", "Location of the GLUT library", library = glut_libname,
490     header = glsubdir + "glut.h", required = False)
491
492 optional_libs_options["X"] = sca_opts.StandardPackageOption(
493     "X", "Location of the X library", library = 'X11',
494     required = False)
495
496 optional_libs_options["freetype"] = sca_opts.StandardPackageOption(
497     "freetype", "Location of freetype2 library", library = "freetype",
498     header = "freetype/config/ftheader.h", required = False)
499
500 if "win32" != platform:
501    optional_libs_options["freetype"].incDir = '/usr/include/freetype2'
502
503 optional_libs_options["fontconfig"] = sca_opts.StandardPackageOption(
504     "fontconfig", "Location of fontconfig library", library = "fontconfig",
505     header = "fontconfig/fontconfig.h", required = False)
506
507 optional_libs_options["zlib"] = sca_opts.StandardPackageOption(
508     "zlib", "Location of the zlib compression library", library = zlib_libname,
509     header = "zlib.h", required = False)
510
511 optional_libs_options["NVPerfSDK"] = sca_opts.StandardPackageOption(
512     "NVPerfSDK", "Location of the NVPerfSDK library", library = "NVPerfSDK",
513     header = "NVPerfSDK.h", required = False)
514
515 collada_lib_prefix = ""
516 if "win32" == platform:
517     collada_lib_prefix = "lib"
518 optional_libs_options["collada"] = OpenSG.ColladaOption.ColladaOption(
519     "collada", "Location of the collada dom library", library =
520     ["%scollada_dae" % collada_lib_prefix,
521      "%scollada_LIBXMLPlugin" % collada_lib_prefix,
522      "%scollada_STLDatabase" % collada_lib_prefix,
523      "%scollada_dom" % collada_lib_prefix,
524      "%scollada_stdErrPlugin" % collada_lib_prefix,
525      "%scollada_dae" % collada_lib_prefix],
526     header = "dae/daeIntegrationObject.h", required = False)
527
528 xml2_lib = ["xml2"]
529 if "win32" == platform:
530     # Link against the static versions of libiconv and libxml2 on Windows.
531     xml2_lib = ["iconv_a", "libxml2_a"]
532 optional_libs_options["xml2"] = sca_opts.StandardPackageOption(
533     "xml2", "Location of the xml2 library", library = xml2_lib,
534     required = False)
535
536 vtk_libs = ['vtkRendering',
537             'vtkIO',
538             'vtkGraphics',
539             'vtkImaging',
540             'vtkFiltering',
541             'vtkCommon',
542             'vtkftgl',
543             'vtkDICOMParser',
544             'vtksys',
545 #            'verdict',
546             'vtkNetCDF'
547 #            'vtkmetaio'
548             ]
549
550 #if "win32" != platform:
551 #    vtk_libs.append('vtkMPEG2Encode')
552
553 optional_libs_options['vtk'] = sca_opts.VTK.VTK(
554    "vtk",
555    "Location of the vtk libraries",
556    required = False,
557    libList = vtk_libs)
558
559 # Feature options - select library/interface features
560 feature_options = {}
561 feature_options["gif"] = sca_opts.BoolOption(
562     "enable_gif", "Enable GIF support", True)
563
564 feature_options["fcptr_mode"] = sca_opts.EnumOption(
565     "fcptr_mode", "Select the mode for field container pointers",
566     "MT_CPTR", ["SINGLE_THREAD", "MT_CPTR"])
567
568 feature_options["disable_deprecated"] = sca_opts.BoolOption(
569     "disable_deprecated", "Disable deprecated interfaces and code", False)
570
571 feature_options["disable_glut_glsubdir"] = sca_opts.BoolOption(
572     "disable_glut_glsubdir", "Do not use GL subdir when including glut.h", False)
573
574 feature_options["enable_osg1_compat"] = sca_opts.BoolOption(
575     "enable_osg1_compat", "Enable OpenSG 1.x compatibility", False)
576
577 feature_options["enable_deprecated_props"] = sca_opts.BoolOption(
578     "enable_deprecated_props", "Enable deprecated property types.", False)
579
580 feature_options["enable_new_osb_io"] = sca_opts.BoolOption(
581     "enable_new_osb_io", "Enable the new OSB IO facilities.", False)
582
583 feature_options["enable_scanparse_regen"] = sca_opts.BoolOption(
584     "enable_scanparse_regen", "Enable regenerating the scanner/parser files using flex and bison", False);
585
586 feature_options["enable_testcontainer"] = sca_opts.BoolOption(
587     "enable_testcontainer", "Enable container used for testing (from Source/Test)", False)
588
589 feature_options["docs_mode"] = sca_opts.EnumOption(
590     "docs_mode", "Select the mode for documentation generation",
591     "NONE", ["NONE", "STANDALONE", "TRAC", "DEVELOPER"])
592
593 feature_options["enable_valgrind_checks"] = sca_opts.BoolOption(
594     "enable_valgrind_checks", "Enable valgrind check code embedded in OpenSG.", False)
595
596 feature_options["enable_memory_debugging"] = sca_opts.BoolOption(
597     "enable_memory_debugging", "Enable memory debugging checks in OpenSG.", False)
598
599 feature_options["enable_scanparse_in_builddir"] = sca_opts.BoolOption(
600     "enable_scanparse_in_builddir", "Enable scanparse files generated into the builddir", False)
601
602 if "win32" == platform:
603     feature_options["enable_win_localstorage"] = sca_opts.BoolOption(
604         "enable_win_localstorage", "Enable use of local storage instead of __declspec to "+
605         "get thread local storage on windows", True)
606
607 if "win32" != platform:
608     feature_options["enable_elf_localstorage"] = sca_opts.BoolOption(
609         "enable_elf_localstorage", "Enable use of elf thread local storage with pthreads",
610         ("linux" == platform))
611
612 # Misc options
613 misc_options = {}
614 #misc_options["icc_compat"] = sca_opts.SimpleOption(
615 #    "icc_gnu_compat", "icc_gnu_compat", "<GCC Version> Make the binaries built " +
616 #                      "with icc compatible with the given verion of gcc. (unsupported)",
617 #                      "", None, None, None)
618
619 # Options to specify additional library/header search paths and librarys to
620 # link agains.
621 extra_libs_options = {}
622 extra_libs_options["incdir"] = SimpleAppendOption('add_incdir', 'CPPPATH', 'Additional include dir')
623 extra_libs_options["libdir"] = SimpleAppendOption('add_libdir', 'LIBPATH', 'Additional library dir')
624 extra_libs_options["lib"]    = SimpleAppendOption('add_lib',    'LIBS',    'Additional library')
625
626 # Group all image format options together.
627 image_format_options = {}
628 image_format_options["jpeg"] = optional_libs_options["jpeg"]
629 image_format_options["tiff"] = optional_libs_options["tiff"]
630 image_format_options["png"]  = optional_libs_options["png"]
631 image_format_options["gif"]  = feature_options["gif"]
632
633 #
634 # 2) Register options
635 #    This should not require any changes unless a new option group is added.
636
637 for opt in extra_libs_options.itervalues():
638     if opt not in image_format_options.itervalues():
639         opts.AddOption(opt)
640
641 opts.AddOption(sca_opts.SeparatorOption("\nBuild/Install settings"))
642 for opt in build_options.itervalues():
643     if opt not in image_format_options.itervalues():
644         opts.AddOption(opt)
645
646 opts.AddOption(sca_opts.SeparatorOption("\nPackage settings (required libs)"))
647 for opt in required_libs_options.itervalues():
648     if opt not in image_format_options.itervalues():
649         opts.AddOption(opt)
650
651 opts.AddOption(sca_opts.SeparatorOption("\nPackage settings (optional libs)"))
652 for opt in optional_libs_options.itervalues():
653     if opt not in image_format_options.itervalues():
654         opts.AddOption(opt)
655
656 for opt in image_format_options.itervalues():
657     opts.AddOption(opt)
658
659
660 opts.AddOption(sca_opts.SeparatorOption("\nAdvanced options"))
661 for opt in feature_options.itervalues():
662     if opt not in image_format_options.itervalues():
663         opts.AddOption(opt)
664
665 for opt in misc_options.itervalues():
666     if opt not in image_format_options.itervalues():
667         opts.AddOption(opt)
668
669 # Add environment builder options
670 base_bldr.addOptions(opts)
671
672 # Add variant building options
673 variant_helper.addOptions(opts)
674
675 #
676 # 3) Process options
677
678 try:
679    opts.Process(common_env)
680 except Exception, ex:
681    if not SConsAddons.Util.hasHelpFlag():
682       print "Option error: ", str(ex)
683       traceback.print_exc()
684       sys.exit(1)
685
686 #
687 # 4) Generate help message
688
689 help_text = \
690 """--- OpenSG Build system ---
691 %s
692 Targets:
693    install - Install OpenSG
694       ex: 'scons install prefix=$HOME/software' to install in your account
695    Type 'scons' to just build it
696
697 """ % (opts.GenerateHelpText(common_env),)
698
699 Help(help_text)
700
701 # --------------------------------------------------------------------------- #
702 # ---------------------------- MAIN BUILD STEPS ----------------------------- #
703 # --------------------------------------------------------------------------- #
704
705 # If we are running the build
706 if not SConsAddons.Util.hasHelpFlag():
707    try:                                   # Try to save the options if possible
708       if not ARGUMENTS.has_key("options_file"):
709          opts.Save(option_filename, common_env)
710    except LookupError, le:
711       pass
712    
713    if common_env.has_key("MSVS"):
714       import pprint
715       print "Found MSVS. using version: ", common_env["MSVS"]["VERSION"]
716       pprint.pprint(common_env["MSVS"])
717
718    # Update settings
719    if common_env.has_key("MSVS"):
720       buildDir += "." + common_env["MSVS"]["VERSION"]
721    if common_env["build_suffix"] != "":
722       buildDir += "." + common_env["build_suffix"]
723      
724    # .fcd processing
725    if common_env["enable_fcd2code"]:
726       registerfcd2codeBuilder(common_env)
727      
728       fcd_files = []
729       for root, dirs, files in os.walk(pj(os.getcwd(),'Source')):
730          fcd_files += [pj(root,f) for f in files if f.endswith(".fcd")]
731      
732       for f in fcd_files:
733          fcd_targets = common_env.fcd2code(source=f)
734          NoClean(fcd_targets)
735    
736    # .fbd processing
737    if common_env["enable_fbd2code"]:
738       registerfbd2codeBuilder(common_env)
739      
740       fbd_files = []
741       for root, dirs, files in os.walk(pj(os.getcwd(),'Source')):
742          fbd_files += [pj(root,f) for f in files if f.endswith(".fbd")]
743      
744       for f in fbd_files:
745          fbd_targets = common_env.fbd2code(source=f)
746          NoClean(fbd_targets)
747
748    # Distcc enable
749    if common_env["enable_distcc"] and WhereIs("distcc"):
750       common_env.Prepend(CXX = "distcc ", CC = &