xref: /petsc/lib/petsc/bin/taucc.py (revision f14a7c29b82d1117d8e3de344377442be395a55f)
1#!/usr/bin/env python3
2
3# Usage:
4#  taucc -cc=g++ -pdt_parse=/../cxxparse -tau_lib_dir=/.../lib COMPILE_OPTIONS
5#
6#  Options:
7#           -cc              : C/C++ compiler
8#           -pdt_parse       : pdtoolkit parser for C++
9#           -tau_lib_dir     : TAU library dir
10#           -v,-verbose      : verbose mode - shows the exact commands invoked
11#           -leave_tmp       : do not delete temporary files
12#           -E               : run preprocessor only
13#
14import commands
15import sys
16import os
17import tempfile
18def runcmd(cmd,verbose):
19  if verbose:
20    print(cmd)
21  (status, output) = commands.getstatusoutput(cmd)
22  if status:
23    raise RuntimeError('Unable to run '+cmd+':\n'+output)
24  elif output:
25    print(output)
26
27def getTauFlags(tau_lib_dir):
28  fd,name=tempfile.mkstemp(prefix='taucc-')
29  try:
30    tau_makefile = str(os.path.join(tau_lib_dir, os.path.basename(os.environ['TAU_MAKEFILE'])))
31  except:
32    tau_makefile = str(os.path.join(tau_lib_dir, 'Makefile.tau-mpi-pdt'))
33  buf  = 'include ' + tau_makefile
34  buf += '''
35tauflags:
36	-@echo TAU_INSTRUMENT0R:${TAU_PREFIX_INSTALL_DIR}/${CONFIG_ARCH}/bin/tau_instrumentor
37	-@echo TAU_DEFS:${TAU_DEFS}
38	-@echo TAU_INCLUDE:${TAU_INCLUDE}
39	-@echo TAU_LIBS:${TAU_LIBS}
40	-@echo TAU_MPI_INC:${TAU_MPI_INC}
41	-@echo TAU_MPI_LIBS:${TAU_MPI_LIBS}
42	-@echo TAU_CXXLIBS:${TAU_CXXLIBS}
43'''
44  os.write(fd,buf)
45  os.close(fd)
46  cmd = 'make -f '+ name + ' tauflags'
47  (status, output) = commands.getstatusoutput(cmd)
48  if status:
49    os.remove(name)
50    raise RuntimeError('Unable to run '+cmd+':\n'+output)
51  os.remove(name)
52  # remove unnecessary stuff from output
53  tau_defs =''
54  tau_include=''
55  tau_libs=''
56  tau_mpi_libs=''
57  for line in output.splitlines():
58    if line.find('TAU_INSTRUMENT0R:') >= 0:  tau_instr = line.replace('TAU_INSTRUMENT0R:','')
59    elif line.find('TAU_DEFS:') >= 0:  tau_defs = line.replace('TAU_DEFS:',' ')
60    elif line.find('TAU_INCLUDE:') >= 0: tau_include = line.replace('TAU_INCLUDE:',' ')
61    elif line.find('TAU_LIBS:') >= 0: tau_libs = line.replace('TAU_LIBS:',' ')
62    elif line.find('TAU_MPI_INC:') >= 0: tau_mpi_inc = line.replace('TAU_MPI_INC:',' ')
63    elif line.find('TAU_MPI_LIBS:') >= 0: tau_mpi_libs = line.replace('TAU_MPI_LIBS:',' ')
64    elif line.find('TAU_CXXLIBS:') >= 0: tau_cxxlibs = line.replace('TAU_CXXLIBS:',' ')
65  return tau_instr,tau_defs,tau_include,tau_libs,tau_mpi_inc,tau_mpi_libs,tau_cxxlibs
66
67def main():
68
69  sourcefiles=[]
70  objfiles=[]
71  libfiles=[]
72  arglist=''
73  pdt_parse='cxxparse'
74  iscparse=0
75  tau_instr='tau_instrumentor'
76  cc='gcc'
77  verbose=0
78  compileonly=0
79  leave_tmp = 0
80
81  for arg in sys.argv[1:]:
82    filename,ext = os.path.splitext(arg)
83    argsplit =  arg.split('=')
84    #look for sourcefiles, validate & add to a list
85    if ext == '.c' or ext == '.cc' or ext == '.cpp' or ext == '.cxx' or ext == '.C':
86      if os.path.isfile(arg):
87        sourcefiles.append(arg)
88    elif argsplit[0] == '-cc':
89      cc = argsplit[1]
90    elif argsplit[0] == '-pdt_parse':
91      pdt_parse = argsplit[1]
92      if pdt_parse.find('cparse') >=0: iscparse = 1
93      elif pdt_parse.find('cxxparse') >=0: iscparse = 0
94      else: sys.exit('Error: Unknown parser - use either cparse or cxxparse: '+pdt_parse)
95    elif arg == '-c':
96        compileonly = 1
97    elif arg == '-E':
98        compileonly = 1
99        arglist += ' '+arg
100    elif arg == '-leave_tmp':
101      leave_tmp = 1
102    elif argsplit[0] == '-tau_lib_dir':
103      tau_lib_dir = argsplit[1]
104    elif arg.startswith('-L') or arg.startswith('-l'):
105      libfiles.append(arg)
106    elif arg == '-v' or arg == '-verbose':
107        verbose  = 1
108        arglist += ' '+arg
109    else:
110      # Now make sure quotes are escaped properly
111      # Group the rest of the arguments into a different list
112      arg=arg.replace('"','\\"')
113      arglist += ' '+arg
114
115  # error if sourcefiles not specified with -c
116  if sourcefiles == [] and compileonly:
117    sys.exit('Error: no sourcefiles specified with -c')
118  # obtain TAU info from TAU makefile
119  tau_instr,tau_defs,tau_include,tau_libs,tau_mpi_inc,tau_mpi_libs,tau_cxxlibs = getTauFlags(tau_lib_dir)
120  if sourcefiles != []:
121    # Now Compile the sourcefiles
122    for sourcefile in sourcefiles:
123      root,ext = os.path.splitext(sourcefile)
124      obj_file = root + '.o'
125      objfiles.append(obj_file) # for use later at linktime
126      if iscparse:
127        if ext == '.c': pdt_file = root+ '.pdb'
128        else: pdt_file = sourcefile+ '.pdb'
129      else:
130        if ext == '.cc' or ext == '.cpp' or ext == '.cxx' or ext == '.C' : pdt_file = root+ '.pdb'
131        else: pdt_file = sourcefile+ '.pdb'
132      tau_file = root +'.inst' + ext
133      cmd1  = pdt_parse + ' ' + sourcefile + arglist + tau_defs + tau_include + tau_mpi_inc
134
135      cmd2  = tau_instr + ' ' + pdt_file + ' ' + sourcefile +' -o '+ tau_file
136      cmd2 += ' -c -rn PetscFunctionReturn -rv PetscFunctionReturnVoid\\(\\)'
137      cmd3  = cc + ' -c ' + tau_file + ' -o ' + obj_file + arglist + tau_defs + tau_include +tau_mpi_inc
138
139
140      runcmd(cmd1,verbose)
141      runcmd(cmd2,verbose)
142      if not leave_tmp: os.remove(pdt_file)
143      runcmd(cmd3,verbose)
144      if not leave_tmp: os.remove(tau_file)
145
146  if not compileonly:
147    objarg=''
148    for objfile in objfiles:
149      objarg += ' ' + objfile
150    libarg=''
151    for libfile in libfiles:
152      libarg += ' '+libfile
153    cmd1  = cc + ' ' + objarg +' '  + arglist + libarg + tau_mpi_libs + tau_libs + tau_cxxlibs
154    runcmd(cmd1,verbose)
155    if not leave_tmp: # delete the objfiles created
156      for objfile in objfiles:
157        os.remove(objfile)
158
159if __name__ ==  '__main__':
160  try:
161    main()
162  except Exception as e:
163    sys.exit('ERROR: '+str(e))
164