Skip to content

Commit 308e115

Browse files
committed
contrib: Script to automate LIBADD changes for components
* This script will search for all of the `Makefile.am` files in each of the project-level components. Then it adds the project-level library to `mca_FRAMEWORK_COMPONENT_la_LIBADD`. - If the library is already in the LIBADD list then it's skipped. So it is safe to run multiple times on the same codebase. Signed-off-by: Joshua Hursey <[email protected]>
1 parent b991135 commit 308e115

File tree

1 file changed

+232
-0
lines changed

1 file changed

+232
-0
lines changed

contrib/libadd_mca_comp_update.py

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
#!/usr/bin/env python
2+
3+
# Copyright (c) 2017 IBM Corporation. All rights reserved.
4+
# $COPYRIGHT$
5+
#
6+
7+
import glob, os, re, shutil
8+
9+
projects= {'opal' : ["$(top_builddir)/opal/lib@[email protected]"],
10+
'orte' : ["$(top_builddir)/orte/lib@[email protected]"],
11+
'ompi' : ["$(top_builddir)/ompi/lib@[email protected]"],
12+
'oshmem' : ["$(top_builddir)/oshmem/liboshmem.la"],
13+
}
14+
# projects= {'ompi' : ["$(top_builddir)/ompi/lib@[email protected]"],
15+
# }
16+
17+
no_anchor_file = []
18+
missing_files = []
19+
skipped_files = []
20+
partly_files = []
21+
updated_files = []
22+
23+
#
24+
# Check of all of the libadd fields are accounted for in the LIBADD
25+
# Return a list indicating which are missing (positional)
26+
#
27+
def check_libadd(content, libadd_field, project):
28+
global projects
29+
30+
libadd_list = projects[project]
31+
libadd_missing = [True] * len(libadd_list)
32+
33+
on_libadd = False
34+
for line in content:
35+
# First libadd line
36+
if re.search( r"^\s*"+libadd_field, line):
37+
# If line continuation, then keep searching after this point
38+
if line[-2] == '\\':
39+
on_libadd = True
40+
41+
for idx, lib in enumerate(libadd_list):
42+
if True == libadd_missing[idx]:
43+
if 0 <= line.find(lib):
44+
libadd_missing[idx] = False
45+
46+
# Line continuation
47+
elif True == on_libadd:
48+
for idx, lib in enumerate(libadd_list):
49+
if True == libadd_missing[idx]:
50+
if 0 <= line.find(lib):
51+
libadd_missing[idx] = False
52+
53+
# No more line continuations, so stop processing
54+
if line[-2] != '\\':
55+
on_libadd = False
56+
break
57+
58+
return libadd_missing
59+
60+
#
61+
# Update all of the Makefile.am's with the proper LIBADD additions
62+
#
63+
def update_makefile_ams():
64+
global projects
65+
global no_anchor_file
66+
global missing_files
67+
global skipped_files
68+
global partly_files
69+
global updated_files
70+
71+
for project, libadd_list in projects.items():
72+
libadd_str = " \\\n\t".join(libadd_list)
73+
74+
print("="*40)
75+
print("Project: "+project)
76+
print("LIBADD:\n"+libadd_str)
77+
print("="*40)
78+
79+
#
80+
# Walk the directory structure
81+
#
82+
for root, dirs, files in os.walk(project+"/mca"):
83+
parts = root.split("/")
84+
if len(parts) != 4:
85+
continue
86+
if parts[-1] == ".libs" or parts[-1] == ".deps" or parts[-1] == "base":
87+
continue
88+
if parts[2] == "common":
89+
continue
90+
91+
print("Processing: "+root)
92+
93+
#
94+
# Find Makefile.am
95+
#
96+
make_filename = os.path.join(root, "Makefile.am")
97+
if False == os.path.isfile( make_filename ):
98+
missing_files.append("Missing: "+make_filename)
99+
print(" ---> Error: "+make_filename+" is not present in this directory")
100+
continue
101+
102+
#
103+
# Stearching for: mca_FRAMEWORK_COMPONENT_la_{LIBADD|LDFLAGS}
104+
# First scan file to see if it has an LIBADD / LDFLAGS
105+
#
106+
libadd_field = "mca_"+parts[2]+"_"+parts[3]+"_la_LIBADD"
107+
ldflags_field = "mca_"+parts[2]+"_"+parts[3]+"_la_LDFLAGS"
108+
has_ldflags = False
109+
has_libadd = False
110+
111+
r_fd = open(make_filename, 'r')
112+
orig_content = r_fd.readlines()
113+
r_fd.close()
114+
libadd_missing = []
115+
116+
for line in orig_content:
117+
if re.search( r"^\s*"+ldflags_field, line):
118+
has_ldflags = True
119+
elif re.search( r"^\s*"+libadd_field, line):
120+
has_libadd = True
121+
122+
if True == has_libadd:
123+
libadd_missing = check_libadd(orig_content, libadd_field, project)
124+
125+
#
126+
# Sanity Check: Was there an anchor field.
127+
# If not skip, we might need to manually update or it might be a
128+
# static component.
129+
#
130+
if False == has_ldflags and False == has_libadd:
131+
no_anchor_file.append("No anchor ("+ldflags_field+"): "+make_filename)
132+
print(" ---> Error: Makefile.am does not contain necessary anchor")
133+
continue
134+
135+
#
136+
# Sanity Check: This file does not need to be updated.
137+
#
138+
if True == has_libadd and all(False == v for v in libadd_missing):
139+
skipped_files.append("Skip: "+make_filename)
140+
print(" Skip: Already updated Makefile.am")
141+
continue
142+
143+
#
144+
# Now go though and create a new version of the Makefile.am
145+
#
146+
r_fd = open(make_filename, 'r')
147+
w_fd = open(make_filename+".mod", 'w')
148+
149+
num_libadds=0
150+
for line in r_fd:
151+
# LDFLAGS anchor
152+
if re.search( r"^\s*"+ldflags_field, line):
153+
w_fd.write(line)
154+
# If there is no LIBADD, then put it after the LDFLAGS
155+
if False == has_libadd:
156+
w_fd.write(libadd_field+" = "+libadd_str+"\n")
157+
# Existing LIBADD field to extend
158+
elif 0 == num_libadds and re.search( r"^\s*"+libadd_field, line):
159+
parts = line.partition("=")
160+
num_libadds += 1
161+
162+
if parts[0][-1] == '+':
163+
w_fd.write(libadd_field+" += ")
164+
else:
165+
w_fd.write(libadd_field+" = ")
166+
167+
# If all libs are missing, then add the full string
168+
# Otherwise only add the missing items
169+
if all(True == v for v in libadd_missing):
170+
w_fd.write(libadd_str)
171+
# Only add a continuation if there is something to continue
172+
if 0 != len(parts[2].strip()):
173+
w_fd.write(" \\")
174+
w_fd.write("\n")
175+
else:
176+
partly_files.append("Partly updated: "+make_filename)
177+
for idx, lib in enumerate(libadd_list):
178+
if True == libadd_missing[idx]:
179+
w_fd.write(lib+" \\\n")
180+
181+
# Original content (unless it's just a line continuation)
182+
if 0 != len(parts[2].strip()) and parts[2].strip() != "\\":
183+
w_fd.write("\t"+parts[2].lstrip())
184+
185+
# Non matching line, just echo
186+
else:
187+
w_fd.write(line)
188+
189+
r_fd.close()
190+
w_fd.close()
191+
192+
#
193+
# Replace the original with the updated version
194+
#
195+
shutil.move(make_filename+".mod", make_filename)
196+
updated_files.append(make_filename)
197+
198+
199+
if __name__ == "__main__":
200+
201+
update_makefile_ams()
202+
203+
print("")
204+
205+
print("="*40);
206+
print("{:>3} : Files skipped".format(len(skipped_files)))
207+
print("="*40);
208+
209+
print("="*40);
210+
print("{:>3} : Files updated, but had some libs already in place.".format(str(len(partly_files))))
211+
print("="*40);
212+
for fn in partly_files:
213+
print(fn)
214+
215+
print("="*40);
216+
print("{:>3} : Files fully updated".format(str(len(updated_files))))
217+
print("="*40);
218+
for fn in updated_files:
219+
print(fn)
220+
221+
print("="*40);
222+
print("{:>3} : Missing Makefile.am".format(str(len(missing_files))))
223+
print("="*40);
224+
for err in missing_files:
225+
print(err)
226+
227+
print("="*40);
228+
print("{:>3} : Missing Anchor for parsing (might be static-only components)".format(str(len(no_anchor_file))))
229+
print("="*40);
230+
for err in no_anchor_file:
231+
print(err)
232+

0 commit comments

Comments
 (0)