amaranth@vela.acs.oakland.edu (Paul Amaranth) (04/16/91)
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 version 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 3002. I would expect most of this to be applicable to 3003 as well. 1) I have some C programs, I want to bind in the runtime routines. How do I do this? 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 staticly 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. 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)? You can't. Only one symbol definition is allowed, and it will be the *first* definition on the >last< link. Here is the quote from the ld info file: In this version of ld, the first definition of each symbol in the link takes precedence and is used even if the first reference follows the definition. The only way I can possibly think of to do this is extremely messy: Make the C and Fortran routines separate modules. Staticly bind them with their libraries. Have them dynamicly call each other. ech. I haven't tried this, however. If you want to bind everything together, write yourself an interface in one language to use the other's routine. I did this with getenv and it works tolerably well. 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 objects: ld -bh:4 -T512 -H512 <your objects> -o intermediat.o \ -bnso -bI:/lib/syscalls.exp -berok -lxlf -bexport:/usr/lib/libg.exp \ -lg -bexport:<your export file> The argument -bexport:<your export file> 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 <C or other modules> 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 intermediate). 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 THE FORTRAN MODULE HAS ALREADY BEEN THROUGH A LINK AND ALL REFERENCES TO THE SYMBOL ARE CONTAINED IN THE FORTRAN MODULE. This can be extremely difficult to find (trust me on this one :-) Is this a bug, a feature, or what? The result will be a slightly larger object than normal. (I say slightly because mine went up 5%, but then its 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: this is one of the things I gave up on. I would like to hear from anyone with more info on this. 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. ----------------------------------------------------- Well, there you have it. If anyone has any other interesting tidbits concerning the linker, I would appreciate hearing them. In particular, if anyone has actually done something I said you can't do, PLEASE let me know. I have not exhaustively persued all avenues; when things were not productive, I tried something else. End of disclaimer, have fun! -- Paul Amaranth office: (313) 370 4541 (also voicemail) (internet) amaranth@vela.acs.oakland.edu | WANTED: Clever saying (bitnet) amaranth@oakland | to fill this space. (uucp) ...!uunet!umich!vela!amaranth | Puns need not apply.