我正在尝试制作一个可以在其他项目中使用的 Qt6 库。我可以在 Qt5 上使用它(使用 qmake),但我似乎无法在 Qt6 上使用它(使用 cmake)。值得注意的是,我的 Qt6 库项目与尝试使用它的 SampleProject 位于不同的文件夹中。
我做错/遗漏了什么?
SampleLibConfig.cmake.in
set(SAMPLELIB_VERSION 1.0.0)
@PACKAGE_INIT@
set_and_check(SAMPLELIB_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")
set_and_check(SAMPLELIB_SYSCONFIG_DIR "@PACKAGE_SYSCONFIG_INSTALL_DIR@")
check_required_components(SampleLib)
CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(SampleLib LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
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 Core Quick)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Quick)
add_library(SampleLib STATIC
SampleLib.cpp
SampleLib.h
SampleRect.qml
SampleLib_global.h
)
include(CMakePackageConfigHelpers)
set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} CACHE PATH "Location of header files" )
set(SYSCONFIG_INSTALL_DIR ${CMAKE_INSTALL_SYSCONFDIR}/${PROJECT_NAME} CACHE PATH "Location of configuration files" )
configure_package_config_file(${PROJECT_NAME}Config.cmake.in
${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
PATH_VARS INCLUDE_INSTALL_DIR SYSCONFIG_INSTALL_DIR)
write_basic_package_version_file(
${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
VERSION 1.0.0
COMPATIBILITY SameMajorVersion)
install(FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
target_include_directories(SampleLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(SampleLib PRIVATE
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Quick)
target_compile_definitions(SampleLib PRIVATE SAMPLELIB_LIBRARY)
SampleLib_global.h
#ifndef SAMPLELIB_GLOBAL_H
#define SAMPLELIB_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(SAMPLELIB_LIBRARY)
# define SAMPLELIB_EXPORT Q_DECL_EXPORT
#else
# define SAMPLELIB_EXPORT Q_DECL_IMPORT
#endif
#endif // SAMPLELIB_GLOBAL_H
SampleLib.h
#ifndef SAMPLELIB_H
#define SAMPLELIB_H
#include "SampleLib_global.h"
class SAMPLELIB_EXPORT SampleLib
{
public:
SampleLib()
{
}
};
#endif // SAMPLELIB_H
SampleRect.qml
import QtQuick 2.15
Rectangle {
color: "purple"
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(SampleProject VERSION 0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
find_package(Qt6 6.4 REQUIRED COMPONENTS Quick)
qt_standard_project_setup()
qt_add_executable(SampleProject
main.cpp
)
qt_add_qml_module(SampleProject
URI SampleProject
VERSION 1.0
QML_FILES Main.qml
)
# 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.
set_target_properties(SampleProject PROPERTIES
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.SampleProject
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)
set(SampleLib_DIR C:/Users/Ricky/Desktop/QTProjects/SampleLib/Build/Release)
find_package(SampleLib REQUIRED)
target_include_directories(SampleProject PRIVATE ${SampleLib_INCLUDE_DIRS})
#Issue: Cannot open input file 'SampleLib.lib'
target_link_libraries(SampleProject PRIVATE
Qt6::Quick
SampleLib
)
include(GNUInstallDirs)
install(TARGETS SampleProject
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
// Issue: I'd expect that I can format this as #include "SampleLib/SampleLib.h" (even though SampleLib is one directory above this project)
#include "../SampleLib/SampleLib.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
// Unresolved external symbol...
SampleLib test;
QQmlApplicationEngine engine;
const QUrl url(u"qrc:/SampleProject/Main.qml"_qs);
QObject::connect(
&engine,
&QQmlApplicationEngine::objectCreationFailed,
&app,
[]() { QCoreApplication::exit(-1); },
Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
主.qml
import QtQuick
// Issue: SampleLib: no such directory.
import "SampleLib"
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
SampleRect {
anchors.fill: parent
//color: "orange"
}
}
你的问题似乎是如何在很多地方重用你自己的库。
我的建议是将你的库项目上传到 GitHub,然后使用 FetchContent 将库获取到您想要在其中使用它的任何项目。这样您的库将与您的主项目一起使用和构建,并且可以在您想要使用它的任何项目中“重新获取”。我整理了一个小例子来说明它是如何工作的。
我已将一个非常小的库项目上传到我的 GitHub,名为 workbench。里面有这些文件:
CMakeLists.txt
cmake_minimum_required(VERSION 3.22.0)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
project(workbench VERSION 1.0.0)
# Using INTERFACE for header only library
add_library(workbench INTERFACE)
# Giving scope to files inside library
target_include_directories(workbench INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
模块.h
#include <string>
static std::string RandomVariable = "Hello from module";
从这里开始,我创建了一个小项目,其中包含我的
workbench
库。看起来如下:
CMakeLists.txt
cmake_minimum_required(VERSION 3.22.0)
project(tester VERSION 1.0.0)
# Allows us to use FetchContent
include(FetchContent)
# Fetches the repository from GitHub
FetchContent_Declare(workbench
GIT_REPOSITORY https://github.com/andrelehto/workbench.git
GIT_TAG v1.0.0
)
# Makes the repository available to us
FetchContent_MakeAvailable(workbench)
add_executable(tester main.cpp)
# Link to library from GitHub
target_link_libraries(tester workbench)
main.cpp
#include <iostream>
#include "module.h"
int main() {
std::cout << RandomVariable << std::endl;
}
请注意,
module.h
现在可以在我们的主项目中使用。