【问题标题】:GCC looks for headers in /usr/local/include when compiling, but not for libraries in /usr/local/lib when linking. Why?GCC 在编译时会在 /usr/local/include 中查找头文件,但在链接时不会在 /usr/local/lib 中查找库。为什么?
【发布时间】:2011-06-15 01:41:13
【问题描述】:

我已经在 /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 标头,但链接器在 /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/ 中查找标题,但在链接时不查找库。为什么?

编辑 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

【问题讨论】:

    标签: c linux gcc linker header


    【解决方案1】:

    include文件搜索路径由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 文件恢复到其初始状态(即,如果之前不存在,则将其删除)。

    【讨论】:

    • 库路径肯定是由gccld命令行上指定的,而不仅仅是编码为ld(尽管它们也可能编码为ld)。只需使用strace 即可查看。
    【解决方案2】:

    这可能是使用黄金链接器的症状,它不会搜索/usr/local/lib,至少在某些版本中是这样。尝试删除包binutils-gold

    【讨论】:

    • -1 因为删除黄金,这是一个更好的链接器,不是最好的建议。
    • 那么有什么更好的建议呢?向所有命令行添加显式-L/usr/local/lib?对于小项目,goldld基本没有区别,除了这个问题。
    • -1 因为在搜索路径方面,gold 和 ld 没有区别。链接时库搜索路径来自 gcc。
    猜你喜欢
    • 1970-01-01
    • 2013-12-05
    • 2020-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-04
    • 2013-07-27
    相关资源
    最近更新 更多