For experience, I'm importing chart.cpp and .h from the dynamic spline example (which works perfectly fine on its own) in my own CMake built app. The example is compiled with a .pro file.
I Tuned the CMakeLists.txt file to include the lib. The result is this file:
cmake_minimum_required(VERSION 3.5)
project(controlCenter VERSION 0.1 LANGUAGES CXX)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
find_package(Qt6 REQUIRED COMPONENTS SerialPort)
find_package(Qt6 REQUIRED COMPONENTS charts)
find_package(Qt6 REQUIRED COMPONENTS gui)
set(PROJECT_SOURCES
main.cpp
mainwindow.cpp
mainwindow.h
mainwindow.ui
chart.cpp
chart.h
)
include_directories(PRIVATE "libraries" "autogenerated" ".")
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_executable(controlCenter
MANUAL_FINALIZATION
${PROJECT_SOURCES}
)
# Define target properties for Android with Qt 6 as:
# set_property(TARGET controlCenter APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
# ${CMAKE_CURRENT_SOURCE_DIR}/android)
# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
else()
if(ANDROID)
add_library(controlCenter SHARED
${PROJECT_SOURCES}
)
# Define properties for Android with Qt 5 after find_package() calls as:
# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
else()
add_executable(controlCenter
${PROJECT_SOURCES}
)
endif()
endif()
target_link_libraries(controlCenter PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
target_link_libraries(controlCenter PRIVATE Qt6::SerialPort)
target_link_libraries(controlCenter PRIVATE Qt6::Charts)
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
# If you are developing for iOS or macOS you should consider setting an
# explicit, fixed bundle identifier manually though.
if(${QT_VERSION} VERSION_LESS 6.1.0)
set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.controlCenter)
endif()
set_target_properties(controlCenter PROPERTIES
${BUNDLE_ID_OPTION}
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)
include(GNUInstallDirs)
install(TARGETS controlCenter
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
if(QT_VERSION_MAJOR EQUAL 6)
qt_finalize_executable(controlCenter)
endif()
With this settings, the linker fails with this error:
ld.exe: CMakeFiles/controlCenter.dir/chart.cpp.obj:chart.cpp:(.rdata$.refptr._ZTV5Chart[.refptr._ZTV5Chart]+0x0): undefined reference to `vtable for Chart'
Chart class containes its destructor (files chart.h and chart.cpp are exactly like in the example):
#ifndef CHART_H
#define CHART_H
#include <QtCharts/QChart>
#include <QtCore/QTimer>
QT_BEGIN_NAMESPACE
class QSplineSeries;
class QValueAxis;
QT_END_NAMESPACE
QT_USE_NAMESPACE
//![1]
class Chart: public QChart
{
Q_OBJECT
public:
Chart(QGraphicsItem *parent = nullptr, Qt::WindowFlags wFlags = {});
virtual ~Chart();
public slots:
void handleTimeout();
private:
QTimer m_timer;
QSplineSeries *m_series;
QStringList m_titles;
QValueAxis *m_axisX;
QValueAxis *m_axisY;
qreal m_step;
qreal m_x;
qreal m_y;
};
//![1]
#endif /* CHART_H */
and :
#include "chart.h"
#include <QtCharts/QAbstractAxis>
#include <QtCharts/QSplineSeries>
#include <QtCharts/QValueAxis>
#include <QtCore/QRandomGenerator>
#include <QtCore/QDebug>
Chart::Chart(QGraphicsItem *parent, Qt::WindowFlags wFlags):
QChart(QChart::ChartTypeCartesian, parent, wFlags),
m_series(0),
m_axisX(new QValueAxis()),
m_axisY(new QValueAxis()),
m_step(0),
m_x(5),
m_y(1)
{
QObject::connect(&m_timer, &QTimer::timeout, this, &Chart::handleTimeout);
m_timer.setInterval(1000);
m_series = new QSplineSeries(this);
QPen green(Qt::red);
green.setWidth(3);
m_series->setPen(green);
m_series->append(m_x, m_y);
addSeries(m_series);
addAxis(m_axisX,Qt::AlignBottom);
addAxis(m_axisY,Qt::AlignLeft);
m_series->attachAxis(m_axisX);
m_series->attachAxis(m_axisY);
m_axisX->setTickCount(5);
m_axisX->setRange(0, 10);
m_axisY->setRange(-5, 10);
m_timer.start();
}
Chart::~Chart()
{
}
What can be the reason?
Hummmm... Clean / cmake / build did it!