root/branches/scons_build_creation/SConstruct

Revision 52, 17.0 kB (checked in by allenb, 2 years ago)

- Fix build issues on windows

  • Only setup builds for tests if the osg libs they use are available
  • Fix linkage problem in material drawable
Line 
1 #!python
2 #
3 # SCons build script for OpenSG
4 #
5
6 # If we have wingide, try loading the debugging extenstions
7 try:
8    import wing.wingdbstub
9    print "Loaded wingdb stub for debugging..."
10 except:
11    pass
12
13 import os, string, sys, re, glob, copy, types, traceback, pprint
14 pj = os.path.join
15
16 print "WARNING:"
17 print "WARNING: The build is currently in development.  It needs the svn version of scons-addons"
18 print "WARNING:"
19
20 sys.path.insert(0,pj('Tools','scons-addons','src'))
21 sys.path.insert(0,pj('Tools','scons-build'))
22
23 import SCons.Environment
24 import SCons
25 import SConsAddons.Util as sca_util
26 import SConsAddons.Options as sca_opts
27 import SConsAddons.Variants as sca_variants
28 import SConsAddons.Builders
29 import SConsAddons.Options.Boost
30 from SConsAddons.EnvironmentBuilder import EnvironmentBuilder
31 from LibraryUtils import *
32 from sets import Set
33
34 # Aliases
35 GetPlatform = sca_util.GetPlatform
36 Export('GetPlatform')
37 pj = os.path.join
38
39 # Build TODO
40 # - Support selection of WS/ES
41 # - Support selection of compiler to build with
42 # - QT support
43 # - Contrib libraries
44 # - Library specific defines (if needed)
45 # - Build on windows
46 # - Project files for windows
47
48 # ------ HELPER METHODS -------- #
49
50    
51 #------------------------------------------------------------------------------
52 # Main build setup
53 #------------------------------------------------------------------------------
54 EnsureSConsVersion(0,96)
55 SourceSignatures('MD5')
56 #SourceSignatures('timestamp')
57 SConsignFile('.sconsign.'+GetPlatform())
58 opensg_version_string = file("VERSION").readline().strip()
59
60 # Figure out what version of CppDom we're using
61 print "Building OpenSG ", opensg_version_string
62
63 platform = sca_util.GetPlatform()
64 unspecified_prefix = "use-instlinks"
65 buildDir = "build." + platform     
66 option_filename = "option.cache." + platform
67
68 # Create base environment to use for option processing
69 if GetPlatform() == "win32":
70    common_env = Environment()
71 else:
72    common_env = Environment(ENV = os.environ)
73 # Setup the directories used for sconf processing
74 common_env["CONFIGUREDIR"] = '.sconf_temp_'+platform
75 common_env["CONFIGURELOG"] = 'sconf.log_'+platform
76 SConsAddons.Builders.registerDefineBuilder(common_env)
77 SConsAddons.Builders.registerSubstBuilder(common_env)
78
79 # Create variant helper and builder
80 variant_helper = sca_variants.VariantsHelper()
81 base_bldr = EnvironmentBuilder()
82
83 # --------------- #
84 # --- OPTIONS --- #
85 # --------------- #
86 # Find all build.info files that may have options
87 build_info_files = []
88 for root, dirs, files in os.walk(pj(os.getcwd(),'Source')):
89    build_info_files += [pj(root,f) for f in files if f == "build.info"]
90
91 print "Build info files found: ", build_info_files
92
93 opts = sca_opts.Options(files = [option_filename, 'options.custom'],
94                                    args= ARGUMENTS)
95
96 # Create option objects
97 boost_options = sca_opts.Boost.Boost("boost","1.31.0",required=True)
98
99 glut_libname = "glut"
100 tiff_libname = "tiff"
101 if "win32" == platform:
102    glut_libname = "glut32"
103    tiff_libname = "tif32"
104    
105 jpeg_option = sca_opts.StandardPackageOption("jpeg","Jpeg library location",
106                                              library="jpeg", required=False)
107 tiff_option = sca_opts.StandardPackageOption("tiff","Tiff library location",
108                                              library=tiff_libname, required=False)
109 png_option = sca_opts.StandardPackageOption("png","PNG library location",
110                                              library="png", required=False)
111 glut_option = sca_opts.StandardPackageOption("glut","GLUT library location",
112                                              library=glut_libname, header="GL/glut.h", required=False)
113
114 format_options = [jpeg_option,tiff_option,png_option]
115 # Setup options
116 opts.AddOption(sca_opts.SeparatorOption("\nStandard settings"))
117 opts.Add('prefix', 'Installation prefix', unspecified_prefix)
118 opts.AddOption(sca_opts.SeparatorOption("\nPackage Options"))
119 opts.AddOption( boost_options )
120 opts.AddOption( glut_option )
121 opts.AddOption(sca_opts.SeparatorOption("\nFormat Options"))
122 for o in format_options:
123    opts.AddOption(o)
124 opts.AddOption(sca_opts.BoolOption("enable_gif","Enable GIF support.",True))   
125 # Custom options
126 opts.AddOption(sca_opts.SeparatorOption("\nAdvanced Options"))
127 opts.AddOption(sca_opts.EnumOption("fcptr_mode","Set the pointer mode to use for field containers",
128                                    "MT_FCPTR",["SINGLE_THREAD","MT_CPTR","MT_FCPTR"]))
129 opts.AddOption(sca_opts.BoolOption("disable_deprecated","Disable deprecated code.",False))
130 opts.AddOption(sca_opts.BoolOption("disable_glut_glsubdir","Do not use GL subdir while including glut.h",False))
131 opts.AddOption(sca_opts.BoolOption("osg_1_compat","Enable opensg 1.x compatibility.",False))
132 opts.AddOption(sca_opts.BoolOption("osg_deprecated_props","Enable deprecated property types.",False))
133 opts.Add("icc_gnu_compat","<GCC Verion> to make the icc resultbinary compatible to the given gcc version. (unsupported)")
134 if "win32" == platform:
135    opts.AddOption(sca_opts.BoolOption("win_localstorage", "Use local storage instead of __declspec to get thread local storage on windows",
136                                       True))
137 if "win32" != platform:
138    opts.AddOption(sca_opts.BoolOption("pthread_elf_tls", "Enable elf thread local storage with pthreads.",
139                                       ("linux"==platform)))
140                                      
141                                    
142 base_bldr.addOptions(opts)             # Add environment builder options
143 variant_helper.addOptions(opts)        # Add variant building options
144
145 try:
146    opts.Process(common_env)               # Process the options
147 except Exception, ex:
148    if not SConsAddons.Util.hasHelpFlag():
149       print "Option error: ", str(ex)
150       traceback.print_exc()
151       sys.exit(1)
152
153 help_text = """--- OpenSG Build system ---
154 %s
155 Targets:
156    install - Install OpenSG
157       ex: 'scons install prefix=$HOME/software' to install in your account
158    Type 'scons' to just build it
159  
160 """%(opts.GenerateHelpText(common_env),)
161
162 #help_text = opts.GenerateHelpText(common_env) + help_text
163 Help(help_text)
164
165
166 # --- MAIN BUILD STEPS ---- #
167 # If we are running the build
168 if not SConsAddons.Util.hasHelpFlag():
169    try:                                   # Try to save the options if possible
170       opts.Save(option_filename, common_env)
171    except LookupError, le:
172       pass
173    
174    # --- Collect all Source and Header files --- #         
175   
176    # --- Find and process all the build.info files ---- #
177    # - Find them
178    # This is a little more complex then I would like. The complexity
179    # comes from the fact that we are recursing in the directories
180    # and that any file found overrides the current settings.
181    # Basic idea is:
182    #   - Keep track of a library stack that we are adding
183    #   - Recurse into each subdirectory of source
184    #   - Keep all file names relative to the Source directory (so they work in builddir)
185    #
186    # When evaluating build.info files:
187    #   input vars:
188    #      option_pass: If true, we are just trying to get options
189    #      opts: If not none, this is an options object that can have options added
190    #   output vars:
191    #      library: Name of the library to add code to
192    #      osg_lib_deps: OpenSG libraries that this one depends upon
193    #      lib_deps: Standard libraries that this one depends upon
194
195    lib_map = {}    # Map from name to library we are using   
196    dir_ignores = [".svn", "ES","EGL"]   
197
198    def scan_libs(base_dir, cur_dir, name_stack):
199       """ Scan library directory.
200           base_dir: Directory to keep all paths relative to
201           cur_dir: Directory to examine.
202           name_stack: Current stack of library names
203       """
204       global lib_map
205       #print "dir: ", cur_dir
206       full_dir = pj(base_dir, cur_dir)
207       dir_contents = [pj(cur_dir,f) for f in os.listdir(full_dir)]
208       files = [f for f in dir_contents if os.path.isfile(pj(base_dir,f))]
209       dirs  = [d for d in dir_contents if os.path.isdir(pj(base_dir,d))]
210       have_build_info = os.path.exists(pj(full_dir,"build.info"))
211       cur_lib = None          # The current library we are adding to
212
213       lib_attrib_names = ["osg_dep_libs","libs","cpppath","libpath",
214                           "osg_test_libs","other_test_libs","test_cpppath", "test_libpath"]
215       # If we have a build info file
216       # - Setup namespace and evaluate it
217       # - Create on demand
218       # - Fill with anything from the file
219       if have_build_info:
220          bi_filename = pj(full_dir,"build.info")
221          print "   Evaluating: ", bi_filename         
222          
223          # Custom options
224          ns = {"option_pass":False,
225                "opts":opts,
226                "library":None,
227                "platform":platform,
228                "compiler":common_env["CXX"],
229                "stop_traversal":False,               
230          }
231          # Options for the lib package
232          for n in lib_attrib_names:
233             ns[n] = []
234            
235          execfile(bi_filename, ns)
236          if ns["stop_traversal"]:          # Don't traverse any further
237             print "   Pruning traversal."
238             return
239          if not ns.has_key("library"):
240             print "Error: Must specify 'library' value in build.info file:", bi_filename
241             sys.exit(1)         
242          lib_name = ns["library"]
243          if not lib_map.has_key(lib_name):
244             lib_map[lib_name] = LibraryInfo(name=lib_name)
245          name_stack.append(lib_name)
246          cur_lib = lib_map[lib_name]
247          
248          # Add all the lib options from the evaluation
249          for n in lib_attrib_names:
250             getattr(cur_lib,n).extend(ns[n])
251          
252      
253       test_files =   [f for f in files if os.path.basename(f).startswith("test") and f.endswith(".cpp")]
254       source_files = [f for f in files if (os.path.splitext(f)[1] in [".cpp",".cc"]) and\
255                                           (f not in test_files)]
256       header_files = [f for f in files if os.path.splitext(f)[1] in [".h",".inl",".ins",".hpp"] and\
257                                          (os.path.basename(f).startswith("OSG"))]     
258      
259       #print "Adding to lib:[%s]  source: [%s]"%(name_stack[-1],source_files)
260       if len(test_files) or len(source_files) or len(header_files):
261          if len(name_stack) == 0:
262             print "Error: Attempted to add source with no library build.info specifed.  In dir: %s"%pj(base_dir,cur_dir)
263             sys.exit(1)
264          lib_name = name_stack[-1]
265          lib_map[lib_name].source_files += source_files
266          lib_map[lib_name].header_files += header_files
267          lib_map[lib_name].test_files   += test_files
268
269       # Recurse into subdirectories
270       for d in dirs:
271          if not os.path.basename(d) in dir_ignores:
272             scan_libs(base_dir, d, copy.copy(name_stack))
273    
274    scan_libs(pj(os.getcwd(),"Source"), '', [])   
275    
276    # Hack to handle the generation of the parser from .y
277    # This pretty hacky to allow using a version of the file from the repository if yacc is not installed
278    if "yacc" in common_env["TOOLS"]:
279       parser_env = common_env.Copy()
280       parser_env.Append(YACCFLAGS = ["-d","-v","-pOSGScanParseSkel_","-bOSGScanParseSkel_"])
281       source_file = "Source/System/FileIO/ScanParseSkel/OSGScanParseSkelParser.yy"
282       target_file = "Source/System/FileIO/ScanParseSkel/OSGScanParseSkelParser.cpp"
283       yfiles = parser_env.CXXFile(target=target_file,source=source_file)   
284       NoClean(yfiles)
285       print "yfiles: ", yfiles
286       #if not yfiles[0] in lib_map["OSGFileIO"].source_files:
287       #   lib_map["OSGFileIO"].source_files.append(yfiles[0])
288       #if not yfiles[1] in lib_map["OSGFileIO"].header_files:
289       #   lib_map["OSGFileIO"].header_files.append(yfiles[1])
290    else:
291       print "WARNING: bison not available.  If you change .yy files they will not be built."
292    
293    # Hack to handle the generation of the scanner from .lpp
294    # This pretty hacky to allow using a version of the file from the repository if lex is not installed
295    if "lex" in common_env["TOOLS"]:
296       lexer_env = common_env.Copy()
297       lexer_env.Append(LEXFLAGS = ["-+","-POSGScanParseSkel_"])
298       source_file = "Source/System/FileIO/ScanParseSkel/OSGScanParseSkelScanner.ll"
299       target_file = "Source/System/FileIO/ScanParseSkel/OSGScanParseSkelScanner.cpp"
300       lfiles = lexer_env.CXXFile(target=target_file,source=source_file)   
301       NoClean(lfiles)
302       Depends(lfiles, "Source/System/FileIO/ScanParseSkel/OSGScanParseSkelParser.hpp") # the scanner includes the token header from the parser...
303       print "lfiles: ", lfiles
304       #if not lfiles[0] in lib_map["OSGFileIO"].source_files:
305       #   lib_map["OSGFileIO"].source_files.append(lfiles[0])
306    else:
307       print "WARNING: flex not available.  If you change .ll files they will not be built."   
308
309    # -- Common builder settings
310    variant_helper.readOptions(common_env)
311    base_bldr.readOptions(common_env)
312    #base_bldr.enableWarnings()
313    base_bldr.enableWarnings(EnvironmentBuilder.MINIMAL)
314  
315    # Apply any common package options
316    # Update environment for boost options
317    boost_options.apply(common_env)   
318      
319    # If defaulting to instlinks prefix:
320    #  - Use symlinks
321    #  - Manually set the used prefix to the instlinks of the build dir
322    if common_env['prefix'] == unspecified_prefix:
323       if hasattr(os,'symlink'):
324          common_env['INSTALL'] = SConsAddons.Util.symlinkInstallFunc
325       common_env['prefix'] = pj( Dir('.').get_abspath(), buildDir, 'instlinks')
326    
327    # --- Setup installation paths --- #
328    paths = {}
329    paths['base']      = os.path.abspath(common_env['prefix'])
330    paths['lib']       = pj(paths['base'], 'lib')
331    paths['include']   = pj(paths['base'], 'include', 'OpenSG')   
332    paths['bin']       = pj(paths['base'], 'bin')   
333    print "using prefix: ", paths['base']         
334      
335    # ---- Generate OSGConfigured.h --- #
336    definemap = {"OSG_DISABLE_DEPRECATED": (common_env["disable_deprecated"],
337                                            "Disable interface that will go away in the future"),               
338                 "OSG_NO_GLUT_GLSUBDIR":(common_env["disable_glut_glsubdir"],"Don't use GL subdir for glut"),
339                 "OSG_MT_FIELDCONTAINERPTR":("MT_FCPTR" == common_env["fcptr_mode"]),
340                 "OSG_MT_CPTR_ASPECT":("MT_CPTR" == common_env["fcptr_mode"]),
341                 "OSG_1_COMPAT":common_env["osg_1_compat"],
342                 "OSG_DEPRECATED_PROPS":common_env["osg_deprecated_props"],
343                
344                 "OSG_WITH_JPG":jpeg_option.isAvailable(),
345                 "OSG_WITH_TIF":tiff_option.isAvailable(),
346                 "OGG_WITH_PNG":png_option.isAvailable(),
347                 "OSG_WITH_GLUT":glut_option.isAvailable(),
348                 "OSG_WITH_GIF":common_env["enable_gif"],
349                }
350    if "win32" == platform:   # Win32 specific defines
351       definemap.update( {"OSG_WIN32_ASPECT_USE_LOCALSTORAGE": common_env["win_localstorage"],} )
352    else:
353       definemap.update( {"OSG_PTHREAD_ELF_TLS":(common_env["pthread_elf_tls"],"Use elf tls with pthreads."),} )
354    
355    common_env.DefineBuilder(pj(paths["include"],"OSGConfigured.h"),Value(definemap),
356                             definemap=definemap)
357    
358    # ---- FOR EACH VARIANT ----- #   
359    # This is the core of the build.
360    print "types: ",    variant_helper.variants["type"]
361    print "libtypes: ", variant_helper.variants["libtype"]
362    print "archs: ",    variant_helper.variants["arch"]   
363    common_env.Append(CPPPATH = [paths['include'],])
364    
365    for combo in variant_helper.iterate(locals(), base_bldr, common_env):           
366       #baseEnv = env_bldr.applyToEnvironment(common_env.Copy(), variant=combo,options=opts)     
367       print "   Processing combo: ", ", ".join(['%s:%s'%(i[0],i[1]) for i in combo.iteritems()])
368
369       inst_paths = copy.copy(paths)
370       if GetPlatform() != "win32" and "debug" == combo["type"]:
371          inst_paths["lib"] = pj(inst_paths["lib"],"debug")     
372       if "x64" == combo["arch"]:
373          inst_paths['lib'] = inst_paths['lib'] + '64'                 
374      
375       Export('build_env','inst_paths','opts', 'variant_pass','combo',
376              'lib_map','boost_options',
377              'shared_lib_suffix','static_lib_suffix')
378      
379       # Process subdirectories
380       sub_dirs = ['Source']   
381       full_build_dir = pj(buildDir,combo_dir)
382       for d in sub_dirs:
383          SConscript(pj(d,'SConscript'), build_dir=pj(full_build_dir, d), duplicate=0)
384    
385    common_env.Alias('install', paths['base'])
386    
387    # Build -config file
388    # - Create string that can build libmap
389    lib_map_build_list = []
390    for (name,lib) in lib_map.iteritems():
391       lib_map_build_list.append(lib.dump())
392    lib_map_str = pprint.pformat(lib_map_build_list)
393    
394    submap = {'@LIB_MAP_STR@':lib_map_str,
395              '@PREFIX@':common_env["prefix"],
396              '@LIBPATH@':paths["lib"],
397              '@INCPATH@':paths["include"],
398              '@VERSION@':opensg_version_string,
399              '@LIBRARY_UTIL_SRC@':file(pj('Tools','scons-build','LibraryUtils.py')).read()}
400    osg_config = common_env.SubstBuilder(pj(paths['bin'],'osg-config'),
401                               'osg-config.in', submap=submap)
402    common_env.AddPostAction(osg_config, Chmod('$TARGET', 0755))
403    common_env.Depends(osg_config, Value(lib_map_str))
404
405    # Close up with aliases and defaults   
406    Default('.')
407
Note: See TracBrowser for help on using the browser.