【转载】usr/bin/ld: cannot find -l<nameOfTheLibrary>
2018-01-02 18:51
609 查看
此文章转自
stackoverflow 中关于问题
原地址:https://stackoverflow.com/questions/30600978/cpp-usr-bin-ld-cannot-find-lnameofthelibrary
编译过程讲的很详细,写的太好了,醍醐灌顶!
Briefly:
not know about where your project libs are located. You have to place it into ld's known directories or specify the full path of your library by
to the linker.
To be able to build your program you need to have your library in
paths and your colleague too. Why? See detailed answer.
Detailed:
At first we should understand what tools do what:
The compiler produces simple
The linker combines a number of
Let's start with some example. For example, you have a project which consists of 3 files:
main.c
func.h
func.c
So, when you compile your source code (
into an object file (
it can't be run yet because it has unresolved symbols. Let's start from the beginning of
The preprocessor after it's job produces the following
and the following
As you may see in
there are no connections to your
and to the
all it's symbols resolved because it has only one function which body is written right inside the
not have
resolved yet because it does not know where it is implemented.
Let's look what is inside
Simply, it contains a symbol which is in text code section so this is our
And let's look what is inside
Our
an implemented and resolved static function
we are able to see it in the object file. But we also see
which marked as unresolved
and thus we are unable to see it's address offset.
For fixing that problem, we have to use the linker. It will take all the object files and resolve all these symbols (
file to the linker. So, let's give all the object files we have to the linker:
The linker will go through
then through
try to resolve symbols and if it goes okay - put it's output to the
If we look the produced output we will see all symbols are resolved:
Here our job is done. Let's look the situation with dynamic(shared) libraries. Let's make a shared library from our
file:
Voila, we have it. Now, let's put it into known dynamic linker library path,
And let's make our project depend on that shared library by leaving
unresolved after compilation and static linkage process, creating an executable and linking it (dynamically) to our shared library (
Now if we look for the symbol in it's symbols table we still have our symbol unresolved:
But this is not a problem anymore because
will be resolved by dynamic loader before each program start. Okay, now let's back to the theory.
Libraries, in fact, are just an object files which are placed into a single archive by using
with a single symbols table which is created by
Compiler, when compiling object files, does not resolve
These symbols will be replaced to addresses by linker. So resolving symbols can be done by two things:
The linker:
does 2 jobs:
a) For static libs or simple object files, this linker changes external symbols in the object files to the addresses of the real entities. For example, if we use C++ name mangling linker will change
b) For dynamic libs it only checks if the symbols can
be resolved (you try to link with correct library) at all but does not replace the symbols by address. If symbols can't be resolved (for example they are not implemented in the shared library you are linking to) - it throws
which is:
i.
- request for an
dynamic loader to be called before executing, so this section just contains a path to the dynamic loader. If you look at your executable which depends on shared library (
for example you will see the interp section
ii.
- a list of shared libraries which
be looking for before executing. You may see them by
Note that
finds all the libraries in your filesystem while readelf only shows what libraries does your program need. So, all of these libraries will be searched by dynamic loader (next paragraph). The linker works at build
time.
Dynamic loader:
It finds and loads all the shared libraries needed by a program (if they were not loaded before), resolves the symbols by replacing them to real addresses right before start of the program, prepares the program to run, and then runs it. It works after
build and before running the program. Less speaking, dynamic linking means resolving symbols in your executable before each program start.
Actually, when you run an
with
(it needs to load some shared libraries) the OS (Linux) runs an interpreter at first but not your program. Otherwise you have an undefined behavior - you have symbols in your program but they are not defined by addresses which usually means that the program
will be unable to work properly.
You may also run dynamic loader by yourself but it is unnecessary (binary is
32-bit architecture elf and
64-bit architecture elf).
Why does the linker claim that
and to put it's name into the
for dynamic loader. Actually, the
exists in almost every c/c++ elf because the
are both shared, and compiler by default links any project dynamically to them. You may link them statically as well but this will enlarge the total executable size. So, if the shared library can't be found your symbols will remain unresolved and you will
be UNABLE to run your application, thus it can't produce an executable. You may get the list
of directories where libraries are usually searched by:
Passing a command to the linker in compiler arguments.
By parsing
By parsing
output.
Some of these methods are explained here.
Dynamic loader tries to find all the libraries by using:
section of ELF file.
of the executable.
variable.
own cache file which contains a compiled list of candidate libraries previously found in the augmented library path.
Default paths: In the default path /lib, and then /usr/lib. If the binary was linked with
ld-linux
search algorithm
Also, note please, that if we are talking about shared libraries, they are not named
in
instead. When you build your application the linker will look for
(which is usually a symlink to
but when you run your application the dynamic loader looks for
instead. For example, let's say we have a library
version is
to semver.
In the filesystem it will look like:
So, to be able to compile you must have all of versioned files (
and a
but for running your app you must have only 3 versioned library files listed first. This also explains why do debian or rpm packages have
separately: normal one (which consists only of the files needed by already compiled applications for running them) which has 3 versioned library files and a devel package which has only symlink file for making it possible to compile the project.
Resume
After all of that:
You, your colleague and EACH user of your application code must have all the libraries in their
system linker paths to be able to compile (build your application). Otherwise, they have to change Makefile (or compile command) to add the shared library location directory by adding
argument.
After successful build you also need your library again to be able to run the program. Your library will be searched by dynamic loader (
so it needs to be in it's paths (see above) or in system linker paths. In most of linux program
distributions, for example, games from steam, there is a shell-script which sets the
which points to all shared libraries needed by the game.
stackoverflow 中关于问题
cpp:
usr/bin/ld: cannot find -l<nameOfTheLibrary>
原地址:https://stackoverflow.com/questions/30600978/cpp-usr-bin-ld-cannot-find-lnameofthelibrary编译过程讲的很详细,写的太好了,醍醐灌顶!
Briefly:
lddoes
not know about where your project libs are located. You have to place it into ld's known directories or specify the full path of your library by
-Lparameter
to the linker.
To be able to build your program you need to have your library in
/bin/ldsearch
paths and your colleague too. Why? See detailed answer.
Detailed:
At first we should understand what tools do what:
The compiler produces simple
object fileswith unresolved symbols (it does not care about symbols so much at it's running time).
The linker combines a number of
objectand
archive files, relocates their data and ties up symbol references into a single file: an executable or a library.
Let's start with some example. For example, you have a project which consists of 3 files:
main.c,
func.hand
func.c.
main.c
#include "func.h" int main() { func(); return 0; }
func.h
void func();
func.c
#include "func.h" void func() { }
So, when you compile your source code (
main.c)
into an object file (
main.o)
it can't be run yet because it has unresolved symbols. Let's start from the beginning of
producing an executableworkflow (without details):
The preprocessor after it's job produces the following
main.c.preprocessed:
void func(); int main() { func(); return 0; }
and the following
func.c.preprocessed:
void func(); void func() { }
As you may see in
main.c.preprocessed,
there are no connections to your
func.cfile
and to the
void func()'s implementation, compiler simply does not know about it, it compiles all the source files separately. So, to be able to compile this project you have to compile both source files by using something like like
cc -c main.c -o main.oand
cc -c func.c -o func.o, this will produce 2 object files,
main.oand
func.o.
func.ohas
all it's symbols resolved because it has only one function which body is written right inside the
func.cbut
main.odoes
not have
funcsymbol
resolved yet because it does not know where it is implemented.
Let's look what is inside
func.o:
$ nm func.o 0000000000000000 T func
Simply, it contains a symbol which is in text code section so this is our
funcfunction.
And let's look what is inside
main.o:
$ nm main.o U func 0000000000000000 T main
Our
main.ohas
an implemented and resolved static function
mainand
we are able to see it in the object file. But we also see
funcsymbol
which marked as unresolved
U,
and thus we are unable to see it's address offset.
For fixing that problem, we have to use the linker. It will take all the object files and resolve all these symbols (
void func();in our example). If the linker somehow is unable to do that it throws a error like
unresolved external symbol:
void func(). This may happen if you don't give the
func.oobject
file to the linker. So, let's give all the object files we have to the linker:
ld main.o func.o -o test
The linker will go through
main.o,
then through
func.o,
try to resolve symbols and if it goes okay - put it's output to the
testfile.
If we look the produced output we will see all symbols are resolved:
$ nm test 0000000000601000 R __bss_start 0000000000601000 R _edata 0000000000601000 R _end 00000000004000b0 T func 00000000004000b7 T main
Here our job is done. Let's look the situation with dynamic(shared) libraries. Let's make a shared library from our
func.csource
file:
gcc -c func.c -o func.o gcc -shared -fPIC -Wl,-soname,libfunc.so.1 -o libfunc.so.1.5.0 func.o
Voila, we have it. Now, let's put it into known dynamic linker library path,
/usr/lib/:
sudo mv libfunc.so.1.5.0 /usr/lib/ # to make program be able to run sudo ln -s libfunc.so.1.5.0 /usr/lib/libfunc.so.1 #creating symlink for the program to run sudo ln -s libfunc.so.1 /usr/lib/libfunc.so # to make compilation possible
And let's make our project depend on that shared library by leaving
func()symbol
unresolved after compilation and static linkage process, creating an executable and linking it (dynamically) to our shared library (
libfunc):
cc main.c -lfunc
Now if we look for the symbol in it's symbols table we still have our symbol unresolved:
$ nm a.out | grep fun U func
But this is not a problem anymore because
funcsymbol
will be resolved by dynamic loader before each program start. Okay, now let's back to the theory.
Libraries, in fact, are just an object files which are placed into a single archive by using
artool
with a single symbols table which is created by
ranlibtool.
Compiler, when compiling object files, does not resolve
symbols.
These symbols will be replaced to addresses by linker. So resolving symbols can be done by two things:
the linkerand
dynamic loader:
The linker:
ld,
does 2 jobs:
a) For static libs or simple object files, this linker changes external symbols in the object files to the addresses of the real entities. For example, if we use C++ name mangling linker will change
_ZNK3MapI10StringName3RefI8GDScriptE10ComparatorIS0_E16DefaultAllocatorE3hasERKS0_to
0x07f4123f0.
b) For dynamic libs it only checks if the symbols can
be resolved (you try to link with correct library) at all but does not replace the symbols by address. If symbols can't be resolved (for example they are not implemented in the shared library you are linking to) - it throws
undefined reference toerror and breaks up the building process because you try to use these symbols but linker can't find such symbol in it's object files which it is processing at this time. Otherwise, this linker adds some information to the
ELFexecutable
which is:
i.
.interpsection
- request for an
interpreter-
dynamic loader to be called before executing, so this section just contains a path to the dynamic loader. If you look at your executable which depends on shared library (
libfunc)
for example you will see the interp section
$ readelf -l a.out:
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238 0x000000000000001c 0x000000000000001c R 1 [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
ii.
.dynamicsection
- a list of shared libraries which
interpreterwill
be looking for before executing. You may see them by
lddor
readelf:
$ ldd a.out linux-vdso.so.1 => (0x00007ffd577dc000) libfunc.so.1 => /usr/lib/libfunc.so.1 (0x00007fc629eca000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fefe148a000) /lib64/ld-linux-x86-64.so.2 (0x000055747925e000) $ readelf -d a.out Dynamic section at offset 0xe18 contains 25 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libfunc.so.1] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
Note that
lddalso
finds all the libraries in your filesystem while readelf only shows what libraries does your program need. So, all of these libraries will be searched by dynamic loader (next paragraph). The linker works at build
time.
Dynamic loader:
ld.soor
ld-linux.
It finds and loads all the shared libraries needed by a program (if they were not loaded before), resolves the symbols by replacing them to real addresses right before start of the program, prepares the program to run, and then runs it. It works after
build and before running the program. Less speaking, dynamic linking means resolving symbols in your executable before each program start.
Actually, when you run an
ELFexecutable
with
.interpsection
(it needs to load some shared libraries) the OS (Linux) runs an interpreter at first but not your program. Otherwise you have an undefined behavior - you have symbols in your program but they are not defined by addresses which usually means that the program
will be unable to work properly.
You may also run dynamic loader by yourself but it is unnecessary (binary is
/lib/ld-linux.so.2for
32-bit architecture elf and
/lib64/ld-linux-x86-64.so.2for
64-bit architecture elf).
Why does the linker claim that
/usr/bin/ld: cannot find -lblpapi3_64in your case? Because it tries to find all the libraries in it's known paths. Why does it search the library if it will be loaded during runtime? Because it needs to check if all the needed symbols can be resolved by this library
and to put it's name into the
.dynamicsection
for dynamic loader. Actually, the
.interpsection
exists in almost every c/c++ elf because the
libcand
libstdc++libraries
are both shared, and compiler by default links any project dynamically to them. You may link them statically as well but this will enlarge the total executable size. So, if the shared library can't be found your symbols will remain unresolved and you will
be UNABLE to run your application, thus it can't produce an executable. You may get the list
of directories where libraries are usually searched by:
Passing a command to the linker in compiler arguments.
By parsing
ld --verbose's output.
By parsing
ldconfig's
output.
Some of these methods are explained here.
Dynamic loader tries to find all the libraries by using:
DT_RPATHdynamic
section of ELF file.
DT_RUNPATHsection
of the executable.
LD_LIBRARY_PATHenvironment
variable.
/etc/ld.so.cache-
own cache file which contains a compiled list of candidate libraries previously found in the augmented library path.
Default paths: In the default path /lib, and then /usr/lib. If the binary was linked with
-z nodefliblinker option, this step is skipped.
ld-linux
search algorithm
Also, note please, that if we are talking about shared libraries, they are not named
.sobut
in
.so.versionformat
instead. When you build your application the linker will look for
.sofile
(which is usually a symlink to
.so.version)
but when you run your application the dynamic loader looks for
.so.versionfile
instead. For example, let's say we have a library
testwhich
version is
1.1.1according
to semver.
In the filesystem it will look like:
/usr/lib/libtest.so -> /usr/lib/libtest.so.1.1.1 /usr/lib/libtest.so.1 -> /usr/lib/libtest.so.1.1.1 /usr/lib/libtest.so.1.1 -> /usr/lib/libtest.so.1.1.1 /usr/lib/libtest.so.1.1.1
So, to be able to compile you must have all of versioned files (
libtest.so.1,
libtest.so.1.1and
libtest.so.1.1.1)
and a
libtest.sofile
but for running your app you must have only 3 versioned library files listed first. This also explains why do debian or rpm packages have
devel-packages
separately: normal one (which consists only of the files needed by already compiled applications for running them) which has 3 versioned library files and a devel package which has only symlink file for making it possible to compile the project.
Resume
After all of that:
You, your colleague and EACH user of your application code must have all the libraries in their
system linker paths to be able to compile (build your application). Otherwise, they have to change Makefile (or compile command) to add the shared library location directory by adding
-L<somePathToTheSharedLibrary>as
argument.
After successful build you also need your library again to be able to run the program. Your library will be searched by dynamic loader (
ld-linux)
so it needs to be in it's paths (see above) or in system linker paths. In most of linux program
distributions, for example, games from steam, there is a shell-script which sets the
LD_LIBRARY_PATHvariable
which points to all shared libraries needed by the game.
相关文章推荐
- usr/bin/ld: cannot find -l<nameOfTheLibrary>
- usr/bin/ld: cannot find -l<nameOfTheLibrary>
- 【转载】/usr/bin/ld: cannot find -lxxx 问题总结
- 【转载】解决/usr/bin/ld: cannot find -lxxx 问题
- [转载]解决/usr/bin/ld: cannot find -lxxx 问题
- 【转载】解决/usr/bin/ld: cannot find -lxxx 问题
- 转载 :make报错:"/usr/bin/ld: cannot find -lXXX"
- [转载]解决/usr/bin/ld: cannot find -lxxx
- (转载)解决/usr/bin/ld: cannot find -lxxx 问题
- /usr/bin/ld: cannot find -l* 错误的解决方法……
- /usr/bin/ld: cannot find -lltdl collect2: ld returned 1 exit status make: *** [sapi/cgi/php-cgi] Err
- <<the architecture of open source applications>> 中关于虚拟机复制与迁移(下)
- 关于usr/bin/ld: cannot find -lxxx问题总结
- 解决g++编译出现/usr/bin/ld: cannot find -lc
- wiggle sort Given a list of integers, sort them so the output is s1 <= s2 >=s3 <=s4 ... sN.
- [解决] [centOS] g++ 带 -static 参数编译时,报错 /usr/bin/ld: cannot find -lm
- Qt编译遇到/usr/bin/ld: cannot find -lGL问题的解决方案
- android源码编译出现/usr/bin/ld: cannot find -llzo2 /usr/bin/ld: cannot find -luuid
- /usr/bin/ld: cannot find -lltdl
- CentOS安装Qt编译错误以及无法调试的问题解决( /usr/bin/ld:cannot find –lGL 和 Debugginghas failed)