I'm creating an add-on for a large piece of software written in Fortran. In my directory I reference subroutines in other directories, which in turn reference more subroutines.
I'm running into trouble because on occasion the developers of the main software change some sub calls.
Location: Saint Paul, MN USA / BSD, CentOS, Debian, OS X, Solaris
Posts: 2,288
Thanks Given: 430
Thanked 480 Times in 395 Posts
Hi.
You didn't mention which standard your Fortran is written to, so you may need to change some parts of the procedure below.
1) One result of a compile is an object file. You can extract linkage symbols from such files with a utility nm, the most often-occurring are entry points, externals, and common block names.
2) You can use a source scanning utility ftnchek.
3) You can generate a link map with ld (it contains the most information, but ironically has always seemed to be the least useful for me).
Here's a sample of these driven by a demonstration script:
Code:
#!/usr/bin/env bash
# @(#) s1 Demonstrate extraction of external names.
# Uncomment to run script as external user.
# export PATH="/usr/local/bin:/usr/bin:/bin"
# Infrastructure details, environment, commands for forum posts.
set +o nounset
pe() { for i;do printf "%s" "$i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }
LC_ALL=C ; LANG=C ; export LC_ALL LANG
pe ; pe "Environment: LC_ALL = $LC_ALL, LANG = $LANG"
pe "(Versions displayed with local utility \"version\")"
c=$( ps | grep $$ | awk '{print $NF}' )
version >/dev/null 2>&1 && s=$(_eat $0 $1) || s=""
[ "$c" = "$s" ] && p="$s" || p="$c"
version >/dev/null 2>&1 && version "=o" $p specimen gfortran ar nm grep ftnchek ld
set -o nounset
# Sample data files, using head & tail as a last resort.
pe
specimen 7 *.f \
|| { pe "(head/tail)"; head -n 5 data*; pe " ||"; tail -n 5 data*; }
# Remove debris from previous runs.
rm -f *.o a.out *.a
pl " Results of compile, scan for externals::"
gfortran -c *.f
# Build the library.
ar sq libs.a libs.o
# Extract and display the symbols.
pl " Sample of nm output:"
# nm -fbsd main.o subs.o libs.a
# nm -fbsd -u main.o subs.o libs.a # Unsatisfied only
# nm -fsysv main.o subs.o libs.a
nm -fposix main.o subs.o libs.a |
tee t1 |
specimen 4
# Massage nm output to obtain entry points, "T", externals, "U".
awk '$2 == "T" { print $1 }' t1 > ent
awk '$2 == "U" { print $1 }' t1 > ext
pl " Non-system externals found:"
grep -v '^_' ext
pl " Unsatisfied externals in this application:"
# Remove matching entry-externals, remove system routines.
grep -v -f ent ext |
grep -v '^_'
pl " Results from ftnchek:"
ftnchek *.f
pl " Create link map from linker (ld):"
gfortran -Wl,--print-map -Wl,--noinhibit-exec -o a.out main.o subs.o libs.a > map.txt
specimen 3 map.txt
pl " Results of execution:"
gfortran -Wl,--noinhibit-exec -o a.out main.o subs.o libs.a
./a.out
exit 0
producing:
Code:
% ./s1
Environment: LC_ALL = C, LANG = C
(Versions displayed with local utility "version")
OS, ker|rel, machine: Linux, 2.6.26-2-amd64, x86_64
Distribution : Debian GNU/Linux 5.0
GNU bash 3.2.39
specimen (local) 1.17
gfortran GNU Fortran (Debian 4.3.2-1.1) 4.3.2
GNU ar (GNU Binutils for Debian) 2.18.0.20080103
GNU nm (GNU Binutils for Debian) 2.18.0.20080103
GNU grep 2.5.3
FTNCHEK Version 3.3 November 2004 Patch Level 1
GNU ld (GNU Binutils for Debian) 2.18.0.20080103
Whole: 7:0:7 of 11 lines in file "libs.f"
subroutine b
call b1
return
end
subroutine b1
call b2
return
end
subroutine b2
return
end
Whole: 7:0:7 of 13 lines in file "main.f"
program m
call a
call b
end
subroutine a
x = 4.0
xo = a1(x)
y = 9.0
yo = a2(y)
z = xo + yo
write(*,*) " z is", z
return
end
Whole: 7:0:7 of 12 lines in file "subs.f"
function a1(x)
a1 = sqrt(x)
return
end
function a2(y)
if ( y .lt. 4.0 ) then
a2 = cubert(y)
else
a2 = sqrt(y)
endif
return
end
-----
Results of compile, scan for externals::
ar: creating libs.a
-----
Sample of nm output:
Edges: 4:0:4 of 20 lines in file "-"
main.o:
MAIN__ T 0000000000000000 0000000000000029
_gfortran_set_options U
_gfortran_st_write U
---
libs.a[libs.o]:
b1_ T 0000000000000010 0000000000000010
b2_ T 0000000000000020 0000000000000006
b_ T 0000000000000000 0000000000000010
-----
Non-system externals found:
a1_
a2_
b_
cubert_
-----
Unsatisfied externals in this application:
cubert_
-----
Results from ftnchek:
FTNCHEK Version 3.3 November 2004
File libs.f:
0 syntax errors detected in file libs.f
File main.f:
0 syntax errors detected in file main.f
File subs.f:
0 syntax errors detected in file subs.f
Warning: Subprogram CUBERT never defined
Invoked in module A2 line 7 file subs.f
(possibly it is an array which was not declared)
-----
Create link map from linker (ld):
subs.o: In function `a2_':
subs.f:(.text+0x57): undefined reference to `cubert_'
Edges: 3:0:3 of 487 lines in file "map.txt"
Archive member included because of file (symbol)
libs.a(libs.o) main.o (b_)
---
*(.note.GNU-stack)
*(.gnu_debuglink)
OUTPUT(a.out elf64-x86-64)
-----
Results of execution:
subs.o: In function `a2_':
subs.f:(.text+0x57): undefined reference to `cubert_'
z is 5.0000000
One advantage to the nm scheme is that it is general, it works with any compiler that produces object files -- c, c++, fortran, etc.
Experimentation and man pages are usually one's best ways to learn.
Gurus,
I came across a typical requirement where the input is like-
TRANS FIRM
DEPT CUST
TRANS CUST
TRANS DEPT
FIRM CUST
& the expected Output is-
CUST
DEPT
FIRM
TRANS
This is basically a dependency list for processing the tables where
FIRM is feeding data to TRANS... (3 Replies)
hello,
can anyone help in changing the executable dependency on a certain shared library. eg, .. say i am having an executable by name utest. when i run UNIX ldd command on it then it shows the libraries on which it depends as follows:
ldd release/utest
release/utest needs:
... (4 Replies)
I'm building on a HP-UX ia64 system. During building, I'm getting an error
ld: Can't find dependent library "libnnz10.so"
Nowhere in my makefile do I link with this library. This library is there in the directory /databases/oracle10.2.0_64BIT/lib. I'm having two source files ora8ibulk.cpp... (1 Reply)
Hi,
I had a make file, something like that,
all:
cd dir1; make
cd dir2; make
the problem is the makefile under dir2 need some objs from dir1, so I need to set some dependency let dir2 run only after the dir1 run is done.
how to set the dependency?
Thanks.
peter (2 Replies)
Hi,
I want to install net-snmp-devel package but i have following dependecy problem.
It's very odd, i don't get it. One of packages is depended on the other one, the other one is depended on the previous one as well. :S :S
Could you help me please?
Here are the steps:
# ls -l
total... (4 Replies)
Hi all
am new to solaris ............
i installed amanda client pkg that time am getting lots of dependency problem..........
is there any Yum server like things in solaris
Regards '
prAn (8 Replies)
Hey guys,
I installed Fedora7 from DVD yesterday. I have previously worked with RHEL4 and Fedora4(As of RPM based systems).
I used to copy all the rpms from the media to a directory.
#mkdir /rpms
#copy /path_to_rpms_in_media/* /rpms/
My intention for doing this was to get around the... (0 Replies)