RPATH must exist at compile time - gcc

Please forgive me if I'm missing something obvious here. I'm developing some applications for another platform, and all of my proprietary libraries are installed to /app/lib. To facilitate this, I specify a runtime library path for each of my binaries as "/app/lib". This works fine; however, it requires that the path "/app/lib" exist in my build environment when linking (even though that directory is empty). I'm using NetBeans, which might be complicating matters, but I can see "-Wl, -rpath /app/lib" being passed to gcc.
I'd like to avoid the need to create an empty "/app/lib" in my build environment, but I don't want to change the file structure on my target platform. If I delete /app/lib from the build environment, I get an error when building that it can't be found. Is there a way to specify a runtime search path without the need for it to exist at link time?

I think the option you are looking for is -Wl,-rpath-link,/path/to/libraries. You need to use both options at once.
The linker will then use -rpath-link to find the libraries at link-time, but it'll encode the -rpath value into the binary for use at run time.

The syntax should be "-Wl,-rpath -Wl,/app/lib" ("-Wl,-rpath,/app/lib" works too). This is a bug in NetBeans. The reason why it's not more critical (and why I didn't notice this before) is that link-time search paths appear to carry over into runtime. Because NetBeans isn't placing a comma between -rpath and /app/lib, /app/lib is being interpreted as a link-time search path. As a result, my dependent libraries are still found at run-time in the appropriate location, but because it's a link-time dependency, the linking fails because /app/lib doesn't exist.

Related

CMake Imported Library Target giving undefined giving undefined symbols on Windows

I'm trying to import libuv into my CMake project so I can link it. I have libuv 1.12.0 installed from here and I placed it in C:\Program Files\libuv\.
project(tls-server LANGUAGES C)
set(LIBUV_ROOT_DIR "C:\\Program Files\\libuv")
add_library(libuv SHARED IMPORTED)
set_property(TARGET libuv PROPERTY IMPORTED_LOCATION "${LIBUV_ROOT_DIR}\\libuv.dll")
set_property(TARGET libuv PROPERTY IMPORTED_IMPLIB "${LIBUV_ROOT_DIR}\\libuv.lib")
add_executable(tls-server "${CMAKE_SOURCE_DIR}/src/main.c")
target_link_libraries(tls-server libuv)
However, given the above code I am still getting undefined symbol errors in Visual Studio:
How can I fix this? I believe the paths are all correct. I'm also using Windows 10.
Never hardcode library paths or names like this in CMake.
Instead use the find_library command, which does a decent job of notifying you early if something is wrong with the provided library.
On Windows in particular, since there are no default locations where libraries are located on the system (something like the /usr/local/lib on *nix systems), you may want to provide an additional customization point for the library's location. I personally like to use environment variables for this, but a normal CMake option will also do:
project(tls-server LANGUAGES C)
find_library(LIBUV_LIBRARIES NAMES uv libuv
HINTS $ENV{LIBUV_ROOT})
add_executable(tls-server ${PROJECT_SOURCE_DIR}/src/main.c)
target_link_libraries(tls-server ${LIBUV_LIBRARIES})
Note that CMake in general never takes care of copying runtime dependencies to the correct place! That is, if libuv was built as a .dll, you must ensure that that .dll is in the correct path when running the program.
You can of course manually insert a copy command in CMake for getting all the dlls into place, but that can be quite cumbersome. Unfortunately there is no more comfortable solution for this problem right now.
Using imported targets here is possible, but really only pays off if you need to pass on more complex properties to the depending target. In my experience, imported targets work best if the dependency provides a fully-fledged package config file. Writing imported targets manually is often not worth the trouble in terms of additional complexity.
I finally managed to solve the issue.
Firstly I reinstalled the binaries from the target library (libuv). Then, I made sure that my cmake was generating x64 project files by using cmake -G "Visual Studio 14 2015 Win64". That was sufficient to get rid of the undefined symbols error. Then all I needed to do was copy the libuv.dll file to the same directory as the executable file, and everything ran fine.
If anyone knows why this error occured, please comment so you can help out other people in the future target the cause of the error better.

Using dynamic library

When I would like to compile a program which uses a dynamic library, do I have to install (i.e. copy to a specific place, say, /usr/share/lib) this library? Or is it ok, if I put this library to any place somewhere and later during linking I point the linker to it, e.g. '-L ./thelibfolder'?
do I have to install (i.e. copy to a specific place, say, /usr/share/lib) this library?
No.
For a UNIX shared library, you need to arrange for two things:
You have to make the library known to the static linker, while linking main executable. Usually this is achieved by adding -L/path/to/directory -lfoo link flags to the link line.
You have to make runtime loader search /path/to/directory as well. This is system-specific. On many systems, setting LD_LIBRARY_PATH environment variable achieves the desired result, though this is usually not the preferred method. Another method is to encode this path into the application itself, e.g. on Linux one would add -Wl,-rpath=/path/to/directory to the application link line.

linking and executable by hand without alternatives

I use gcc more than any other compiler, so I will shape my example with this compiler suite, but i have experienced this problem with almost all the suite that i have tried like gcc, mingw, clang and msvc.
gcc offers this flags:
-l you write the name foo, gcc will find a corrisponding library named libfoo
-L you append the path where the libs lives and gcc tries to match the required libraries to the ones that it finds in that path
-rpath basically a pool of different path for the same lib so the executable is "smart" enough to look for alternatives if he needs one.
the problem is big for me, no one of this solves my problem and each one of this flags suffer the same problem: ambiguity.
if I just want to link a library that i know there is no way to do this without including a dose of ambiguity in the best case scenario, what i want is:
linking 1 specific library only, and only the 1 that I specify with a precise name and path
avoid auto-completion mechanism like the one on the name given to -l because my libs are named foo.so not libfoo.so
relative path for the linked libs
only consider the explicitly given set of libraries, no other automation of any kind should be involved, no pool of libs, no search-paths, no nothing else, I prefer list of errors instead of an executable linked to a random library
I often deal with different libs in different releases, they often share the same name for historical and compatibility reasons, it's a nightmare compiling and linking with gcc because I never got the one that I want linked to my executable.
Thanks.
The easiest way to do this is to simply specify the library.
gcc -o test test.o /path/my_library.so /path/to_other_library.a
The obvious downside to this approach if of course that if you move that library then your application won't work anymore but since you state that you have the libraries at fixed locations it should work in your case.

Compile with GCC and relocate the linked libraries

I have my soft.c and I compile it successfully and link it against /usr/lib/myLib.so.
Everything it's ok except for the fact that it's not what I'm looking for, i would like to manage the final path considered for the linking, in other words i want GCC to consider the library /usr/lib/myLib.so but I also want the final linking to be a relative path, kinda like ../myLib.so.
The usual scenario is
./soft linked to -> /usr/lib/myLib.so
I want
./soft linked to -> ../myLib.so
Obiviously I also need GCC to manage any cross referenced library, for example if /usr/lib/myLib.so is linked to other libs i want all the libraries involved to be relocated in the relative path so ../myLib.so can fully work from a relative path .
How to achieve that ?
Thanks.
You could include run-time search path information in the binaries, using the -rpath option to the linker (passed to gcc as -Wl,-rpath,.
Note that this is generally frowned upon by distribution maintainers, as there should be a single system-wide library search path so conflicts are caught early.

How do I force Xcode to link to a custom version of a system framework?

I have a project that uses OpenAL. The project is built against the 10.5 SDK, and the version of the OpenAL.framework in 10.5 causes some problems. I want to link to a custom-built version of the OpenAL.framework that resides in my source tree.
However, Xcode resolutely refuses to do this. No matter what I try, it insists on linking to the framework located at /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/OpenAL.framework/OpenAL. Here are a couple of things I've tried without success:
Set the path to the framework directory in a variety of ways (relative, absolute) using -F.
Pass the linker the -Z flag to eliminate default link paths, then explicitly pass /System/Library further on in the link process, to ensure that it sees the system paths after my custom library path.
Build my library using a prelinking pass, and explicitly pass the library inside the framework to THAT.
According to man gcc, passing the -F parameter should be sufficient to ensure that a link path is searched before the default paths. Either this isn't happening correctly or I'm misunderstanding the problem, and it seems too simple and obvious to be a linker problem :-)

Resources