c - GCC 在编译时在/usr/local/include 中查找头文件,但在链接时不在/usr/local/lib 中查找库。为什么?

标签 c linux gcc linker header

我已经在/usr/中安装了发行版提供的 SQLite 版本 - 版本 3.4.2。 我已经安装在/usr/local/SQLite 版本 3.7.4。

/usr/include/sqlite3.h 将 SQLITE_VERSION_NUMBER 定义为 3004002
/usr/local/include/sqlite3.h 将 SQLITE_VERSION_NUMBER 定义为 3007004

版本 3007004 有函数 sqlite3_initialize(),版本 3004002 没有。

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

当我编译下面的示例程序时:

#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;
}

当像这样编译和链接(使用 gcc 4.2.4)时,预处理器在/usr/local/include/中找到版本 3.7.4 的 sqlite3.h header ,但是链接器在查找/usr/lib 时失败/libsqlite3.so 用于符号。

$ 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

当然我可以指定 lib 目录,它会链接正确版本的库。

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

在链接时,gcc 似乎默认在/usr/include/之前在/usr/local/include/中查找 header ,但不查找库。为什么?

编辑 1:根据 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

最佳答案

包含文件搜索路径由gcc定义,但库搜索路径编码为ld,它来自一个单独的项目;这些不一定是同步的。

你可以做的一件事是修补 specs 文件,如果它存在,可以在与 libgcc 相同的目录中找到;您可以使用

获取后者的路径
gcc -print-libgcc-file-name

如果那里没有specs 文件,请使用

创建一个
gcc -dumpspecs >specs

并通过调用验证 gcc 正在读取它

gcc -v

寻找包含%{L*}的行,并在其后面添加-L/usr/local/lib(以空格分隔)。 Gcc 然后会在链接时将命令行中任何 -L 选项后面的这个参数传递给 ld

为了恢复默认值,只需将 specs 文件恢复到其初始状态(即,如果它之前不存在,则将其删除)。

关于c - GCC 在编译时在/usr/local/include 中查找头文件,但在链接时不在/usr/local/lib 中查找库。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4791699/

相关文章:

c - 何时一起编译文件以及何时使用库

linux - 如何对一系列输入运行 grep 命令?

gcc - MinGW 4.8.1 C++11 线程支持

c - 如何从预处理器启用内在函数

c++ - SDL 中的每像素 2D 圆形碰撞检测

c - 使用递归函数添加数字

将华氏度转换并舍入为摄氏度

linux - linux 下使用 Eclipse 和 CMake 的 boost::thread 的链接器问题

c - 结构体 C 中的 sizeof 数组

c - i2c_master_recv 的值从何而来?