Yet another gcc oddity

Article by khorben on 14/12/2006 17:16:44
Well, I have to admit that I could hardly work nowadays if I did not have tools such as gcc. But when it makes you lose a couple days for undocumented crap, it really makes you wonder how lucky you could be by accident when you first started using it.

Consider static linking for instance. It generally consists of few arguments:
gcc -o executable object1.o object2.o library1.a library2.a
As a matter of fact, while testing my libc with my programs, I found myself doing this:
cc -W -Wall -g -O2 -nostdinc -I /home/khorben/Projects/libc/include -c basename.c
cc -static -nostartfiles -nostdlib /home/khorben/Projects/libc/src/start.o /home/khorben/Projects/libc/src/libc.a -o basename basename.o
basename.o(.text+0xd): In function `_basename':
/home/khorben/Projects/utils/basename.c:18: undefined reference to `basename'
*** Error code 1

Now you're gonna say, I'm too much of a "static" fan, or my libc simply does not have basename(). Actually, although my libc does not do much yet, I know for fact that all of my symbols are there:

$ nm ~/Projects/utils/basename.o
00000000 t _basename
00000074 t _usage
U basename
U fwrite
00000098 T main
U puts
U stderr
U strcmp

$ nm ~/Projects/libc/src/libgen.o
00000000 T basename
0000009f T dirname
U strlen

$ nm ~/Projects/libc/src/libc.a | grep basename
00000000 T basename

So... What the fuck? At this stage I was puzzled, but I thought I remembered something about the order of arguments supplied to gcc. I mean, gcc is certainly not using getopt() (sadly), but if there actually is such a thing it should be in its manual. Here's what it says:

You can mix options and other arguments. For the most part, the order
you use doesn't matter. Order does matter when you use several options
of the same kind; for example, if you specify -L more than once, the
directories are searched in the order specified.

No luck here: I am not supplying any option besides "-o" that is not unique, or not already before anything else. So I kept googling a bit, and eventually ended up there:
I quote:
Be careful about the order of the parameters when using
gcc; the -l option is a linker option, and thus needs to be
placed AFTER the name of the file to be compiled. This is
quite different from the normal option syntax. If you place
the -l option before the filename, it may fail to link at all,
and you can end up with mysterious errors.

And, guess what? That was it:

cc -o basename basename.o -static -nostartfiles -nostdlib /home/khorben/Projects/libc/src/start.o /home/khorben/Projects/libc/src/libc.a
$ ./basename dir/file
Fine, I won't start my re-implementation of gcc (yet).