I'm trying to use boost::filesystem::exists function. When I'm trying to link, I'm getting
/usr/local/include/boost/filesystem/operations.hpp:289: undefined reference to `boost::filesystem::detail::status(boost::filesystem::path const&, boost::system::error_code*)'
error.
I googled for a while and found only "link-with-boost" answers. In my case -lboost_system and -lboost_filesystem specified for linker, but it doesn't seem to work.
Actually I can use boost::filesytem::path (for example), but when I'm trying to use anything, which needs boost/filesystem.hpp header, I'm getting linker errors.
Any ideas?
P.S. I'm using gcc-4.6.4 and boost lib installed from repos, but I assume gcc-4.6.4 is default gcc version for my ubuntu 12.04. I guess I don't need to compile boost from source?
There are many options to the linker (ld) to specify the search path to resolve shared libraries, man ld will give you all the options. Suppose you have boost installed in /usr/local/lib, you could add one of these options to gcc to pass along to the linker:
-L=/usr/local/lib
Directories specified on the command line are searched before the default directories. All -L options apply to all -l options, regardless of the order in which the options appear.
If searchdir begins with "=", then the "=" will be replaced by the sysroot prefix, a path specified when the linker is configured. The -L option only sets a compile-time library search path; if you want a shared library to be found at runtime then its directory must be known at runtime.
-Wl,-rpath,/usr/local/lib
Add a directory to the runtime library search path. This is used when linking an ELF executable with shared objects. All -rpath arguments are concatenated and passed to the runtime linker, which uses them to locate shared objects at runtime. The -rpath option is also used when locating shared objects which are needed by shared objects explicitly included in the link; see the description of the -rpath-link option. If -rpath is not used when linking an ELF executable, the contents of the environment variable "LD_RUN_PATH" will be used if it is defined.
Another alternative is to add to your LD_LIBRARY_PATH the location of your boost libraries.
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
The linker (ld) uses LD_LIBRARY_PATH as one of the search paths to locate required shared libraries.
You can read more about the linker and shared libraries here.
To fully understand why your installation isn't finding the boost libraries by default you might find this answer at stackexchange informative.
This SO answer suggests using boost m4.
Related
I have two versions of boost installed on cluster. The old one is in standard location while the new one in my home directory. Since I have no su privilege I cannot delete the old one. I exported environment variables for boost (and for other libraries) as follows:
export PATH=/truba/home/osibliyev/boost/bin:$PATH
export LD_LIBRARY_PATH=/truba/home/osibliyev/boost/lib:$LD_LIBRARY_PATH
export LIBRARY_PATH=/truba/home/osibliyev/boost/lib:$LIBRARY_PATH
export CPLUS_INCLUDE_PATH=/truba/home/osibliyev/boost/include:$CPLUS_INCLUDE_PATH
After compiling with make, I get the following error at linking stage:
/usr/bin/ld: warning: libboost_serialization.so.1.64.0, needed by
/truba/home/osibliyev/boost/lib/libboost_mpi.so, may conflict with
libboost_serialization.so.1.53.0 /usr/bin/ld: loadmap.o: undefined
reference to symbol '_ZN5boost7archive17archive_exceptionC2ERKS1_'
/truba/home/osibliyev/boost/lib/libboost_serialization.so.1.64.0:
error adding symbols: DSO missing from command line
lboost_serialization is already added to LDADD:
LDADD = -lmetis -lmpi -lboost_mpi -lboost_serialization -lboost_log -lboost_log_setup -lboost_thread -lpthread -lboost_date_time -lboost_filesystem -lboost_system -lboost_timer
I am sort of sure that the error is because of conflict because other libraries are linked without problem and only boost complains. This does not happen on my machine where there is only one boost version. What can I do to solve this error?
How your toolchain's header and library search paths are determined is implementation-specific. There is no universal rule for what environment variables, if any, affect them, or how.
The specific environment variables you are trying to use and the values you are setting for them indicate a UNIX-style system. You should be aware that
on such a system, the PATH variable sets the search path for executables, not libraries or headers.
on those systems that recognize it, LD_LIBRARY_PATH designates extra directories for the dynamic linker's search path -- these are relevant at run time, not build time.
CPLUS_INCLUDE_PATH is recognized by the GNU C++ compiler, and maybe others, for designating additional directories to search for include files. This is relevant to you for finding the Boost headers, but not the libraries. With GNU compilers, the directories listed in this variable will be searched before the standard directories.
LIBRARY_PATH is recognized by the GNU linker, and possibly others, as designating additional directories to search for libraries. Like CPLUS_INCLUDE_PATH, this is relevant to you, but it does not allow you to substitute your libraries for like-named others found in one of the standard locations, because the standard directories are searched before these.
Your error messages suggest that The linker is finding a mixture of Boost v1.53 and v1.64 libraries. Probably that means that the former reside in a directory that is search first -- likely a system directory such as /usr/lib -- but not all the Boost libraries you are trying to link are found there; some are found in your v1.64 installation. Given that what you've already tried does not work, there is unlikely to be any environment variable you can set to fix that. As I said, however, it's implementation-dependent, and although I suspect you're using the GNU toolchain, you haven't specified.
With the GNU toolchain, if you want the linker to search your personal Boost installation for libraries before it searches the standard directories then you'll need to instruct it specifically to do so via command-line option. As discussed in comments, you can accomplish that by adding -L/truba/home/osibliyev/boost/lib to your Automake LDADD variable.
I've been programming a while but I still don't fully understand how the linker behaves.
For example, today I downloaded and installed a library that I want to use in my application in Linux. (It was Xerces - for parsing XML files).
I created a makefile and gave it the path to the .so and .a files in my command : -L/usr/local/lib and also told it the name of the library to include : -lxerces-c-3.1.
My application compiled fine but failed during runtime with "cannot open shared object file libxerces-c-3.1.so". Why would this be the case, when I properly give it the path and name in the makefile?
I then added the library path to the LD_LIBRARY_PATH variable in my .bashrc file and then it worked. That's fine , but if I now remove the path to the library in my makefile and don't even include the name of the library , it still works.
I'm confused as to what is going on here. How can it still find the correct library just by assigning the path to the LD_LIBRARY_PATH variable and will only work if I do so? I have read elsewhere to not even use LD_LIBRARY_PATH.
I appreciate any answer for this. The question is a bit long and hopefully not off-topic but I hope others can learn from it too. Thanks
compilation and running are different things. :)
1) A make file contains rules on how to build your application. So when you write a rule like:
-L/usr/local/lib -lxerces-c-3.1
You are passing options to the linker. The -L option tells the linker to add additional libraries (in this case '/usr/local/lib') to the linker's search path. The -l option names the library that should be linked in.
2) When you go to run an executable, the loader needs to find all the required libraries. For example, on a Linux system you can use the ldd command to see what shared libraries are used. For example on my system:
ldd FEParser
linux-vdso.so.1 => (0x00007ffcdc7c9000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f835b143000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f835ae3d000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f835ac27000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f835a862000)
/lib64/ld-linux-x86-64.so.2 (0x00007f835b447000)
From this, you can see the name of the library that is linked to the left of the '=>' token, and the path to the library to the right. If a library is not found it will show up as missing.
Now in your case, you were able to successfully compile and link your program due to giving the path and library name to use. You were not able to run the program due to the loader not being able to find the library at run time.
You have several options here:
1) you can move the library in a directory that is in the loaders search path.
2) you can modify LD_LIBRARY_PATH which adds additional directories to the loaders search path. Additionally, the directories specified in LD_LIBRARY_PATH will be passed to the linker (it will be appended after all -L flags). You do need to be careful with this, as if you set it globally (say in .bashrc), then it will effect all compilations that you do. You may or may not want this behavior.
3) As others have specified you can use -Wl,rpath=...., but it is deprecated, and I rarely use it.
4) If you need the library installed in an unusual location, you can add a create a file under /etc/ld.so.conf.d that contains, for example (file is yaml.conf):
# yaml default configuration
/opt/yaml/lib
At system boot, the loader reads all the files in this directory and appends the paths to the loader path. If you make a modification to this directory you can use the ldconfig command to cause the loader to reprocess /etc/ld.so.con.d. N.B. I know this works on centOS and Ubuntu flavors of GNU/Linux - can't speak authoritatively on other flavors.
Compile your program with -Wl,-rpath=/usr/local/lib. This way you'll add /usr/local/lib to runtime library search patch of your program and you won't need the LD_LIBRARY_PATH
Warning: since modern dynamic linkers consider rpath as deprecated you can set also runpath (which supersedes it) by specifying -Wl,-rpath=/usr/local/lib,--enable-new-dtags
There is no mystery here. Default library paths for linker (one you call to make your executable file, for example, ld) and runtime linker (one which is responsible for loading shared libraries when you execute your program, for example, ld.so) are different. Runtime linker uses LD_LIBRARY_PATH, while linker uses whatever was configured when ld was build.
In your case, looks like /usr/local/lib is part of one, but not another.
If you're using static linking, all you have to do is tell the linker where your library is at compile/link time. The library (or as much of it as is necessary) gets copied into your executable, and your executable is standalone.
But for various reasons, these days we generally use dynamic linking, not static linking. With dynamic linking, you have to tell the linker where to find the library at compile/link time, and the dynamic linker (ld.so) has to be able to find the library at run time.
If the library was in one of the standard places (/lib, /usr/lib, etc.) there's no problem. But if you linked against a library in a nonstandard place, in general, you have to add that nonstandard place to your LD_LIBRARY_PATH, so that the runtime linker will always be able to find it.
I am working on centos. I installed boost version 1.45.0 on my system. The programs are compiled correctly but whenever I type command to see output it gives following error:
./a.out: error while loading shared libraries:
libboost_thread.so.1.45.0: cannot open shared object file: No such
file or directory
In addition to the other answers, you can also set the DT_RPATH elf tag when linking your executable
-Wl,-rpath,/path/to/boost/libraries -L /path/to/boost/libraries -lboost_whatever
This way you don't have to remember to set your LD_LIBRARY_PATH if the libraries are installed in a non-standard location.
How did you install the boost libraries?
The problem you're likely having is that the linker can not find the libraries, and when you built your program, you had to manually specify additional library paths to search for libraries.
A quick fix you can do is to set LD_LIBRARY_PATH to include the directory where the boost thread library is:
export LD_LIBRARY_PATH=/path/to/boost/libs:$LD_LIBRARY_PATH
./runExecutable
You need to set the LD_LIBRARY_PATH environment variable to include the path to the Boost libraries (they're possibly in /usr/local/lib, etc).
In bash, this is simply
export LD_LIBRARY_PATH=/path/to/boost:$LD_LIBRARY_PATH
First I built the Boost libraries that require building by going to /usr/local/boost_1_49_0/ and running the bootstrap.sh. This went off alright.
Step (1) created all the .so and .a files in /usr/local/boost_1_49_0/stage/lib
I tested linking against a library, say lboost_regex and #include <boost/regex> in my source code. This also went off alright.
Finally trying out the example on asio, I tried:
g++ -I/usr/local/boost_1_49_0 MAIN.cpp -o MAIN -L/usr/local/boost_1_49_0/stage/lib -lboost_thread -lboost_system -lpthread
(4) compiled alright. But when I run the program with ./MAIN, I get the following error:
./MAIN: error while loading shared libraries: libboost_system.so.1.49.0: cannot open shared object file: No such file or directory
The -L option only sets a compile-time library search path; if you want a shared library to be found at runtime then its directory must be known at runtime.
One way to set this with g++ is to pass -rpath to the linker, via the compiler; in your case you could say -Wl,-rpath -Wl,/usr/local/boost_1_49_0/stage/lib. (This embeds the directory in the executable.)
Another way is to install the libraries in a place that the linker searches by default (e.g. /usr/local/lib might be such a place, depending on how the system is configured).
Yet another way is to set an environment variable such as LD_LIBRARY_PATH (Linux or Solaris) or DYLD_LIBRARY_PATH (Mac OS X), to tell the linker where to search when launching executables from the shell where the variable is set.
Are you sure the shared library is in a place where the loader can find it? Either put it in a system wide directory or the same directory as the executable.
Here's a link with more information about the loader.
I am working on centos. I installed boost version 1.45.0 on my system. The programs are compiled correctly but whenever I type command to see output it gives following error:
./a.out: error while loading shared libraries:
libboost_thread.so.1.45.0: cannot open shared object file: No such
file or directory
In addition to the other answers, you can also set the DT_RPATH elf tag when linking your executable
-Wl,-rpath,/path/to/boost/libraries -L /path/to/boost/libraries -lboost_whatever
This way you don't have to remember to set your LD_LIBRARY_PATH if the libraries are installed in a non-standard location.
How did you install the boost libraries?
The problem you're likely having is that the linker can not find the libraries, and when you built your program, you had to manually specify additional library paths to search for libraries.
A quick fix you can do is to set LD_LIBRARY_PATH to include the directory where the boost thread library is:
export LD_LIBRARY_PATH=/path/to/boost/libs:$LD_LIBRARY_PATH
./runExecutable
You need to set the LD_LIBRARY_PATH environment variable to include the path to the Boost libraries (they're possibly in /usr/local/lib, etc).
In bash, this is simply
export LD_LIBRARY_PATH=/path/to/boost:$LD_LIBRARY_PATH