Why, when I include certain libraries, do I also have to specify the name of the library when I compile the program with gcc?
For example, today I started teaching myself how to use ncurses, so naturally I had:
But when I compile, I have to add -lcurses to my command line. Why? It’s always been my understanding that when the code goes through the preprocessor, the #include line is essentially replaced with everything from curses.h. So what the dilly?
Libraries and header files are two different things. You’re right about the way the preprocessor handles header files in #include statements. Those header files often contain function declarations which specify the name of some external function, its return type, and the parameters it takes, but nothing more.
The -l switch to GCC specifies an object library to be linked to your final program. These libraries have to contain the executable code definitions for all of the library functions your program calls. Object library files end in .o by default (or .so for shared object libraries).
As a general rule, anything outside the C standard library requires linking against some library.
The exceptions I can think of are that the standard math functions (e.g. cos(3), exp(3), etc.) require a -lm, and system calls, which aren’t part of the stdlib, do not require extra linkage.
If you have ever written a program with more than one .c file, this will be clearer.
You might have:
foo.c - source code for ‘foo’ module
foo.h - declarations of functions in foo
main.c - your program - uses foo.
You want to include foo.h in main.c in order to compile. Note some compilers will not force you to include this - if you invoke a function that has not been declared, the compiler will simply assume that function will exist somewhere in the final executable.
Once you compile, you’ll have main.o and foo.o ‘object files’. main.o attempts to invoke functions in foo.o, so somehow main.o must be linked to foo.o. The linker can stick these object files together in an executable so that main can run properly.
Linking to a library is no different than linking to an object - in fact, static libraries are just a collection of objects and (depending on system) be easily broken down into component .o files.
So, the .h file merely lets you compile, or perhaps just lets you compile in a safer way. The library lets you actually execute code.
Thanks, people. That makes more sense now.
If you look in a system header file, you’ll basically see a lot of extern declarations… your curses.h might contain: extern int addnstr(const char *, int);
This just tells the compiler that the function addnstr takes a pointer to const char and an int, returns an int, and is defined in another file. You can get by without this declaration; the compiler will assume it returns int and you’ll probably get a warning.
If the declaration didn’t use extern, the compiler would give you an error because it expects the function to be defined in the same file (this is good when you misspell a function name). But with extern, the compiler can put markers in the object file that say “put the address of addnstr here at link time”.
When you use the command-line switch -lcurses, it means “search the library path for a file called libcurses.a, and link that into the project”, since libcurses.a contains the actual code for the functions.
Heh, that’ll teach me to spend so much time writing.