From e7045bc1b3012ef4909167aeb808f04d97d0755d Mon Sep 17 00:00:00 2001 From: Dom Heinzeller Date: Fri, 8 Dec 2017 16:20:31 -0700 Subject: [PATCH] Add logic and hack script to correct object names in cap objects when using the PGI compiler (not fully ISO_C compliant) --- makefile | 25 +++++++++++++----- pgifix.py | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 6 deletions(-) create mode 100755 pgifix.py diff --git a/makefile b/makefile index 94ac349e9..6144ba48c 100644 --- a/makefile +++ b/makefile @@ -22,7 +22,7 @@ VER_PATCH = 0 FFLAGS += -I../fms -I../fms/include -fPIC -CPPDEFS = -DNEW_TAUCTMAX -DSMALL_PE -DNEMS_GSM +CPPDEFS += -DNEW_TAUCTMAX -DSMALL_PE -DNEMS_GSM SRCS_f = \ ./physics/cnvc90.f \ @@ -144,14 +144,15 @@ SRCS_F90 = \ ./GFS_layer/GFS_radiation_driver.F90 \ ./GFS_layer/GFS_restart.F90 \ ./GFS_layer/GFS_typedefs.F90 \ - ./IPD_layer/IPD_driver_cap.F90 \ ./IPD_layer/IPD_driver.F90 \ ./IPD_layer/IPD_typedefs.F90 - SRCS_c = -DEPEND_FILES = $(SRCS_f) $(SRCS_f90) $(SRCS_F) $(SRCS_F90) +CAPS_F90 = \ + ./IPD_layer/IPD_driver_cap.F90 + +DEPEND_FILES = $(SRCS_f) $(SRCS_f90) $(SRCS_F) $(SRCS_F90) $(CAPS_F90) OBJS_f = $(SRCS_f:.f=.o) OBJS_f90 = $(SRCS_f90:.f90=.o) @@ -161,10 +162,12 @@ OBJS_c = $(SRCS_c:.c=.o) OBJS = $(OBJS_f) $(OBJS_f90) $(OBJS_F) $(OBJS_F90) $(OBJS_c) +CAPS = $(CAPS_F90:.F90=.o) + all default: depend $(LIBRARY) -$(LIBRARY): $(OBJS) - $(FC) -shared -Wl,-soname,$(LIBRARY).$(VER_MAJOR) $(OBJS) $(LDFLAGS) $(NCEPLIBS) -o $(LIBRARY).$(VER_MAJOR).$(VER_MINOR).$(VER_PATCH) +$(LIBRARY): $(OBJS) $(CAPS) + $(FC) -shared -Wl,-soname,$(LIBRARY).$(VER_MAJOR) $(OBJS) $(CAPS) $(LDFLAGS) $(NCEPLIBS) -o $(LIBRARY).$(VER_MAJOR).$(VER_MINOR).$(VER_PATCH) ln -sf $(LIBRARY).$(VER_MAJOR).$(VER_MINOR).$(VER_PATCH) $(LIBRARY) ln -sf $(LIBRARY).$(VER_MAJOR).$(VER_MINOR).$(VER_PATCH) $(LIBRARY).$(VER_MAJOR) @@ -177,6 +180,16 @@ $(LIBRARY): $(OBJS) ./GFS_layer/GFS_diagnostics.o : ./GFS_layer/GFS_diagnostics.F90 $(FC) $(FFLAGS) $(OTHER_FFLAGS) -O0 -c $< -o $@ +ifneq (,$(findstring PGIFIX,$(CPPDEFS))) +$(CAPS): + $(FC) $(FFLAGS) $(OTHER_FFLAGS) -c $< -o $@ + # Apply a fix specific to the PGI compiler (rename objects in cap object files) + ./pgifix.py $@ +else +$(CAPS): + $(FC) $(FFLAGS) $(OTHER_FFLAGS) -c $< -o $@ +endif + .PHONY: clean clean: @echo "Cleaning gfsphysics ... " diff --git a/pgifix.py b/pgifix.py new file mode 100755 index 000000000..fd1ba45f6 --- /dev/null +++ b/pgifix.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python + +import argparse +import os +import subprocess +import sys + +parser = argparse.ArgumentParser(description='Fix cap objects produced by PGI compiler') +parser.add_argument("cap") + +def parse_args(): + args = parser.parse_args() + cap = args.cap + return cap + +def execute(cmd, debug = True, abort = True): + """Runs a local command in a shell. Waits for completion and + returns status, stdout and stderr. If abort = True, abort in + case an error occurs during the execution of the command.""" + + if debug: + print 'Executing "{0}"'.format(cmd) + p = subprocess.Popen(cmd, stdout = subprocess.PIPE, + stderr = subprocess.PIPE, shell = True) + (stdout, stderr) = p.communicate() + status = p.returncode + if debug: + message = 'Execution of "{0}" returned with exit code {1}\n'.format(cmd, status) + message += ' stdout: "{0}"\n'.format(stdout.rstrip('\n')) + message += ' stderr: "{0}"'.format(stderr.rstrip('\n')) + print message + if not status == 0: + message = 'Execution of command {0} failed, exit code {1}\n'.format(cmd, status) + message += ' stdout: "{0}"\n'.format(stdout.rstrip('\n')) + message += ' stderr: "{0}"'.format(stderr.rstrip('\n')) + if abort: + raise Exception(message) + else: + print message + return (status, stdout.rstrip('\n'), stderr.rstrip('\n')) + +def correct_cap_object_names(fixcmd, cap): + (cappath, capname) = os.path.split(cap) + pgiprefix = capname.rstrip('.o').lower() + '_' + # Get list of all symbols in cap object + nmcmd = 'nm {0}'.format(cap) + (status, stdout, stderr) = execute(nmcmd) + del nmcmd + # Parse all symbols and generate objcopy command + for line in stdout.split('\n'): + try: + (address, symboltype, objectname) = line.split() + except ValueError: + continue + if not symboltype == 'T': + continue + if objectname.startswith(pgiprefix): + newname = objectname[len(pgiprefix):] + if newname.endswith('_cap'): + fixcmd += '--redefine-sym {0}={1} '.format(objectname, newname) + return fixcmd + +def correct_object_names(fixcmd, cap): + tmp = cap + '.tmp' + fixcmd += '{0} {1}'.format(cap, tmp) + execute(fixcmd) + mvcmd = 'mv -v {0} {1}'.format(tmp, cap) + execute(mvcmd) + +def main(): + cap = parse_args() + fixcmd = 'objcopy ' + fixcmd = correct_cap_object_names(fixcmd, cap) + if not fixcmd == 'objcopy ': + correct_object_names(fixcmd, cap) + +if __name__ == '__main__': + main() \ No newline at end of file