在上一篇文章中,我们成功生成并执行了自己的HelloWorld,接下来将进一步完善其构建方法,使其更加方便更加自动化。同时也会介绍安装打包以及增加程序功能的方法。
本文涉及的代码已上传至github,后文会介绍使用方法。
设置CMakeLists中的变量来更改VS项目的默认设置
上篇文章结尾我们得到了一个有控制台窗口的HelloWorld程序。我们可以通过修改Visual Studio中的设置来隐藏控制台窗口。
也可以在CMakeLists.txt中添加如下内容达到相同效果:
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
很多设置都可以通过在CMakeLists.txt中设置变量或者在执行cmake命令时添加参数来完成,如此便无需频繁的调整VS的设置。比如我们希望构建的VS项目默认编译64位的Release程序,可以在build目录下执行如下命令:
cmake -A x64 -DCMAKE_CONFIGURATION_TYPES=Release ..
其中 -A x64设置VS工程为64位,后面的参数用来设置编译模式为Release
编写build.bat
有没有觉得要输入那么长的命令很难记很麻烦?没关系,我们可以通过编写脚本文件来解决这个问题,在Windows中是.bat文件,通过编写和执行.bat文件,我们可以自动地执行一批命令。
在源代码根路径下编写build.bat如下:
@echo off
::delete build dir
if "%1"=="delete" goto _DEL
if not exist build md build
cd build
cmake -A x64 -DCMAKE_CONFIGURATION_TYPES=Release ..
cd ..
goto _END
:_DEL
rd build/s/q
goto _END
:_END
此后通过以下命令,便可以很方便的构建和删除项目了。
build.bat
build.bat delete
这里使用git bash时360会拦截,可以通过Windows控制台执行
制作安装包
我们可以通过CMake很方便的制作程序的安装包。
在Windows下我们可以通过NSIS软件来制作拥有安装界面的安装包(需要先安装NSIS),这种简单的程序也可以直接打包成.tar.gz,在其他电脑上解压即可使用,大概就是免安装绿色硬盘版吧 ^_^单就这个程序来说两种包差别不大,在代码中也仅仅是一个变量值的区别。
如果要制作NSIS包,设置
set(CPACK_GENERATOR NSIS)
制作tar.gz,只需设置
set(CPACK_GENERATOR TGZ)
主要利用的是install命令和CPack模块。
在CMakeLists.txt中添加如下代码:
set(CMAKE_INSTALL_PREFIX ${PROJECT_BINARY_DIR}/installed)
set(WINDEPLOYQT_DIR F:/QT/5.10.1/msvc2017_64/bin)
#exec windeployqt automatically when build install in VS
install(CODE "execute_process(COMMAND ${WINDEPLOYQT_DIR}/windeployqt.exe
${PROJECT_BINARY_DIR}/Release/${PROJECT_NAME}.exe)")
install(DIRECTORY ${PROJECT_BINARY_DIR}/Release/ DESTINATION /)
set(CPACK_GENERATOR NSIS)
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
set(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${VERSION_PATCH})
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${PROJECT_NAME})
INCLUDE(CPack)
install命令可以把需要的文件安装到指定的路径,CPack则把install安装的文件制作成安装包。
注意install(CODE ……)那一行,我们将前面所讲的windeployqt命令写进CMakeLists.txt中,生成install时会自动执行该命令。
修改CMakeLists.txt后需要在build文件夹下执行cmake .. 才能生效,之后VS项目中会多出两项。
右击INSTALL选择生成,在build目录下会生成一个Release文件夹,里面包括HelloWorld.exe及其所需的依赖文件。
右击PACKAGE选择生成,则会在build目录下得到一个安装包。
打开安装包,是不是有点像模像样呢?
更方便增删源代码文件的CMakeLists.txt
在之前的CMakeLists.txt中,我们是通过文件名枚举的形式向项目中添加代码文件的
set(project_ui
MainWindow.ui)
set(project_headers
MainWindow.h)
set(project_sources
demoMain.cpp MainWindow.cpp)
add_executable(${PROJECT_NAME} ${project_headers} ${project_ui} ${project_sources})
等同于
add_executable(${PROJECT_NAME} MainWindow.h MainWindow.ui demoMain.cpp MainWindow.cpp)
这样做的不便之处在于,当我们每次新增代码文件时,都要修改CMakeLists.txt,虽然对小程序来说这并没有什么影响,但是当项目变得庞大复杂时,改动可能会变得繁琐且麻烦,代码也会臃肿而易错。我们可以利用CMake的file命令来获取目录内相应后缀的文件。
file(GLOB SOURCE_FILE *.cpp)
file(GLOB UI_FILE *.ui)
file(GLOB HEAD_FILE *.h)
set(project_ui
${UI_FILE})
set(project_headers
${HEAD_FILE})
set(project_sources
${SOURCE_FILE})
add_executable(${PROJECT_NAME} ${project_headers} ${project_ui} ${project_sources})
这样,当我们添加.cpp .ui .h三种文件时,文件都会自动地被CMake识别,无需修改CMakeLists.txt。
当项目更加复杂时,我们可能需要更加复杂的命令和逻辑来保证项目构建的自动化,程序嘛,一大意义就是代替人工来完成重复机械化的工作。
最终完整的CMakeLists.txt如下
cmake_minimum_required(VERSION 3.12.0)
#set PROJECT_NAME and version
project(HelloWorld)
set(VERSION_MAJOR 0)
set(VERSION_MINOR 0)
set(VERSION_PATCH 1)
#set path for QT
set(CMAKE_PREFIX_PATH F:/QT/5.10.1/msvc2017_64)
#without console by default
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
# Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Instruct CMake to run moc automatically when needed
set(CMAKE_AUTOMOC ON)
# Create code from a list of Qt designer ui files
set(CMAKE_AUTOUIC ON)
find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui)
file(GLOB SOURCE_FILE *.cpp)
file(GLOB UI_FILE *.ui)
file(GLOB HEAD_FILE *.h)
set(project_ui
${UI_FILE})
set(project_headers
${HEAD_FILE})
set(project_sources
${SOURCE_FILE})
add_executable(${PROJECT_NAME} ${project_headers} ${project_ui} ${project_sources})
# Use the widgets module from Qt 5
target_link_libraries(${PROJECT_NAME}
PUBLIC
Qt5::Core
Qt5::Gui
Qt5::Widgets)
set(CMAKE_INSTALL_PREFIX ${PROJECT_BINARY_DIR}/installed)
set(WINDEPLOYQT_DIR F:/QT/5.10.1/msvc2017_64/bin)
#exec windeployqt automatically when build install in VS
install(CODE "execute_process(COMMAND ${WINDEPLOYQT_DIR}/windeployqt.exe
${PROJECT_BINARY_DIR}/Release/${PROJECT_NAME}.exe)")
install(DIRECTORY ${PROJECT_BINARY_DIR}/Release/ DESTINATION /)
set(CPACK_GENERATOR TGZ)
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
set(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${VERSION_PATCH})
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${PROJECT_NAME})
INCLUDE(CPack)
修改或增加代码后的构建方法
现在我们给HelloWorld增加一个新的窗口,有简单的乘法计算功能。
为了实现这个功能我们修改了部分已有代码,并增加了如下文件,详见github
(如果有人希望在文章中详细写出代码和ui文件的创建过程,欢迎留言。虽然感觉也不会有什么人看)
multiplyDialog.cpp
multiplyDialog.h
multiplyDialog.ui
文件编写完成后只需进入build目录执行cmake ..
即可
可见新增的文件已经被添加到项目中。右击install生成新的可执行文件即可。
更新
以此仓库最新节点为例,假设你已经编译成功并成功执行了程序,此时你希望添加一个新的窗口。
可能vs2019已经提供了更好的支持,不过仅在此提供一种可行的但可能有些繁琐的方式。
创建ui及对应的.h和.cpp
使用designer 或creator看习惯吧,总之创建一个新ui文件,注意修改objectName。
TestDialog.h
#ifndef TESTDIALOG_H
#define TESTDIALOG_H
#include <QDialog>
namespace Ui {
class TestDialog;
}
class TestDialog : public QDialog
{
Q_OBJECT
public:
explicit TestDialog(QWidget *parent = nullptr);
~TestDialog();
private:
Ui::TestDialog *ui;
};
#endif
TestDialog.cpp
#include "TestDialog.h"
#include "ui_TestDialog.h"
#include "Mylog.h"
TestDialog::TestDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::TestDialog)
{
ui->setupUi(this);
this->setAttribute(Qt::WA_DeleteOnClose);
}
TestDialog::~TestDialog()
{
std::cout << "TestDialog destroyed" << std::endl;
delete ui;
}
文件创建好后,打开git bash或cmd窗口
这里你得保证CMakeList.txt的配置能够自动获取新创建的文件(此仓库最新节点的CMakeList.txt是可以的,如果你使用的是文章(一)中的CMakeList.txt,你还得手动的把新增的文件添加进去)
之后再打开.sln,可以看到解决方案中已经包含了新创建的文件
此时应该已经可以正确编译了,更新一下主窗口的函数,在其中创建新窗口
void MainWindow::openMultiply()
{
//multiplyDialog* mul = new multiplyDialog(this);
TestDialog* t = new TestDialog(this);
std::cout << "in open" << std::endl;
//mul->show();
t->show();
}
右键解决方案管理器中的INSTALL选择生成
如果成功编译,此时再打开程序,主窗口中的按钮就会创建一个新窗口出来了。
从github获取此项目的方法
至此我们的HelloWorld就结束了。使用git clone获取项目代码:
git clone https://github.com/tinyprogramer/Qt_CMake_VS.git
获取代码后,记得先把CMakeLists.txt中Qt路径那一行改成你自己电脑中的Qt路径
set(CMAKE_PREFIX_PATH F:/QT/5.10.1/msvc2017_64)
之后在此目录中按照前述执行build.bat即可