LD_LIBRARY_PATH 不起作用

San*_* Li 4 c linker gcc zlib

我正在尝试编译一个使用 zlib 的演示,我认为我已经正确设置了 LD_LIBRARY_PATH,但它不适用于 -lz 标志,您能帮我找出问题所在吗?

lisanhu@lisanhu-XPS-15-9550:kseq$ echo $LD_LIBRARY_PATH 
/home/lisanhu/mine/repos/zlib/output/lib
lisanhu@lisanhu-XPS-15-9550:kseq$ make
gcc -g -O2 kseq_test.c -o kseq_test -lz
/usr/bin/ld: cannot find -lz
collect2: error: ld returned 1 exit status
Makefile:3: recipe for target 'all' failed
make: *** [all] Error 1
lisanhu@lisanhu-XPS-15-9550:kseq$ gcc -static -o kseq_test kseq_test.o -lz -L/home/lisanhu/mine/repos/zlib/output/lib
lisanhu@lisanhu-XPS-15-9550:kseq$
Run Code Online (Sandbox Code Playgroud)

问题是,如果我使用-L强制搜索文件夹,它可以工作,如果我将该文件夹放在 LD_LIBRARY_PATH 中,它就不起作用。我很确定我已经使用过export LD_LIBRARY_PATH,但仍然不起作用。

这很烦人,因为如果我需要编译其他需要它的代码,那么设置环境变量来搜索库会更容易。

- - - - - - - 更新 - - - - - -

在另一台服务器上我尝试了这个并且运行顺利

[lisanhu@farber tmp]$ export LD_LIBRARY_PATH=/home/1677/mine/repos/zlib/zlib-1.2.8
[lisanhu@farber tmp]$ ls
gmon.out  kseq.h  kseq.tar  kseq_test  kseq_test.c  Makefile
[lisanhu@farber tmp]$ make
cc -g -O2 kseq_test.c -o kseq_test -lz
[lisanhu@farber tmp]$ ldd kseq_test
    linux-vdso.so.1 =>  (0x00007fffb01a6000)
    libz.so.1 => /home/1677/mine/repos/zlib/zlib-1.2.8/libz.so.1 (0x00007f9556c83000)
    libc.so.6 => /lib64/libc.so.6 (0x00000031fa400000)
    /lib64/ld-linux-x86-64.so.2 (0x00000031fa000000)
[lisanhu@farber tmp]$ 
Run Code Online (Sandbox Code Playgroud)

那么我的配置可能是正确的?有任何想法吗?我已经在装有 Ubuntu 16.04 和 Fedora 25 的笔记本电脑上尝试过,并于 2017 年 2 月 16 日更新至稳定版本。我只能说服务器不是最近更新的。我想知道最新的gcc是否有问题?

- - - - - - - 更新 - - - - - -

我可能知道是什么原因导致了这个问题。错误消息是cannot find -lz。它似乎被视为-lz单个文件。我发现在使用中同时存在-l和标志,而它可能会转换为类似的东西,并发现我们没有这两个标志的参数,然后将它们组合在一起作为单个文件参数?不完全确定我的推论,但有人知道如何处理这种情况吗?-zld-lz

- - - - - - - 更新 - - - - - -

完整的Makefile

all:kseq.h kseq_test.c
        $(CC) -g -O2 kseq_test.c -o kseq_test -lz

clean:
        rm -f *.o
Run Code Online (Sandbox Code Playgroud)

- - - - - - - 更新 - - - - - -

第三部分可能不是有效的解释,因为在将 -v 附加到 cc 之后,我发现 -lz 已成功传递给链接器

San*_* Li 7

更新于 09/05/2020

终于弄清楚了问题,从而为关心的人更新此答案。

当您编译代码时,您告诉它使用诸如 之类的标志搜索共享库-lfoo,编译器将为-L中显示的每个文件夹添加标志LIBRARY_PATH,并且链接器ld将搜索-L除默认位置之外的每个文件夹。如果链接器找不到该文件libfoo.solibfoo.a,它将失败。

解决这个问题的方法是在-L编译行中添加库的文件夹,但这通常意味着您需要更改 Makefile,我认为这不是最佳实践。

另一种方法是将您的库文件夹放入LIBRARY_PATH,因为gcc大多数编译器会-L在传递给链接器之前自动向这些文件夹添加标志,并且无论您是使用静态库还是动态库进行编译,编译器都只会检查LIBRARY_PATH. 所以LD_LIBRARY_PATH在编译过程中是没有用的。

LD_LIBRARY_PATH当你实际运行你的程序时,系统会检查。这是允许系统上存在同一库的多个版本的好方法。例如,一些旧代码可能需要 CUDA 9,而一些新代码可能需要 CUDA 11,LD_LIBRARY_PATH在这种情况下很有用。

===

最后找到解决办法。只是不要使用 LD_LIBRARY_PATH 并使用 LIBRARY_PATH 代替。它运行良好且顺利。从 GNU ld 得到的想法是找不到那里的库 仍然不清楚原因是什么,但至少现在工作正常。

lisanhu@lisanhu-XPS-15-9550:kseq$ export LD_LIBRARY_PATH=~/mine/repos/zlib/output/lib;
lisanhu@lisanhu-XPS-15-9550:kseq$ make
cc -g -O2 kseq_test.c -o kseq_test -lz
/usr/bin/ld: cannot find -lz
clang-3.9: error: linker command failed with exit code 1 (use -v to see invocation)
Makefile:2: recipe for target 'all' failed
make: *** [all] Error 1
lisanhu@lisanhu-XPS-15-9550:kseq$ ls
kseq.h  kseq_test.c  kseq_test.o  Makefile  test.seq
lisanhu@lisanhu-XPS-15-9550:kseq$ export LIBRARY_PATH=~/mine/repos/zlib/output/lib;
lisanhu@lisanhu-XPS-15-9550:kseq$ make
cc -g -O2 kseq_test.c -o kseq_test -lz
lisanhu@lisanhu-XPS-15-9550:kseq$ ls
kseq.h  kseq_test  kseq_test.c  kseq_test.o  Makefile  test.seq
lisanhu@lisanhu-XPS-15-9550:kseq$ ldd kseq_test
    linux-vdso.so.1 =>  (0x00007fffcd135000)
    /lib/$LIB/liblsp.so => /lib/lib/x86_64-linux-gnu/liblsp.so (0x00007f5fe93cb000)
    libz.so.1 => /home/lisanhu/mine/repos/zlib/output/lib/libz.so.1 (0x00007f5fe91b1000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5fe8dca000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f5fe8bc6000)
    /lib64/ld-linux-x86-64.so.2 (0x000056051fc0c000)
lisanhu@lisanhu-XPS-15-9550:kseq$ 
Run Code Online (Sandbox Code Playgroud)


kcr*_*gie 6

LD_LIBRARY_PATH 用于在运行时查找共享库。在你的情况下,你想在编译时提供一个路径......默认情况下这不是一个环境变量(除非你的 makefile 明确地查看你的环境)。您需要将其在命令行上传递给编译器,例如:

gcc -g -O2 kseq_test.c -o kseq_test -L /home/lisanhu/mine/repos/zlib/output/lib -lz
Run Code Online (Sandbox Code Playgroud)