首页 > 解决方案 > 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 的引用'

标签: c++cmakeqt5qmainwindow

解决方案


推荐阅读