I got an answer to my query about linking [1]:
From: Mark Grosberg <XXXXXXXXXXXXXXXXX>
To: sean@conman.org
Subject: Unix linkers.
Date: Fri, 16 Feb 2007 14:18:53 -0500 (EST)
> SPC posts:
> > So let me get this straight: I link against the library, and the program doesn't work. I link against the object files, and it works just fine.
>
> Okay.
>
> Anybody care to explain?
>
I have had stuff like this happen to me periodically. It is basically a weakness in the design of UNIX linkers. Sadly, a modern UNIX machine with gigs of RAM and high speed multiple CPU (Central Processing Unit)'s is still linking like it's a PDP-11 [2].
One possability is that there is a netsnmp.a somewhere in the system library path [there is, which explains why my recompiled version with debugging information didn't work—heck, that explains quite a bit of the wierdness even though the version that was installed and the version I installed were the same —Editor] and it doesn't match the headers you are compiling against. But you probably did install the libraries yourself—beware! Sometimes on Linux they have shared libraries that the linker will try to link against first! I think -V or -vv will print out the commands GCC is actually doing. Or just try adding -L/home/spc/apps/net-snmp-5.1.2/snmplib [I did—it didn't work. I think I'll have to uninstall the system supplied SNMP libraries —Editor]
And I would not use the “~” there since GCC won't expand it and your shell probably wouldn't either. But that's just the most obvious. I've had far more “interesting” problems with UNIX linkers.
At least, my most common problem has been that when you have lots of circular references I always end up naming library files 20 times on the command line. A modern linker will continue to resolve from libraries until all dependencies are satisfied.
Normally failing to list say syscore.a 10 times on the command line simply results in an error. However, this stupidity can work both ways—sometimes you end up pulling in the wrong object module in that pile of libraries because UNIX just goes through the libraries one at a time rather than resolving symbols from their nearest source (like the library that just generated the external!).
There are other bad things that can happen to you too; weak symbols [3] are normally “NULL” (usually all 0's) unless they happen to be satisfied explicitly (by say, naming a .o)—the linker won't go looking for them. Combine that with defensive software that does something dumb (meaning: not crash) on an unexpected NULL pointer and you can get strange behavior like that.
And lets not forget some systems that try to make everything a shared library call even if you specify a .a (Oh, I see this awesome .so here for you—haha). UNIX shared libraries just suck. Avoid them unless you enjoy say bleeding out of your ass—in which case go for it!
What I've found (and I'm not even linking for UNIX, I just happen to be linking on UNIX) is that I make a linker definition file—which yeah, it's totally GNU specific—that can then tell the linker what to do (the GROUP() [4] directive will often resolve libraries the way they are supposed to be resolved).
But I've learned almost never to use .a files under UNIX. I just build up a list of 1,000 or so .o files for my latest creation and let the linker chug through them.
Welcome to the future!
-MYG
[links added by me —Editor]
A lot of information there that I wasn't even aware of, like weak symbols, linking scripts and the GROUP() directive. I can see I have quite a bit of reading to do.
[2] http://www.psych.usyd.edu.au/pdp-11/
[3] http://en.wikipedia.org/wiki/Weak_symbol
[4] http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/gnu-linker/simple-commands.html