I am porting a project from Qmake to Cmake. Most of its utilities are now ok, and I already made the Cmake file for all of them. However, two projects are failing to compile on a "Undefined reference for vtable" linker error :
TaskTestLib/libTaskTestLib.a(remotejobsrunnerconfigurationtest.cpp.o): na função
RemoteJobsRunnerConfigurationTest::RemoteJobsRunnerConfigurationTest()': remotejobsrunnerconfigurationtest.cpp:(.text+0x2293): referência indefinida a
vtable for RemoteJobsRunnerConfigurationTest' TaskTestLib/libTaskTestLib.a(abstractjobconfigurationtest.cpp.o): na funçãoAbstractJobConfigurationTest::AbstractJobConfigurationTest()': abstractjobconfigurationtest.cpp:(.text+0x2315): referência indefinida a
vtable for AbstractJobConfigurationTest' collect2: error: ld returned 1 exit status
The class involved is a test class as expected by Qt Test. Here are the simplified project dependencies of the failing project :
TaskSingleTest -> needs TaskTestLib -> needs QtToolsLib
The RemoteJobsRunnerConfigurationTest stated in the error is part of TaskTestLib. It inherits AbstractJobConfigurationTest that is also part of TaskTestLib, which itself inherits from QtTestSuite that is from QtToolsLib.
The strange thing is that I have another test project already ported to Cmake that compiles and links well. Using it as an example, I noticed that those linking issues only happen with test classes from TaskTestLib. Other test libs (There have many) link fine. The issue would seem to be in the TaskTestLib project file, but it is nearly exactly the same as a working one. Here is TaskTestLib (failing lib) Cmake file :
cmake_minimum_required (VERSION 3.2)
project (TaskTestLib)
file(GLOB SOURCES "../../src/*")
set(INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../src/")
add_library(TaskTestLib ${SOURCES})
set_target_properties(TaskTestLib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${INCLUDE_DIR}")
target_link_libraries (TaskTestLib TaskLib QtToolsLib)
And ParsersTestLib (working lib) Cmake file :
cmake_minimum_required (VERSION 3.2)
project (ParsersTestLib)
file(GLOB SOURCES "../../src/*")
set(INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../src/")
add_library(ParsersTestLib ${SOURCES})
set_target_properties(ParsersTestLib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${INCLUDE_DIR}")
target_link_libraries (ParsersTestLib ParsersLib QtToolsLib)
Here are the classes involved in the linking error :
class RemoteJobsRunnerConfigurationTest : public AbstractJobConfigurationTest
{
Q_OBJECT
public:
RemoteJobsRunnerConfigurationTest() = default;
//RemoteJobsRunnerConfigurationTest();
virtual ~RemoteJobsRunnerConfigurationTest() = default;
private Q_SLOTS:
void testConfigure_ConfFileProperty();
void testConfigure_TimedRunProperty_data();
void testConfigure_TimedRunProperty();
protected:
AbstractJobConfiguration* CreateNewConfiguration() const override;
private:
void TestConfFileProperty(const std::string& propertyValue);
void TestTimedRunProperty(const std::string& propertyValue, const bool expectedValue);
};
class AbstractJobConfigurationTest : public QtTestSuite
{
Q_OBJECT
public:
AbstractJobConfigurationTest();
virtual ~AbstractJobConfigurationTest() = default;
private Q_SLOTS:
void testConfigure_NullConfiguration();
void testConfigure_UnknownProperty();
void testConfigure_UnknownSubObject();
protected:
AbstractJob *TestConfiguration(ConfigurationObject* confObject,
const std::vector<std::string>& expectedErrorMessages);
AbstractJob *TestConfigurationWithoutErrors(ConfigurationObject* confObject);
virtual AbstractJobConfiguration* CreateNewConfiguration() const = 0;
ConfigurationObject* CreateSimpleConfigurationObject(
const std::string& property, const std::string& value);
private:
AbstractJob* RunConfiguration(ConfigurationObject* confObject,
std::vector<std::string> &errorMessages);
void CheckErrorMessages(const std::vector<std::string> &errorMessages,
const std::vector<std::string> &expectedErrorMessages);
std::string BuildUnknownError(const std::string& object,
const std::string& name) const;
};
AbstractJobConfigurationTest::AbstractJobConfigurationTest()
: QtTestSuite("", "")
{
}
AbstractJobConfiguration*RemoteJobsRunnerConfigurationTest::CreateNewConfiguration() const
{
return new RemoteJobsRunnerConfiguration();
}
I don't think posting QtTestSuite code or its project Cmake file is relevant as they compile and link fine with the other project using them. I've only posted the parts of the cpp file that I found relevant, but I can post more if asked (including other project files, etc...).
Does anyone have an idea of why is this project not linking?
EDIT
The answer to the related question here does not answer my problem :
- My "Makefiles" are up to date, I regenerate them from Cmake and the problem still appears.
- There are no unimplemented pure virtual functions. Someone raised the pure virtual CreateNewConfiguration() method in AbstractJobConfigurationTest, but the class is not being instanciated anywhere. It is its child class that is being instanciated, and it does implement the pure virtual method.
Also, please note that there is an existing qmake project for this project, and the qmake project is building and linking the project correctly, with the same source code. Therefore, I expect the issue to be in the Cmake files.