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

发布于 2024-10-13 22:21:36 字数 1933 浏览 1 评论 0原文

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

编辑1:根据蒂姆·波斯特的建议:

$ 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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一生独一 2024-10-20 22:21:36

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

您可以做的一件事是修补 specs 文件,如果存在,可以在与 libgcc 相同的目录中找到该文件; 来获取后者的路径

gcc -print-libgcc-file-name

您可以使用“如果那里没有 specs 文件,请使用以下命令创建一个文件”

gcc -dumpspecs >specs

来验证 gcc 是否正在读取该文件

gcc -v

,并通过调用“查找包含 %{L*} 的行”,并在其后面添加-L/usr/local/lib(以空格分隔)。然后,在链接时,Gcc 将在命令行中的任何 -L 选项之后将此参数传递给 ld

为了恢复默认设置,只需将规范文件恢复到其初始状态(即,如果以前不存在则将其删除)。

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).

毁梦 2024-10-20 22:21:36

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

This may be symptom of using the gold linker, which does not search /usr/local/lib, at least in some versions. Try removing the package binutils-gold.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文