Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GCC looks for headers in /usr/local/include when compiling, but not for libraries in /usr/local/lib when linking. Why?

I have installed in /usr/ the distribution provided version of SQLite - version 3.4.2. I have installed in /usr/local/ SQLite version 3.7.4.

/usr/include/sqlite3.h defines SQLITE_VERSION_NUMBER as 3004002
/usr/local/include/sqlite3.h defines SQLITE_VERSION_NUMBER as 3007004

Version 3007004 has the function sqlite3_initialize(), version 3004002 does not.

$ nm -D /usr/local/lib/libsqlite3.so | grep sqlite3_initialize
00018e20 T sqlite3_initialize

When I compile the following example program:

#include <stdio.h>
#include <sqlite3.h>

// This should fail if including /usr/include/sqlite3.h
#if SQLITE_VERSION_NUMBER != 3007004
    #error "SQLite version is not 3.7.4"
#endif

int main() {
    printf( "%d\n", SQLITE_VERSION_NUMBER );
    sqlite3_initialize();
    return 0;
}

When compiled and linked (with gcc 4.2.4) like this the preprocessor finds the sqlite3.h header for version 3.7.4 in /usr/local/include/, but the linker fails as it's looking in /usr/lib/libsqlite3.so for the symbols.

$ gcc -Wall test.c -o cpp -lsqlite3
/tmp/cc4iSSN6.o: In function `main':
test.c:(.text+0x26): undefined reference to `sqlite3_initialize'
test.c:(.text+0x2b): undefined reference to `sqlite3_shutdown'
collect2: ld returned 1 exit status

Of course I can specify the lib directory and it links the correct version of the library.

$ gcc -Wall test.c -o cpp -L/usr/local/lib -lsqlite3
$ ./cpp
3007004
$

It seems by default gcc looks in /usr/local/include/ before /usr/include/ for headers, but not for libraries when linking. Why?

Edit 1: As suggested by Tim Post:

$ sudo ldconfig -n /usr/local/lib
$ ldconfig -p | grep sqlite3
    libsqlite3.so.0 (libc6) => /usr/local/lib/libsqlite3.so.0
    libsqlite3.so.0 (libc6) => /usr/lib/libsqlite3.so.0
    libsqlite3.so (libc6) => /usr/local/lib/libsqlite3.so
    libsqlite3.so (libc6) => /usr/lib/libsqlite3.so
$ gcc -Wall cpp.c -o cpp -lsqlite3
/tmp/ccwPT9o0.o: In function `main':
cpp.c:(.text+0x26): undefined reference to `sqlite3_initialize'
cpp.c:(.text+0x2b): undefined reference to `sqlite3_shutdown'
collect2: ld returned 1 exit status
like image 939
x-x Avatar asked Jan 25 '11 09:01

x-x


People also ask

Where does GCC look for header files?

GCC looks for headers requested with #include " file " first in the directory containing the current file, then in the directories as specified by -iquote options, then in the same places it would have looked for a header requested with angle brackets.

Which option in GCC is used to specify the location of the .h files?

gcc -I adds include directory of header files.

Does GCC include a linker?

c "). GCC uses a separate linker program (called ld.exe ) to perform the linking.


1 Answers

The include file search path is defined by gcc, but the library search path is encoded into ld, which is from a separate project; these are not necessarily synchronized.

One thing you could do is patch the specs file, which, if it exists, can be found in the same directory as libgcc; you can get the path to the latter using

gcc -print-libgcc-file-name

If there is no specs file there, create one using

gcc -dumpspecs >specs

and verify that gcc is reading it, by calling

gcc -v

Look for a line containing %{L*}, and add -L/usr/local/lib behind it (separated by spaces). Gcc will then pass this argument following any -L options from the command line to ld when linking.

In order to restore the defaults, just revert the specs file to its initial state (i.e. delete it if it didn't exist before).

like image 83
Simon Richter Avatar answered Sep 28 '22 03:09

Simon Richter