转自:http://blog.firetree.net/2005/07/21/static-linking-on-aix/
Static Linking on AIX
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 the C library, you must add the -bdynamic option to the end of any compilation sections 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 any fix 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.
michael said,
19 January, 2006 @ 23:29
did you ever get/find a copy of /lib/syscalls.exp ???????
alex said,
24 January, 2006 @ 23:19
michael: No, I’m afaid not. We looked through all of the system packages, but the file was nowhere to be found. Perhaps it’s only to be found on a more recent version of AIX. I’m still stuck on v5.1.
Frankly, I wasn’t that bothered about statically linking libc. The calls interface to libc is probably more stable than the OS-level interface, so why would you want to statically link it? My goal was binary portability, which is probably better served by dynamically linked libc.
I suppose there may be paranoid security reasons for wanting to statically link…
Jonas said,
26 January, 2006 @ 14:29
FYI: I just managed to link libc statically using the example above. The system is running AIX 4.3.3.
Sébastien said,
31 January, 2006 @ 15:51
On my system, it seems like the /lib/syscalls.exp file comes from the bos.adt.syscalls fileset :
Hope this’ll help
alex said,
21 February, 2006 @ 16:21
UPDATE!!
I’ve added some extra text about Oracle’s
libclntst.a
static library.Blaise said,
16 June, 2006 @ 10:53
I’ve the same problem. The hint to install bos.adt.syscalls helped!
Yogesh said,
30 June, 2007 @ 08:40
Thanks, Nice artical .. i am able to compile static binaries with this informetion.