Reputation: 1059
I am quite new to CMake and still struggling with the fundamentals. Currently I try to tell CMake to first download ZLib from GitHub and then use it for my BuildTest app. (By the way, I use Qt Creator to manage my project.) To my understanding, I have to use ExternalProject_Add to download and install zlib, and then I can link the installed library to my project. But whatever I do, I can't get it running, probably due to some misunderstanding of how CMake works. Executing CMake alone gives no error, but when I create my project, it fails with the following message:
ninja: error: 'zlib-install/lib/libz.a', needed by 'appBuildTest.exe', missing and no known rule to make it
This is consistent with the fact that the zlib-install
folder is empty, although I would expect the build to download ZLib and install it to this folder. Since I added add_dependencies(appBuildTest zlib)
, I would also expect that the build is finished before the linker tries to link it to my app. I suppose I am overlooking something simple, but I seem to be unable to find the issue.
This is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
project(BuildTest VERSION 0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 6.5 REQUIRED COMPONENTS Quick)
qt_standard_project_setup(REQUIRES 6.5)
set(ZLIB_DIR "${CMAKE_SOURCE_DIR}/ThirdParty/zlib")
set(ZLIB_BINARY_DIR "${CMAKE_BINARY_DIR}/zlib-build")
# Add zlib as an external project using Git to download it
include(ExternalProject)
ExternalProject_Add(
zlib
PREFIX ${ZLIB_BINARY_DIR}
GIT_REPOSITORY https://github.com/madler/zlib.git
GIT_TAG master
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/zlib-install
)
qt_add_executable(appBuildTest
main.cpp
)
qt_add_qml_module(appBuildTest
URI BuildTest
VERSION 1.0
QML_FILES
Main.qml
)
target_link_libraries(appBuildTest
PRIVATE Qt6::Quick
${CMAKE_BINARY_DIR}/zlib-install/lib/libz.a # Link with zlib
)
target_include_directories(appBuildTest
PRIVATE ${CMAKE_BINARY_DIR}/zlib-install/include
)
# Add the zlib build dependency to ensure it is built before the application
add_dependencies(appBuildTest zlib)
# Install the application
include(GNUInstallDirs)
install(TARGETS appBuildTest
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
If you like to have a minimal running example, I employed a very simple GUI (Main.qml):
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
visible: true
width: 300
height: 200
title: "BuildTest - Zlib Example"
Rectangle {
width: parent.width
height: parent.height
color: "#ffffff"
// A simple button
Button {
text: "Compress/Decompress Data"
anchors.centerIn: parent
onClicked: {
// Trigger compression and decompression from C++
console.log("Button clicked")
}
}
Text {
id: resultText
text: "Press the button to start"
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 20
}
}
}
And this is a main.cpp that should use ZLib:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QByteArray>
#include <QTextStream>
#include <QVariant>
#include <QDebug>
#include <zlib.h>
void compressAndDecompressData() {
QByteArray originalData = "Some text that will be compressed and decompressed using zlib.";
// Compress the data
uLongf compressedSize = compressBound(originalData.size());
QByteArray compressedData(compressedSize, Qt::Uninitialized);
int result = compress(reinterpret_cast<Bytef*>(compressedData.data()), &compressedSize, reinterpret_cast<const Bytef*>(originalData.constData()), originalData.size());
if (result != Z_OK) {
qWarning("Compression failed");
return;
}
// Decompress the data
QByteArray decompressedData(originalData.size(), Qt::Uninitialized);
uLongf decompressedSize = originalData.size();
result = uncompress(reinterpret_cast<Bytef*>(decompressedData.data()), &decompressedSize, reinterpret_cast<const Bytef*>(compressedData.constData()), compressedSize);
if (result != Z_OK) {
qWarning("Decompression failed");
return;
}
// Display the original, compressed, and decompressed data
qDebug() << "Original data:" << originalData;
qDebug() << "Decompressed data:" << decompressedData;
}
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
compressAndDecompressData();
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/Main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
Upvotes: 0
Views: 23