C++ 通过CMake实现Qt项目

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25989448/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 11:29:12  来源:igfitidea点击:

Implementing Qt project through CMake

c++qt

提问by user3877872

I am trying to build and run very simple and basic example of Qt through Cmake, removing the .pro file. The following is the code for Qt project(the directory structure for the Qt project automatically generated is

我正在尝试通过 Cmake 构建和运行非常简单和基本的 Qt 示例,删除 .pro 文件。下面是Qt工程的代码(Qt工程自动生成的目录结构为

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

mainwindow.h

主窗口.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

主窗口.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();
}

This is my CmakeLists.txt

这是我的 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

主窗口.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>

When I build the project and run Cmake, it points to file mainwindow.h indicating 'ui_mainwindow.h' no such file or directory.

当我构建项目并运行 Cmake 时,它​​指向文件 mainwindow.h,指示 'ui_mainwindow.h' 没有这样的文件或目录。

回答by Gluttton

Your script has several errors, also a few things can be improved. After changes it will belooks like:

您的脚本有几个错误,还有一些可以改进的地方。更改后将如下所示:

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)

Errors:

错误

  1. Wrong add_executabledirective. You try to add a library, but for this purpose you need to use target_link_libraries. So instead of:

    add_executable(Cmake main.cpp mainwindow)
    

    You need:

    add_executable(Cmake main.cpp)
    target_link_libraries (Cmake mainwindow)
    
  2. And one more mistake is missing *.cppfiles in the add_librarydirective:

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

  1. 错误的add_executable指令。您尝试添加一个库,但为此您需要使用target_link_libraries. 所以而不是:

    add_executable(Cmake main.cpp mainwindow)
    

    你需要:

    add_executable(Cmake main.cpp)
    target_link_libraries (Cmake mainwindow)
    
  2. 还有一个错误是指令中缺少*.cpp文件add_library

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

Recommendations:

建议

  1. Also setting version of CMakewould be appropriate. If you use CMAKE_AUTOMOCyou need a version not less than 2.8.6, and if you use CMAKE_AUTOUICyou need a version not less than 3.0.2:

    cmake_minimum_required(VERSION 3.0.2)
    
  2. Using qt5_wrap_cppwith CMAKE_AUTOMOCisn't necessary.

  3. When you use CMAKE_AUTOMOCusage CMAKE_AUTOUICinstead of qt5_wrap_uiwill be more appropriate.

  4. This script is correct for the project with the following structure in the file system:

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

    If you have another structure you should use include_directoriesas was mentioned by @steveire.

  5. (UPD) Since, I've written this answer, I suggested it several times for beginners who try to meet with Qtthrough CMake. They complain of an inappropriate name of the project - "Cmake". For beginners who just meet with CMakeis difficult to realize where cmake- is just part of the project name (and isn't mandatory) and where cmakeis part of a directive (and is mandatory). So I'd like to replace the name of the project from "Cmake" to "MyProject". This reduces connection between question and answer, but on the other hand this makes the answer more friendly for beginners.

  6. (UPD) As was mentioned by @Erik Sj?lund qt5_use_modulesis obsoleteand target_link_librariesshould be used instead.

  1. 设置 version ofCMake也是合适的。如果你使用CMAKE_AUTOMOC你需要一个不低于2.8.6的版本,如果你使用CMAKE_AUTOUIC你需要一个不低于3.0.2的版本:

    cmake_minimum_required(VERSION 3.0.2)
    
  2. 没有必要使用qt5_wrap_cppwith CMAKE_AUTOMOC

  3. 当你使用CMAKE_AUTOMOC用法CMAKE_AUTOUIC而不是qt5_wrap_ui会更合适。

  4. 此脚本适用于文件系统中具有以下结构的项目:

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

    如果你有另一种结构,你应该使用@steveireinclude_directories提到的。

  5. ( UPD) 因为,我已经写了这个答案,我多次向试图Qt通过CMake. 他们抱怨项目名称不合适——“Cmake”。对于刚接触的初学者来说,CMake很难意识到cmake-在哪里只是项目名称的一部分(并且不是强制性的),而cmake在哪里是指令的一部分(并且是强制性的)。所以我想将项目名称从“Cmake”替换为“MyProject”。这减少了问题和答案之间的联系,但另一方面,这使答案对初学者更加友好。

  6. ( UPD) 正如@Erik Sj 所提到的那样?lundqt5_use_modules已过时target_link_libraries应改为使用。

Note: Personally I have had unsuccessful experience with CMAKE_AUTOMOC; it's good for a simple project with plain structure. I've had problems with a case when my include files were stored into a separate directory:

注意:我个人有过不成功的经验CMAKE_AUTOMOC;它适用于结构简单的简单项目。当我的包含文件存储到单独的目录中时,我遇到了问题:

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

And when files with the same name were into different subdirectories:

当具有相同名称的文件位于不同的子目录中时:

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

Finally: This is a suggestion based on my personal opinion, but I'd like to propose more explicit versionof the script without usage of CMAKE_AUTOMOCand CMAKE_AUTOUIC, it's more verbose but in other hand you have more control:

最后:这是基于我个人意见的建议,但我想提出更明确的脚本版本,而不使用CMAKE_AUTOMOCand CMAKE_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)

The complete version of the projects source code is available at GitLab.

项目源代码的完整版本可在GitLab 上获得

回答by steveire

You didn't show us where the CMakeLists.txt is in the directory structure. If it's at top-level then you would have

您没有向我们展示 CMakeLists.txt 在目录结构中的位置。如果它是顶级的,那么你会有

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

and you would need

你需要

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/headers)

Anyway, find out where the ui_*.h file is being generated, and add the directory with include_directories.

无论如何,找出生成 ui_*.h 文件的位置,并将目录添加到include_directories.