GCC 编译时在 /usr/local/include 中查找标头,但在链接时不在 /usr/local/lib 中查找库。为什么?
我已经在 /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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
包含文件搜索路径由gcc定义,但库搜索路径被编码为ld,它来自一个单独的项目;这些不一定是同步的。
您可以做的一件事是修补 specs 文件,如果存在,可以在与 libgcc 相同的目录中找到该文件; 来获取后者的路径
您可以使用“如果那里没有 specs 文件,请使用以下命令创建一个文件”
来验证 gcc 是否正在读取该文件
,并通过调用“查找包含
%{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
If there is no specs file there, create one using
and verify that gcc is reading it, by calling
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).
这可能是使用 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 packagebinutils-gold
.