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
Implementing Qt project through CMake
提问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:
错误:
Wrong
add_executable
directive. You try to add a library, but for this purpose you need to usetarget_link_libraries
. So instead of:add_executable(Cmake main.cpp mainwindow)
You need:
add_executable(Cmake main.cpp) target_link_libraries (Cmake mainwindow)
And one more mistake is missing
*.cpp
files in theadd_library
directive:add_library(mainwindow mainwindow.cpp ${Cmake_hdr_moc} ${Cmake_form_hdr})
错误的
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})
Recommendations:
建议:
Also setting version of
CMake
would be appropriate. If you useCMAKE_AUTOMOC
you need a version not less than 2.8.6, and if you useCMAKE_AUTOUIC
you need a version not less than 3.0.2:cmake_minimum_required(VERSION 3.0.2)
Using
qt5_wrap_cpp
withCMAKE_AUTOMOC
isn't necessary.When you use
CMAKE_AUTOMOC
usageCMAKE_AUTOUIC
instead ofqt5_wrap_ui
will be more appropriate.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_directories
as was mentioned by @steveire.(UPD) Since, I've written this answer, I suggested it several times for beginners who try to meet with
Qt
throughCMake
. They complain of an inappropriate name of the project - "Cmake". For beginners who just meet withCMake
is 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.(UPD) As was mentioned by @Erik Sj?lund
qt5_use_modules
is obsoleteandtarget_link_libraries
should be used instead.
设置 version of
CMake
也是合适的。如果你使用CMAKE_AUTOMOC
你需要一个不低于2.8.6的版本,如果你使用CMAKE_AUTOUIC
你需要一个不低于3.0.2的版本:cmake_minimum_required(VERSION 3.0.2)
没有必要使用
qt5_wrap_cpp
withCMAKE_AUTOMOC
。当你使用
CMAKE_AUTOMOC
用法CMAKE_AUTOUIC
而不是qt5_wrap_ui
会更合适。此脚本适用于文件系统中具有以下结构的项目:
Project ├── CMakeLists.txt ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h └── mainwindow.ui
如果你有另一种结构,你应该使用@steveire
include_directories
提到的。( UPD) 因为,我已经写了这个答案,我多次向试图
Qt
通过CMake
. 他们抱怨项目名称不合适——“Cmake”。对于刚接触的初学者来说,CMake
很难意识到cmake-在哪里只是项目名称的一部分(并且不是强制性的),而cmake在哪里是指令的一部分(并且是强制性的)。所以我想将项目名称从“Cmake”替换为“MyProject”。这减少了问题和答案之间的联系,但另一方面,这使答案对初学者更加友好。( UPD) 正如@Erik Sj 所提到的那样?lund
qt5_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_AUTOMOC
and CMAKE_AUTOUIC
, it's more verbose but in other hand you have more control:
最后:这是基于我个人意见的建议,但我想提出更明确的脚本版本,而不使用CMAKE_AUTOMOC
and 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
.