Qt6 CMake: Creating Static and Dynamic Libraries in Qt

Hi~ This is Weekly Qt, dedicated to sharing valuable Qt knowledge.As projects grow larger, they need to be divided into multiple modules for development, reducing coupling and facilitating collaboration among multiple developers. At this point, it is inevitable to create static and dynamic libraries.This article introduces the CMake interface provided by Qt for creating static and dynamic libraries: qt_add_library().

Example program demonstrating how to display a button from a custom control library in a window. The project structure is as follows:

/BuildWidgetAppWithLib ✗ tree |-- CMakeLists.txt`-- src    |-- app    |   |-- CMakeLists.txt    |   |-- main.cpp    |   |-- mainwindow.cpp    |   |-- mainwindow.h    |   `-- mainwindow.ui    `-- libcontrols        |-- CMakeLists.txt        |-- cpushbutton.cpp        `-- cpushbutton.h

01 Creating Library FilesFirst, create a library file and add a custom button class to it. Let’s take a look at the CMakeLists.txt file for creating the library: BuildWidgetAppWithLib/src/libcontrols/CMakeLists.txt

qt_add_library(controls SHARED    cpushbutton.cpp    cpushbutton.h)target_link_libraries(controls PRIVATE Qt6::Widgets)target_include_directories(controls INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

The qt_add_library() function creates a dynamic library, which is essentially a wrapper around CMake’s add_library(), adding some Qt-specific logic. This function has been supported since Qt 6.2, with the following prototype:

qt_add_library(target    [STATIC | SHARED | MODULE | INTERFACE | OBJECT]    [MANUAL_FINALIZATION]    sources...)

Common parameters include:

  • STATIC: Indicates the creation of a static library
  • SHARED: Indicates the creation of a dynamic library
target_link_libraries(controls PRIVATE Qt6::Widgets)

Since the library uses content from QWidgets, it is necessary to add the corresponding dependency.

target_include_directories(controls INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

target_include_directories() ensures that all targets using this library will include the specified path, making it easy to find the cpushbutton.h header file. From the project structure, we can see that cpushbutton.h is in the same directory as CMakeLists.txt, so we can simply add ${CMAKE_CURRENT_SOURCE_DIR}.

`-- libcontrols  |-- CMakeLists.txt  |-- cpushbutton.cpp  `-- cpushbutton.h

The implementation of CPushButton is quite simple, inheriting from QPushButton and then writing a stylesheet to implement the custom button.

Qt6 CMake: Creating Static and Dynamic Libraries in Qt

#include "cpushbutton.h"CPushButton::CPushButton(QWidget *parent)    : QPushButton{parent}{    this->setStyleSheet(R"(        QPushButton {            background-color: #1b60e7;            border-radius: 6px;            color: white;            padding: 6px;            font-size: 14px;            border-style: solid;            border-width: 2px;            border-color: #0541b2;        }        QPushButton:hover {            background-color: #366ef4;        }        QPushButton:pressed {            background-color: #0541b2;        }    )");}

02 Using the Library

Next, use the custom control library in the executable project’s CMakeLists.txt:

BuildWidgetAppWithLib/src/app/CMakeLists.txt

find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)set(PROJECT_SOURCES        main.cpp        mainwindow.cpp        mainwindow.h        mainwindow.ui)qt_add_executable(BuildWidgetAppWithLib    MANUAL_FINALIZATION    ${PROJECT_SOURCES})target_link_libraries(BuildWidgetAppWithLib PRIVATE    controls    Qt${QT_VERSION_MAJOR}::Widgets)

We only need to focus on target_link_libraries(BuildWidgetAppWithLib PRIVATE controls…), which links the controls library, our previously defined library.

Then, use the custom control in our source code:

#include "mainwindow.h"#include "./ui_mainwindow.h"#include "cpushbutton.h"MainWindow::MainWindow(QWidget *parent)    : QMainWindow(parent)    , ui(new Ui::MainWindow){    ui->setupUi(this);    auto button = new CPushButton(this);    button->setText("CPushButton");    button->setObjectName("cpushButton");    ...    ui->verticalLayout->addWidget(button, 0, Qt::AlignmentFlag::AlignHCenter);}

03 Main Project File

Now, let’s take a look at the sub CMakeLists.txt added in the main project file, BuildWidgetAppWithLib/CMakeLists.txt

cmake_minimum_required(VERSION 3.16)project(BuildWidgetAppWithLib VERSION 0.1 LANGUAGES CXX)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)qt_standard_project_setup()add_subdirectory(src/libcontrols)add_subdirectory(src/app)set_target_properties(BuildWidgetAppWithLib PROPERTIES    WIN32_EXECUTABLE ON    MACOSX_BUNDLE ON)

After compiling and running, the effect is as follows:

Qt6 CMake: Creating Static and Dynamic Libraries in Qt

References

[1]https://doc.qt.io/qt-6.8/en/cmake-get-started.html#building-libraries

We welcome submissions to [email protected], with no formatting requirements. Your best practices deserve to be seen!

Related Articles

Qt6 CMake: Goodbye qmake, Introduction to CMake

Qt6 CMake: Building QWidgets Applications

Qt6 CMake: Managing Qt Resource Files

Leave a Comment