forked from ZedThree/fort_depend.py
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfort_depend.py
More file actions
executable file
·174 lines (135 loc) · 4.71 KB
/
fort_depend.py
File metadata and controls
executable file
·174 lines (135 loc) · 4.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#!/usr/bin/python
import os
import re
#Definitions
def run(files=None,verbose=True,overwrite=None,output=None,macros={}):
l=create_file_objs(files,macros)
mod2fil=file_objs_to_mod_dict(file_objs=l)
depends=get_depends(fob=l,m2f=mod2fil)
if verbose:
for i in depends.keys():
print "\033[032m"+i+"\033[039m depends on :\033[034m"
for j in depends[i]: print "\t"+j
print "\033[039m"
if output is None:
output = "makefile.dep"
tmp=write_depend(outfile=output,dep=depends,overwrite=overwrite)
return depends
def write_depend(outfile="makefile.dep",dep=[],overwrite=False):
"Write the dependencies to outfile"
#Test file doesn't exist
if os.path.exists(outfile):
if not(overwrite):
print "\033[031mWarning file exists.\033[039m"
opt=raw_input("Overwrite? Y... for yes.")
else:
opt="y"
if opt.lower().startswith("y"):
pass
else:
return
#Open file
f=open(outfile,'w')
for i in dep.keys():
tmp,fil=os.path.split(i)
stri="\n"+fil.split(".")[0]+".o"+" : "
for j in dep[i]:
tmp,fil=os.path.split(j)
stri=stri+" \\\n\t"+fil.split(".")[0]+".o"
stri=stri+"\n"
f.write(stri)
f.close()
return
def get_source(ext=[".f90",".F90"]):
"Return all files ending with any of ext"
tmp=os.listdir(".")
fil=[]
for i in ext:
fil.extend(filter(lambda x: x.endswith(i),tmp))
return fil
def create_file_objs(files=None, macros={}):
l=[]
if files is None:
files = get_source()
for i in files:
source_file = file_obj()
source_file.file_name = i
source_file.uses = get_uses(i,macros)
source_file.contains = get_contains(i)
l.append(source_file)
return l
def get_uses(infile=None, macros={}):
"Return which modules are used in infile after expanding macros"
p=re.compile("^\s*use\s*(?P<moduse>\w*)\s*(,)?\s*(only)?\s*(:)?.*?$",re.IGNORECASE).match
uses=[]
with open(infile,'r') as f:
t=f.readlines()
for i in t:
tmp=p(i)
if tmp:
uses.append(tmp.group('moduse').strip())
# Remove duplicates
uniq_mods = list(set(uses))
for i, mod in enumerate(uniq_mods):
for k, v in macros.items():
if re.match(k, mod, re.IGNORECASE):
uniq_mods[i] = mod.replace(k,v)
return uniq_mods
def get_contains(infile=None):
"Return all the modules that are in infile"
p=re.compile("^\s*module\s*(?P<modname>\w*?)\s*$",re.IGNORECASE).match
contains=[]
with open(infile,'r') as f:
t=f.readlines()
for i in t:
tmp=p(i)
if tmp:
contains.append(tmp.group('modname').strip())
# Remove duplicates before returning
return list(set(contains))
def file_objs_to_mod_dict(file_objs=[]):
"Turn a list of file_objs in a dictionary, containing which modules depend on which files"
dic={}
for i in file_objs:
for j in i.contains:
dic[j.lower()]=i.file_name
return dic
def get_depends(fob=[],m2f=[]):
deps={}
for i in fob:
tmp=[]
for j in i.uses:
try:
tmp.append(m2f[j.lower()])
except:
print "\033[031mError\033[039m module \033[032m"+j+"\033[039m not defined in any files. Skipping..."
deps[i.file_name]=tmp
return deps
class file_obj:
def __init__(self):
self.file_name=None
self.uses=None
self.contains=None
self.depends_on=None
#Script
if __name__ == "__main__":
import argparse
# Add command line arguments
parser = argparse.ArgumentParser(description='Generate Fortran dependencies')
parser.add_argument('-f','--files',nargs='+',help='Files to process')
parser.add_argument('-D',nargs='+',action='append',metavar='NAME=DESCRIPTION',
help="""The macro NAME is replaced by DEFINITION in 'use' statements""")
parser.add_argument('-o','--output',nargs=1,help='Output file')
parser.add_argument('-v','--verbose',action='store_true',help='explain what is done')
parser.add_argument('-w','--overwrite',action='store_true',help='Overwrite output file without warning')
# Parse the command line arguments
args = parser.parse_args()
# Assemble a dictionary out of the macro definitions
macros = {}
if args.D:
for arg in args.D:
for var in arg:
temp = var.split('=')
macros[temp[0]] = temp[1]
output = args.output[0] if args.output else None
run(files=args.files, verbose=args.verbose, overwrite=args.overwrite, macros=macros, output=output)