Oddly enough, the task has a solution and the libraries necessary for the application can really be put in a separate directory and without using dynamic loading of libraries using only static linking. This is done with the help of the so-called Assemblies (builds), whose support appeared in Windows XP .
In short, the technology is as follows. A manifest file is inserted into the executable file of the application, which instructs the application to use some assembly. The executable file loader reads this manifest and searches for a directory with an assembly , and among the search paths there is a directory with an executable file of the application.
Now in more detail, on an example and in details.
Let's create the simplest C ++ application:
#include <iostream> int main(int, char*[]) { std::cout << "Hello, World!" << std::endl; }
Being compiled using the MinGW compiler (MinGW-builds 6.3.0), this application in my case requires the files libgcc_s_sjlj-1.dll , libstdc++-6.dll and libwinpthread-1.dll . At the same time, the executable file itself imports only libstdc++-6.dll , which, in turn, imports the other two. Let's call our "assembly", for example, libs , create the directory libs in the directory with the main executable file of our application and place the three DLLs mentioned above inside it.
Next, create a manifest. The name of the manifest file must consist of the name of the assembly and have the extension .manifest , that is, in our case, libs.manifest . The contents of the file should be as follows:
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity name="libs" version="1.0.0.0" type="win32" /> <file name="libstdc++-6.dll" /> <file name="libgcc_s_sjlj-1.dll" /> <file name="libwinpthread-1.dll" /> </assembly>
It should be noted that although our application imports only one library, you need to register everything in the manifest, otherwise the application will not work. Thus, we have the following directory and file structure ( app.exe is the name of our application):
ββ app.exe ββ libs ββ libs.manifest ββ libgcc_s_sjlj-1.dll ββ libstdc++-6.dll ββ libwinpthread-1.dll
And finally, the final chord! We create the manifesto which we will implement in our application. Let it be in a file named manifest.xml :
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="libs" version="1.0.0.0" language="*" /> </dependentAssembly> </dependency> </assembly>
The build parameters specified in this manifest should be the same as the ones we specified earlier. Now it only remains to create a resource file in which to point to our manifest.
#include <windows.h> CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "manifest.xml"
and link it to the application (in the case of CMake , for example, by specifying the name of the resource file in the source list).
LD_LIBRARY_PATH). - 0andriy