c++ - QMainWindow - 没有使用 CMake 的此类文件或目录
问题描述
我在使用 CMake 和 Qt5 时遇到问题。所以我的项目看起来像这样:
├── CMakeLists.txt
├── inc
│ └── qtbasicapp
│ ├── app
│ │ ├── Application.hpp
│ │ ├── fwd.hpp
│ │ └── IApplication.hpp
│ └── windows
│ ├── fwd.hpp
│ ├── IWindow.hpp
│ ├── main
│ │ └── MainWindow.hpp
│ └── Window.hpp
├── src
│ ├── app
│ │ ├── Application.cpp
│ │ └── CMakeLists.txt
│ ├── CMakeLists.txt
│ ├── main.cpp
│ └── windows
│ ├── CMakeLists.txt
│ ├── main
│ │ ├── CMakeLists.txt
│ │ └── MainWindow.cpp
│ └── Window.cpp
CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
project(BasicProject LANGUAGES CXX)
add_subdirectory(dependencies)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt5 COMPONENTS Widgets REQUIRED)
set(INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/inc)
set(DEPENDENCY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/dependencies)
set(HEADERS_DIR ${INCLUDE_DIR})
add_subdirectory(src)
add_subdirectory(test)
src/CMakeLists.txt:
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_subdirectory(app)
add_subdirectory(windows)
add_library(mainlib STATIC)
target_link_libraries(mainlib PUBLIC
qtbasicapp_app_lib
qtbasicapp_windows_lib
qtbasicapp_windows_main_lib
)
set(SOURCE_FILES
./main.cpp
)
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
target_include_directories(${PROJECT_NAME}
PUBLIC
${HEADERS_DIR}
${Qt5Widgets_INCLUDE_DIRS}
)
target_link_libraries(${PROJECT_NAME}
PUBLIC
mainlib
Qt5::Widgets
)
src/windows/CMakeLists.txt:
set(LIB_NAME qtbasicapp_windows_lib)
add_library(${LIB_NAME} OBJECT)
target_sources(${LIB_NAME}
PUBLIC
${INCLUDE_DIR}/qtbasicapp/windows/fwd.hpp
${INCLUDE_DIR}/qtbasicapp/windows/IWindow.hpp
${INCLUDE_DIR}/qtbasicapp/windows/Window.hpp
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/Window.cpp
)
target_include_directories(${LIB_NAME}
PUBLIC
${HEADERS_DIR}
)
target_compile_options(${LIB_NAME} PUBLIC -Werror -Wall -Wextra)
add_subdirectory(main)
src/windows/main/CMakeLists.txt:
set(LIB_NAME qtbasicapp_windows_main_lib)
find_package(Qt5 COMPONENTS Widgets REQUIRED)
add_library(${LIB_NAME} OBJECT)
target_sources(${LIB_NAME}
PUBLIC
${INCLUDE_DIR}/qtbasicapp/windows/main/MainWindow.hpp
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/MainWindow.cpp
)
target_include_directories(${LIB_NAME}
PUBLIC
${HEADERS_DIR}
/usr/include/x86_64-linux-gnu/qt5/QtWidgets
)
target_link_libraries(${LIB_NAME}
PUBLIC
Qt5::Widgets
)
target_compile_options(${LIB_NAME} PUBLIC -Werror -Wall -Wextra)
在 inc/qtbasicapp/windows/main/MainWindow.hpp 文件中,我包含 QMainWindow 并出现错误:
错误:
/usr/bin/c++ -I/home/konrad/dev/cpp/qt_basic_application/repository/inc -g -Werror -Wall -Wextra -std=gnu++17 -MD -MT src/app/CMakeFiles/qtbasicapp_app_lib.dir/Application.cpp.o -MF src/app/CMakeFiles/qtbasicapp_app_lib.dir/Application.cpp.o.d -o src/app/CMakeFiles/qtbasicapp_app_lib.dir/Application.cpp.o -c /home/konrad/dev/cpp/qt_basic_application/repository/src/app/Application.cpp
In file included from /home/konrad/dev/cpp/qt_basic_application/repository/src/app/Application.cpp:4:
/home/konrad/dev/cpp/qt_basic_application/repository/inc/qtbasicapp/windows/main/MainWindow.hpp:8:10: fatal error: QMainWindow: No such file or directory
8 | #include <QMainWindow>
| ^~~~~~~~~~~~~
compilation terminated.
[2/4] Building CXX object src/windows/main/CMakeFiles/qtbasicapp_windows_main_lib.dir/MainWindow.cpp.o
ninja: build stopped: subcommand failed.
主窗口.hpp:
#ifndef QTBASICAPP_WINDOWS_MAIN_MAINWINDOW_HPP_
#define QTBASICAPP_WINDOWS_MAIN_MAINWINDOW_HPP_
#include <qtbasicapp/windows/Window.hpp>
#include <qtbasicapp/windows/fwd.hpp>
#include <QMainWindow> // ERROR
namespace qtbasicapp
{
namespace windows
{
namespace main
{
class MainWindow : public Window, public QMainWindow
{
Q_OBJECT
public:
static IWindowPtr create(); //IWindowPtr from fwd.hpp
void open() override;
void close() override;
private:
MainWindow();
QWidget* mainWidget_;
};
} // namespace main
} // namespace windows
} // namespace qtbasicapp
#endif //QTBASICAPP_WINDOWS_MAIN_MAINWINDOW_HPP_
应用程序.hpp
#ifndef QTBASICAPP_APP_APPLICATION_HPP_
#define QTBASICAPP_APP_APPLICATION_HPP_
#include <qtbasicapp/app/IApplication.hpp>
#include <qtbasicapp/app/fwd.hpp>
#include <qtbasicapp/windows/fwd.hpp>
namespace qtbasicapp
{
namespace app
{
enum class ApplicationStatus
{
NoError = 0,
Warning = -1,
Fatal = -2
};
class Application : public IApplication
{
public:
static IApplicationPtr create();
~Application() override;
void start() const override;
void exit() const override;
private:
Application();
ApplicationStatus status_;
windows::IWindowPtr window_;
};
} // namespace app
} // namespace qtbasicapp
#endif // QTBASICAPP_APP_APPLICATION_HPP_
应用程序.cpp
#include <iostream>
#include <qtbasicapp/app/Application.hpp>
#include <qtbasicapp/windows/main/MainWindow.hpp> // ERROR
namespace qtbasicapp
{
namespace app
{
IApplicationPtr Application::create()
{
return std::unique_ptr<Application>(new Application);
}
Application::Application()
: status_(ApplicationStatus::NoError)
, window_(qtbasicapp::windows::main::MainWindow::create())
{}
Application::~Application()
{
exit();
}
void Application::start() const
{
std::cout << "Starting application" << std::endl;
}
void Application::exit() const
{
std::cout << "Closing application" << std::endl;
}
} // namespace app
} // namespace qtbasicapp
编辑:在 windows/CMakeLists.txt 中添加包含和链接库会产生相同的结果。
如果我添加
target_link_libraries(${LIB_NAME}
PUBLIC
Qt5::Widgets
)
到 app/CMakeLists.txt 我得到:/home/konrad/dev/cpp/qt_basic_application/repository/src/windows/main/MainWindow.cpp:13:未定义对 qtbasicapp::windows::main::MainWindow 的 vtable 的引用'
解决方案
推荐阅读
- sql - LIMIT 基于迄今为止 DISTINCT `foreign_key` 的 COUNT
- android - 如何检查连接而不改变离子4中的状态?
- android-emulator - 在 Windows 10 上安装带有 HAXM 的 Android 模拟器之前,我应该卸载 Hyper-V 吗?
- android - 如何检查是否支持音频流?
- jakarta-ee - 如何向 Java Web 应用程序添加模块化特性
- elasticsearch - 如何在弹性搜索中对多个索引的结果进行排序和限制
- javascript - 我想比较当前日期的日期,如果日期位于日期之间,则禁用按钮
- laravel - 如何检查用户是否为管理员?
- r - dplyr - 变异:DT 中转义的列为假:数据表标题已编辑;是 (dplyr - mutate: 使用动态变量名...(用于`DT::datatable`))
- android - 访问更新的列表视图的第一个元素会导致 System.ArgumentOutOfRangeException