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.
Related
A very simple Qt project fails to build for me with Qt 5.10 in a Docker container (with an image derived from opensuse:tumbleweed). The project is as follows:
sh-4.4# cat test.pro
TEMPLATE = app
TARGET = test
INCLUDEPATH += .
INCLUDEPATH += sub
HEADERS = obj.h sub/iface.h
SOURCES = obj.cpp main.cpp
sh-4.4# cat sub/iface.h
#pragma once
#include <QtPlugin>
class Interface
{
public:
virtual ~Interface () {}
};
Q_DECLARE_INTERFACE (Interface, "org.meh.interface/1.0")
sh-4.4# cat obj.h
#pragma once
#include <QObject>
#include <sub/iface.h>
class Obj : public QObject
{
Q_OBJECT
Q_INTERFACES (Interface)
};
sh-4.4# cat obj.cpp
#include "obj.h"
sh-4.4# cat main.cpp
int main() {}
In this case moc complains as follows:
obj.h:9: Error: Undefined interface
Everything is fine in another container with Qt 5.9, and everything is also fine with Qt 5.10 when the project is built in openSUSE Build Service (which uses something else instead of Docker). Some quick googling did not reveal any relevant bugreports for recent Qt versions.
What could be wrong?
Running moc under strace shows Operation not permitted on various statx calls, which sheds some light on why exactly it fails (also, related to this question). This pull request is hopefully going to fix this.
Did you try to run the container with the --privileged (see Which capabilities are needed for statx to stop giving EPERM)?
I've followed the steps described in https://wiki.qt.io/How_to_link_to_a_dll
but, somehow I still get undefined reference errors.
This is what I did:
add to my .pro file the library folder path via INCLUDEPATH+=
add to my .pro file the .dll via LIBS+=
include the .dll (in my case "okFrontPanelDLL.h") via #include in my code
I don't know if it matters, but my library is taken from: http://intantech.com/files/RhythmStim_API_Release_170328.zip
and the extracted folder contains a single .dll and multiple source and header files (do i have to add all sources and headers from the library via SOURCES+= and HEADERS+=?).
Currently, I can declare a variable based on a class defined in the library
okCFrontPanel *dev;
but accessing functions defined for the class, e.g. calling the constructor like
dev = new okCFrontPanel;
leads to an undefined reference error.
edit: I tried direcly adding the source and header files form the library into my Sources folder instead of linking the library and the code works fine, so there is (probably) at least nothing wrong with how I am trying to use the functionalities of the library.
edit2: further information:
OS: Win 7 64 bit
Qt version: 5.9.0
compiler: MinGW 32bit
file location: /[PROJECT FOLDER]/mylibrary
#include <QCoreApplication>
#include "myLibrary/okFrontPanelDLL.h"
int main(int argc, char *argv[])
{
// QCoreApplication a(argc, argv);
// return a.exec();
printf("hello world\n");
okCFrontPanel *dev;
dev = new okCFrontPanel;
// dev->BoardModel;
// If only one Opal Kelly board is plugged in to the host computer, we can use this.
dev->OpenBySerial();
// Set XEM6010 PLL to default configuration to produce 100 MHz FPGA clock.
dev->LoadDefaultPLLConfiguration();
// Upload RhythmStim bitfile which is compiled from RhythmStim Verilog code.
dev->ConfigureFPGA("mylibrary/main.bit");
printf("omg dis is working\n");
}
I am using QT to make an application for Embedded linux device. When I started my application, mouse & keyboard was not working. From searching about this problem, I came to know that we need to run below command before starting the application:
export QWS_MOUSE_PROTO="USB:/dev/input/event-mouse"
export QWS_KEYBOARD="USB:/dev/input/event-keyboard"
After running above commands, I was able to use mouse and keyboard in my application. But this looks a bit odd because whenever I need to run my application, I have to run those commands. Also I will be setting my application to auto run after the boot so in that case I won't be able to run those commands. So I was wondering if I can include these commands somewhere in my code so that they automatically run and then application starts. Can anyone please guide me here. Please help. Thanks.
Instead of running your application, you could run a script:
#! /usr/bin/env bash
export QWS_MOUSE_PROTO="USB:/dev/input/event-mouse"
export QWS_KEYBOARD="USB:/dev/input/event-keyboard"
my_application
You can also set the environment variables inside of your application, before Qt is started. Use setenv:
#include <cstdlib>
int main(int argc, char ** argv) {
// Set default values if none are set.
setenv("QWS_MOUSE_PROTO", "USB:/dev/input/event-mouse", 0);
setenv("QWS_KEYBOARD", "USB:/dev/input/event-keyboard", 0);
QApplication app(argc, argv);
...
return app.exec();
}
External QWS_MOUSE_PROTO and QWS_KEYBOARD will override the internal defaults since the override parameter is set to zero. This is the desired behavior.
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?
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