I have a Qt5 C++ project with a main app and a (created by me) shared library. It compiles and executes and I am able to deploy it. The issue is, that by deployment I need to put the compiled dll of my shared library in the same directory as the main executable. However, I preffer to keep the top level folder relatively clean and put the necessary files in an appropriate sub-tree of folders. So, my question is, what should I put in the *.pro file in order to change the path of the dll to myApp/myLib, where myApp is the folder where the main app's executable resides.
可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
回答1:
Since Windows does the search of DLL's for your program, and not the program itself, you can't tell your makefile where to search for the libraries.
You can, however:
- Add the desired folder where the dll's go to the PATH.
- Make a startup script, that sets the path where the libraries are, and then start the program.
- Compile statically, if you comply with the LPGL or Qt Comercial license, depending your case.
As a side note: Qt Plugins does what you want, but core dependencies aren't Qt plugins themselves.
回答2:
The Dynamic-Link Library Search Order is fairly static. To include subdirectories requires, that you customize DLL loading. There are a number of ways to accomplish what you are looking for.
- Delay loading the libraries (see Linker Support for Delay-Loaded DLLs) and adjusting the search paths during application startup.
By default, a compile-time dynamically linked library is loaded during process initialization, before any of your code runs. The linker provides options to delay load a DLL until the program calls a function in that DLL. That gives you a window of opportunity during application startup to adjust the DLL search paths1 (with a call to SetDllDirectory, for example).
Note: Keep in mind that globals are initialized before any user code runs. If the initializer for a global references a symbol from a delay load library, that library, too, is loaded before any user code runs. This is not a solution for those scenarios. - Delay loading libraries using custom delay load helpers (see Understanding the Helper Function and Developing Your Own Helper Function).
For each import, the system calls into the helper functions. Among other things, the helper functions are responsible for loading the modules. This allows to implement an arbitrarily complex library search. In this specific case it's probably easiest to set a notification hook for library loading only (see Calling Conventions, Parameters, and Return Type).
There are other ways, that may seem attractive, but you shouldn't really be using those. Here is a list including the rationale why not to use them:
- Changing the
PATH
environment variable: While easy to implement, this is a global solution to a local problem. Changing a global environment variable impacts the entire system. It can be modified by the user and other software, essentially breaking your application. And it uses up precious environment space (What is the maximum length of an environment variable?). - Changing the current directory: The current directory is part of the dynamic-link library search order, so changing it (e.g. through the startup directory setting of a .lnk) might work. However, the current directory is shared across all threads of a process, and any thread can change it at any time. In essence, this makes the current directory useless (for anything, really).
1 If you know the libraries ahead of time, you could instead manually load them (LoadLibrary), and have them picked up by the delay load helper functions. This will fail, though, in case any of these modules have dependencies that cannot be found in the standard search paths.