I've spent the last several hours trying to link a C++ program statically on our ageing AIX machine. As I've come to expect from IBM's compiler - nothing's ever that simple. What did I expect? They don't even provide a man page, and the linker always kicks out thousands of irrelevant warnings by design.
The system is running IBM VisualAge 5 on AIX 5.1. I said it was ageing.
Always finish with -bdynamic
Dynamic linking (-bdynamic) is the default for AIX's xlC compiler. The documentation says that the -bstatic option turns on static linking. OK, but try using this option and you get dozens of 'undefined symbol' errors for symbols that should be defined in libc:
ld: 0711-317 ERROR: Undefined symbol: errno ld: 0711-317 ERROR: Undefined symbol: _exit ld: 0711-317 ERROR: Undefined symbol: open
Apparently, you can't link libc statically. Here's the relevant quote, hidden away on page 102 of some blasted PDF:
To avoid possible problems with unresolved linker errors when linking theC library, you must add the -bdynamic option to the end of any compilationsections that use the -bstatic option.
Note: Actually the documentation says you can statically link ``libc``, but you might not want to. That said, I've not been able to make it work. See below for the secret.
ranlib libz.a
I had trouble with linking Zlib of all things. I got these six severe errors:
ld: 0711-212 SEVERE ERROR: Symbol .__divus, found in the global symbol table of archive /lib/libz.a, was not defined in archive member libz.so.1. ld: 0711-212 SEVERE ERROR: Symbol __divus, found in the global symbol table of archive /lib/libz.a, was not defined in archive member libz.so.1. ld: 0711-212 SEVERE ERROR: Symbol .__mulh, found in the global symbol table of archive /lib/libz.a, was not defined in archive member libz.so.1. ld: 0711-212 SEVERE ERROR: Symbol __mulh, found in the global symbol table of archive /lib/libz.a, was not defined in archive member libz.so.1. ld: 0711-212 SEVERE ERROR: Symbol .__quous, found in the global symbol table of archive /lib/libz.a, was not defined in archive member libz.so.1. ld: 0711-212 SEVERE ERROR: Symbol __quous, found in the global symbol table of archive /lib/libz.a, was not defined in archive member libz.so.1.
AIX's libz.a is at fault. Simply running ranlib on it fixes the problem. You have to make a copy first, since the current one may be in use and therefore locked:
# cd /lib # cp libz.a libz.a.new # ranlib libz.a.new # mv libz.a libz.a.old && mv libz.a.new libz.a
Oracle OCI Library
So how on earth do you link Oracle's OCI library statically on AIX? Here are the errors:
ld: 0711-317 ERROR: Undefined symbol: pw_wait ld: 0711-317 ERROR: Undefined symbol: pw_post ld: 0711-317 ERROR: Undefined symbol: pw_config ld: 0711-317 ERROR: Undefined symbol: aix_ora_pw_version3_required ld: 0711-317 ERROR: Undefined symbol: ksmsgl_ ld: 0711-317 ERROR: Undefined symbol: kcbkclx_
Naturally there's no documentation provided by Oracle, but digging around in the OCI examples reveals the following two options:
-bI:$(ORACLE_HOME)/lib/pw-syscall.exp -bI:$(ORACLE_HOME)/lib/ksms.imp
The -bI option isn't even mentioned in IBM's 'documentation' for xlC. However, I think it just points to a file that lists symbols to import. I don't have the inclination to explore that further right now.
UPDATE!!
I've belatedly discovered that Oracle provide a (little known) static library: libclntst9.a. (For Oracle 10, the library would be libclntst10.a and so on.) Naturally you'd imagine that you can simply add that to your link line as -lclntst. Well, nearly. You need to include a few other libraries too. On Linux the link line is:
-lclntst9 -lnsl -ldl -lm
For Solaris, you need a few more libraries:
-lclntst9 -lnsl -lsocket -lgen -ldl -laio -lkstat -lm
Thanks to Josh Chu on the Oracle Forums.
static libc
A bit of exploration in the man page for ld reveals the following:
To link a program using the libc.a library as a non-shared library, enter:
cc -o pgm pgm.o -bnso -bI:/lib/syscalls.exp
However this comes with the following warning:
Any application that is statically linked is NOT binary portable from anyfix or release level to any other fix or release level.
nso stands for no shared objects, so this sounds promising. However, the file /lib/syscalls.exp is not to be found on my system, so I suppose I'll never know whether this works or not.