[an error occurred while processing this directive]

How do I statically bind Fortran libraries and dynamically bind C libraries?

From: amaranth@vela.acs.oakland.edu (Paul Amaranth)

[ Editor's note: Part of this is also discussed above under the C compiler
section, but I felt it was so valuable that I have left it all in.
I've done some minor editing, mostly typographical. ]

The linker and binder are rather versatile programs, but it is not
always clear how to make them do what you want them to. In particular,
there are times when you do not want to use shared libraries, but
rather, staticly bind the required routines into your object. Or, you
may need to use two versions of the same routine (eg, Fortran & C). Here
are the results of my recent experiments. I would like to thank Daniel
Premer and Brad Hollowbush, my SE, for hints. Any mistakes or omissions
are my own and I have tended to interchange the terms "linker" and
"binder". These experiments were performed on AIX 3.1.2. Most of this
should be applicable to later upgrades of 3.1.

1) I have some C programs, I want to bind in the runtime routines. How
do I do this? [Mentioned in section 2.04 of this article as well, ed.]

You can put the -bnso binder command on the link line. You should
also include the -bI:/lib/syscalls.exp control argument:

$ cc *.o -bnso -bI:/lib/syscalls.exp -o foo

This will magically do everything you need. Note that this will bind
_all_ required routines in. The -bI argument tells the linker that
these entry points will be resolved dynamically at runtime (these are
system calls). If you omit this you will get lots of unresolved
reference messages.

2) I want to statically bind in the Fortran runtime so a) my customers
do not need to buy it and b) I don't have to worry about the runtime
changing on a new release. Can I use the two binder arguments in
1) to do this?

You should be able to do so, but, at least under 3002, if you do
you will get a linker error referencing getenv. In addition, there
are a number of potential conflicts between Fortran and C routines.
The easy way just does not work. See the section on
2 stage linking for C and Fortran on how to do this. The getenv
problem is a mess, see the section on Comments & Caveats for more.

From: Gary R. Hook

The xlf runtime is a no-charge feature, you can download and install
it without having to buy it. This change was made >2 years ago.

3) I have a mixture of C and Fortran routines, how can I make sure
that the C routines reference the C getenv, while the Fortran routines
reference the Fortran getenv (which has different parameters and, if
called mistakenly by a C routine results in a segmentation fault)?

From Mike Heath (mike@pencom.com):

Use -brename:symbol1,symbol2 when pre-linking the modules from one
of the languages. It does not matter which one you choose.

4) I have C and Fortran routines. I want to bind in the xlf library, while
letting the rest of the libraries be shared. How do I do this?

You need to do a 2 stage link. In the first stage, you bind in the
xlf library routines, creating an intermediate object file. The
second stage resolves the remaining references to the shared libraries.

This is a general technique that allows you to bind in specific system
routines, while still referencing the standard shared libraries.

Specifically, use this command to bind the xlf libraries to the Fortran

$ ld -bh:4 -T512 -H512 -o intermediat.o \
-bnso -bI:/lib/syscalls.exp -berok -lxlf -bexport:/usr/lib/libg.exp \
-lg -bexport:

The argument -bexport: specifies a file with the
name of all entry points that are to be visible outside the intermediate
module. Put one entrypoint name on a line. The -bI:/lib/libg.exp line
is required for proper functioning of the program. The -berok argument
tells the binder that it is ok to have unresolved references, at least
at this time (you would think -r would work here, but it doesn't seem to).
The -bnso argument causes the required modules to be imported
into the object. The -lxlf, of course, is the xlf library.

Then, bind the intermediate object with the other shared libraries in
the normal fashion:

$ ld -bh:4 -T512 -H512 intermediate.o \
/lib/crt0.o -lm -lc

Note the absence of -berok. After this link, all references should
be resolved (unless you're doing a multistage link and making another

NOTE THE ORDER OF MODULES. This is extremely important if, for example,
you had a subroutine named "load" in your Fortran stuff. Putting the
C libraries before the intermediate module would make the C "load"
the operable definition, rather than the Fortran version EVEN THOUGH
be extremely difficult to find (trust me on this one :-) Is this
a bug, a feature, or what?

[As mentioned in section 2.03 of this article, it is a feature that you
can replace individual objects in linked files, ed.]

The result will be a slightly larger object than normal. (I say slightly
because mine went up 5%, but then it's a 2 MB object :-)

Comments & Caveats:

From the documentation the -r argument to the linker should do what
-berok does. It does not. Very strange results come from using the
-r argument. I have not been able to make -r work in a sensible manner
(even for intermediate links which is what it is supposed to be for).

Note from Mike Heath (mike@pencom.com):

'ld -r' is essentially shorthand for 'ld -berok -bnogc -bnoglink'.
Certainly, using -berok with an export file (so garbage collection
can be done) is preferable to ld -r, but the latter is easier.

When binding an intermediate module, use an export file to define the
entry points you want visible in the later link. If you don't do this,
you'll get the dreaded "unresolved reference" error. Import files name
entry points that will be dynamically resolved (and possibly where).

If you are in doubt about what parameters or libraries to link, use the
-v arg when linking and modify the exec call that shows up into
an ld command. Some thought about the libraries will usually yield an
idea of when to use what. If you don't know what an argument is for,
leave it in. It's there for a purpose (even if you don't understand it).

Watch the order of external definitions (ie, libraries) when more than
one version of a routine may show up, eg "load". The first one defined
on the ld command line is the winner.

The getenv (and system and signal) problem is a problem that started out
minor, got somewhat worse in 3003 and, eventually will be correctly fixed.
Basically, you should extract the 3002 version of these three routines
from xlf.a before doing the update and save them away, then link these
routines in if you use these Fortran system services.

[an error occurred while processing this directive]