I have a QT application app.exe and a QT plugin plugin.dll. My plugin.dll depends on many other dynamic libraries (e.g. lib1.dll, lib2.dll and so on). To distribute my project I have this folder structure (ignoring QT libraries):
app.exe
plugins\
plugin.dll
lib1.dll
lib2.dll
lib3.dll
The problem is that there are too many dependences on libX.dll and I want to hide them in a plugin folder, e.g.:
app.exe
plugin\
plugin.dll
lib1.dll
lib2.dll
lib3.dll
But this way libraries libX.dll are "unseen" to my plugin, so that it cannot be loaded. Is there any way to solve this problem?
I am using this code to import libX.dll in plugin.dll's pro-file:
LIBS += -Lpath -l lib1 -l lib2 -l lib3
One of the ways of solving this problem is:
Link all libraries dynamically (at runtime)
Add extra location to search for the libraries
These changes should be done in plugin.dll code:
/* Declare a pointer to import function */
typedef void (*FUNCTION)();
FUNCTION f;
/* Make system search the DLLs in my plugin folder */
// Variable "app" contains directory of the application, not the plugin
QDir app = QDir(qApp->applicationDirPath());
// Combine path
QString plugin_path = app.filePath("plugins/");
// Adding full path for DLL search
SetDllDirectory(plugin_path.toStdWString().c_str());
/* Linking the library */
QLibrary mylib("mylib.dll");
f = (FUNCTION ) mylib.resolve("function");
if (f != NULL)
f(); // You got the function from DLL
else
return; // DLL could not be loaded
This solution has disadvanges:
It is not platform independent (I think you can avoid using SetDllDirectory in UNIX-like systems but I am not sure)
If you import a lot of functions you will have a lot of pointers
Does any one know pure Qt solution?
Related
I have a .pri file which can be included both in a library project and in an app project. Some details in there are dependent on the current build type (lib or app).
What is the recommended way to detect if the current project is either an executable, a static library or a dynamic library?
What is the recommended way to detect if the current project is either an executable, a static library or a dynamic library?
The bundled scripts do inspect TEMPLATE and CONFIG variables. Here is an example code to perform such tests:
defineReplace(projectType) {
contains(TEMPLATE, ".*lib") {
CONFIG(shared, static|shared): return("dynlib")
return("lib")
}
contains(TEMPLATE, ".*app"): return("app")
return("other")
}
# example usage
prj = $$projectType()
equals(prj, "app"): message("Building the application")
else: message("Doing something different")
I've switched versions of QT (from 5.10.1 to 5.12.2) to get a more recent version of Mingw32 (from GCC/G++ 5.3 -> 7.3). The reasoning behind this is that have multiple products using the same library and using an old version of gcc is less than ideal. We've never had any issues with build before, but now I get the following error:
":-1: error: No rule to make target 'res/resources.qrc', needed by 'release/qrc_resources.cpp'. Stop."
Oddly enough, it does not stop the build from generating a completely functioning executable.
So far I've tried:
Cleaning the directory and building again
Deleting the build directory and building again
Not selecting shadow build option
Forcing Qmake (Build -> Run Qmake)
Creating a new .pro.user file
Deleting the whole repo, cloning it again, rebuilding the dependencies (we have a library which it relies on) and rebuilding QT
Adding the .qrc file to the includes (I know this was silly, but I was at my wits end)
Checking for deleted files (None that I can see)
Checking file names for inconsistencies(They seem ok)
Here is my qrc file
<RCC>
<qresource prefix="/">
<file>images/cnctbtn_connected.png</file>
<file>images/cnctbtn_connecting.png</file>
<file>images/cnctbtn_disconnected.png</file>
<file>images/configbtn.png</file>
<file>images/flash.png</file>
<file>images/logbtn.png</file>
<file>images/streambtn_start.png</file>
<file>images/streambtn_stop.png</file>
<file>images/d_logo_outlined.ico</file>
<file>images/d_logo_small.png</file>
<file>images/d_logo_small_outlined.png</file>
</qresource>
</RCC>
The list of resources which are located in the images folder
cnctbtn_connected.png
cnctbtn_connecting.png
cnctbtn_disconnected.png
configbtn.png
d_logo_small.png
d_logo_small_outlined.png
flash.png
logbtn.png
streambtn_start.png
streambtn_stop.png
d_logo_outlined.ico
The qrc_resource_File.cpp also looks ok. I see the bytes of the images in it, their names and assorted namespace declarations and functions in that name space.
The one thing I'm unsure of is why the images folder has it's on name in the resource name list.
Note: I've removed the bytes in this array, for my eyes and yours.
static const unsigned char qt_resource_name[] = {
// images
// cnctbtn_disconnected.png
// cnctbtn_connected.png
// cnctbtn_connecting.png
// streambtn_start.png
// d_logo_outlined.ico
// d_logo_small.png
// streambtn_stop.png
// d_logo_small_outlined.png
};
Ideally there would be no build error, which I don't really understand since I can see and use the executable produced. If you need any other information, don't hesitate to ask!
I have experienced certain problems when using libraries in premake4 scripts.
1) When creating a shared library (.dll) on Windows 10 using a premake4 script, it creates the dll fine, but it also creates a static library of small size (2K).
In my case, I was creating a shared library named MathLib.dll using a premake4 script. It did that correctly, but it also created a file named libMathLib.a of size 2K. (It may be empty.)
I don't see why there was a need for the Makefile generated by premake4 to create libMathLib.a, when in fact the objective was to create a .dll file. I think this may be a premake4 bug and I have raised it on the premake4 Issue tracker on github.
The premake4 lua script is as follows:
-- Dir : Files > C > SW > Applications > Samples >
-- premakeSamples > premake-sharedlib-create
--#!lua
-- A solution contains projects,
-- and defines the available configurations
solution "MathLib"
configurations { "Debug", "Release" }
-- A project defines one build target
project "MathLib"
kind "SharedLib"
language "C++"
files { "**.h", "**.cpp" }
includedirs {"../../../ProgramLibraries/Headers/"}
-- Create target library in Files > C > SW >
-- Applications > ProgramLibraries
targetdir "../../../ProgramLibraries/"
configuration "Debug"
defines { "DEBUG" }
flags { "Symbols" }
configuration "Release"
defines { "NDEBUG" }
flags { "Optimize" }
-- Register the "runmakefile" action.
newaction
{
trigger = "runmakefile",
description = "run the generated makefile to create the executable using the default ('debug' config)",
execute = function()
os.execute("make")
end
}
-- Register the "runmakefilerelease" action.
newaction
{
trigger = "runmakefilerelease",
description = "run the generated makefile to create the executable using the 'release' config)",
execute = function()
os.execute("make config=release")
end
}
2) The above problem is more serious than it sounds. Supposing I had already created a genuine static library named libMathLib.a in the Libraries dir, using a separate premake4 script. Subsequently, if I also create a shared library named MathLib.dll in the same directory as the static library, a dummy static library (possibly empty) would be created and replace the earlier genuine static library.
3) -- EDIT -- : I had reported this point (use of a static library) as a problem, but it has started working now. I don't know the reason, but the only difference, as far as I am aware, is that I had shut down and restarted my PC (and therefore my MSYS session on Windows 10). Therefore I am deleting this point.
How can I solve the above 2 problems?
That's the import library. You can turn it off with Premake's NoImportLib flag.
flags { "NoImportLib" }
So I have a Q_OBJECT tagged class, which requires pregenerated .moc to be usable.
In my .qbs file, I have a CppApplication item; this seems to be the wrong type of project, as qbs does not call moc ClassName.cpp to generate moc's for me. What should be used instead/tweaked?
-
So I knew about Qt.core dependency, but it wasn't working on my crippled install of Qt; while I was trying to fix it, these facts came up:
It was required to detect Qt toolchain (qbs-setup-qt) and call qbs-config-ui
Qbs indeed stores the build rules in core.qbs, linked in via Qt/core dependency.
it's possible to copy/paste the build rules into my own .qbs file and avoid external dependencies; I'm considering this as a dirty hack for deploying the code on really crippled build systems (now I have a word for Qt support on Gentoo).
I think you might be missing the dependency of the application on the Qt-modules.
The rule for generation of the moc files is part of the Qt.core module.
You might add this dependency with:
CppApplication {
name: "MyApp"
files: "path_to_source/**"
Depends { name: "Qt.core" } // Optional
Depends { name: "Qt.widgets" }
}
As all other Qt modules have an implicit dependency on Qt.core the explicit dependency could on Qt.core could be skipped if there is a dependency on a different Qt-module (Qt.widgets in this example).
More details could be found at http://doc.qt.io/qbs/qt-modules.html
I'm trying to write a test suit for my Qt(c++) application using google test, the main problem is that my application consists of one main program and various shared libs. Everything was working just fine, until I tried to do some code coverage using gcov/lcov (which don't operate on dynamic libs), so I modified all my .pro file to have a static lib compilation using :
CONFIG += staticlib create_prl
QMAKE_LFLAGS += -static
LIBS += ../../Libs/lib*.a
The problem is that google test test application is something like this:
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
so it detects the linkage at runtime, which means that when I compile the test application here is no warning or whatever that indicate a problem, and when running the test application it execute 0 test because it doesn't found any.
my solution (quit annoying one) is to define in each class which will be used for test a phony public static member and do an operation for the main test application on it:
class SETTINGS_TESTS_SHARED_EXPORT SettingsTests: public testing::Test {
public:
SettingsTests();
virtual ~SettingsTests();
static bool dummy;
protected:
virtual void SetUp();
virtual void TearDown();
private:
Settings* _setting0;
Settings* _setting1;
Settings* _setting2;
};
using namespace MBI::SETTINGS;
using namespace MBI::TESTS;
int main(int argc, char **argv) {
SettingsTests::dummy = true;
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
so I can force the linkage of that lib on my application.
I have also found the option -u to do something like that in gcc but doesn't seem to work. have anyone have a way to force static library linking if no symbol can be detected in compile time ?
I don't completely understand the question, it's not explained what ::testing::InitGoogleTest and RUN_ALL_TESTS actually do, and how they're related to dynamic linking.
But: you can make the GNU linker ignore unresolved symbols at link time by using the option --unresolved-symbols=ignore-all , or if you need to pass the option to gcc, -Wl,--unresolved-symbols=ignore-all.
In the google test doc there is a mention of linkage problem with visual c++ dll:
Important note for Visual C++ users
If you put your tests into a library and your main() function is in a different library or in your .exe file, those tests will not run. The reason is a bug in Visual C++. When you define your tests, Google Test creates certain static objects to register them. These objects are not referenced from elsewhere but their constructors are still supposed to run. When Visual C++ linker sees that nothing in the library is referenced from other places it throws the library out. You have to reference your library with tests from your main program to keep the linker from discarding it. Here is how to do it. Somewhere in your library code declare a function:
__declspec(dllimport) int PullInMyLibrary() { return 0; }
If you put your tests in a static library (not DLL) then __declspec(dllexport) is not required. Now, in your main program, write a code that invokes that function:
int PullInMyLibrary();
static int dummy = PullInMyLibrary();
This will keep your tests referenced and will make them register themselves at startup.
In addition, if you define your tests in a static library, add /OPT:NOREF to your main program linker options. If you use MSVC++ IDE, go to your .exe project properties/Configuration Properties/Linker/Optimization and set References setting to Keep Unreferenced Data (/OPT:NOREF). This will keep Visual C++ linker from discarding individual symbols generated by your tests from the final executable.
There is one more pitfall, though. If you use Google Test as a static library (that's how it is defined in gtest.vcproj) your tests must also reside in a static library. If you have to have them in a DLL, you must change Google Test to build into a DLL as well. Otherwise your tests will not run correctly or will not run at all. The general conclusion here is: make your life easier - do not write your tests in libraries!
And the solution adopted is pretty much what I did with g++. I'm suspecting the fact that qmake produce intermediary file moc_* and that my code in linked against that.