/[escript]/trunk/site_scons/site_init.py
ViewVC logotype

Diff of /trunk/site_scons/site_init.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

temp_trunk_copy/scons/scons_extensions.py revision 1384 by phornby, Fri Jan 11 02:29:38 2008 UTC trunk/site_scons/site_init.py revision 3981 by jfenwick, Fri Sep 21 02:47:54 2012 UTC
# Line 1  Line 1 
1    
2    ##############################################################################
3  # Extensions to Scons  #
4    # Copyright (c) 2003-2012 by University of Queensland
5  import py_compile  # http://www.uq.edu.au
6  import sys  #
7  import os  # Primary Business: Queensland, Australia
8  import time  # Licensed under the Open Software License version 3.0
9  import glob  # http://www.opensource.org/licenses/osl-3.0.php
10  import fnmatch  #
11  import types  # Development until 2012 by Earth Systems Science Computational Center (ESSCC)
12    # Development since 2012 by School of Earth Sciences
13  from SCons.Script.SConscript import SConsEnvironment  #
14    ##############################################################################
15  ###############################################################################  
16  def matchingFiles(env,directory,includes='*',excludes=None) :  __copyright__="""Copyright (c) 2003-2012 by University of Queensland
17    http://www.uq.edu.au
18      # Pre-process for more convenient arguments  Primary Business: Queensland, Australia"""
19    __license__="""Licensed under the Open Software License version 3.0
20      if isinstance(includes,str) :  http://www.opensource.org/licenses/osl-3.0.php"""
21          includes = env.Split(includes)  __url__="https://launchpad.net/escript-finley"
22    
23      if isinstance(excludes,str) :  import sys, os, time, py_compile, re, subprocess
24          excludes = env.Split(excludes)  
25    def findLibWithHeader(env, libs, header, paths, lang='c'):
26      def fn_filter(node):      from SCons.Script.SConscript import Configure
27          fn = os.path.basename(str(node))      inc_path=''
28          match = False      lib_path=''
29          for include in includes:      # 'paths' may be a prefix, so look for lib and include subdirectories
30              if fnmatch.fnmatchcase( fn, include ):      if type(paths)==str:
31                  match = True          # find the header file first
32            for i in 'include','include64','include32','inc':
33                inc=os.path.join(paths, i)
34                if os.path.isfile(os.path.join(inc, header)):
35                    inc_path=inc
36                  break                  break
37            if inc_path=='':
38                raise RuntimeError('%s not found under %s'%(header,paths))
39    
40          if match and not excludes is None:          # now try to find a lib directory
41              for exclude in excludes:          for l in 'lib','lib64','lib32':
42                  if fnmatch.fnmatchcase( fn, exclude ):              lp=os.path.join(paths, l)
43                      match = False              if os.path.isdir(lp):
44                      break                  lib_path=lp
45                    break
46          return match          if lib_path=='':
47                raise RuntimeError('No lib directory found under %s'%paths)
48      def filter_nodes(where):      else:
49          contents = glob.glob( os.path.join(str(where),"*") )          if os.path.isfile(os.path.join(paths[0], header)):
50          children = [ x for x in contents if fn_filter(x) ]              inc_path=paths[0]
         nodes = []  
         for f in children:  
             nodes.append(gen_node(f))  
         return nodes  
   
     def gen_node(n):  
         """Checks first to see if the node is a file or a dir, then  
         creates the appropriate node. [code seems redundant, if the node  
         is a node, then shouldn't it just be left as is?  
         """  
         if type(n) in (type(''), type(u'')):  
             path = n  
51          else:          else:
52              path = n.abspath              raise RuntimeError('%s not found under %s'%(header,paths[0]))
53            if os.path.isdir(paths[1]):
54          if os.path.isdir(path):              lib_path=paths[1]
             return env.Dir(n)  
   
         return env.File(n)  
   
     here = env.Dir(directory)  
     nodes = filter_nodes(here)  
   
     node_srcs = [n.srcnode() for n in nodes]  
   
     src = here.srcnode()  
     if src is not here:  
         for s in filter_nodes(src):  
             if s not in node_srcs:  
                 # Probably need to check if this node is a directory  
                 nodes.append(  
                     gen_node(os.path.join(str(directory),  
                                           os.path.basename(str(s)))))  
   
     return nodes  
 #==============================================================================  
 SConsEnvironment.matchingFiles = matchingFiles  
 ###############################################################################  
   
   
   
 ###############################################################################  
 def InstallPyModule(env,target_dir,source,shlib=None,excludes=None) :  
   
     # put the .so/.dll over in  <target_dir>  
     if shlib :  
         shtarg = env.Install(target_dir, shlib)  
   
     # Gather the python sources  
     python_src = env.matchingFiles(source, "*.py",excludes=excludes)  
   
     # Here is a hack to deal with the (possibly not yet generated)  
     # __init__.py. The problem is that the python_src list is built before  
     # __init__.py is updated from __init__.in. The AlwaysBuild call  
     # ensures that this does not cause a problem, except on the first  
     # build after a clean checkout, in which case there is no old  
     # __init__.py in src, and hence it does not make it into python_src!  
   
     init_input = env.matchingFiles(source, "__init__.in")  
     if init_input :  
         if python_src :  
             names = [x.name for x in python_src]  
             if "__init__.py" not in names :  
                 python_src.append(env.File(os.path.join(str(source),  
                                                         "__init__.py")))  
55          else:          else:
56              python_src = [env.File(os.path.join(str(source),"__init__.py"))]              raise RuntimeError('%s is not a valid path.'%paths[1])
               
     # decide if we're doing py or pyc distribn and install.  
   
     if  env['distrib_py_src'] :  
         pytarg = env.Install(target_dir, python_src)  
     else:  
         pyc = env.PyCompile(python_src)  
         pytarg = env.Install(target_dir, pyc)  
57    
58      if shlib :      # now try the library
59          targ_ret = env.Flatten([pytarg] + [shtarg])      conf=Configure(env.Clone())
60        conf.env.AppendUnique(CPPPATH = [inc_path])
61        conf.env.AppendUnique(LIBPATH = [lib_path])
62        if type(libs)==str: libs=[libs]
63        # we can't check for each library by itself since they may depend on each
64        # other, so we add all libraries to the link line and check only for one
65        conf.env.AppendUnique(LIBS = libs)
66        if not conf.CheckLibWithHeader(libs[0], header, lang):
67            conf.Finish()
68            raise RuntimeError('Unable to link against %s (paths: %s, %s)'%(libs,inc_path,lib_path))
69    
70        conf.Finish()
71        return inc_path, lib_path
72    
73    def detectModule(env, module):
74        if env['pythoncmd']=='python':
75            try:
76                __import__(module)
77            except ImportError:
78                return False
79      else:      else:
80          targ_ret = pytarg          p=subprocess.call([env['pythoncmd'],'-c','import %s'%module])
81            if p!=0:
82                return False
83        return True
84    
     return targ_ret  
 #==============================================================================  
 SConsEnvironment.InstallPyModule = InstallPyModule  
 ###############################################################################  
   
 ###############################################################################  
 def installDirectory(env,target,source,includes="*", excludes=None,  
                      recursive=False):  
       
       
     if os.path.isfile(str(target)) :  
         raise UserError("target must be a directory")  
   
     if os.path.isfile(str(source)) :  
         raise UserError("source must be a directory")  
   
     source_files = env.matchingFiles(source,includes,excludes)  
   
     ret_targ = []  
   
     for f in source_files :  
         if f.isfile() :  
             targ = env.Install(target,f)  
             ret_targ.append(targ)  
   
         if f.isdir() and recursive :  
             x = os.path.basename(str(f))  
             t = env.Dir(os.path.join(str(target),x))  
             targ = env.installDirectory(t,f,includes,excludes,recursive)  
             ret_targ += targ  
       
     return ret_targ  
 #==============================================================================  
 SConsEnvironment.installDirectory = installDirectory  
 ###############################################################################  
   
 ###############################################################################  
85  # Code to build .pyc from .py  # Code to build .pyc from .py
86  def build_py(target, source, env):  def build_py(target, source, env):
87      py_compile.compile(str(source[0]), str(target[0]))      try:
88      return 0         py_compile.compile(str(source[0]), str(target[0]), doraise=True)
89           return 0
90  def doSubstitution(target,source,env) :      except py_compile.PyCompileError, e:
91      import product_info as PI         print e
92      data = source[0].get_contents()         return 1
93      data = data.replace('$ProductName$',PI.PRODUCT_NAME)        
     data = data.replace('$LowerProductName$',PI.product_name)  
     data = data.replace('$ProductVersion$',PI.product_version)  
     data = data.replace('$VersionString$',PI.pkg_version_string)  
     data = data.replace('$SVNRevision$',PI.svn_revision)  
     open(str(target[0]),'w').write(data)  
     return 0  
94    
95  # Code to run unit_test executables  # Code to run unit_test executables
96  def runUnitTest(target, source, env):  def runUnitTest(target, source, env):
97    time_start = time.time()    time_start = time.time()
98    app = str(source[0].abspath)    app = str(source[0].abspath)
99    if env['useMPI']: app = env['mpi_run'] + ' ' + app    pn, sn= os.path.split(app)
100      if not os.name== "nt":
101         app = "cd "+pn+"; "+os.path.join(env['bininstall'], "run-escript")+" -bv "+os.path.join('.',sn)
102      else:
103          if env['usempi']:
104              app = "cd %s & mpiexec -np %s -genvlist PYTHONPATH,OMP_NUM_THREADS,"\
105                "FINLEY_TEST_DATA,PYVISI_TEST_DATA_ROOT,PYVISI_WORKDIR,PATH %s"\
106                %(pn,env['ENV']['ESCRIPT_NUM_NODES'], sn)
107          else:
108               app = "cd "+ pn +" & "+sn
109    print "Executing test: " + app    print "Executing test: " + app
110    if not env.Execute(app):    if not env.Execute(app):
111      open(str(target[0]),'w').write("PASSED\n")      open(str(target[0]),'w').write("PASSED\n")
# Line 192  def runUnitTest(target, source, env): Line 117  def runUnitTest(target, source, env):
117  def runPyUnitTest(target, source, env):  def runPyUnitTest(target, source, env):
118     time_start = time.time()     time_start = time.time()
119     app = str(source[0].abspath)     app = str(source[0].abspath)
120     if env['useMPI']:     pn, sn= os.path.split(app)
121       app = env['mpi_run'] +' lib/pythonMPI ' + app     if os.name== "nt":
122           if env['usempi']:
123               app = "cd %s & mpiexec -np %s -genvlist PYTHONPATH,OMP_NUM_THREADS,"\
124                  "FINLEY_TEST_DATA,PYVISI_TEST_DATA_ROOT,PYVISI_WORKDIR,PATH %s\pythonMPIredirect.exe %s"\
125                  %(pn,env['ENV']['ESCRIPT_NUM_NODES'],env['libinstall'],sn)
126           else:
127               app = "cd "+ pn +" & "+sys.executable + " " + sn
128     else:     else:
129       app = sys.executable + " " + app       app = "cd "+pn+"; "+os.path.join(env['bininstall'], "run-escript")+" -ov "+sn
130     print "Executing test: " + app     print "Executing test: ",app
131     if env.Execute(app) == 0:     if env.Execute(app) == 0:
132        open(str(target[0]),'w').write("PASSED\n")        open(str(target[0]),'w').write("PASSED\n")
133     else:     else:
# Line 204  def runPyUnitTest(target, source, env): Line 135  def runPyUnitTest(target, source, env):
135     print "Test execution time: ", round(time.time() - time_start, 1), " seconds wall time for " + str(source[0].abspath)     print "Test execution time: ", round(time.time() - time_start, 1), " seconds wall time for " + str(source[0].abspath)
136     return None     return None
137    
138  def addBuilders(env) :  def eps2pdf(target, source, env):
139      py_builder = env.Builder(action = build_py,  #   if env.Execute("epstopdf "+str(source[0].abspath)+" -o "+str(target[0].abspath))!=0:
140                               suffix = '.pyc',     if env.Execute("ps2pdf -dEPSCrop "+str(source[0].abspath)+" "+str(target[0].abspath))!=0:
141                               src_suffix = '.py',         return 1
142                               single_source=True)     return None
   
     env.Append(BUILDERS = {'PyCompile' : py_builder});  
   
     substituter = env.Builder(action = doSubstitution,  
                               suffix = '',  
                               src_suffix = '.in',  
                               single_source=True )  
   
     env.Append(BUILDERS = {'VariableSubstitution' : substituter});  
   
     runUnitTest_builder = env.Builder(action = runUnitTest,  
                                       suffix = '.passed',  
                                       src_suffix=env.get('PROGSUFFIX',''),  
                                       single_source=True)  
   
     env.Append(BUILDERS = {'RunUnitTest' : runUnitTest_builder});  
   
     runPyUnitTest_builder = env.Builder(action = runPyUnitTest,  
                                         suffix = '.passed',  
                                         src_suffix='.py',  
                                         single_source=True)  
   
     env.Append(BUILDERS = {'RunPyUnitTest' : runPyUnitTest_builder});  
     return  
 #==============================================================================  
 SConsEnvironment.addBuilders = addBuilders  
 ###############################################################################  
   
 ###############################################################################  
 def epydocAction(target, source, env):  
   
     doc_dir = os.path.dirname(str(target[0].abspath))  
   
     cmd = [  
         [env['epydoc_path'], "-qqqq", "-o", doc_dir, str(source[0].tpath)]  
           ]  
     print 'executing epydoc...'  
     return env.Execute(cmd,"Build epydoc documentation")  
   
   
 def epydocDepend(env, target, source,  
                  src_pattern="*.py",  
                  file_names=['index.html','epydoc.css'],  
                  subdirs=['private','public']) :  
     """  
     \brief add a dependency between the directory containing the doco and that  
            containing the source  
     \param target - the directory containing index.html for the doco,  
                     and the private and public sub-directories.  
     \param source - the python module source directory  
     """  
     the_subdirs = [os.path.join(target.abspath,sub) for sub in subdirs]  
     the_targets = [os.path.join(target.abspath,file) for file in file_names]  
   
   
     ret_target = target  
       
     # if absolutely anything goes wrong, turn this on.  
     force_build = False  
   
     dst_time = 0  
     src_time = 1  
   
     try:  
   
         # have a shot at digging out all the source file times.  
         src_time = max(  
             [os.path.getmtime(str(x))  
              for x in env.matchingFiles(source,src_pattern) +  
                       [source.abspath]]  
             )  
   
         # now try to find the target files and their mod time.  
         a = [os.path.getmtime(os.path.join(target.abspath,str(x)))  
              for x in file_names ]  
   
         for directory in the_subdirs :  
             # include the mod time of the directory  
             a += [os.path.getmtime(str(directory))]  
   
             # now go for the mod times of all files below the subdirs.  
             if os.path.isdir(str(directory)) :  
                 a += [os.path.getmtime(str(x))  
                       for x in env.matchingFiles(directory,"*")]  
   
             else:  
                 # if it is not a directory, and we expected it to be  
                 # do something nasty.  
                 # we're in a try anyway.  
                 force_build = True  
                 os.unlink(directory)  
   
         dst_time = max(a)  
               
     except:  
         # Force an unlink and re-build.  
         force_build = True  
           
     if src_time > dst_time or force_build :  
         for x in the_targets :  
             try:  
                 os.unlink(x)  
             except OSError:  
                 pass  
   
         ret_target = env.Command(the_targets,source,epydocAction)  
       
   
     env.Clean(target, the_subdirs + file_names)  
   
     return ret_target  
 #==============================================================================  
 SConsEnvironment.epydocDepend = epydocDepend  
 ###############################################################################  
   
   
 ###############################################################################  
 def genSConscriptCalls(env,dir_list):  
   
     for d in dir_list :  
         print 'calling SConscript in "./%s"' %(d)  
         env.SConscript(dirs = [d],  
                        build_dir='build/$PLATFORM/' + str(d),  
                        duplicate=0)  
   
   
     return  
 #==============================================================================  
 SConsEnvironment.genSConscriptCalls = genSConscriptCalls  
 ###############################################################################  
   
   
 ###############################################################################  
 def print_all_nodes(env,dirnode, level=0):  
     """Print all the scons nodes that are children of this node, recursively."""  
     if type(dirnode)==type(''):  
         dirnode=env.Dir(dirnode)  
     dt = type(env.Dir('.'))  
     for f in dirnode.all_children():  
         if type(f) == dt:  
             print "%s%s: .............."%(level * ' ', str(f))  
             env.print_all_nodes(f, level+2)  
         print "%s%s"%(level * ' ', str(f))  
   
 #==============================================================================  
 SConsEnvironment.print_all_nodes = print_all_nodes  
 ###############################################################################  
     
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
 ###############################################################################  
 def Glob(env,dir='.',includes="*",excludes=None, scan_dir=True):  
   
     """Similar to glob.glob, except globs SCons nodes, and thus sees  
     generated files and files from build directories.  Basically, it sees  
     anything SCons knows about.  A key subtlety is that since this function  
     operates on generated nodes as well as source nodes on the filesystem,  
     it needs to be called after builders that generate files you want to  
     include.  
   
     It will return both Dir entries and File entries  
     """  
   
     # Pre-process for more convenient arguments  
   
     if isinstance(includes,str) :  
         includes = env.Split(includes)  
   
     if isinstance(excludes,str) :  
         excludes = env.Split(excludes)  
   
     def fn_filter(node):  
         fn = os.path.basename(str(node))  
         match = 0  
         for include in includes:  
             if fnmatch.fnmatchcase( fn, include ):  
                 match = 1  
                 break  
   
         if match == 1 and not excludes is None:  
             for exclude in excludes:  
                 if fnmatch.fnmatchcase( fn, exclude ):  
                     match = 0  
                     break  
   
         return match  
   
     def filter_nodes(where):  
         contents = where.all_children(scan=scan_dir)  
         children = [ x for x in contents if fn_filter(x) ]  
         nodes = []  
         for f in children:  
             nodes.append(gen_node(f))  
         return nodes  
   
     def gen_node(n):  
         """Checks first to see if the node is a file or a dir, then  
         creates the appropriate node. [code seems redundant, if the node  
         is a node, then shouldn't it just be left as is?  
         """  
         if type(n) in (type(''), type(u'')):  
             path = n  
         else:  
             path = n.abspath  
         if os.path.isdir(path):  
             return env.Dir(n)  
         else:  
             return env.File(n)  
   
     here = env.Dir(dir)  
     nodes = filter_nodes(here)  
   
     node_srcs = [n.srcnode() for n in nodes]  
   
     src = here.srcnode()  
     if src is not here:  
         for s in filter_nodes(src):  
             if s not in node_srcs:  
                 # Probably need to check if this node is a directory  
                 nodes.append(  
                     gen_node(os.path.join(dir,os.path.basename(str(s)))))  
143    
144      return nodes  def effectiveName(inname):
145       m=re.compile("^r1i[0-9]{1,2}n[0-9]{1,2}$")   # savanna names take the form r1i?n?
146       if m.match(inname):
147        return "savanna"
148       return inname

Legend:
Removed from v.1384  
changed lines
  Added in v.3981

  ViewVC Help
Powered by ViewVC 1.1.26