I'd like to think that linkers did what you said, Leor, but I am still
under the impression that when a linker searches a library (such as
lib1.lib) it looks at the header and finds the name of a function it
is trying to resolve and then includes the entire library. Can it, in
fact, only pull out the function and place it in the exe? I don't
remember us doing that in the OS/360 linker, and the fact that
compiling the functions separately results in smaller exe would seem
to confirm that the entire module is included otherwise.
Of course, this could (and probably is) different with each linker,
making the whole conversation a troll.
Can one of the current developers here confirm that some linker
somewhere does in fact selectively pull function code from libraries
when linking?
I'll try some tests with g++ and report back.
Yeah, I wasn't sure exactly how to go about testing this. I'm pretty sure
that at some point in the past I've verified this behavior, but I haven't
really delved into it in ages.
I figured I'd have a better chance at getting accurate size measurements
under Unix, but unfortunately I have no C/C++ development tools in my
Cygwin installation.
So I resorted to good ole' MSVC to see what I could come up with. The
executable size doesn't mean squat with MSVC, because it always seem to
round up for some reason, but I figured there ought to be an option to
print out a symbol table I could search for the usual suspects. I created
the following program, which I compiled once with the log10 call in there
and once without:
//
// does using one fn out of a lib drag in all the others?
//
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
double d = sqrt(5.0);
cout << "chi = (" << d << " + 1 ) / 2" << endl;
// Compared with and without the following line:
// d = log10(d);
cout << "log10(d) = " << d << endl;
return 0;
}
In the resulting map file for compiling as shown, there was exactly one
occurrence of the pattern "log10" in the generated map file (MSVC 7.1, /Fm
option), shown with surrounding context (3 lines total, I've wrapped them
manually and put a space between):
0002:00002278 ??_C@_04COOMCNPB@sinh?$AA@
00414278 LIBC:fpexcept.obj
0002:00002280 ??_C@_05HGHHAHAP@log10?$AA@
00414280 LIBC:fpexcept.obj
0002:00002288 ??_C@_03MGHMBJCF@log?$AA@
00414288 LIBC:fpexcept.obj
This looks to be some sort of master symbol dispatch table, but I'd guess
it does not represent address of actual code. But I don't know for sure.
In the /other/ map file (with the log10 call uncommented), I still get the
same entries as above (different addresses), PLUS:
0001:00005610 _log10 00406610 f LIBC:log10.obj
0001:00005650 __CIlog10 00406650 f LIBC:log10.obj
0001:0000568b __CIlog10_default 0040668b f LIBC:log10.obj
0001:0000569f __log10_default 0040669f LIBC:log10.obj
0001:00008a50 __CIlog10_pentium4 00409a50 f
LIBC:log10_pentium4.obj
0001:00008a68 __log10_pentium4 00409a68
LIBC:log10_pentium4.obj
0001:0000564f _$$$00002 0040664f f LIBC:log10.obj
So my guess would be that all those additional lines represent stuff that
got dragged into the executable for version #2 that was not in version #1.
Or I may be totally in dreamland. I don't know.
-leor