ADflow  v1.0
ADflow is a finite volume RANS solver tailored for gradient-based aerodynamic design optimization.
fort_depend.py
Go to the documentation of this file.
1 #!/usr/bin/python
2 import os
3 import re
4 
5 
6 # Definitions
7 def run(files=None, verbose=True, overwrite=None, output=None, macros={}, build=""):
8 
9  fileList = create_file_objs(files, macros)
10  mod2fil = file_objs_to_mod_dict(file_objs=fileList)
11  depends = get_depends(fob=fileList, m2f=mod2fil)
12 
13  if verbose:
14  for i in depends.keys():
15  print("\033[032m" + i + "\033[039m depends on :\033[034m")
16  for j in depends[i]:
17  print("\t" + j)
18  print("\033[039m")
19 
20  if output is None:
21  output = "makefile.dep"
22 
23  write_depend(outfile=output, dep=depends, overwrite=overwrite, build=build)
24 
25  return depends
26 
27 
28 def write_depend(outfile="makefile.dep", dep=[], overwrite=False, build=""):
29  "Write the dependencies to outfile"
30  # Test file doesn't exist
31  if os.path.exists(outfile):
32  if not (overwrite):
33  print("\033[031mWarning file exists.\033[039m")
34  opt = input("Overwrite? Y... for yes.")
35  else:
36  opt = "y"
37  if opt.lower().startswith("y"):
38  pass
39  else:
40  return
41 
42  # Open file
43  f = open(outfile, "w")
44  f.write("# This file is generated automatically. DO NOT EDIT!\n")
45  for i in dep.keys():
46  tmp, fil = os.path.split(i)
47  stri = "\n" + os.path.join(build, fil.split(".")[0] + ".o" + " : ")
48  for j in dep[i]:
49  tmp, fil = os.path.split(j)
50  stri = stri + " \\\n\t" + os.path.join(build, fil.split(".")[0] + ".o")
51  stri = stri + "\n"
52  f.write(stri)
53  f.close()
54  return
55 
56 
57 def get_source(ext=[".f90", ".F90"]):
58  "Return all files ending with any of ext"
59  tmp = os.listdir(".")
60  fil = []
61  for i in ext:
62  fil.extend(filter(lambda x: x.endswith(i), tmp))
63  return fil
64 
65 
66 def create_file_objs(files=None, macros={}):
67  fileList = []
68 
69  if files is None:
70  files = get_source()
71 
72  for i in files:
73  source_file = file_obj()
74 
75  source_file.file_name = i
76  source_file.uses = get_uses(i, macros)
77  source_file.contains = get_contains(i)
78 
79  fileList.append(source_file)
80 
81  return fileList
82 
83 
84 def get_uses(infile=None, macros={}):
85  "Return which modules are used in infile after expanding macros"
86  p = re.compile("^\s*use\s+(?P<moduse>\w*)\s*(,)?\s*(only)?\s*(:)?.*?$", re.IGNORECASE).match
87 
88  uses = []
89 
90  with open(infile, "r") as f:
91  t = f.readlines()
92 
93  for i in t:
94  tmp = p(i)
95  if tmp:
96  uses.append(tmp.group("moduse").strip())
97 
98  # Remove duplicates
99  uniq_mods = list(set(uses))
100 
101  for i, mod in enumerate(uniq_mods):
102  for k, v in macros.items():
103  if re.match(k, mod, re.IGNORECASE):
104  uniq_mods[i] = mod.replace(k, v)
105 
106  return uniq_mods
107 
108 
109 def get_contains(infile=None):
110  "Return all the modules that are in infile"
111  p = re.compile("^\s*module\s*(?P<modname>\w*)", re.IGNORECASE).match
112 
113  contains = []
114 
115  with open(infile, "r") as f:
116  t = f.readlines()
117 
118  for i in t:
119  tmp = p(i)
120  if tmp:
121  contains.append(tmp.group("modname").strip())
122 
123  # Remove duplicates before returning
124  return list(set(contains))
125 
126 
127 def file_objs_to_mod_dict(file_objs=[]):
128  "Turn a list of file_objs in a dictionary, containing which modules depend on which files"
129  dic = {}
130  for i in file_objs:
131  for j in i.contains:
132  dic[j.lower()] = i.file_name
133  return dic
134 
135 
136 def get_depends(fob=[], m2f=[]):
137  deps = {}
138  for i in fob:
139  tmp = []
140  for j in i.uses:
141  try:
142  if m2f[j.lower()] != i.file_name:
143  tmp.append(m2f[j.lower()])
144  except Exception:
145  if j in ["petsc", "mpi", "iso_fortran_env", "cgns"]:
146  # these dependence will be resolved through the included libraries
147  # there is no need to scare the user with the error message
148  continue
149  elif j[-2:] == "_b" or j[-2:] == "_d":
150  # these are AD routines
151  continue
152  else:
153  # actual missing dependencies
154  print(
155  "\033[031mError\033[039m module \033[032m"
156  + j
157  + "\033[039m not defined in any files. Skipping..."
158  )
159 
160  deps[i.file_name] = tmp
161 
162  return deps
163 
164 
165 class file_obj:
166  def __init__(self):
167  self.file_namefile_name = None
168  self.usesuses = None
169  self.containscontains = None
170  self.depends_ondepends_on = None
171 
172 
173 # Script
174 if __name__ == "__main__":
175  import argparse
176 
177  # Add command line arguments
178  parser = argparse.ArgumentParser(description="Generate Fortran dependencies")
179  parser.add_argument("-f", "--files", nargs="+", help="Files to process")
180  parser.add_argument(
181  "-D",
182  nargs="+",
183  action="append",
184  metavar="NAME=DESCRIPTION",
185  help="""The macro NAME is replaced by DEFINITION in 'use' statements""",
186  )
187  parser.add_argument("-b", "--build", nargs=1, help="Build Directory (prepended to all files in output", default="")
188  parser.add_argument("-o", "--output", nargs=1, help="Output file")
189  parser.add_argument("-v", "--verbose", action="store_true", help="explain what is done")
190  parser.add_argument("-w", "--overwrite", action="store_true", help="Overwrite output file without warning")
191 
192  # Parse the command line arguments
193  args = parser.parse_args()
194 
195  # Assemble a dictionary out of the macro definitions
196  macros = {}
197  if args.D:
198  for arg in args.D:
199  for var in arg:
200  temp = var.split("=")
201  macros[temp[0]] = temp[1]
202 
203  output = args.output[0] if args.output else None
204  build = args.build[0] if args.build else ""
205 
206  run(files=args.files, verbose=args.verbose, overwrite=args.overwrite, macros=macros, output=output, build=build)
real(kind=realtype), dimension(:, :, :), pointer p
def get_depends(fob=[], m2f=[])
Definition: fort_depend.py:136
def file_objs_to_mod_dict(file_objs=[])
Definition: fort_depend.py:127
def run(files=None, verbose=True, overwrite=None, output=None, macros={}, build="")
Definition: fort_depend.py:7
def get_contains(infile=None)
Definition: fort_depend.py:109
def create_file_objs(files=None, macros={})
Definition: fort_depend.py:66
def write_depend(outfile="makefile.dep", dep=[], overwrite=False, build="")
Definition: fort_depend.py:28
def get_source(ext=[".f90", ".F90"])
Definition: fort_depend.py:57
def get_uses(infile=None, macros={})
Definition: fort_depend.py:84