Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LD_LIBRARY_PATH does not work

Tags:

c

gcc

zlib

linker

I'm trying to compile a demo which uses zlib, and I think I've done correct set up for LD_LIBRARY_PATH but it does not work with -lz flag, would you please help me find what's the problem?

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$

The problem is that if I use -L to force searching the folder, it works, if I put that folder in LD_LIBRARY_PATH, it doesn't work. I'm pretty sure I've used export LD_LIBRARY_PATH but it still doesn't work.

This is annoying because if I need to compile someone else's code that needs it, it's easier to set up a environment variable to search for the libraries.

--------------Update------------

On another server I tried this and it works smoothly

[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]$ 

So my configuration may be correct? Any ideas? I've tried it on my laptops with Ubuntu 16.04 and Fedora 25, updated to stable on Feb. 16, 2017. The server I can only tell it's not newly updated. I'm wondering whether there's problem with the newest gcc?

--------------Update------------

I may know what causes the problem. The error message is cannot find -lz. It seems to treat -lz as a single file. I find there's both -l and -z flag in the usage of ld while it may convert -lz to something like that and find we don't have a parameter for both of the flags and then combine them together as a single file parameter? Not fully sure about my inference but does anyone have any idea of how to handle this case?

--------------Update------------

Full Makefile

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

clean:
        rm -f *.o

--------------Update------------

The 3rd section may not be a valid explanation because after appending -v to cc, I've found -lz is successfully passed to the linker

like image 865
Sanhu Li Avatar asked Dec 14 '22 00:12

Sanhu Li


2 Answers

Update on 09/05/2020

Finally clear about the problem, and thus update this answer for anyone who cares.

When you are compiling your code, you told it to search for a shared library using flags like -lfoo, the compiler will add -L flag for each folder presented in LIBRARY_PATH, and the linker ld will search each -L folder besides the default locations. If the linker could not find the file libfoo.so or libfoo.a, it will fail.

The way to solve this problem is to add -L to the compiling line with the folder of your library, but this usually means you will need to change your Makefile and it's not the best practice I think.

Another way is to put your library folder(s) to LIBRARY_PATH, because gcc and most compilers will automatically add -L flags to those folders before passing to the linker, and no matter whether you are compiling with static or dynamic libraries, the compiler will only check LIBRARY_PATH. So LD_LIBRARY_PATH is useless during compiling.

LD_LIBRARY_PATH will be check by the system when you actually run your program. This is a good way to allow multiple versions of the same library existing on your system. For example, some old code may need CUDA 9, and some new code might need CUDA 11, and LD_LIBRARY_PATH is useful in such cases.

===

Finally find a solution to it. Just don't use LD_LIBRARY_PATH and use LIBRARY_PATH instead. It works fine and smoothly. Get the idea from GNU ld cannot find library which is there Still not clear what's the reason but at least it works fine now.

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$ 
like image 96
Sanhu Li Avatar answered Dec 31 '22 00:12

Sanhu Li


LD_LIBRARY_PATH is for finding shared libraries at runtime. In your case, you want to provide a path at compile time... this isn't an environment variable by default (unless your makefile looks at your environment explicitly). You need to pass it on the command line to the compiler, eg:

gcc -g -O2 kseq_test.c -o kseq_test -L /home/lisanhu/mine/repos/zlib/output/lib -lz
like image 40
kcraigie Avatar answered Dec 31 '22 00:12

kcraigie