forked from SpakowitzLab/wlcsim
-
Notifications
You must be signed in to change notification settings - Fork 1
/
fort_depend.py
executable file
·188 lines (148 loc) · 5.68 KB
/
fort_depend.py
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
175
176
177
178
179
180
181
182
183
184
185
186
187
#!/usr/bin/env python
import os
import re
#Definitions
def run(files=None,verbose=True,overwrite=None,output=None,macros={},build='',compile_string=''):
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,build=build,compile_string=compile_string)
return depends
def write_depend(outfile="makefile.dep",dep=[],overwrite=False,build='',compile_string=''):
"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')
f.write('# This file is generated automatically. DO NOT EDIT!\n')
for i in dep.keys():
fil,_=os.path.splitext(i)
# make each object file depend on it's source file
stri="\n"+os.path.join(build, fil+".o"+" : src/defines.inc src/third_party/mersenne_twister.o "+i)
for j in dep[i]:
fdep,_=os.path.splitext(j)
stri=stri+" \\\n\t"+os.path.join(build, fdep+".o")
stri=stri+"\n"
if compile_string:
stri=stri+"\t"+compile_string+" "+i
stri=stri+" -o "+os.path.join(build, fil+".o")
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
intrinsic = re.compile("^\s*use\s*(,)?\s*(only)?\s*,\s*intrinsic.*$",re.IGNORECASE).match
uses=[]
with open(infile,'r') as f:
t=f.readlines()
for i in t:
tmp=p(i)
if tmp and not intrinsic(i):
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*)",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[031mWarning:\033[039m module \033[032m"+j+"\033[039m used in "+i.file_name+" 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('-b','--build',nargs=1,help='Build Directory (prepended to all files in output',
default='')
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')
parser.add_argument('-c','--compile-string',nargs=1,help='String to compile with')
# 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
build = args.build[0] if args.build else ''
compile_string = args.compile_string[0] if args.compile_string else ''
run(files=args.files, verbose=args.verbose, overwrite=args.overwrite,
macros=macros, output=output, build=build,
compile_string=compile_string)