I have two installations of wxWidgets, one in /usr/... and one private.
I don't have permissions to change the central directory.
My question is how can i make my private installation the active one?
If i only add it to the PATH setenv, it dosn't work correctly since i'm missing the LIBS.
The usual way to do something like that is to add the folder with your "private" libs to your LD_LIBRARY_PATH environment variable (assuming you're using bash and your shared libraries are in "/home/myLogin/wxWidgets/lib"),
export LD_LIBRARY_PATH="/home/myLogin/wxWidgets/lib:$LD_LIBRARY_PATH"
From The Linux Documentation Project - 3.3.1. LD_LIBRARY_PATH
You can temporarily substitute a different library for this particular execution. In Linux, the environment variable LD_LIBRARY_PATH is a colon-separated set of directories where libraries should be searched for first, before the standard set of directories
Related
So I am working on a project that is intended to run on a remote server. I develop the program on a local pc, compile it, then upload it to the remote server. Both the local pc and the remote server are run on CentOS 7.7.
The program is developed using the CLion IDE, configured with CMake. The program depends a few shared libraries, which are supposed to link to the executable according to what I wrote in CMake. At my local PC, I can compile and run the program perfectly. However, after I scp the whole directory of the project to the remote server, the executable fails to run. It cannot find any of the ".so" files, according to what ldd says.
This is my CMakeList.txt, with every path being relative path, instead of absolute path.
cmake_minimum_required(VERSION 3.15)
project(YS_Test)
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_PATH_ src)
file(GLOB SOURCE_FILES_ ${SOURCE_PATH_}/*.*)
set(PROJECT_LIBS_ libTapQuoteAPI.so libTapTradeAPI.so libTapDataCollectAPI.so)
include_directories(api/include)
link_directories(api/lib/linux)
add_executable(YS_Test ${SOURCE_FILES_})
target_link_libraries(YS_Test ${PROJECT_LIBS_})
Please do not tell me to set LD_LIBRARY_PATH to fix my issue. The program worked fine on my local pc without LD_LIBRARY_PATH, so I expect it to run on the remote server without LD_LIBRARY_PATH. I would like to know what is really going on here, instead of a work around. Thanks!
If I understand your problem correctly, you want to ship your compiled YS_Test program along with some dependencies and have it run on a remote server. By default an executable will only look in the directories configured in /etc/ld.so, which will not include the deploy path.
Note: Typically you do not deploy your entire build directory but only the compiled artifacts and dependencies. For this answer I will assume you deploy the binary and its dependencies to the same directory.
You have two options:
Require users of your program to set LD_LIBRARY_PATH, either by themselves or by a wrapper script. This variable will instruct the dynamic linker to look in the specified directories as well. Even if you do not like this solution, it is by far the most common approach.
Add -Wl,-rpath='$ORIGIN' to your linker options. This will add a DT_RUNPATH attribute to the executable's dynamic section. As you are using CMake you can also set this using BUILD_RPATH and/or INSTALL_RPATH target properties.
The ld.so manpage describes this attribute as follows:
If a shared object dependency does not contain a slash, then it is
searched for in the following order:
...
Using the directories specified in the DT_RUNPATH dynamic section
attribute of the binary if present.
The $ORIGIN part expands to the directory containing the program or shared
object.
If you really insist on shipping your build directory (eg during development), you can take a look at the CMake BUILD_RPATH_USE_ORIGIN property (and its usual global counterpart CMAKE_BUILD_RPATH_USE_ORIGIN), this will embed relative paths into binaries instead of absolute paths.
As you don't want a workaround (#Botje has given you two already), I will try an explanation instead. In your development machine, if you use this command:
ldd YS_Test
You will see all the shared libraries used by your program, with their corresponding paths. The libTapQuoteAPI.so libTapTradeAPI.so libTapDataCollectAPI.so are found at your 'api/lib/linux' directory, but resolved with full absolute paths. If you do the same at your server, some shared objects can't be resolved because they aren't at the same location.
If you use one of these commands (not sure which are available in Centos):
chrpath --list YS_Test
or
patchelf --print-rpath YS_Test
You will see the RPATH or RUNPATH tags embedded in your program. This is the path used by the Linux linker to locate dependencies that are outside the standard ld locations. You may find extended explanations on Internet about this, like this one or the Wikipedia article.
Breaking my promise, I give you a third workaround: use patchelf or chrpath at your server after scp to change the embedded RPATH tag, pointing it relative to $ORIGIN (which represents the program location).
I am working off of a cluster and since I do not have sudo privileges there, I had to install a toolkit at a different path ~/bin/tool_kit. This path now contains the following directories: bin, include and lib. This may be a very newbie question, but what changes do I make to my .bashrc so that I am able to use this toolkit.
For example, the $PATH variable might be augmented like:
export PATH = ~/bin/tool_kit/bin:$PATH. How do I include lib and include?
bin is the only location you definitely need to do anything with:
# using end of the PATH, unless you know you want to override like-named system binaries
PATH=$PATH:$HOME/bin/tool_kit/bin
No export is needed here, as the PATH variable is already in the environment.
If and only if your software didn't compile in a rpath pointing to the anticipated runtime library locations, you may also wish to set an LD_LIBRARY_PATH:
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH+$LD_LIBRARY_PATH:}$HOME/bin/tool_kit/lib
include files are used only when compiling other software, and are not generally needed at runtime.
This should be really simple, but I'm having trouble. I want to include some shared Qt libraries with my application in the installation folder so the user doesn't have to download Qt separately. On Windows, this seemed to work fine, but Ubuntu complains about not being to find the Qt libraries when they are in the same folder as the application.
How do I add the installation directory to shared library search path?
I was able to add the installation directory to shared library search path by adding the following lines to the .pro file, which set the rpath of the binary to $ORIGIN (the install folder). I needed to add the location of QT libs on my current machine (/usr/lib/qt5.5 and /usr/lib/qt5.5/lib) so that the project would build in QtCreator.
unix:!macx {
# suppress the default RPATH if you wish
QMAKE_LFLAGS_RPATH=
# add your own with quoting gyrations to make sure $ORIGIN gets to the command line unexpanded
QMAKE_LFLAGS += "-Wl,-rpath,\'\$$ORIGIN\':/usr/lib/qt5.5:/usr/lib/qt5.5/lib"
}
(The unix:!macx line makes it apply to linux only)
Windows, Linux and OSX behave quite differently. Windows is easiest: dump all the dll's in the application dir. OSX is next and Linux is most difficult.
Linux has certain search paths for searching shared objects. These search paths are mainly system libraries and possibly some user libraries. As you do not want to mess around with system files of your user one would prefer to have the shared objects in the application dir. This is possible but you have to tell Linux to read that directory. You can do this with setting the environment variable LD_LIBRARY_PATH. You can do this with a script. See my answer.
Assume that a program needs a shared library(bar.so) under the folder /usr/lib/foo. I understand if the bar.so was directly under /usr/lib, it would be automatically found. But as in my case the library could not be found automatically, because -I think so- it is under the folder /usr/lib/foo. However there are tons of other folders under /usr/lib and the corresponding programs using those libraries are working seamlessly.
So, how does this process work and how can I fix my issue?
Thanks.
Individual programs can control where they search for their libraries.
Also the search path can be controlled using the LD_LIBRARY_PATH env var:
http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
Try appending /usr/lib/foo to your LD_LIBRARY_PATH env var.
I am deploying a locally-compiled app to a remote Linux server. Since I don't have root account I cannot put needed shared libraries to /usr/lib
Is there a way to overcome this? I put libraries in same folder and changed "path" variable but did not work.
Two simple options.
You can set the LD_LIBRARY_PATH variable inside your script (see Section 3.3.1. of the shared libraries HOWTO). There are problems with this approach for production code, but if set in a wrapper script is probably ok.
You can call your app with the libraries specified on the command line by invoking the ld-linux program loader directly, as described in the manpage and HOWTO:
/lib/ld-linux.so.2 --library-path PATH EXECUTABLE