1
1
openmpi/contrib/libadd_mca_comp_update.py
Joshua Hursey 7a3f1ff75e 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 <jhursey@us.ibm.com>
2017-08-24 11:56:16 -04:00

231 строка
7.6 KiB
Python
Исполняемый файл

#!/usr/bin/env python
# Copyright (c) 2017 IBM Corporation. All rights reserved.
# $COPYRIGHT$
#
import glob, os, re, shutil
projects= {'opal' : ["$(top_builddir)/opal/lib@OPAL_LIB_PREFIX@open-pal.la"],
'orte' : ["$(top_builddir)/orte/lib@ORTE_LIB_PREFIX@open-rte.la"],
'ompi' : ["$(top_builddir)/ompi/lib@OMPI_LIBMPI_NAME@.la"],
'oshmem' : ["$(top_builddir)/oshmem/liboshmem.la"],
}
no_anchor_file = []
missing_files = []
skipped_files = []
partly_files = []
updated_files = []
#
# Check of all of the libadd fields are accounted for in the LIBADD
# Return a list indicating which are missing (positional)
#
def check_libadd(content, libadd_field, project):
global projects
libadd_list = projects[project]
libadd_missing = [True] * len(libadd_list)
on_libadd = False
for line in content:
# First libadd line
if re.search( r"^\s*"+libadd_field, line):
# If line continuation, then keep searching after this point
if line[-2] == '\\':
on_libadd = True
for idx, lib in enumerate(libadd_list):
if True == libadd_missing[idx]:
if 0 <= line.find(lib):
libadd_missing[idx] = False
# Line continuation
elif True == on_libadd:
for idx, lib in enumerate(libadd_list):
if True == libadd_missing[idx]:
if 0 <= line.find(lib):
libadd_missing[idx] = False
# No more line continuations, so stop processing
if line[-2] != '\\':
on_libadd = False
break
return libadd_missing
#
# Update all of the Makefile.am's with the proper LIBADD additions
#
def update_makefile_ams():
global projects
global no_anchor_file
global missing_files
global skipped_files
global partly_files
global updated_files
for project, libadd_list in projects.items():
libadd_str = " \\\n\t".join(libadd_list)
print("="*40)
print("Project: "+project)
print("LIBADD:\n"+libadd_str)
print("="*40)
#
# Walk the directory structure
#
for root, dirs, files in os.walk(project+"/mca"):
parts = root.split("/")
if len(parts) != 4:
continue
if parts[-1] == ".libs" or parts[-1] == ".deps" or parts[-1] == "base":
continue
if parts[2] == "common":
continue
print("Processing: "+root)
#
# Find Makefile.am
#
make_filename = os.path.join(root, "Makefile.am")
if False == os.path.isfile( make_filename ):
missing_files.append("Missing: "+make_filename)
print(" ---> Error: "+make_filename+" is not present in this directory")
continue
#
# Stearching for: mca_FRAMEWORK_COMPONENT_la_{LIBADD|LDFLAGS}
# First scan file to see if it has an LIBADD / LDFLAGS
#
libadd_field = "mca_"+parts[2]+"_"+parts[3]+"_la_LIBADD"
ldflags_field = "mca_"+parts[2]+"_"+parts[3]+"_la_LDFLAGS"
has_ldflags = False
has_libadd = False
r_fd = open(make_filename, 'r')
orig_content = r_fd.readlines()
r_fd.close()
libadd_missing = []
for line in orig_content:
if re.search( r"^\s*"+ldflags_field, line):
has_ldflags = True
elif re.search( r"^\s*"+libadd_field, line):
has_libadd = True
if True == has_libadd:
libadd_missing = check_libadd(orig_content, libadd_field, project)
#
# Sanity Check: Was there an anchor field.
# If not skip, we might need to manually update or it might be a
# static component.
#
if False == has_ldflags and False == has_libadd:
no_anchor_file.append("No anchor ("+ldflags_field+"): "+make_filename)
print(" ---> Error: Makefile.am does not contain necessary anchor")
continue
#
# Sanity Check: This file does not need to be updated.
#
if True == has_libadd and all(False == v for v in libadd_missing):
skipped_files.append("Skip: "+make_filename)
print(" Skip: Already updated Makefile.am")
continue
#
# Now go though and create a new version of the Makefile.am
#
r_fd = open(make_filename, 'r')
w_fd = open(make_filename+".mod", 'w')
num_libadds=0
for line in r_fd:
# LDFLAGS anchor
if re.search( r"^\s*"+ldflags_field, line):
w_fd.write(line)
# If there is no LIBADD, then put it after the LDFLAGS
if False == has_libadd:
w_fd.write(libadd_field+" = "+libadd_str+"\n")
# Existing LIBADD field to extend
elif 0 == num_libadds and re.search( r"^\s*"+libadd_field, line):
parts = line.partition("=")
num_libadds += 1
if parts[0][-1] == '+':
w_fd.write(libadd_field+" += ")
else:
w_fd.write(libadd_field+" = ")
# If all libs are missing, then add the full string
# Otherwise only add the missing items
if all(True == v for v in libadd_missing):
w_fd.write(libadd_str)
# Only add a continuation if there is something to continue
if 0 != len(parts[2].strip()):
w_fd.write(" \\")
w_fd.write("\n")
else:
partly_files.append("Partly updated: "+make_filename)
for idx, lib in enumerate(libadd_list):
if True == libadd_missing[idx]:
w_fd.write(lib+" \\\n")
# Original content (unless it's just a line continuation)
if 0 != len(parts[2].strip()) and parts[2].strip() != "\\":
w_fd.write("\t"+parts[2].lstrip())
# Non matching line, just echo
else:
w_fd.write(line)
r_fd.close()
w_fd.close()
#
# Replace the original with the updated version
#
shutil.move(make_filename+".mod", make_filename)
updated_files.append(make_filename)
if __name__ == "__main__":
update_makefile_ams()
print("")
print("="*40);
print("{:>3} : Files skipped".format(len(skipped_files)))
print("="*40);
print("="*40);
print("{:>3} : Files updated, but had some libs already in place.".format(len(partly_files)))
print("="*40);
for fn in partly_files:
print(fn)
print("="*40);
print("{:>3} : Files fully updated".format(len(updated_files)))
print("="*40);
for fn in updated_files:
print(fn)
print("="*40);
print("{:>3} : Missing Makefile.am".format(len(missing_files)))
print("="*40);
for err in missing_files:
print(err)
print("="*40);
print("{:>3} : Missing Anchor for parsing (might be static-only components)".format(len(no_anchor_file)))
print("="*40);
for err in no_anchor_file:
print(err)