I have two static libraries:

/usr/X11R6/lib/libX11.a - Standard library, ~ 1.5MB
./libxbgi.a - Created by me, ~60KB
Now I use the following commands to compile a program, test.c: $gcc -o test test.c -lm -L /usr/X11R6/lib -lX11 -L . -lxbgi This works fine, the executable test is 33KB, which is as expected.

If I change the order of linker inputs: $gcc -o test test.c -lm -L . -lxbgi -L /usr/X11R6/lib -lX11 the result is exactly the same as before.

Now I copied libX11.a to the current directory and tried to compile the same program: $gcc -o test test.c -lm -L . -lxbgi -lX11 It compiles, but the size of output file is an ugly 822KB.

If I change the order of linker inputs: $gcc -o test test.c -lm -L . -lX11 -lxbgi the compilation fails, I get linker errors for the functions defined in both the libraries.

Can anybody explain this behavior? Specifically, what is the difference between the first two and the last two sets of commands, when the library I'm referring to is the same?

Recommended Answers

All 6 Replies

Interesting..
1. I didn't know that -lXYZ could be interpreted by linker as libXYZ.a as well. (thought it's always seen as libXYZ.so). I checked gcc manuals (gcc 4.2.0) and seems fine.
2. Only reasons I can think of why this could be happening is:
A) There are object and library files with same name in the path.
B) May be the order has something to do with the way (and how many) symbols are resolved.

Finally it's tough to believe that this:
$gcc -o test test.c -lm -L . -lxbgi -lX11
works and this
$gcc -o test test.c -lm -L . -lX11 -lxbgi
doesn't !

Interesting..
1. I didn't know that -lXYZ could be interpreted by linker as libXYZ.a as well. (thought it's always seen as libXYZ.so).

I believe this may be the reason, though dont know exactly how.

2. Only reasons I can think of why this could be happening is:
A) There are object and library files with same name in the path.

No, there are no .o files in the path, if thats what you meant.

Finally it's tough to believe that this:
$gcc -o test test.c -lm -L . -lxbgi -lX11
works and this
$gcc -o test test.c -lm -L . -lX11 -lxbgi
doesn't !

Well, its true!

Well, its true!

Yeah, I believe you, it's just tough to believe. :D

Here is the excerpt from gcc guide if you can figure something more:
3.13 Options for Linking

These options come into play when the compiler links object files into an executable output file. They are meaningless if the compiler is not doing a link step. object-file-nameA file name that does not end in a special recognized suffix is considered to name an object file or library. (Object files are distinguished from libraries by the linker according to the file contents.) If linking is done, these object files are used as input to the linker.
-c-S-EIf any of these options is used, then the linker is not run, and object file names should not be used as arguments. See Overall Options.

-llibrary-l librarySearch the library named library when linking. (The second alternative with the library as a separate argument is only for POSIX compliance and is not recommended.) It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, `foo.o -lz bar.o' searches library `z' after file foo.o but before bar.o. If bar.o refers to functions in `z', those functions may not be loaded.
The linker searches a standard list of directories for the library, which is actually a file named liblibrary.a. The linker then uses this file as if it had been specified precisely by name.
The directories searched include several standard system directories plus any that you specify with -L.
Normally the files found this way are library files—archive files whose members are object files. The linker handles an archive file by scanning through it for members which define symbols that have so far been referenced but not defined. But if the file that is found is an ordinary object file, it is linked in the usual fashion. The only difference between using an -l option and specifying a file name is that -l surrounds library with `lib' and `.a' and searches several directories.

-lobjcYou need this special case of the -l option in order to link an Objective-C or Objective-C++ program.

@thekashyap
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, `foo.o -lz bar.o' searches library `z' after file foo.o but before bar.o. If bar.o refers to functions in `z', those functions may not be loaded.

This could be the reason for difference between commands 3 and 4...

I also thought on those lines, but in that case #1 should fail as well.. :)

Found the reason, finally...
@thekashyap
You were actually right!

1. I didn't know that -lXYZ could be interpreted by linker as libXYZ.a as well. (thought it's always seen as libXYZ.so). I checked gcc manuals (gcc 4.2.0) and seems fine.

I checked and it turns out there is a shared library /usr/X11R6/lib/libX11.so. So I figure -lX11 refers to libX11.so if it is present, otherwise it refers to libX11.a. That should explain the difference in file size in cases 1 and 3.

Then I copied libX11.so to the current directory, the last two commands work fine and produce exactly the same output as the first two! So I guess order of linker inputs depends only for static libraries.

The only problem is with the manual!:icon_cheesygrin:

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.