Подтвердить что ты не робот

Внедрение проекта Qt через CMake

Я пытаюсь создать и запустить очень простой и простой пример Qt через Cmake, удалив файл .pro. Ниже приведен код для проекта Qt (структура каталогов для проекта Qt автоматически сгенерирована

Cmake (my project name)
├── headers
│   └── mainwindow.h
├── sources
│   ├── main.cpp
│   └── mainwindow.cpp
└── forms
    └── mainwindow.ui

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

Это мой CmakeLists.txt

project(Cmake)

find_package(Qt5Widgets)

set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)

QT5_WRAP_CPP(Cmake_hdr_moc mainwindow.h)
QT5_WRAP_UI(Cmake_form_hdr mainwindow.ui)

add_library(mainwindow ${Cmake_hdr_moc} ${Cmake_form_hdr})
qt5_use_modules(mainwindow Widgets)

add_executable(Cmake main.cpp mainwindow)
qt5_use_modules(Cmake Core Gui Widgets)

mainwindow.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralWidget"/>
  <widget class="QMenuBar" name="menuBar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>400</width>
     <height>29</height>
    </rect>
   </property>
  </widget>
  <widget class="QToolBar" name="mainToolBar">
   <attribute name="toolBarArea">
    <enum>TopToolBarArea</enum>
   </attribute>
   <attribute name="toolBarBreak">
    <bool>false</bool>
   </attribute>
  </widget>
  <widget class="QStatusBar" name="statusBar"/>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

Когда я создаю проект и запускаю Cmake, он указывает на файл mainwindow.h, указывающий "ui_mainwindow.h" нет такого файла или каталога.

4b9b3361

Ответ 1

В вашем script есть несколько ошибок, и некоторые вещи могут быть улучшены. После изменений он будет выглядеть следующим образом:

cmake_minimum_required(VERSION 3.0.2)
project(MyProject)

find_package(Qt5Widgets)

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)

add_library(mainwindow mainwindow.cpp)
target_link_libraries (mainwindow Qt5::Widgets)

add_executable(MyProject main.cpp)
target_link_libraries (MyProject mainwindow)

Ошибки:

  • Неверная директива add_executable. Вы пытаетесь добавить библиотеку, но для этого вам нужно использовать target_link_libraries. Поэтому вместо:

    add_executable(Cmake main.cpp mainwindow)
    

    Вам нужно:

    add_executable(Cmake main.cpp)
    target_link_libraries (Cmake mainwindow)
    
  • И еще одна ошибка в файле *.cpp отсутствует в директиве add_library:

    add_library(mainwindow mainwindow.cpp ${Cmake_hdr_moc} ${Cmake_form_hdr})

Рекомендации:

  • Также будет уместна установка версии CMake. Если вы используете automoc, вам нужна версия не менее 2.8.6, и если вы используете autouic, вам нужна версия не менее 3.0.2:

    cmake_minimum_required(VERSION 3.0.2)
    
  • Использование qt5_wrap_cpp с automock не требуется.

  • При использовании automock использование autouic вместо qt5_wrap_ui будет более подходящим.

  • Этот script корректен для проекта со следующей структурой в файловой системе:

    Project
    ├── CMakeLists.txt
    ├── main.cpp
    ├── mainwindow.cpp
    ├── mainwindow.h
    └── mainwindow.ui
    

    Если у вас есть другая структура, вы должны использовать include_directories, как было упомянуто @steveire.

  • (UPD). Поскольку я написал этот ответ, я предложил его несколько раз для новичков, которые пытаются встретиться с Qt через CMake. Они жалуются на неправильное название проекта - "Cmake". Для новичков, которые просто встречаются с CMake, трудно понять, где cmake - это просто часть имени проекта (и не является обязательным) и где cmake является частью директивы (и является обязательным). Поэтому я хотел бы заменить название проекта с "Cmake" на "MyProject". Это уменьшает связь между вопросом и ответом, но, с другой стороны, это делает ответ более дружелюбным для начинающих.

  • (UPD) Как уже упоминалось, @Erik Sjölund qt5_use_modules устарел и target_link_libraries следует использовать вместо этого.

Примечание. Лично у меня был неудачный опыт работы с automock; это хорошо для простого проекта с простой структурой. У меня были проблемы с случаем, когда мои включенные файлы были сохранены в отдельный каталог:

.
├── include
│   └── QtClass.h
└── src
    └── QtClass.cpp

И когда файлы с тем же именем были в разных подкаталогах:

.
├── NamespaceA
│   ├── QtClass.cpp
│   └── QtClass.h
└── NamespaceB
    ├── QtClass.cpp
    └── QtClass.h

Наконец: Это предложение основано на моем личном мнении, но я хотел бы предложить более явную версию script без использования automock и autouic, это более многословно, но в другой руке у вас больше контроля:

cmake_minimum_required (VERSION 2.8.12)
project (MyProject)

find_package (Qt5Widgets)

set (MyProjectLib_src ${PROJECT_SOURCE_DIR}/mainwindow.cpp)
set (MyProjectLib_hdr ${PROJECT_SOURCE_DIR}/mainwindow.h)
set (MyProjectLib_ui  ${PROJECT_SOURCE_DIR}/mainwindow.ui)
set (MyProjectBin_src ${PROJECT_SOURCE_DIR}/main.cpp)

qt5_wrap_cpp(MyProjectLib_hdr_moc ${MyProjectLib_hdr})
qt5_wrap_ui (MyProjectLib_ui_moc  ${MyProjectLib_ui})

include_directories (${PROJECT_SOURCE_DIR})
include_directories (${PROJECT_BINARY_DIR})

add_library (MyProjectLib SHARED 
    ${MyProjectLib_src}
    ${MyProjectLib_hdr_moc}
    ${MyProjectLib_ui_moc}
)
target_link_libraries (MyProjectLib Qt5::Widgets)

add_executable(MyProject ${MyProjectBin_src})
target_link_libraries (MyProject MyProjectLib)

Полная версия исходного кода проекта доступна по адресу GitLab.

Ответ 2

Вы не показали нам, где CMakeLists.txt находится в структуре каталогов. Если на верхнем уровне у вас будет

add_executable(Cmake sources/main.cpp sources/mainwindow.cpp)

и вам понадобится

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/headers)

В любом случае, выясните, где сгенерирован файл ui _ *. h, и добавьте каталог с include_directories.