Prevent autotools from setting rpath when compiling my program - c

I'm working on an example autotools project which builds a shared library and a program. The program should link to the shared library. But when I build the program libtool will set the rpath like this:
RPATH=/usr/local/lib
which I don't want.
According to the Debian Wiki libtool isn't supposed to set the rpath when the library is in the default search path (libtool's role).
According to this site /usr/local/lib should be in the default search path of the linker.
The library and the program are build by the same autotools project, so the library is not installed when the program is build.
Does anybody have an idea why libtool sets the rpath anyway?

with readelf readelf -d libfftw3_mpi.so you can check if your lib contains such a attribute in the dynamic section.
with export LD_DEBUG=libs you can debug the search path used to find your libs
with chrpath -r the rpath can be changed
As answered in https://stackoverflow.com/a/33520976/4379130 by #bonoparte

Related

Using protoc inside CMakeLists from a non-standard directory gives "cannot open shared object file: No such file or directory" error

I have a C application using CMake to generate Makefiles on Linux. The application contains .c as well as .proto files. Now I need to genearte .pb-c.c and .pb-c.h using protoc command in the CMakeLists.txt so that when I do cmake . the cmake generates the corresponding .pb-c and .pb-h. The protoc is used as:
execute_process(COMMAND bash -c "${PROTOC_PATH} --c_out=${CMAKE_CURRENT_SOURCE_DIR}/ --proto_path=${PROTO_DIR}/ ${PROTO_DIR}/*.proto")
The problem is that my protoc binary and related .so file is not in /usr/bin and /usr/lib or /usr/local/bin and /usr/local/lib. They are in a directory inside the project - $HOME/project-name/dependencies/bin/protoc and $HOME/project-name/dependencies/lib/libprotobuf.so.12
Due to this I am getting error - error while loading shared libraries: libprotobuf.so.12: cannot open shared object file: No such file or directory
But if I give the command as
execute_process(COMMAND bash -c "protoc--c_out=${CMAKE_CURRENT_SOURCE_DIR}/ --proto_path=${PROTO_DIR}/ ${PROTO_DIR}/*.proto") and run cmake . then it works fine as linker is able to get the .so file from /usr/lib
Mentioned below is a part of my CMakeLists.txt file
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath=${PROTOC_LIB_PATH} -L${PROTOC_LIB_PATH} -lprotobuf")
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,-rpath=${PROTOC_LIB_PATH} -L${PROTOC_LIB_PATH} -lprotobuf")
execute_process(COMMAND bash -c "${PROTOC_PATH} --c_out=${CMAKE_CURRENT_SOURCE_DIR}/ --proto_path=${PROTO_DIR}/ ${PROTO_DIR}/*.proto")
But it's not working due to aforementioned error.
Also for those who might say it's a duplicate I have looked into and tried the following SO questions:
Turning on linker flags with CMake
I don't understand -Wl,-rpath -Wl,
CMake link to external library
Does cmake have something like target_link_options?
CMAKE RPATH not working - could not find shared object file
https://serverfault.com/q/279068/435497
How to add linker flag for libraries with CMake?
https://serverfault.com/a/926072/435497
If you do not have a special use case, you do not need to call protoc yourself. Let CMake do this for you.
Have a look at: https://cmake.org/cmake/help/v3.16/module/FindProtobuf.html
and Cmake : find protobuf package in custom directory
I found this link which has a script showing how to create a PROTOBUF_GENERATE_C function which can then be used to generate the .pb-c abd .pb-h files.
From the above script I got the idea to make use of find_program which is similar to find_library in a way that it lets you pass the PATHS/PATH option so that CMake looks for the required program in the mentioned path.

Linking SDL2 with gcc

After having downloaded the development library for SDL2 and attempting to link it with the -lSDL2 command in gcc, I am told that the library can not be found. Is there a specific directory i should place the framework in ? Or can I specify the directory in the command line so it knows where to link it from?
You use the -l (lower-case L) to tell the linker to link with a specific library.
You use the -L option to tell the linker about which folders to search for libraries.
So if you have install SDL2 in a non-standard location, use the -L option to specify where the library is installed, just like you use the -I (capital i) to specify where headers are for the preprocessor to find them.
If you have not placed it within one of the standard paths where to search for libraries, you should set and export a correctly defined LD_LIBRARY_PATH/LIBRARY_PATH variable.
This discussion contains enough information.

CMake keeps linking to libraries under /usr/lib64 even full paths to another libraries are given

I am building a package with CMake (3.0.2). This package relies on boost_python and some others. There is an older version in /usr/lib64 and I have another newer version in my own directory /home/x/opt/boost-1.56/lib. There is an symbol link /home/x/opt/boost-1.56/lib64 to deal with the multi-arch gcc.
However, even if I set BOOST_ROOT=/home/x/opt/boost-1.56/lib, and in CMakeCache.txt there is
//Boost python library (release)
Boost_PYTHON_LIBRARY_RELEASE:FILEPATH=/home/x/opt/boost-1.56/lib/libboost_python.a
The generated link.txt contains such a line, instead of the full path:
-Wl,-Bstatic -lboost_python
And when make, it links to the one under /usr/lib64/, which is wrong.
Question:
How to make CMake to use the full path? As documented, only when libraries under system default folders are dealt with -Bstatic, which should not be my case.
Why -Wl,-Bstatic -lboost_python does not work even I have "/home/x/opt/boost-1.56/lib" in LD_LIBRARY_PATH and LIBRARY_PATH? From my limited knowledge they should override the system default.
Information:
gcc --print-search-dir gives:
/home/x/opt/boost-1.56/lib/x86_64-unknown-linux-gnu/4.9.2/
/home/x/opt/boost-1.56/lib/../lib64/
/lib/x86_64-unknown-linux-gnu/4.9.2/
/lib/../lib64/
/usr/lib/x86_64-unknown-linux-gnu/4.9.2/
/usr/lib/../lib64/
/home/x/opt/boost-1.56/lib/
/lib/
/usr/lib/
set(Boost_NO_SYSTEM_PATHS ON)
This will allow it to ignore everything but BOOST_ROOT
Solution (partially only):
CMake uses -Bstatic if there it thinks that the boost libraries it chooses are in the system path, including that related to enviromental variables. Else it use the full path.
I still cannot find why LIBRARY_PATH cannot override the system
So to make it work, REMOVE everything in LIBRARY_PATH and LD_LIBRARY_PATH will do the trick: CMake will use full path in that case.
Add this at the beginn oingf your top level CMakeLists.txt
cmake_minimum_required(VERSION 3.3)
and use cmake 3.3.0 or later.
Interestingly, with cmake 3.11.1 set(Boost_NO_SYSTEM_PATHS ON) did not work for me.

scons executable + shared library in project directory

Here's a sample SConscript file:
env = Environment()
hello_lib = env.SharedLibrary('hello', ['libhello.c'])
exe = env.Program('main', ['main.c'], LIBS=hello_lib)
env.Install('/usr/lib', hello_lib)
env.Install('/usr/bin', exe)
env.Alias('install', '/usr/bin')
env.Alias('install', '/usr/lib')
It builds one shared library, and one executable linked to that library:
$ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
gcc -o libhello.os -c -fPIC libhello.c
gcc -o libhello.so -shared libhello.os
gcc -o main.o -c main.c
gcc -o main main.o libhello.so
scons: done building targets.
Now, the issue is the created executable will not find the shared library when running it from the project directory,
which is quite natural, since neither the LD_LIBRARY_PATH env variable is set, or
any RPATH is set in the executable:
[fedora 00:07:10 2 ~] $ ./main
./main: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory
I can always set the LD_LIBRARY_PATH variable while developing, but this becomes cumbersome if the project has a directory hierarchy with several shared libraries in sub_directories.
The GNU autotools/libtool solves this by automagically set the RPATH of the executable to wherever the shared libraries are built in the project directory, which allows for easy running/testing the executable while developing. And it relinks the executable when installing it to leave out those RPATH which arn't needed anymore.
Is there anything similar to what autotools does that can be done with scons to ease testing the executables while developing ?
Is there any recommended way to build applications using shared libraries with scons, that makes it easy to run the executable from the build directory ?
You could modify each of the SConscript files which produce libraries, like so:
hello_lib = env.SharedLibrary('#/lib/hello', ['libhello.c'])
All of your shared libraries are now located in a single directory.
The SConscript which produces an executable becomes:
exe = env.Program('main', ['main.c'], LIBPATH='#/lib', LIBS=hello_lib)
Then you will be able to set LD_LIBRARY_PATH to $PWD/lib.
It looks like you are looking for the RPATH option in scons.
From the wiki page, the RPATH is described as scons as the following.
A list of paths to search for shared libraries when running programs.
Currently only used in the GNU linker (gnulink) and IRIX linker
(sgilink). Ignored on platforms and toolchains that don't support it.
Note that the paths added to RPATH are not transformed by scons in any
way: if you want an absolute path, you must make it absolute yourself.

mongo c libs not found on Mac with Eclipse

I built MongoDB C drivers from a tar distro on OSX (Mavericks). Built ok and installed to /usr/local/lib along with libbson. Made links to /usr/lib.
It built libbson-1.0.0.dylib, libbson-1.0.la, libmongoc-1.0.0.dylib, and libmongoc-1.0.la.
Not "*.a" files built tho, for whatever reason, by the makefile.
I added /usr/local/lib to my Eclipse project's lib dir params, and includes to /usr/local/include.
The includes were found during compile but linking failed because symbols from the libbson & libmongoc were not found. I'm winding about the lack of "*.a" files--not sure if Eclipse knows what to do with dylib files.
How can I make Eclipse find the needed libs?
Have you tried to add "-llibbson-1.0.0 -llibbson-1.0 -llibmongoc-1.0" to the linker flags ?

Resources