Skip to content

Commit a69a842

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 a69a842

File tree

1 file changed

+218
-0
lines changed

1 file changed

+218
-0
lines changed

contrib/libadd_mca_comp_update.py

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

0 commit comments

Comments
 (0)