Shared libraries on Windows - dependencies using wrong dll - c++

I have a C++ code that uses gdal as library. Compiled with intel c++ compiler 16 on visual studio 2013.
In the configuration, I specify the gdal library path and library file to link with:
Additional Library Directories: C:\OSGeo4W64\lib (where gdal_i.lib is)
Additional Dependencies: gdal_i.lib
It used to work a few months ago, but something must have changed in my system. Now, when I try my executable, I get a popup with error:
The ordinal 361 could not be located in the dynamic link library SSLEAY32.dll
I can fix it by copying the SSLEAY32.dll from the gdal folder in the executable folder or by removing any call to gdal from my code, but I would like to fix my system rather. How to tell Windows to look in the right directory (I played with the PATH a lot with no success).
Using Dependency Walker, it seems that the gdal.dll is not the one from my OSGEO path, but is taken from my miniconda install. Is there a clean way to fix it? I though that if a library had its dependencies in the same folder, those ones would be used.
EDIT: Solution, thanks to Naidu's answer:
add C:\OSGeo4W64\bin; at the beginning of my path, such that the correct gdal202.dll is used in priority.
but now python does not start anymore, because it is not selecting its own gdal libraries in the miniconda folder but rather in OSGeo4W64... I can get one or the other working with the same path but not both
solution place first in the PATH the directory of Miniconda python executable, then OSGeo4W64 libraries path, then Miniconda libraries path

Additional Library Directories will helps in only for looking up the .lib (static libraries) files, but not for DLLs.
The DLLs are looked up as shown in the order in below link.
https://msdn.microsoft.com/en-us/library/7d83bc18.aspx
So now, if your intended DLL is to be picked up, then place the DLL in any of the locations in first 4 steps said in above link..... or you can edit the PATH variable of user variables of Environment variables, with your DLL location.
Because
User variables take precedence over system environment variables. The
user path is appended to the system path.

Related

How to apply the libraries and plugins configuration loaded in QLibraryInfo in a QApplication?

Context: I have built a c++ executable using Qt 5.13.1 on an OpenSUSE platform (some Linux distribution).
I have to install it on a platform that already have an old Qt version installed and I can't get rid of it.
So I have installed the proper version of the needed Qt shared libraries (plus the platforms plugins) at a custom location and set up a qt.conf file that will specify the library path to use (same thing for the plugin path).
My own Qt installation folder contains:
A lib/ directory which contains the libraries to use.
A plugins/ directory which contains the platforms/ plugin folder.
The qt.conf file is installed alongside my executable and is filled as follows:
[Paths]
Prefix = relative_path/from/executable_location/to/install_dir/
I don't need to specify the lib/ and plugins/ directories in the entries Libraries and Plugins because they are defaulted at these values.
But even if I set them explicitly, it changes nothing.
I also tried with absolute paths but it changes nothing too.
Issue: The issue I encounter is that my executable does not load the libraries, neither find the platforms plugins, despite the qt.conf file is successfully loaded.
I have displayed the output of the following instructions:
QLibraryInfo::location(QLibraryInfo::PrefixPath);
QLibraryInfo::location(QLibraryInfo::LibrariesPath);
QLibraryInfo::location(QLibraryInfo::PluginsPath);
And they contains what's I specified in my qt.conf file. So the issue does not come from here.
Question: I have checked that QLibraryInfo field members had been properly initialized but it seems that my QApplication instance just ignore it.
How to make the QLibraryInfo configuration to be applied by the QApplication instance ?
I know that there exist a QCoreApplication::addLibraryPath() member than could be used to load libraries but I can't find anything alike for the Qt plugins as well.
But I'm pretty sure that we don't have to use this function since the information are already loaded by QLibraryInfo.
EDIT:
After some more investigations, I've found that it works fine for loading the plugins.
The problem remains the same for loading the libraries. It seems that I missed something but I cannot figure it out.
For now, I use the LD_PRELOAD environment variable in order to make it work (which is quite ugly).
EDIT 2:
I found two threads on internet about guys having the same issue:
https://forum.qt.io/topic/58499/solved-problems-with-setting-paths-to-libs-and-plugins-in-qt-app-s-executable-file
https://www.qtcentre.org/threads/32236-qt-conf-(again)-on-windows
The second one is explaining why the library load does not work.
Actually, in order to be able to parse the qt.conf file, the application needs to have the Core module loaded (libQt5Core.so.5 in my case) which makes sense (I should have thought of it).
The issue here is that libQt5Core.so.5 is one of the libraries to load (it's a vicious circle), so the executable cannot run at all.
Solution (still not load any library): It seems that I can't avoid to either load libQt5Core.so.5 with LD_PRELOAD or add it alongside the executable location.
Note: We can use LD_LIBRARY_PATH instead of LD_PRELOAD if there is no already existing Qt installation in the system "lib" directories.
I use LD_PRELOAD here because I want my Qt installation to take precedence over the already existing one (and be loaded first/instead of the system installed ones).
The problem with your libraries is that the Linux dynamic linker only searches a few standard locations, and other paths configured in /etc/ld.so.conf. One workaround is the environment variable LD_LIBRARY_PATH with the paths of your libraries. Another is the RPATH/RUNPATH values embedded in your binaries. CMake uses RPATH by default, and you can use QMAKE_RPATH in Qmake projects too. You can assemble by hand a directory with programs and libraries related using RPATH, but my advice is to create AppDir / AppImage packages using linuxdeployqt which is very similar to using the official Qt tools windeployqt and macdeployqt.
I have finally found out what was wrong.
qt.conf is parsed by Qt Core at runtime.
But the executable dependencies are loaded before the QApplication even exists. If they are not found, the program will just crash right at the beginning (dependencies loading step). And so, qt.conf will never be parsed.
In my case, I have an already existing installation of Qt in the system libraries folder. These are the ones that are found by the loader.
In this case, the dependencies are found and the programs runs (assuming there's no incompatibility between the two versions).
But even if the qt.conf is now parsed, the good version of the library will still not be loaded because the loader already has loaded the dependencies from the wrong Qt install (found at loading step).
Therefore the morality is: We cannot load executable dependencies by using qt.conf because they must be known before execution time (when the loader is looking for them).
Possible solutions:
Install the libraries in one of the folder searched by the loader (/usr/lib/ for example). If there is an already installed version of the libraries, remove it if possible, or if not, do ensure/check that you placed the proper version in a folder that will be searched first by the loader.
Use LD_LIBRARY_PATH to tell the loader where to search for libraries (if a wrong version is already installed, use LD_PRELOAD instead because LD_LIBRARY_PATH will not take precedence over what's inside /etc/ld.so.conf).
Set a rpath (which locates the proper installation directory of the libraries) when building the executable.
Add the required shared libraries in the executable directory.
(Not tested) Explicitly call the loader at application startup with the --library-path option (for example: "$ /lib/ld-linux.so.2 --library-path my_lib_path executable").
I may have missed other workarounds, this list is not guaranteed to be exhaustive.

Preventing CMake from finding installed libraries instead of "local" libraries

I'm working on multiple projects at the same time (some libraries, and some games that depend on them). They're all on GitHub, in separate repos.
For convenience, I pull every repo in a "workspace folder", like this:
/home/myWorkspace/Library1/
/home/myWorkspace/Library2/
/home/myWorkspace/Library3/
/home/myWorkspace/App1/
/home/myWorkspace/App2/
I have FindLibrary1, FindLibrary2 and FindLibrary3 .cmake files, which, in order, look for the library in ../ (which corresponds to the "myWorkspace" folder), then /usr/lib/.
While on Windows CMake finds the libraries in myWorkspace/, on Linux, no matter what, installed libraries are always found first.
Since I'd like to work in myWorkspace/ folder, then installing the libraries after I'm done, I'd prefer CMake to find and link everything within the myWorkspace/ folder.
I'd also like CMake to search for the libraries in /usr/lib/ and /usr/local/lib/ if there is no myWorkspace/ folder, but if myWorkspace/ exists, it should have the priority.
Examples of CMake files I'm using:
SSVUtils: library with no dependancies
SSVUtils CMakeLists: https://github.com/SuperV1234/SSVUtils/blob/master/CMakeLists.txt
FindSSVUtils.cmake: https://github.com/SuperV1234/SSVUtils/blob/master/cmake/modules/FindSSVUtils.cmake
SSVUtilsJson: library that depends on SSVUtils and SSVJsonCpp
SSVUtilsJson CMakeLists: https://github.com/SuperV1234/SSVUtilsJson/blob/master/CMakeLists.txt
FindSSVUtilsJson.cmake: https://github.com/SuperV1234/SSVUtilsJson/blob/master/cmake/modules/FindSSVUtilsJson.cmake
Any ideas how I can prioritize the myWorkspace/ folder while still having the possibility to find libs in file system paths?
By default, find_path (or find_library, etc.) first checks for files in the system standard locations, before searching in the values provided in PATH. That's why "installed" libraries are always found first on Linux (but not on Windows, that doesn't have standard locations for installed libraries).
You can disable that behavior by using the NO_CMAKE_SYSTEM_PATH option: it will skip detection of files in standard locations.
Now... if you still want to use the installed libraries as a fallback when local versions are not found, you can do it in a two step process:
find_path(... NO_CMAKE_SYSTEM_PATH)
if (nothing_found)
find_path(...)
endif()

Eclipse C++ project not resolving LD_LIBRARY_PATH include variables

I have a C++ project I am importing and it is using activemq libraries. After I import the project, I set the LD_LIBRARY_PATH variable under environment to point to
/usr/local/include/activemq-cpp-3.4.2
This allows the project to see all the libraries for activemq and I can see it show up in my includdes folder in the project explorer. When I go to Build Project, I am getting tons of errors to references of includes/objects that are inside /usr/local/include/activemq-cpp-3.4.2. The interesting thing is that the binary is still being produced, yet there are about 80 errors due to the library files not being found. How is the binary being made? Also, what must I do to the LD_LIBRARY_PATH environment variable so the project is properly including those files?
I have tried launching eclipse with the
./eclipse -clean
But that didn't seem to help. Any ideas are welcome, and thank you in advance!
EDIT:
I am using Eclipse Juno with C++ verseion 4.1.2 on Redhat 4.X
LD_LIBRARY_PATH isn't used for locating include directories. It's used to inform the system of a list of directories to search for shared libraries: compiled support libraries, not e.g. SDKs for Eclipse.
You should use the project's properties to add to the places that are searched for includes: C++ General->Paths and Symbols->Includes
Also use the properties - not LD_LIBRARY_PATH - if you do need to link against other libraries: : C++ General->Paths and Symbols->Library Paths
Finding header files is not the purpose of LD_LIBRARY_PATH. That environment variable is to tell the OS where to start looking for shared libraries — *.so files. The OS looks for those when preparing the execute your program. The compiler uses the include path to search for headers when it encounters an #include statement in your source code.
Don't modify LD_LIBRARY_PATH to affect compilation of your program.
Eclipse lets you set your include path in your project options.

How can I find libraries to load them dynamically with dlopen

In the project I am working on, we provide the possibility to dynamically load additional features. For that we use dlopen.
To find this libraries we have something we call module path. There we have a default path, where the shared libraries are (a lot of them are shipped).
At the moment we have two default paths: we first look in the build directory for the shared library and afterwards in the install directory. This is because it should also be possible to run the application without installing it (so in that case it needs to look first in the build directory).
Now the problem ist, if a user builds the application from source and installs it with make install, the libraries in her build directory are loaded by default. This will result in a crash. So it only works if the user afterwards removes or renames the build directory.
No the question: is there a trick (either by C++ or by the build system) to know whether the application is installed or not. The problem is, that the functionality is implemented in a shared library and the implemented way to search for modules has to work also for other applications that link against our library (so we can not rely on the path of the executable). We use CMake as a build system.
To make the situation even harder, the solution has to work on Windows, Linux and Mac OS X.
EDIT:
I further investigated and the problem is more complicated. This is the situation:
There is a small executable a
Furthermore there is a "main" library main.so
then there is a dynamically loaded library lib.so
lib.so links against main.so
The problem is, that lib.so has the absolute path to main.so in the build directory in its rpath. Thanks to the tip of #MSalters I now was able to make a hack to make sure to load the correct version of lib.so (the one in the install directory) but since it has the build path in the rpath it loads the wrong main.so (so in fact there are two copies of main.so in the memory - this messes things up).
Is there a way to remove this reference to the build path from the library? I tried all options of cmake related to rpath without success
Can't you check where the executable itself is? If it's in the build directories, use build libraries -- if it's in the install, use install?
getcwd() has equivalents on all of those platforms, but it might not be what you want -- it depends on how you run the executable.
To get the process's location is system specific, I think, but it shouldn't be too hard to wrap that.
The installed version should not have the build directory in the rpath.
You might want to do the linking twice (once for the build version and once for the installed version). Usually, on *nix systems, the installed binary has some static path where it tries to find plugins. You might define some environment variable (or command-line argument) to overload it for the build execution (and use a wrapper script to set it in the build environment).
Check how it is solved by some projects (Firefox for example).
I don't know much about windows system but I think the standard way of doing this is to search plugins in the same directory as the executable.

eclipse sfml library issues

I pulled out an application that I wrote in C++ using the sfml library, but I'm having trouble setting up the library in Eclipse. I specified the include path, the lib path and included all the necessary .so libraries to link to. the application compiles fine but it complains at runtime about missing libraries. Why is this happening? Didn't I include the path to the libraries in the project settings already? I have even tried to place all the .so's in the executable directory with no luck.
There is only the name of the shared lib stored in the executable. At program startup the dynamic linker then searches for the specified libs in its search paths. You can add/specify search paths by placing them colon separated in the environment variable LD_LIBRARY_PATH or by specifying them in /etc/ld.so.conf (at least if you use some unix based OS). On windows the whole PATH environment variable is used when searching for dynamic-link libraries (DLL).
To see the paths of shared libraries used by a given application run ldd applicationPath.