c_include_path vs ld_library_path - c++

On either Ubunutu 12.04 or Springdale 6.4, using gcc and g++, what's the difference between C_INCLUDE_PATH (or CPLUS_INCLUDE_PATH) and LD_LIBRARY_PATH? Is the LD one only used at run-time, and the other two only at compile-time?
Since the INCLUDE and LIBRARY_PATH environment variables seem to be ignored by GCC on these operating systems, which should I set when constructing my ~/.bashrc file to make it as portable as possible (modulo changes in the actual paths) across modern Linux OSes?

LD_LIBRARY_PATH is an environment variable which tells in which directories the dll loader should look for dynamic libraries when you start an executable. The variable is dangerous and deprecated
LIBRARY_PATH - tells linker where too look for libraries while building exe or lib
INCLUDE_PATH - tells where to look for files referred in #include statements
In any case, LIBRARY_PATH and INCLUDE_PATH should be set in a particular build-system, not in bashrc. The easier a script can build c-sources, the more probable your PC may be infected with a rootkit.
BTW: gcc is a wrapper which invokes a proper compiler (e.g. cc or g++) and linker.
g++ is gnu c++ compiler
EDIT
Explanation, why LD_LIBRARY_PATH is dangerous.
I haven't used Linux for a couple of years and I wonder, that this env-variable is still in current distributions. It was considered as deprecated when I was using Linux (around 2006) as it provides very easy to exploit hook.
The problem with it is, it prescribes the order of path's in which ld.so - dynamic linker looks for required libraries. If LD_LIBRARY_PATH contained a writable directory, a hacker (in new speech a cybercriminal) could place in that directory a library with a name likely to be found in a system directory (e.g. /usr/lib). This library could first do any dirty job and then call the original library. Exploiting LD_LIBRARY_PATH is much easier then compromising binaries in system directories. And also such an exploit is hard to detect.

Related

Load .so from directory relative to loading executable

For various reasons mostly to do with inertia, we don't have a make install target.
Rather, we build our large C++ codebase directly into an FHS-like tree;
output/
bin/
lib/
etc/
...
We've recently switched some third-party libraries to dynamic linking, and so we push a number of .so libraries into lib/.
Now, we're used to being able to just launch our executables from bin/, but that no longer works because the loader doesn't search our lib/ directory.
LD_LIBRARY_PATH would solve this, but we would prefer not to have to provide it before every single executable invocation, and we don't want to stick it in the shell's environment, because we typically switch between a number of different build trees in the same shell.
We've considered adding an rpath entry in the generated ELF, but relative paths are typically resolved against $PWD, not the executable's dirname.
Is there a way to nudge the loader to look in dirname(argv[0])/../lib for .so libs?
Basically, I understand that there are lots of ways we can change our habits to make this work (and probably should), but we prefer not to at this point, so can we coerce the Linux so loader to do what we want? Thanks!
Yes, it is possible using rpath and ${ORIGIN} macro, which is recognized by ld.so at runtime.
From man ld.so:
ld.so understands certain strings in an rpath specification
(DT_RPATH or DT_RUNPATH); those strings are substituted as follows
$ORIGIN (or equivalently ${ORIGIN})
This expands to the directory containing the application executable.
More variables are available. You don't need to coerce the loader to anything. It has the feature for you. :)

How to prefer one library location vs. another one with Clang?

I have a system-wide libc++.so in /usr/lib64. I want to link my binary against another libc++.so which is located somewhere else, say, in $HOME/.local/lib. Also, I want to be able to find all other libraries the same way as before, assuming that $HOME/.local/lib contains only libc++.so.
I'm trying to do this like: clang++ -L$HOME/.local/lib -lc++, but the compiler still links against /usr/lib64/libc++.so.
How to force the compiler (or linker) to link against a specific library location?
-L adds the directory to the search path used by the linker. This has no effect on the search paths used at runtime. At runtime, the search paths, in order, are:
The environment variable LD_LIBRARY_PATH
rpath specified in the executable
System library path
While you can achieve what you want by specifying the environment variable LD_LIBRARY_PATH=$HOME/.local/lib, it is a bad solution since it modifies the search paths of all executables. Specifying the rpath is a much cleaner solution since it only affects the behaviour of your executable. You can do this through the linker option of your toolchain, which is likely -rpath. So the command would be clang++ -rpath $HOME/.local/lib -lc++.

How to get libstdcxx implicit link directory in a portable manner in CMake

The background is our project have to work with different GCC versions (ABI might not be compatible) and several versions of GCC are installed in our build server. We use a wrapper project to set LD_LIBRARY_PATH, prepare the environment by export LD_LIBRARY_PATH=/path/to/gcclib/ and launch our application within the wrapper script.
Since different flavors of gcc/g++ are used, we want to know if there's an easy way to get the implicit library path that libstdc++.so is linked against. For example, one of the GCC tools are installed in /opt/gcc4/gcc4.7/bin/g++ and the libstdc++.so can be found in /opt/gcc4/gcc4.7/lib/ while another GCC variant might be found in /usr/local/bin/g++ and /usr/lib/libstdc++.so.
I suppose you are specifying an absolute path when setting CMAKE_{C,CXX}_COMPILER vars. In this case you can use it to obtain library dir:
get_filename_component(GCC_PATH ${CMAKE_C_COMPILER} PATH)
#now ${GCC_PATH} contains "/opt/gcc4/gcc4.7/bin", for example
set(LIBSTD_PATH "${GCC_PATH}/../lib")
For system compiler you can use an if statement:
if(GCC_PATH STREQUAL /usr/local/bin)
set(LIBSTD_PATH "/usr/lib")
endif()

Linux C++ linker /usr/bin/ld

I wrote a small application on Redhat Linux 6 using g++ 4.4.6. After compilation, I received an error
/usr/bin/ld: cannot find -lcrypto
I did a search for the crypto library and find them here,
[root#STL-DUNKEL01 bin]# find / -name libcrypto*
/usr/lib64/libcrypto.so.0.9.8e
/usr/lib64/libcrypto.so.10
/usr/lib64/libcrypto.so.6
/usr/lib64/libcrypto.so.1.0.0
My question is whether the compilation error is caused by /usr/bin/ld not having /usr/lib64/ in the search path? If yes, how can I add it?
Thanks.
No, you have likely incorrectly diagnosed the cause.
You need a libcrypto.so to link against. This is usually a symlink to one of the actual libraries, whose soname (libcrypto.so.??) will be embedded into the binary. Only that library is needed at runtime, but the symlink is necessary to compile.
See Diego E. Pettenò: Linkers and names for more details.
You have to add -L/usr/lib64 when calling gcc or ld.
Note, you can specify LD_LIBRARY_PATH as well/instead, but it is considered harmful to do so. (The link mentions Solaris specifically, but the issues apply to other OSs as well.)
Quote:
LD_LIBRARY_PATH is used in preference to any run time or default system linker path. If (God forbid) you had it set to something like /dcs/spod/baduser/lib, if there was a hacked version of libc in that directory (for example) your account could be compromised. It is for this reason that set-uid programs completely ignore LD_LIBRARY_PATH.
When code is compiled and depends on this to work, it can cause confusion where different versions of a library are installed in different directories, for example there is a libtiff in /usr/openwin/lib and /usr/local/lib. In this case, the former library is an older one used by some programs that come with Solaris.
Sometimes when using precompiled binaries they may have been built with 3rd party libraries in specific locations; ideally code should either ship with the libraries and install into a certain location or link the code as a pre-installation step. Solaris 7 introduces $ORIGIN which allows for a relative library location to be specified at run time (see the Solaris Linker and Libraries Guide). The alternative is to set LD_LIBRARY_PATH on a per-program basis, either as a wrapper program to the real program or a shell alias. Note however, that LD_LIBRARY_PATH may be inherited by programs called by the wrapped one ...
Add the directory to /etc/ld.so.conf
then run "sudo ldconfig" to make the changes take effect.
You can provide the directories to search for the libraries in as a parameter to gcc like so -L<directory_to_search_in>. And note that there can be multiple parameters to -L. Also, are you trying to build a 32-bit application or a 64-bit one?

Using -rpath and $ORIGIN with libtool-based projects?

I am trying to incorporate a libtool-based package into a project of my own, perhaps in a non-standard way. Here is my goal:
Build external project:
./configure --prefix=$HOME/blah --etcetera && make && make install
Build my own project which depends upon the external project's shared libraries and executables at runtime:
gcc -I$HOME/blah/include -L$HOME/blah/lib -o $HOME/blah/bin/program
Package everything into a single "localized" tarball... that is, while I have everything in $HOME/blah on the build host I want the ability to extract the tarball to any arbitrary directory (on some other host) without having to futz with my environment. The intent is to allow multiple versions of my project to coexist side-by-side without any nasty "cross-pollination".
I know that I can use -rpath '$ORIGIN/../lib' for my project to ensure that the right shared libraries always get loaded at runtime. However, it seems that libtool insists on assigning its own -rpath setting based on the exact path of $HOME/blah/lib, which breaks if I happen to untar everything into a different directory (say, for example, $HOME/blah.2011-06-02).
Is there a way around this limitation? I see a rather lengthy rpath discussion between debian and libtool folks on the topic, but it's somewhat old and inconclusive beyond "we disagree".
Among the options presented here on Rpathissue on the debian Wiki, using chrpath in your 'install' step or some post-processing script sounds like a viable option. (It's available on a bunch of distros via your favorite package manager.)
It doesn't require patching libtool which is a plus IMO.
Note that it has some limitations: can only save the new rpath if it's shorter (or same length) as the original one.
The other (pragmatic) option is to remove the rpath (chrpath can do that), and just have a wrapper script that sets LD_LIBRARY_PATH to whatever is necessary for your app. That has a chance of being slightly more portable too (if you handle the other shared library path environment vars some OSes have).