xref: /petsc/config/gmakegentest.py (revision 29921a8f05c7587ede8fed409dd5e8ff5aa91522)
1*29921a8fSScott Kruger#!/usr/bin/env python
2*29921a8fSScott Kruger
3*29921a8fSScott Krugerimport os,shutil, string, re
4*29921a8fSScott Krugerfrom distutils.sysconfig import parse_makefile
5*29921a8fSScott Krugerimport sys
6*29921a8fSScott Krugerimport logging
7*29921a8fSScott Krugerimport types
8*29921a8fSScott Krugersys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
9*29921a8fSScott Krugerfrom cmakegen import Mistakes, stripsplit, AUTODIRS, SKIPDIRS
10*29921a8fSScott Krugerfrom cmakegen import defaultdict # collections.defaultdict, with fallback for python-2.4
11*29921a8fSScott Krugerfrom gmakegen import *
12*29921a8fSScott Kruger
13*29921a8fSScott Krugerimport inspect
14*29921a8fSScott Krugerthisscriptdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
15*29921a8fSScott Krugersys.path.insert(0,thisscriptdir)
16*29921a8fSScott Krugerimport testparse
17*29921a8fSScott Krugerimport example_template
18*29921a8fSScott Kruger
19*29921a8fSScott Krugerclass generateExamples(Petsc):
20*29921a8fSScott Kruger  """
21*29921a8fSScott Kruger    gmakegen.py has basic structure for finding the files, writing out
22*29921a8fSScott Kruger      the dependencies, etc.
23*29921a8fSScott Kruger  """
24*29921a8fSScott Kruger  def __init__(self,petsc_dir=None, petsc_arch=None, verbose=False, single_ex=False):
25*29921a8fSScott Kruger    super(generateExamples, self).__init__(petsc_dir=None, petsc_arch=None, verbose=False)
26*29921a8fSScott Kruger
27*29921a8fSScott Kruger    self.single_ex=single_ex
28*29921a8fSScott Kruger    self.arch_dir=os.path.join(self.petsc_dir,self.petsc_arch)
29*29921a8fSScott Kruger    self.ptNaming=True
30*29921a8fSScott Kruger    # Whether to write out a useful debugging
31*29921a8fSScott Kruger    #if verbose: self.summarize=True
32*29921a8fSScott Kruger    self.summarize=True
33*29921a8fSScott Kruger
34*29921a8fSScott Kruger    # For help in setting the requirements
35*29921a8fSScott Kruger    self.precision_types="single double quad int32".split()
36*29921a8fSScott Kruger    self.integer_types="int32 int64".split()
37*29921a8fSScott Kruger    self.languages="fortran cuda cxx".split()    # Always requires C so do not list
38*29921a8fSScott Kruger
39*29921a8fSScott Kruger    # Things that are not test
40*29921a8fSScott Kruger    self.buildkeys=testparse.buildkeys
41*29921a8fSScott Kruger
42*29921a8fSScott Kruger    # Adding a dictionary for storing sources, objects, and tests
43*29921a8fSScott Kruger    # to make building the dependency tree easier
44*29921a8fSScott Kruger    self.sources={}
45*29921a8fSScott Kruger    self.objects={}
46*29921a8fSScott Kruger    self.tests={}
47*29921a8fSScott Kruger    for pkg in PKGS:
48*29921a8fSScott Kruger      self.sources[pkg]={}
49*29921a8fSScott Kruger      self.objects[pkg]=[]
50*29921a8fSScott Kruger      self.tests[pkg]={}
51*29921a8fSScott Kruger      for lang in LANGS:
52*29921a8fSScott Kruger        self.sources[pkg][lang]={}
53*29921a8fSScott Kruger        self.sources[pkg][lang]['srcs']=[]
54*29921a8fSScott Kruger        self.tests[pkg][lang]={}
55*29921a8fSScott Kruger
56*29921a8fSScott Kruger    # Copy petsc tests harness script
57*29921a8fSScott Kruger    harness_file=os.path.join(self.petsc_dir,"config","petsc_harness.sh")
58*29921a8fSScott Kruger    reports_file=os.path.join(self.petsc_dir,"config","report_tests.sh")
59*29921a8fSScott Kruger    self.testroot_dir=os.path.join(self.arch_dir,"tests")
60*29921a8fSScott Kruger    if not os.path.isdir(self.testroot_dir): os.makedirs(self.testroot_dir)
61*29921a8fSScott Kruger    shutil.copy(harness_file,self.testroot_dir)
62*29921a8fSScott Kruger    shutil.copy(reports_file,self.testroot_dir)
63*29921a8fSScott Kruger
64*29921a8fSScott Kruger    return
65*29921a8fSScott Kruger
66*29921a8fSScott Kruger  def nameSpace(self,srcfile,srcdir):
67*29921a8fSScott Kruger    """
68*29921a8fSScott Kruger    Because the scripts have a non-unique naming, the pretty-printing
69*29921a8fSScott Kruger    needs to convey the srcdir and srcfile.  There are two ways of doing this.
70*29921a8fSScott Kruger    """
71*29921a8fSScott Kruger    if self.ptNaming:
72*29921a8fSScott Kruger      cdir=srcdir.split('src')[1].lstrip("/").rstrip("/")
73*29921a8fSScott Kruger      prefix=cdir.replace('/examples/','_').replace("/","_")+"-"
74*29921a8fSScott Kruger      nameString=prefix+srcfile
75*29921a8fSScott Kruger    else:
76*29921a8fSScott Kruger      #nameString=srcdir+": "+srcfile
77*29921a8fSScott Kruger      nameString=srcfile
78*29921a8fSScott Kruger    return nameString
79*29921a8fSScott Kruger
80*29921a8fSScott Kruger  def getLanguage(self,srcfile):
81*29921a8fSScott Kruger    """
82*29921a8fSScott Kruger    Based on the source, determine associated language as found in gmakegen.LANGS
83*29921a8fSScott Kruger    Can we just return srcext[1:\] now?
84*29921a8fSScott Kruger    """
85*29921a8fSScott Kruger    langReq=None
86*29921a8fSScott Kruger    srcext=os.path.splitext(srcfile)[-1]
87*29921a8fSScott Kruger    if srcext in ".F90".split(): langReq="F90"
88*29921a8fSScott Kruger    if srcext in ".F".split(): langReq="F"
89*29921a8fSScott Kruger    if srcext in ".cxx".split(): langReq="cxx"
90*29921a8fSScott Kruger    if srcext == ".cu": langReq="cu"
91*29921a8fSScott Kruger    if srcext == ".c": langReq="c"
92*29921a8fSScott Kruger    if not langReq: print "ERROR: ", srcext, srcfile
93*29921a8fSScott Kruger    return langReq
94*29921a8fSScott Kruger
95*29921a8fSScott Kruger  def getArgLabel(self,testDict):
96*29921a8fSScott Kruger    """
97*29921a8fSScott Kruger    In all of the arguments in the test dictionary, create a simple
98*29921a8fSScott Kruger    string for searching within the makefile system.  For simplicity in
99*29921a8fSScott Kruger    search, remove "-", for strings, etc.
100*29921a8fSScott Kruger    Also, concatenate the arg commands
101*29921a8fSScott Kruger    For now, ignore nsize -- seems hard to search for anyway
102*29921a8fSScott Kruger    """
103*29921a8fSScott Kruger    # Collect all of the args associated with a test
104*29921a8fSScott Kruger    argStr=("" if not testDict.has_key('args') else testDict['args'])
105*29921a8fSScott Kruger    if testDict.has_key('subtests'):
106*29921a8fSScott Kruger      for stest in testDict["subtests"]:
107*29921a8fSScott Kruger         sd=testDict[stest]
108*29921a8fSScott Kruger         argStr=argStr+("" if not sd.has_key('args') else sd['args'])
109*29921a8fSScott Kruger
110*29921a8fSScott Kruger    # Now go through and cleanup
111*29921a8fSScott Kruger    argStr=re.sub('{{(.*?)}}',"",argStr)
112*29921a8fSScott Kruger    argStr=re.sub('-'," ",argStr)
113*29921a8fSScott Kruger    for digit in string.digits: argStr=re.sub(digit," ",argStr)
114*29921a8fSScott Kruger    argStr=re.sub("\.","",argStr)
115*29921a8fSScott Kruger    argStr=re.sub(",","",argStr)
116*29921a8fSScott Kruger    argStr=re.sub('\+',' ',argStr)
117*29921a8fSScott Kruger    argStr=re.sub(' +',' ',argStr)  # Remove repeated white space
118*29921a8fSScott Kruger    return argStr.strip()
119*29921a8fSScott Kruger
120*29921a8fSScott Kruger  def addToSources(self,exfile,root,srcDict):
121*29921a8fSScott Kruger    """
122*29921a8fSScott Kruger      Put into data structure that allows easy generation of makefile
123*29921a8fSScott Kruger    """
124*29921a8fSScott Kruger    pkg=self.relpath(self.petsc_dir,root).split("/")[1]
125*29921a8fSScott Kruger    fullfile=os.path.join(root,exfile)
126*29921a8fSScott Kruger    relpfile=self.relpath(self.petsc_dir,fullfile)
127*29921a8fSScott Kruger    lang=self.getLanguage(exfile)
128*29921a8fSScott Kruger    self.sources[pkg][lang]['srcs'].append(relpfile)
129*29921a8fSScott Kruger    if srcDict.has_key('depends'):
130*29921a8fSScott Kruger      depSrc=srcDict['depends']
131*29921a8fSScott Kruger      depObj=os.path.splitext(depSrc)[0]+".o"
132*29921a8fSScott Kruger      self.sources[pkg][lang][exfile]=depObj
133*29921a8fSScott Kruger
134*29921a8fSScott Kruger    # In gmakefile, ${TESTDIR} var specifies the object compilation
135*29921a8fSScott Kruger    testsdir=self.relpath(self.petsc_dir,root)+"/"
136*29921a8fSScott Kruger    objfile="${TESTDIR}/"+testsdir+os.path.splitext(exfile)[0]+".o"
137*29921a8fSScott Kruger    self.objects[pkg].append(objfile)
138*29921a8fSScott Kruger    return
139*29921a8fSScott Kruger
140*29921a8fSScott Kruger  def addToTests(self,test,root,exfile,execname,testDict):
141*29921a8fSScott Kruger    """
142*29921a8fSScott Kruger      Put into data structure that allows easy generation of makefile
143*29921a8fSScott Kruger      Organized by languages to allow testing of languages
144*29921a8fSScott Kruger    """
145*29921a8fSScott Kruger    pkg=self.relpath(self.petsc_dir,root).split("/")[1]
146*29921a8fSScott Kruger    #nmtest=self.nameSpace(test,root)
147*29921a8fSScott Kruger    rpath=self.relpath(self.petsc_dir,root)
148*29921a8fSScott Kruger    nmtest=os.path.join(rpath,test)
149*29921a8fSScott Kruger    lang=self.getLanguage(exfile)
150*29921a8fSScott Kruger    self.tests[pkg][lang][nmtest]={}
151*29921a8fSScott Kruger    self.tests[pkg][lang][nmtest]['exfile']=os.path.join(rpath,exfile)
152*29921a8fSScott Kruger    self.tests[pkg][lang][nmtest]['exec']=execname
153*29921a8fSScott Kruger    self.tests[pkg][lang][nmtest]['argLabel']=self.getArgLabel(testDict)
154*29921a8fSScott Kruger    return
155*29921a8fSScott Kruger
156*29921a8fSScott Kruger  def getFor(self,subst,i,j):
157*29921a8fSScott Kruger    """
158*29921a8fSScott Kruger      Get the for and done lines
159*29921a8fSScott Kruger    """
160*29921a8fSScott Kruger    forlines=""
161*29921a8fSScott Kruger    donlines=""
162*29921a8fSScott Kruger    indent="   "
163*29921a8fSScott Kruger    nsizeStr=subst['nsize']
164*29921a8fSScott Kruger    for loop in re.findall('{{(.*?)}}',subst['nsize']):
165*29921a8fSScott Kruger      lindex=string.ascii_lowercase[i]
166*29921a8fSScott Kruger      forline=indent*j+"for "+lindex+" in '"+loop+"'; do"
167*29921a8fSScott Kruger      nsizeStr=re.sub("{{"+loop+"}}","${"+lindex+"}",nsizeStr)
168*29921a8fSScott Kruger      donline=indent*j+"done"
169*29921a8fSScott Kruger      forlines=forlines+forline+"\n"
170*29921a8fSScott Kruger      donlines=donlines+donline+"\n"
171*29921a8fSScott Kruger      i=i+1
172*29921a8fSScott Kruger      j=j+1
173*29921a8fSScott Kruger    subst['nsize']=nsizeStr
174*29921a8fSScott Kruger    argStr=subst['args']
175*29921a8fSScott Kruger    for loop in re.findall('{{(.*?)}}',subst['args']):
176*29921a8fSScott Kruger      lindex=string.ascii_lowercase[i]
177*29921a8fSScott Kruger      forline=indent*j+"for "+lindex+" in '"+loop+"'; do"
178*29921a8fSScott Kruger      argStr=re.sub("{{"+loop+"}}","${"+lindex+"}",argStr)
179*29921a8fSScott Kruger      donline=indent*j+"done"
180*29921a8fSScott Kruger      forlines=forlines+forline+"\n"
181*29921a8fSScott Kruger      donlines=donlines+donline+"\n"
182*29921a8fSScott Kruger      i=i+1
183*29921a8fSScott Kruger      j=j+1
184*29921a8fSScott Kruger    subst['args']=argStr
185*29921a8fSScott Kruger
186*29921a8fSScott Kruger    # The do lines have reverse order with respect to indentation
187*29921a8fSScott Kruger    dl=donlines.rstrip("\n").split("\n")
188*29921a8fSScott Kruger    dl.reverse()
189*29921a8fSScott Kruger    donlines="\n".join(dl)+"\n"
190*29921a8fSScott Kruger
191*29921a8fSScott Kruger    return forlines,donlines,i,j
192*29921a8fSScott Kruger
193*29921a8fSScott Kruger
194*29921a8fSScott Kruger  def getExecname(self,exfile,root):
195*29921a8fSScott Kruger    """
196*29921a8fSScott Kruger      Generate bash script using template found next to this file.
197*29921a8fSScott Kruger      This file is read in at constructor time to avoid file I/O
198*29921a8fSScott Kruger    """
199*29921a8fSScott Kruger    rpath=self.relpath(self.petsc_dir,root)
200*29921a8fSScott Kruger    if self.single_ex:
201*29921a8fSScott Kruger      execname=rpath.split("/")[1]+"-ex"
202*29921a8fSScott Kruger    else:
203*29921a8fSScott Kruger      execname=os.path.splitext(exfile)[0]
204*29921a8fSScott Kruger    return execname
205*29921a8fSScott Kruger
206*29921a8fSScott Kruger  def getSubstVars(self,testDict,rpath,testname):
207*29921a8fSScott Kruger    """
208*29921a8fSScott Kruger      Create a dictionary with all of the variables that get substituted
209*29921a8fSScott Kruger      into the template commands found in example_template.py
210*29921a8fSScott Kruger      TODO: Cleanup
211*29921a8fSScott Kruger    """
212*29921a8fSScott Kruger    subst={}
213*29921a8fSScott Kruger    # Handle defaults
214*29921a8fSScott Kruger    if not testDict.has_key('nsize'): testDict['nsize']=1
215*29921a8fSScott Kruger    if not testDict.has_key('filter'): testDict['filter']=""
216*29921a8fSScott Kruger    if not testDict.has_key('args'): testDict['args']=""
217*29921a8fSScott Kruger    defroot=(re.sub("run","",testname) if testname.startswith("run") else testname)
218*29921a8fSScott Kruger    if not testDict.has_key('redirect_file'): testDict['redirect_file']=defroot+".tmp"
219*29921a8fSScott Kruger    if not testDict.has_key('output_file'): testDict['output_file']="output/"+defroot+".out"
220*29921a8fSScott Kruger
221*29921a8fSScott Kruger    # Setup the variables in template_string that need to be substituted
222*29921a8fSScott Kruger    subst['srcdir']=os.path.join(self.petsc_dir,rpath)
223*29921a8fSScott Kruger    subst['label']=self.nameSpace(defroot,subst['srcdir'])
224*29921a8fSScott Kruger    subst['output_file']=os.path.join(subst['srcdir'],testDict['output_file'])
225*29921a8fSScott Kruger    subst['exec']="../"+testDict['execname']
226*29921a8fSScott Kruger    subst['redirect_file']=testDict['redirect_file']
227*29921a8fSScott Kruger    subst['filter']=testDict['filter']
228*29921a8fSScott Kruger    subst['testroot']=self.testroot_dir
229*29921a8fSScott Kruger    subst['testname']=testname
230*29921a8fSScott Kruger
231*29921a8fSScott Kruger    # Be careful with this
232*29921a8fSScott Kruger    if testDict.has_key('command'): subst['command']=testDict['command']
233*29921a8fSScott Kruger
234*29921a8fSScott Kruger    # These can have for loops and are treated separately later
235*29921a8fSScott Kruger    if testDict.has_key('nsize'): subst['nsize']=str(testDict['nsize'])
236*29921a8fSScott Kruger    if testDict.has_key('args'):  subst['args']=testDict['args']
237*29921a8fSScott Kruger
238*29921a8fSScott Kruger    #Conf vars
239*29921a8fSScott Kruger    subst['mpiexec']=self.conf['MPIEXEC']  # make sure PETSC_DIR is defined!
240*29921a8fSScott Kruger    subst['diff']=self.conf['DIFF']
241*29921a8fSScott Kruger    subst['rm']=self.conf['RM']
242*29921a8fSScott Kruger    subst['grep']=self.conf['GREP']
243*29921a8fSScott Kruger
244*29921a8fSScott Kruger    return subst
245*29921a8fSScott Kruger
246*29921a8fSScott Kruger  def getCmds(self,subst,i):
247*29921a8fSScott Kruger    """
248*29921a8fSScott Kruger      Generate bash script using template found next to this file.
249*29921a8fSScott Kruger      This file is read in at constructor time to avoid file I/O
250*29921a8fSScott Kruger    """
251*29921a8fSScott Kruger    indent="   "
252*29921a8fSScott Kruger    nindent=i # the start and has to be consistent with below
253*29921a8fSScott Kruger    cmdLines=""
254*29921a8fSScott Kruger    # MPI is the default -- but we have a few odd commands
255*29921a8fSScott Kruger    if not subst.has_key('command'):
256*29921a8fSScott Kruger      cmd=indent*nindent+self._substVars(subst,example_template.mpitest)
257*29921a8fSScott Kruger    else:
258*29921a8fSScott Kruger      cmd=indent*nindent+self._substVars(subst,example_template.commandtest)
259*29921a8fSScott Kruger    cmdLines=cmdLines+cmd+"\n\n"
260*29921a8fSScott Kruger
261*29921a8fSScott Kruger    cmd=indent*nindent+self._substVars(subst,example_template.difftest)
262*29921a8fSScott Kruger    cmdLines=cmdLines+cmd+"\n"
263*29921a8fSScott Kruger    return cmdLines
264*29921a8fSScott Kruger
265*29921a8fSScott Kruger  def _substVars(self,subst,origStr):
266*29921a8fSScott Kruger    """
267*29921a8fSScott Kruger      Substitute varial
268*29921a8fSScott Kruger    """
269*29921a8fSScott Kruger    Str=origStr
270*29921a8fSScott Kruger    for subkey in subst:
271*29921a8fSScott Kruger      if type(subst[subkey])!=types.StringType: continue
272*29921a8fSScott Kruger      patt="@"+subkey.upper()+"@"
273*29921a8fSScott Kruger      Str=re.sub(patt,subst[subkey],Str)
274*29921a8fSScott Kruger    return Str
275*29921a8fSScott Kruger
276*29921a8fSScott Kruger  def genRunScript(self,testname,root,isRun,srcDict):
277*29921a8fSScott Kruger    """
278*29921a8fSScott Kruger      Generate bash script using template found next to this file.
279*29921a8fSScott Kruger      This file is read in at constructor time to avoid file I/O
280*29921a8fSScott Kruger    """
281*29921a8fSScott Kruger    # runscript_dir directory has to be consistent with gmakefile
282*29921a8fSScott Kruger    testDict=srcDict[testname]
283*29921a8fSScott Kruger    rpath=self.relpath(self.petsc_dir,root)
284*29921a8fSScott Kruger    runscript_dir=os.path.join(self.testroot_dir,rpath)
285*29921a8fSScott Kruger    if not os.path.isdir(runscript_dir): os.makedirs(runscript_dir)
286*29921a8fSScott Kruger    fh=open(os.path.join(runscript_dir,testname+".sh"),"w")
287*29921a8fSScott Kruger    petscvarfile=os.path.join(self.arch_dir,'lib','petsc','conf','petscvariables')
288*29921a8fSScott Kruger
289*29921a8fSScott Kruger    subst=self.getSubstVars(testDict,rpath,testname)
290*29921a8fSScott Kruger
291*29921a8fSScott Kruger    # Now substitute the key variables into the header and footer
292*29921a8fSScott Kruger    header=self._substVars(subst,example_template.header)
293*29921a8fSScott Kruger    footer=re.sub('@TESTSROOT@',subst['testroot'],example_template.footer)
294*29921a8fSScott Kruger
295*29921a8fSScott Kruger    # Start writing the file
296*29921a8fSScott Kruger    fh.write(header+"\n")
297*29921a8fSScott Kruger
298*29921a8fSScott Kruger    # If there is a TODO or a SKIP then we do it before writing out the
299*29921a8fSScott Kruger    # rest of the command (which is useful for working on the test)
300*29921a8fSScott Kruger    # SKIP and TODO can be for the source file or for the runs
301*29921a8fSScott Kruger    if srcDict.has_key("SKIP") or srcDict.has_key("TODO"):
302*29921a8fSScott Kruger      if srcDict.has_key("TODO"):
303*29921a8fSScott Kruger        todo=re.sub("@TODOCOMMENT@",srcDict['TODO'],example_template.todoline)
304*29921a8fSScott Kruger        fh.write(todo+"\ntotal=1; todo=1\n")
305*29921a8fSScott Kruger        fh.write(footer+"\n")
306*29921a8fSScott Kruger        fh.write("exit\n\n\n")
307*29921a8fSScott Kruger      elif srcDict.has_key("SKIP") or srcDict.has_key("TODO"):
308*29921a8fSScott Kruger        skip=re.sub("@SKIPCOMMENT@",srcDict['SKIP'],example_template.skipline)
309*29921a8fSScott Kruger        fh.write(skip+"\ntotal=1; skip=1\n")
310*29921a8fSScott Kruger        fh.write(footer+"\n")
311*29921a8fSScott Kruger        fh.write("exit\n\n\n")
312*29921a8fSScott Kruger    elif not isRun:
313*29921a8fSScott Kruger      skip=re.sub("@SKIPCOMMENT@",testDict['SKIP'],example_template.skipline)
314*29921a8fSScott Kruger      fh.write(skip+"\ntotal=1; skip=1\n")
315*29921a8fSScott Kruger      fh.write(footer+"\n")
316*29921a8fSScott Kruger      fh.write("exit\n\n\n")
317*29921a8fSScott Kruger    elif testDict.has_key('TODO'):
318*29921a8fSScott Kruger      todo=re.sub("@TODOCOMMENT@",testDict['TODO'],example_template.todoline)
319*29921a8fSScott Kruger      fh.write(todo+"\ntotal=1; todo=1\n")
320*29921a8fSScott Kruger      fh.write(footer+"\n")
321*29921a8fSScott Kruger      fh.write("exit\n\n\n")
322*29921a8fSScott Kruger
323*29921a8fSScott Kruger    # Need to handle loops
324*29921a8fSScott Kruger    i=8  # for loop counters
325*29921a8fSScott Kruger    j=0  # for indentation
326*29921a8fSScott Kruger
327*29921a8fSScott Kruger    doForP=False
328*29921a8fSScott Kruger    if "{{" in subst['args']+subst['nsize']:
329*29921a8fSScott Kruger      doForP=True
330*29921a8fSScott Kruger      flinesP,dlinesP,i,j=self.getFor(subst,i,j)
331*29921a8fSScott Kruger      fh.write(flinesP+"\n")
332*29921a8fSScott Kruger
333*29921a8fSScott Kruger    # Subtests are special
334*29921a8fSScott Kruger    if testDict.has_key("subtests"):
335*29921a8fSScott Kruger      substP=subst   # Subtests can inherit args but be careful
336*29921a8fSScott Kruger      if not substP.has_key("arg"): substP["arg"]=""
337*29921a8fSScott Kruger      jorig=j
338*29921a8fSScott Kruger      for stest in testDict["subtests"]:
339*29921a8fSScott Kruger        j=jorig
340*29921a8fSScott Kruger        subst=substP
341*29921a8fSScott Kruger        subst.update(testDict[stest])
342*29921a8fSScott Kruger        subst['nsize']=str(subst['nsize'])
343*29921a8fSScott Kruger        if not testDict[stest].has_key('args'): testDict[stest]['args']=""
344*29921a8fSScott Kruger        subst['args']=substP['args']+testDict[stest]['args']
345*29921a8fSScott Kruger        doFor=False
346*29921a8fSScott Kruger        if "{{" in subst['args']+subst['nsize']:
347*29921a8fSScott Kruger          doFor=True
348*29921a8fSScott Kruger          flines,dlines,i,j=self.getFor(subst,i,j)
349*29921a8fSScott Kruger          fh.write(flines+"\n")
350*29921a8fSScott Kruger        fh.write(self.getCmds(subst,j)+"\n")
351*29921a8fSScott Kruger        if doFor: fh.write(dlines+"\n")
352*29921a8fSScott Kruger    else:
353*29921a8fSScott Kruger      fh.write(self.getCmds(subst,j)+"\n")
354*29921a8fSScott Kruger      if doForP: fh.write(dlinesP+"\n")
355*29921a8fSScott Kruger
356*29921a8fSScott Kruger    fh.write(footer+"\n")
357*29921a8fSScott Kruger    os.chmod(os.path.join(runscript_dir,testname+".sh"),0777)
358*29921a8fSScott Kruger    return
359*29921a8fSScott Kruger
360*29921a8fSScott Kruger  def  genScriptsAndInfo(self,exfile,root,srcDict):
361*29921a8fSScott Kruger    """
362*29921a8fSScott Kruger    Generate scripts from the source file, determine if built, etc.
363*29921a8fSScott Kruger     For every test in the exfile with info in the srcDict:
364*29921a8fSScott Kruger      1. Determine if it needs to be run for this arch
365*29921a8fSScott Kruger      2. Generate the script
366*29921a8fSScott Kruger      3. Generate the data needed to write out the makefile in a
367*29921a8fSScott Kruger         convenient way
368*29921a8fSScott Kruger     All tests are *always* run, but some may be SKIP'd per the TAP standard
369*29921a8fSScott Kruger    """
370*29921a8fSScott Kruger    debug=False
371*29921a8fSScott Kruger    fileIsTested=False
372*29921a8fSScott Kruger    execname=self.getExecname(exfile,root)
373*29921a8fSScott Kruger    isBuilt=self._isBuilt(exfile,srcDict)
374*29921a8fSScott Kruger    for test in srcDict:
375*29921a8fSScott Kruger      if test in self.buildkeys: continue
376*29921a8fSScott Kruger      if debug: print self.nameSpace(exfile,root), test
377*29921a8fSScott Kruger      srcDict[test]['execname']=execname   # Convenience in generating scripts
378*29921a8fSScott Kruger      isRun=self._isRun(srcDict[test])
379*29921a8fSScott Kruger      self.genRunScript(test,root,isRun,srcDict)
380*29921a8fSScott Kruger      srcDict[test]['isrun']=isRun
381*29921a8fSScott Kruger      if isRun: fileIsTested=True
382*29921a8fSScott Kruger      self.addToTests(test,root,exfile,execname,srcDict[test])
383*29921a8fSScott Kruger
384*29921a8fSScott Kruger    # This adds to datastructure for building deps
385*29921a8fSScott Kruger    if fileIsTested and isBuilt: self.addToSources(exfile,root,srcDict)
386*29921a8fSScott Kruger    #print self.nameSpace(exfile,root), fileIsTested
387*29921a8fSScott Kruger    return
388*29921a8fSScott Kruger
389*29921a8fSScott Kruger  def _isBuilt(self,exfile,srcDict):
390*29921a8fSScott Kruger    """
391*29921a8fSScott Kruger    Determine if this file should be built.
392*29921a8fSScott Kruger    """
393*29921a8fSScott Kruger    # Get the language based on file extension
394*29921a8fSScott Kruger    lang=self.getLanguage(exfile)
395*29921a8fSScott Kruger    if lang=="f" and not self.have_fortran:
396*29921a8fSScott Kruger      srcDict["SKIP"]="Fortran required for this test"
397*29921a8fSScott Kruger      return False
398*29921a8fSScott Kruger    if lang=="cu" and not self.conf.has_key('PETSC_HAVE_CUDA'):
399*29921a8fSScott Kruger      srcDict["SKIP"]="CUDA required for this test"
400*29921a8fSScott Kruger      return False
401*29921a8fSScott Kruger    if lang=="cxx" and not self.conf.has_key('PETSC_HAVE_CXX'):
402*29921a8fSScott Kruger      srcDict["SKIP"]="C++ required for this test"
403*29921a8fSScott Kruger      return False
404*29921a8fSScott Kruger
405*29921a8fSScott Kruger    # Deprecated source files
406*29921a8fSScott Kruger    if srcDict.has_key("TODO"): return False
407*29921a8fSScott Kruger
408*29921a8fSScott Kruger    # isRun can work with srcDict to handle the requires
409*29921a8fSScott Kruger    if srcDict.has_key("requires"):
410*29921a8fSScott Kruger      if len(srcDict["requires"])>0:
411*29921a8fSScott Kruger        return self._isRun(srcDict)
412*29921a8fSScott Kruger
413*29921a8fSScott Kruger    return True
414*29921a8fSScott Kruger
415*29921a8fSScott Kruger
416*29921a8fSScott Kruger  def _isRun(self,testDict):
417*29921a8fSScott Kruger    """
418*29921a8fSScott Kruger    Based on the requirements listed in the src file and the petscconf.h
419*29921a8fSScott Kruger    info, determine whether this test should be run or not.
420*29921a8fSScott Kruger    """
421*29921a8fSScott Kruger    indent="  "
422*29921a8fSScott Kruger    debug=False
423*29921a8fSScott Kruger
424*29921a8fSScott Kruger    # MPI requirements
425*29921a8fSScott Kruger    if testDict.has_key('nsize'):
426*29921a8fSScott Kruger      if testDict['nsize']>1 and self.conf.has_key('MPI_IS_MPIUNI'):
427*29921a8fSScott Kruger        if debug: print indent+"Cannot run parallel tests"
428*29921a8fSScott Kruger        testDict['SKIP']="Parallel test with serial build"
429*29921a8fSScott Kruger        return False
430*29921a8fSScott Kruger
431*29921a8fSScott Kruger    # The requirements for the test are the sum of all the run subtests
432*29921a8fSScott Kruger    if testDict.has_key('subtests'):
433*29921a8fSScott Kruger      if not testDict.has_key('requires'): testDict['requires']=""
434*29921a8fSScott Kruger      for stest in testDict['subtests']:
435*29921a8fSScott Kruger        if testDict[stest].has_key('requires'):
436*29921a8fSScott Kruger          testDict['requires']=testDict['requires']+" "+testDict[stest]['requires']
437*29921a8fSScott Kruger
438*29921a8fSScott Kruger
439*29921a8fSScott Kruger    # Now go through all requirements
440*29921a8fSScott Kruger    if testDict.has_key('requires'):
441*29921a8fSScott Kruger      for requirement in testDict['requires'].split():
442*29921a8fSScott Kruger        requirement=requirement.strip()
443*29921a8fSScott Kruger        if not requirement: continue
444*29921a8fSScott Kruger        if debug: print indent+"Requirement: ", requirement
445*29921a8fSScott Kruger        isNull=False
446*29921a8fSScott Kruger        if requirement.startswith("!"):
447*29921a8fSScott Kruger          requirement=requirement[1:]; isNull=True
448*29921a8fSScott Kruger        # Scalar requirement
449*29921a8fSScott Kruger        if requirement=="complex":
450*29921a8fSScott Kruger          if self.conf['PETSC_SCALAR']=='complex':
451*29921a8fSScott Kruger            testDict['SKIP']="Non-complex build required"
452*29921a8fSScott Kruger            if isNull: return False
453*29921a8fSScott Kruger          else:
454*29921a8fSScott Kruger            testDict['SKIP']="Complex build required"
455*29921a8fSScott Kruger            return False
456*29921a8fSScott Kruger        # Precision requirement for reals
457*29921a8fSScott Kruger        if requirement in self.precision_types:
458*29921a8fSScott Kruger          if self.conf['PETSC_PRECISION']==requirement:
459*29921a8fSScott Kruger            testDict['SKIP']="not "+requirement+" required"
460*29921a8fSScott Kruger            if isNull: return False
461*29921a8fSScott Kruger          else:
462*29921a8fSScott Kruger            testDict['SKIP']=requirement+" required"
463*29921a8fSScott Kruger            return False
464*29921a8fSScott Kruger        # Precision requirement for ints
465*29921a8fSScott Kruger        if requirement in self.integer_types:
466*29921a8fSScott Kruger          if requirement=="int32":
467*29921a8fSScott Kruger            if self.conf['PETSC_SIZEOF_INT']==4:
468*29921a8fSScott Kruger              testDict['SKIP']="not int32 required"
469*29921a8fSScott Kruger              if isNull: return False
470*29921a8fSScott Kruger            else:
471*29921a8fSScott Kruger              testDict['SKIP']="int32 required"
472*29921a8fSScott Kruger              return False
473*29921a8fSScott Kruger          if requirement=="int64":
474*29921a8fSScott Kruger            if self.conf['PETSC_SIZEOF_INT']==8:
475*29921a8fSScott Kruger              testDict['SKIP']="NOT int64 required"
476*29921a8fSScott Kruger              if isNull: return False
477*29921a8fSScott Kruger            else:
478*29921a8fSScott Kruger              testDict['SKIP']="int64 required"
479*29921a8fSScott Kruger              return False
480*29921a8fSScott Kruger        # Datafilespath
481*29921a8fSScott Kruger        if requirement=="datafilespath":
482*29921a8fSScott Kruger          testDict['SKIP']="Requires DATAFILESPATH"
483*29921a8fSScott Kruger          return False
484*29921a8fSScott Kruger        # Defines -- not sure I have comments matching
485*29921a8fSScott Kruger        if "define(" in requirement:
486*29921a8fSScott Kruger          reqdef=requirement.split("(")[1].split(")")[0]
487*29921a8fSScott Kruger          val=(reqdef.split()[1] if " " in reqdef else "")
488*29921a8fSScott Kruger          if self.conf.has_key(reqdef):
489*29921a8fSScott Kruger            if val:
490*29921a8fSScott Kruger              if self.conf[reqdef]==val:
491*29921a8fSScott Kruger                if isNull:
492*29921a8fSScott Kruger                  testDict['SKIP']="Null requirement not met: "+requirement
493*29921a8fSScott Kruger                  return False
494*29921a8fSScott Kruger              else:
495*29921a8fSScott Kruger                testDict['SKIP']="Required: "+requirement
496*29921a8fSScott Kruger                return False
497*29921a8fSScott Kruger            else:
498*29921a8fSScott Kruger              if isNull:
499*29921a8fSScott Kruger                testDict['SKIP']="Null requirement not met: "+requirement
500*29921a8fSScott Kruger                return False
501*29921a8fSScott Kruger          else:
502*29921a8fSScott Kruger            testDict['SKIP']="Requirement not met: "+requirement
503*29921a8fSScott Kruger            return False
504*29921a8fSScott Kruger
505*29921a8fSScott Kruger        # Rest should be packages that we can just get from conf
506*29921a8fSScott Kruger        petscconfvar="PETSC_HAVE_"+requirement.upper()
507*29921a8fSScott Kruger        if self.conf.get(petscconfvar):
508*29921a8fSScott Kruger          if isNull:
509*29921a8fSScott Kruger            testDict['SKIP']="Not "+petscconfvar+" requirement not met"
510*29921a8fSScott Kruger            return False
511*29921a8fSScott Kruger        else:
512*29921a8fSScott Kruger          if debug: print "requirement not found: ", requirement
513*29921a8fSScott Kruger          testDict['SKIP']=petscconfvar+" requirement not met"
514*29921a8fSScott Kruger          return False
515*29921a8fSScott Kruger
516*29921a8fSScott Kruger    return True
517*29921a8fSScott Kruger
518*29921a8fSScott Kruger  def genPetscTests_summarize(self,dataDict):
519*29921a8fSScott Kruger    """
520*29921a8fSScott Kruger    Required method to state what happened
521*29921a8fSScott Kruger    """
522*29921a8fSScott Kruger    if not self.summarize: return
523*29921a8fSScott Kruger    indent="   "
524*29921a8fSScott Kruger    fhname="GenPetscTests_summarize.txt"
525*29921a8fSScott Kruger    fh=open(fhname,"w")
526*29921a8fSScott Kruger    print "See ", fhname
527*29921a8fSScott Kruger    for root in dataDict:
528*29921a8fSScott Kruger      relroot=self.relpath(self.petsc_dir,root)
529*29921a8fSScott Kruger      pkg=relroot.split("/")[1]
530*29921a8fSScott Kruger      fh.write(relroot+"\n")
531*29921a8fSScott Kruger      allSrcs=[]
532*29921a8fSScott Kruger      for lang in LANGS: allSrcs=allSrcs+self.sources[pkg][lang]['srcs']
533*29921a8fSScott Kruger      for exfile in dataDict[root]:
534*29921a8fSScott Kruger        # Basic  information
535*29921a8fSScott Kruger        fullfile=os.path.join(root,exfile)
536*29921a8fSScott Kruger        rfile=self.relpath(self.petsc_dir,fullfile)
537*29921a8fSScott Kruger        builtStatus=(" Is built" if rfile in allSrcs else " Is NOT built")
538*29921a8fSScott Kruger        fh.write(indent+exfile+indent*4+builtStatus+"\n")
539*29921a8fSScott Kruger
540*29921a8fSScott Kruger        for test in dataDict[root][exfile]:
541*29921a8fSScott Kruger          if test in self.buildkeys: continue
542*29921a8fSScott Kruger          line=indent*2+test
543*29921a8fSScott Kruger          fh.write(line+"\n")
544*29921a8fSScott Kruger          # Looks nice to have the keys in order
545*29921a8fSScott Kruger          #for key in dataDict[root][exfile][test]:
546*29921a8fSScott Kruger          for key in "isrun abstracted nsize args requires script".split():
547*29921a8fSScott Kruger            if not dataDict[root][exfile][test].has_key(key): continue
548*29921a8fSScott Kruger            line=indent*3+key+": "+str(dataDict[root][exfile][test][key])
549*29921a8fSScott Kruger            fh.write(line+"\n")
550*29921a8fSScott Kruger          fh.write("\n")
551*29921a8fSScott Kruger        fh.write("\n")
552*29921a8fSScott Kruger      fh.write("\n")
553*29921a8fSScott Kruger    #fh.write("\nClass Sources\n"+str(self.sources)+"\n")
554*29921a8fSScott Kruger    #fh.write("\nClass Tests\n"+str(self.tests)+"\n")
555*29921a8fSScott Kruger    fh.close()
556*29921a8fSScott Kruger    return
557*29921a8fSScott Kruger
558*29921a8fSScott Kruger  def genPetscTests(self,root,dirs,files,dataDict):
559*29921a8fSScott Kruger    """
560*29921a8fSScott Kruger     Go through and parse the source files in the directory to generate
561*29921a8fSScott Kruger     the examples based on the metadata contained in the source files
562*29921a8fSScott Kruger    """
563*29921a8fSScott Kruger    debug=False
564*29921a8fSScott Kruger    # Use examplesAnalyze to get what the makefles think are sources
565*29921a8fSScott Kruger    #self.examplesAnalyze(root,dirs,files,anlzDict)
566*29921a8fSScott Kruger
567*29921a8fSScott Kruger    dataDict[root]={}
568*29921a8fSScott Kruger
569*29921a8fSScott Kruger    for exfile in files:
570*29921a8fSScott Kruger      #TST: Until we replace files, still leaving the orginals as is
571*29921a8fSScott Kruger      #if not exfile.startswith("new_"+"ex"): continue
572*29921a8fSScott Kruger      if not exfile.startswith("ex"): continue
573*29921a8fSScott Kruger
574*29921a8fSScott Kruger      # Convenience
575*29921a8fSScott Kruger      fullex=os.path.join(root,exfile)
576*29921a8fSScott Kruger      relpfile=self.relpath(self.petsc_dir,fullex)
577*29921a8fSScott Kruger      if debug: print relpfile
578*29921a8fSScott Kruger      dataDict[root].update(testparse.parseTestFile(fullex))
579*29921a8fSScott Kruger      # Need to check and make sure tests are in the file
580*29921a8fSScott Kruger      # if verbosity>=1: print relpfile
581*29921a8fSScott Kruger      if dataDict[root].has_key(exfile):
582*29921a8fSScott Kruger        self.genScriptsAndInfo(exfile,root,dataDict[root][exfile])
583*29921a8fSScott Kruger
584*29921a8fSScott Kruger    return
585*29921a8fSScott Kruger
586*29921a8fSScott Kruger  def walktree(self,top,action="printFiles"):
587*29921a8fSScott Kruger    """
588*29921a8fSScott Kruger    Walk a directory tree, starting from 'top'
589*29921a8fSScott Kruger    """
590*29921a8fSScott Kruger    #print "action", action
591*29921a8fSScott Kruger    # Goal of action is to fill this dictionary
592*29921a8fSScott Kruger    dataDict={}
593*29921a8fSScott Kruger    for root, dirs, files in os.walk(top, topdown=False):
594*29921a8fSScott Kruger      if not "examples" in root: continue
595*29921a8fSScott Kruger      if not os.path.isfile(os.path.join(root,"makefile")): continue
596*29921a8fSScott Kruger      bname=os.path.basename(root.rstrip("/"))
597*29921a8fSScott Kruger      if bname=="tests" or bname=="tutorials":
598*29921a8fSScott Kruger        eval("self."+action+"(root,dirs,files,dataDict)")
599*29921a8fSScott Kruger      if type(top) != types.StringType:
600*29921a8fSScott Kruger          raise TypeError("top must be a string")
601*29921a8fSScott Kruger    # Now summarize this dictionary
602*29921a8fSScott Kruger    eval("self."+action+"_summarize(dataDict)")
603*29921a8fSScott Kruger    return dataDict
604*29921a8fSScott Kruger
605*29921a8fSScott Kruger  def gen_gnumake(self, fd,prefix='srcs-'):
606*29921a8fSScott Kruger    """
607*29921a8fSScott Kruger     Overwrite of the method in the base PETSc class
608*29921a8fSScott Kruger    """
609*29921a8fSScott Kruger    def write(stem, srcs):
610*29921a8fSScott Kruger        fd.write('%s :=\n' % stem)
611*29921a8fSScott Kruger        for lang in LANGS:
612*29921a8fSScott Kruger            fd.write('%(stem)s.%(lang)s := %(srcs)s\n' % dict(stem=stem, lang=lang, srcs=' '.join(srcs[lang]['srcs'])))
613*29921a8fSScott Kruger            fd.write('%(stem)s += $(%(stem)s.%(lang)s)\n' % dict(stem=stem, lang=lang))
614*29921a8fSScott Kruger    for pkg in PKGS:
615*29921a8fSScott Kruger        srcs = self.gen_pkg(pkg)
616*29921a8fSScott Kruger        write(prefix + pkg, srcs)
617*29921a8fSScott Kruger    return self.gendeps
618*29921a8fSScott Kruger
619*29921a8fSScott Kruger  def gen_pkg(self, pkg):
620*29921a8fSScott Kruger    """
621*29921a8fSScott Kruger     Overwrite of the method in the base PETSc class
622*29921a8fSScott Kruger    """
623*29921a8fSScott Kruger    return self.sources[pkg]
624*29921a8fSScott Kruger
625*29921a8fSScott Kruger  def write_gnumake(self,dataDict):
626*29921a8fSScott Kruger    """
627*29921a8fSScott Kruger     Write out something similar to files from gmakegen.py
628*29921a8fSScott Kruger
629*29921a8fSScott Kruger     There is not a lot of has_key type checking because
630*29921a8fSScott Kruger     should just work and need to know if there are bugs
631*29921a8fSScott Kruger
632*29921a8fSScott Kruger     Test depends on script which also depends on source
633*29921a8fSScott Kruger     file, but since I don't have a good way generating
634*29921a8fSScott Kruger     acting on a single file (oops) just depend on
635*29921a8fSScott Kruger     executable which in turn will depend on src file
636*29921a8fSScott Kruger    """
637*29921a8fSScott Kruger    # Open file
638*29921a8fSScott Kruger    arch_files = self.arch_path('lib','petsc','conf', 'testfiles')
639*29921a8fSScott Kruger    arg_files = self.arch_path('lib','petsc','conf', 'testargfiles')
640*29921a8fSScott Kruger    fd = open(arch_files, 'w')
641*29921a8fSScott Kruger    fa = open(arg_files, 'w')
642*29921a8fSScott Kruger
643*29921a8fSScott Kruger    # Write out the sources
644*29921a8fSScott Kruger    gendeps = self.gen_gnumake(fd,prefix="testsrcs-")
645*29921a8fSScott Kruger
646*29921a8fSScott Kruger    # Write out the tests and execname targets
647*29921a8fSScott Kruger    fd.write("\n#Tests and executables\n")    # Delimiter
648*29921a8fSScott Kruger    testdeps=" ".join(["test-"+pkg for pkg in PKGS])
649*29921a8fSScott Kruger    testexdeps=" ".join(["test-ex-"+pkg for pkg in PKGS])
650*29921a8fSScott Kruger    fd.write("test: testex "+testdeps+" report_tests\n")    # Main test target
651*29921a8fSScott Kruger    # Add executables to build right way to make the `make test` look
652*29921a8fSScott Kruger    # nicer
653*29921a8fSScott Kruger    fd.write("testex: "+testexdeps+"\n")    # Main test target
654*29921a8fSScott Kruger
655*29921a8fSScott Kruger    for pkg in PKGS:
656*29921a8fSScott Kruger      # These grab the ones that are built
657*29921a8fSScott Kruger      # Package tests
658*29921a8fSScott Kruger      testdeps=" ".join(["test-"+pkg+"-"+lang for lang in LANGS])
659*29921a8fSScott Kruger      fd.write("test-"+pkg+": "+testdeps+"\n")
660*29921a8fSScott Kruger      testexdeps=" ".join(["test-ex-"+pkg+"-"+lang for lang in LANGS])
661*29921a8fSScott Kruger      fd.write("test-ex-"+pkg+": "+testexdeps+"\n")
662*29921a8fSScott Kruger      # This needs work
663*29921a8fSScott Kruger      if self.single_ex:
664*29921a8fSScott Kruger        execname=pkg+"-ex"
665*29921a8fSScott Kruger        fd.write(execname+": "+" ".join(self.objects[pkg])+"\n\n")
666*29921a8fSScott Kruger      for lang in LANGS:
667*29921a8fSScott Kruger        testdeps=""
668*29921a8fSScott Kruger        for ftest in self.tests[pkg][lang]:
669*29921a8fSScott Kruger          test=os.path.basename(ftest)
670*29921a8fSScott Kruger          basedir=os.path.dirname(ftest)
671*29921a8fSScott Kruger          testdeps=testdeps+" "+self.nameSpace(test,basedir)
672*29921a8fSScott Kruger        fd.write("test-"+pkg+"-"+lang+":"+testdeps+"\n")
673*29921a8fSScott Kruger
674*29921a8fSScott Kruger        # test targets
675*29921a8fSScott Kruger        for ftest in self.tests[pkg][lang]:
676*29921a8fSScott Kruger          test=os.path.basename(ftest)
677*29921a8fSScott Kruger          basedir=os.path.dirname(ftest)
678*29921a8fSScott Kruger          testdir="${TESTDIR}/"+basedir+"/"
679*29921a8fSScott Kruger          nmtest=self.nameSpace(test,basedir)
680*29921a8fSScott Kruger          rundir=os.path.join(testdir,test)
681*29921a8fSScott Kruger          #print test, nmtest
682*29921a8fSScott Kruger          script=test+".sh"
683*29921a8fSScott Kruger
684*29921a8fSScott Kruger          # Deps
685*29921a8fSScott Kruger          exfile=self.tests[pkg][lang][ftest]['exfile']
686*29921a8fSScott Kruger          fullex=os.path.join(self.petsc_dir,exfile)
687*29921a8fSScott Kruger          localexec=self.tests[pkg][lang][ftest]['exec']
688*29921a8fSScott Kruger          execname=os.path.join(testdir,localexec)
689*29921a8fSScott Kruger
690*29921a8fSScott Kruger          # SKIP and TODO tests do not depend on exec
691*29921a8fSScott Kruger          if exfile in self.sources[pkg][lang]['srcs']:
692*29921a8fSScott Kruger            #print "Found dep: "+exfile, execname
693*29921a8fSScott Kruger            fd.write(nmtest+": "+execname+"\n")
694*29921a8fSScott Kruger          else:
695*29921a8fSScott Kruger            # Still add dependency to file
696*29921a8fSScott Kruger            fd.write(nmtest+": "+fullex+"\n")
697*29921a8fSScott Kruger          cmd=testdir+"/"+script
698*29921a8fSScott Kruger          fd.write("\t-@"+cmd+"\n")
699*29921a8fSScott Kruger          # Now write the args:
700*29921a8fSScott Kruger          fa.write(nmtest+"_ARGS='"+self.tests[pkg][lang][ftest]['argLabel']+"'\n")
701*29921a8fSScott Kruger
702*29921a8fSScott Kruger        # executable targets -- add these to build earlier
703*29921a8fSScott Kruger        testexdeps=""
704*29921a8fSScott Kruger        if not self.single_ex:
705*29921a8fSScott Kruger          for exfile in self.sources[pkg][lang]['srcs']:
706*29921a8fSScott Kruger            localexec=os.path.basename(os.path.splitext(exfile)[0])
707*29921a8fSScott Kruger            basedir=os.path.dirname(exfile)
708*29921a8fSScott Kruger            testdir="${TESTDIR}/"+basedir+"/"
709*29921a8fSScott Kruger            execname=os.path.join(testdir,localexec)
710*29921a8fSScott Kruger            testexdeps=testexdeps+" "+execname
711*29921a8fSScott Kruger          fd.write("test-ex-"+pkg+"-"+lang+":"+testexdeps+"\n")
712*29921a8fSScott Kruger
713*29921a8fSScott Kruger        for exfile in self.sources[pkg][lang]['srcs']:
714*29921a8fSScott Kruger          root=os.path.join(self.petsc_dir,os.path.dirname(exfile))
715*29921a8fSScott Kruger          basedir=os.path.dirname(exfile)
716*29921a8fSScott Kruger          testdir="${TESTDIR}/"+basedir+"/"
717*29921a8fSScott Kruger          base=os.path.basename(exfile)
718*29921a8fSScott Kruger          objfile=testdir+os.path.splitext(base)[0]+".o"
719*29921a8fSScott Kruger          linker=self.getLanguage(exfile)[0].upper()+"LINKER"
720*29921a8fSScott Kruger          if self.sources[pkg][lang].has_key(exfile):
721*29921a8fSScott Kruger            # Dependency for file
722*29921a8fSScott Kruger            objfile=objfile+" "+self.sources[pkg][lang][exfile]
723*29921a8fSScott Kruger            print objfile
724*29921a8fSScott Kruger          if not self.single_ex:
725*29921a8fSScott Kruger            localexec=os.path.basename(os.path.splitext(exfile)[0])
726*29921a8fSScott Kruger            execname=os.path.join(testdir,localexec)
727*29921a8fSScott Kruger            localobj=os.path.basename(objfile)
728*29921a8fSScott Kruger            petsc_lib="${PETSC_"+pkg.upper()+"_LIB}"
729*29921a8fSScott Kruger            fd.write("\n"+execname+": "+objfile+" ${libpetscall}\n")
730*29921a8fSScott Kruger            # There should be a better way here
731*29921a8fSScott Kruger            line="\t-cd "+testdir+"; ${"+linker+"} -o "+localexec+" "+localobj+" "+petsc_lib
732*29921a8fSScott Kruger            fd.write(line+"\n")
733*29921a8fSScott Kruger          linker=self.getLanguage(exfile)[0].upper()+"LINKER"
734*29921a8fSScott Kruger
735*29921a8fSScott Kruger    fd.write("helptests:\n\t -@grep '^[a-z]' ${generatedtest} | cut -f1 -d:\n")
736*29921a8fSScott Kruger    # Write out tests
737*29921a8fSScott Kruger    return
738*29921a8fSScott Kruger
739*29921a8fSScott Kruger  def writeHarness(self,output,dataDict):
740*29921a8fSScott Kruger    """
741*29921a8fSScott Kruger     This is set up to write out multiple harness even if only gnumake
742*29921a8fSScott Kruger     is supported now
743*29921a8fSScott Kruger    """
744*29921a8fSScott Kruger    eval("self.write_"+output+"(dataDict)")
745*29921a8fSScott Kruger    return
746*29921a8fSScott Kruger
747*29921a8fSScott Krugerdef main(petsc_dir=None, petsc_arch=None, output=None, verbose=False, single_ex=False):
748*29921a8fSScott Kruger    if output is None:
749*29921a8fSScott Kruger        output = 'gnumake'
750*29921a8fSScott Kruger
751*29921a8fSScott Kruger
752*29921a8fSScott Kruger    pEx=generateExamples(petsc_dir=petsc_dir, petsc_arch=petsc_arch, verbose=verbose, single_ex=single_ex)
753*29921a8fSScott Kruger    dataDict=pEx.walktree(os.path.join(pEx.petsc_dir,'src'),action="genPetscTests")
754*29921a8fSScott Kruger    pEx.writeHarness(output,dataDict)
755*29921a8fSScott Kruger
756*29921a8fSScott Krugerif __name__ == '__main__':
757*29921a8fSScott Kruger    import optparse
758*29921a8fSScott Kruger    parser = optparse.OptionParser()
759*29921a8fSScott Kruger    parser.add_option('--verbose', help='Show mismatches between makefiles and the filesystem', action='store_true', default=False)
760*29921a8fSScott Kruger    parser.add_option('--petsc-arch', help='Set PETSC_ARCH different from environment', default=os.environ.get('PETSC_ARCH'))
761*29921a8fSScott Kruger    parser.add_option('--output', help='Location to write output file', default=None)
762*29921a8fSScott Kruger    parser.add_option('-s', '--single_executable', dest='single_executable', action="store_false", help='Whether there should be single executable per src subdir.  Default is false')
763*29921a8fSScott Kruger    opts, extra_args = parser.parse_args()
764*29921a8fSScott Kruger    if extra_args:
765*29921a8fSScott Kruger        import sys
766*29921a8fSScott Kruger        sys.stderr.write('Unknown arguments: %s\n' % ' '.join(extra_args))
767*29921a8fSScott Kruger        exit(1)
768*29921a8fSScott Kruger    main(petsc_arch=opts.petsc_arch, output=opts.output, verbose=opts.verbose, single_ex=opts.single_executable)
769