从编译.cpp文件到CMake

对于一个源文件main.cpp,如何编译成可执行文件呢?

g++ -o main main.cpp 

以上只有一个源文件main.cpp,然而一个实际的工程中,其源文件一般有很多,并且通常按照功能模块,放在若干个目录中。此时如果每次都手动一条条执行编译命令,很显然是不现实的,因此就有了Makefile文件,如下:

main: main.cpp
    g++ -o main main.c

Makefile文件用于描述整个工程的编译、链接的规则。

Makefile文件编写完毕之后,编译整个工程你所要做的唯一的一件事就是执行make命令,就可以将整个工程进行 “自动化编译”,极大提高了效率。

Make功能全面、程序员可直接编写Makefile文件。

然而,手写Makefile是比较困难而且容易出错,尤其在进行跨平台开发时,必须针对不同平台分别编写Makefile,会增加跨平台开发难度。CMake会根据项目文件CMakeLists.txt文件内容,自动生成Makefile或者build.ninja。

CMake项目构建过程

┌─────────────────┐
│ CMakeLists.txt  │ (用户编写)
└────────┬────────┘
         ↓
┌─────────────────┐
│     cmake       │ (配置和生成)
└────────┬────────┘
         ↓
┌─────────────────┐
│  Makefile       │ (生成的构建文件)
│  build.ninja    │
│  .sln/.vcxproj  │
└────────┬────────┘
         ↓
┌─────────────────┐
│  make/ninja/    │ (实际构建工具)
│  msbuild        │
└────────┬────────┘
         ↓
┌─────────────────┐
│  可执行文件/库   │ (最终产物)
└─────────────────┘

Qt Creator中的CMake指令

新建一个HellooQt 项目。

  • 配置
# -S F:/qt_project/HelloQt 
# 指定源码目录(Source)
# 
# -B F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug
# 指定构建目录(Build)
# 
# 作用:CMake 读取 CMakeLists.txt,并检测编译器(MinGW g++)、查找 Qt6 库,在构建目录中生成 build.ninja 等构建文件
cmake.exe -S F:/qt_project/HelloQt -B F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug
  • 构建
# --build	进入编译阶段(区别于 -S/-B 的配置阶段)
# F:\qt_project\HelloQt\build\Desktop_Qt_6_10_2_MinGW_64_bit-Debug  指定构建目录
# --target all	指定构建目标为 all(编译所有目标:CMakeLists.txt 中定义的所有可执行文件和库)
#
# 这条命令是编译阶段,CMake 本身并不直接编译,而是作为统一入口,自动调用底层构建工具:
# cmake --build  →  检测构建目录使用的构建系统
#                              ↓
#               发现 build.ninja(Ninja 构建系统)
#                              ↓
#               自动调用:ninja.exe -f build.ninja all
# 你无需关心底层是 Ninja 还是 Make,cmake --build 统一封装了调用。
cmake.exe --build F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug --target all

    点击【Build】->【Build Project “HelloQt”】,在底部的 “Compile Output” 窗口显示的编译信息:

    00:18:12: Starting: "C:\Program Files\CMake\bin\cmake.exe" --build F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug --target all
    [1/5 0.9/sec] Automatic MOC and UIC for target HelloQt
    [2/5 0.4/sec] Building CXX object CMakeFiles/HelloQt.dir/main.cpp.obj
    [3/5 0.7/sec] Building CXX object CMakeFiles/HelloQt.dir/HelloQt_autogen/mocs_compilation.cpp.obj
    [4/5 0.9/sec] Building CXX object CMakeFiles/HelloQt.dir/mywidget.cpp.obj
    [5/5 1.0/sec] Linking CXX executable HelloQt.exe
    00:18:17: The command "C:\Program Files\CMake\bin\cmake.exe --build F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug --target all" finished successfully.
    00:18:17: Elapsed time: 00:05.

    以上构建时的输出比较精简,如果想查看完整的构建信息,可以为CMake指定一个--verbose选项,如下:

    23:24:32: Running steps for project HelloQt...
    23:24:32: Starting: "C:\Program Files\CMake\bin\cmake.exe" --build F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug --target all --verbose
    Change Dir: 'F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug'
    
    Run Build Command(s): C:/msys64/ucrt64/bin/ninja.exe -v all
    [1/5 1.1/sec] C:\WINDOWS\system32\cmd.exe /C "cd /D F:\qt_project\HelloQt\build\Desktop_Qt_6_10_2_MinGW_64_bit-Debug && "C:\Program Files\CMake\bin\cmake.exe" -E cmake_autogen F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug/CMakeFiles/HelloQt_autogen.dir/AutogenInfo.json Debug && "C:\Program Files\CMake\bin\cmake.exe" -E touch F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug/HelloQt_autogen/timestamp && "C:\Program Files\CMake\bin\cmake.exe" -E cmake_transform_depfile Ninja gccdepfile F:/qt_project/HelloQt F:/qt_project/HelloQt F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug/HelloQt_autogen/deps F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug/CMakeFiles/d/16f2c0b2e7dc64d2f580d0d74891bb9b962b7f0d605002cb71edfbea8e0dc8ef.d"
    [2/5 0.6/sec] C:\Qt\Tools\mingw1310_64\bin\g++.exe -DMINGW_HAS_SECURE_API=1 -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NEEDS_QMAIN -DQT_WIDGETS_LIB -DUNICODE -DWIN32 -DWIN64 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -D_UNICODE -D_WIN64 -IF:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug/HelloQt_autogen/include -isystem C:/Qt/6.10.2/mingw_64/include/QtCore -isystem C:/Qt/6.10.2/mingw_64/include -isystem C:/Qt/6.10.2/mingw_64/mkspecs/win32-g++ -isystem C:/Qt/6.10.2/mingw_64/include/QtWidgets -isystem C:/Qt/6.10.2/mingw_64/include/QtGui -DQT_QML_DEBUG -g -fdiagnostics-color=always -MD -MT CMakeFiles/HelloQt.dir/HelloQt_autogen/mocs_compilation.cpp.obj -MF CMakeFiles\HelloQt.dir\HelloQt_autogen\mocs_compilation.cpp.obj.d -o CMakeFiles/HelloQt.dir/HelloQt_autogen/mocs_compilation.cpp.obj -c F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug/HelloQt_autogen/mocs_compilation.cpp
    [3/5 0.9/sec] C:\Qt\Tools\mingw1310_64\bin\g++.exe -DMINGW_HAS_SECURE_API=1 -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NEEDS_QMAIN -DQT_WIDGETS_LIB -DUNICODE -DWIN32 -DWIN64 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -D_UNICODE -D_WIN64 -IF:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug/HelloQt_autogen/include -isystem C:/Qt/6.10.2/mingw_64/include/QtCore -isystem C:/Qt/6.10.2/mingw_64/include -isystem C:/Qt/6.10.2/mingw_64/mkspecs/win32-g++ -isystem C:/Qt/6.10.2/mingw_64/include/QtWidgets -isystem C:/Qt/6.10.2/mingw_64/include/QtGui -DQT_QML_DEBUG -g -fdiagnostics-color=always -MD -MT CMakeFiles/HelloQt.dir/mywidget.cpp.obj -MF CMakeFiles\HelloQt.dir\mywidget.cpp.obj.d -o CMakeFiles/HelloQt.dir/mywidget.cpp.obj -c F:/qt_project/HelloQt/mywidget.cpp
    [4/5 1.2/sec] C:\Qt\Tools\mingw1310_64\bin\g++.exe -DMINGW_HAS_SECURE_API=1 -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NEEDS_QMAIN -DQT_WIDGETS_LIB -DUNICODE -DWIN32 -DWIN64 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -D_UNICODE -D_WIN64 -IF:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug/HelloQt_autogen/include -isystem C:/Qt/6.10.2/mingw_64/include/QtCore -isystem C:/Qt/6.10.2/mingw_64/include -isystem C:/Qt/6.10.2/mingw_64/mkspecs/win32-g++ -isystem C:/Qt/6.10.2/mingw_64/include/QtWidgets -isystem C:/Qt/6.10.2/mingw_64/include/QtGui -DQT_QML_DEBUG -g -fdiagnostics-color=always -MD -MT CMakeFiles/HelloQt.dir/main.cpp.obj -MF CMakeFiles\HelloQt.dir\main.cpp.obj.d -o CMakeFiles/HelloQt.dir/main.cpp.obj -c F:/qt_project/HelloQt/main.cpp
    [5/5 1.4/sec] C:\WINDOWS\system32\cmd.exe /C "cd . && C:\Qt\Tools\mingw1310_64\bin\g++.exe -DQT_QML_DEBUG -g -mwindows CMakeFiles/HelloQt.dir/HelloQt_autogen/mocs_compilation.cpp.obj CMakeFiles/HelloQt.dir/main.cpp.obj CMakeFiles/HelloQt.dir/mywidget.cpp.obj -o HelloQt.exe -Wl,--out-implib,libHelloQt.dll.a -Wl,--major-image-version,0,--minor-image-version,0  C:/Qt/6.10.2/mingw_64/lib/libQt6Widgets.a  C:/Qt/6.10.2/mingw_64/lib/libQt6Gui.a  C:/Qt/6.10.2/mingw_64/lib/libQt6Core.a  -lmpr  -luserenv  -lmingw32  C:/Qt/6.10.2/mingw_64/lib/libQt6EntryPoint.a  -lshell32  -ld3d11  -ldxgi  -ldxguid  -ld3d12  -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ."
    
    23:24:36: The command "C:\Program Files\CMake\bin\cmake.exe --build F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug --target all --verbose" finished successfully.
    23:24:36: Elapsed time: 00:04.
    •  清除
    # --build	进入编译阶段操作
    # F:\qt_project\HelloQt\build\Desktop_Qt_6_10_2_MinGW_64_bit-Debug  指定构建目录
    # --target clean	执行 清理目标,删除编译产物
    #
    # CMake 将此命令转交给底层 Ninja 执行:
    # cmake --build ... --target clean
    #                ↓
    #   ninja.exe -f build.ninja clean
    #                ↓
    #   删除所有由编译产生的中间文件和输出文件
    cmake.exe --build F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug --target clean

    UIC

    在qt的bin文件夹下能找到uic.exe

    uic.exe可以将.ui文件(内部是xml文本)生成.h文件。uic工具会去解析.uixml格式文件,依次读取其中的字段,比如widthheightproperty等,来生成对应的C++代码。生成的.h文件可能为:

    class Ui_MyWidget
    {
    public:
        QPushButton *btnStart;
        QPushButton *btnStop;
    
        void setupUi(QWidget *MyWidget)
        {
            if (MyWidget->objectName().isEmpty())
                MyWidget->setObjectName("MyWidget");
            MyWidget->resize(800, 600);
            // 只有将 btnStart 的父窗口设置为传递过来的MyWidget,才能在MyWidget show出来时,才将 btnStart 也显示出来
            btnStart = new QPushButton(MyWidget);
            btnStart->setObjectName("btnStart");
            btnStart->setGeometry(QRect(230, 260, 131, 51));
            // 只有将 btnStop 的父窗口设置为传递过来的MyWidget,才能在MyWidget show出来时,才将 btnStop 也显示出来
            btnStop = new QPushButton(MyWidget);
            btnStop->setObjectName("btnStop");
            btnStop->setGeometry(QRect(370, 260, 131, 51));
    
            retranslateUi(MyWidget);
    
            QMetaObject::connectSlotsByName(MyWidget);
        } // setupUi
    
        void retranslateUi(QWidget *MyWidget)
        {
            MyWidget->setWindowTitle(QCoreApplication::translate("MyWidget", "MyWidget", nullptr));
            btnStart->setText(QCoreApplication::translate("MyWidget", "START", nullptr));
            btnStop->setText(QCoreApplication::translate("MyWidget", "STOP", nullptr));
        } // retranslateUi
    
    };
    
    namespace Ui {
        // 这个Ui命名空间中的 MyWidget 类,本身是空实现,但是它继承自 Ui_MyWidget 类
        // Ui_MyWidget 类就是和 mywidget.ui 这个xml文件一一对应的。
        
        // 比如在ui设计界面拖放两个按钮,可以在其xml文件中看到两个按钮的属性
        // uic 工具就会根据xml文件中的属性,在 ui_mywidget.h 文件中,生成对应的代码
        // 比如在ui设计界面设置两个按钮的文本为“START”和“STOP”,调整坐标,那么在生成的这个.h文件中,就会生成对应的代码,如上↑
        class MyWidget: public Ui_MyWidget {};
    } // namespace Ui

    MOC

    Meta-Object Compiler(元对象编译器,简称 moc)是 Qt 框架 的核心工具之一,负责处理 Qt 的元对象系统(Meta-Object System)。

    moc 是一个预处理器/代码生成器,它读取 C++ 头文件(通常是包含 Q_OBJECT 宏的类定义),然后生成额外的 C++ 代码(moc_*.cpp 文件)。这些生成的代码实现了 Qt 的元对象功能,包括:

    • 信号与槽(Signals & Slots):实现对象间的松散耦合通信机制

    • 运行时类型信息(RTTI):提供 QObject::metaObject() 获取类的元数据

    • 动态属性系统:支持运行时属性查询和修改

    • 国际化支持tr() 函数的字符串翻译机制

    // widget.h
    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include <QWidget>
    
    class Widget : public QWidget
    {
        Q_OBJECT
    
    public:
        Widget(QWidget *parent = nullptr);
        ~Widget();
    };
    #endif // WIDGET_H
    
    
    // widget.cpp
    #include "widget.h"
    
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
    {
    }
    
    Widget::~Widget()
    {
    }

    经过moc,可以将cpp文件生成 moc_.cpp文件,其中包含:

    • 信号的实现代码(emit mySignal() 实际调用的函数)

    • 元对象表(类名、方法、属性等元数据)

    • 槽函数的调用分发逻辑

    #include <memory>
    #include "../../../../widget.h"
    #include <QtCore/qbytearray.h>
    #include <QtCore/qmetatype.h>
    #if !defined(Q_MOC_OUTPUT_REVISION)
    #error "The header file 'widget.h' doesn't include <QObject>."
    #elif Q_MOC_OUTPUT_REVISION != 67
    #error "This file was generated using the moc from 5.14.2. It"
    #error "cannot be used with the include files from this version of Qt."
    #error "(The moc has changed too much.)"
    #endif
    
    QT_BEGIN_MOC_NAMESPACE
    QT_WARNING_PUSH
    QT_WARNING_DISABLE_DEPRECATED
    struct qt_meta_stringdata_Widget_t {
        QByteArrayData data[1];
        char stringdata0[7];
    };
    #define QT_MOC_LITERAL(idx, ofs, len) \
        Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
        qptrdiff(offsetof(qt_meta_stringdata_Widget_t, stringdata0) + ofs \
            - idx * sizeof(QByteArrayData)) \
        )
    static const qt_meta_stringdata_Widget_t qt_meta_stringdata_Widget = {
        {
    QT_MOC_LITERAL(0, 0, 6) // "Widget"
    
        },
        "Widget"
    };
    #undef QT_MOC_LITERAL
    
    static const uint qt_meta_data_Widget[] = {
    
     // content:
           8,       // revision
           0,       // classname
           0,    0, // classinfo
           0,    0, // methods
           0,    0, // properties
           0,    0, // enums/sets
           0,    0, // constructors
           0,       // flags
           0,       // signalCount
    
           0        // eod
    };
    
    void Widget::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
    {
        Q_UNUSED(_o);
        Q_UNUSED(_id);
        Q_UNUSED(_c);
        Q_UNUSED(_a);
    }
    
    QT_INIT_METAOBJECT const QMetaObject Widget::staticMetaObject = { {
        QMetaObject::SuperData::link<QWidget::staticMetaObject>(),
        qt_meta_stringdata_Widget.data,
        qt_meta_data_Widget,
        qt_static_metacall,
        nullptr,
        nullptr
    } };
    
    
    const QMetaObject *Widget::metaObject() const
    {
        return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
    }
    
    void *Widget::qt_metacast(const char *_clname)
    {
        if (!_clname) return nullptr;
        if (!strcmp(_clname, qt_meta_stringdata_Widget.stringdata0))
            return static_cast<void*>(this);
        return QWidget::qt_metacast(_clname);
    }
    
    int Widget::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
    {
        _id = QWidget::qt_metacall(_c, _id, _a);
        return _id;
    }
    QT_WARNING_POP
    QT_END_MOC_NAMESPACE
    

    为什么需要 moc?

    C++ 原生不支持反射和信号槽机制。moc 通过代码生成在编译期注入这些能力,而不是依赖复杂的模板元编程或运行时开销较大的方案。这使得 Qt 能够在保持 C++ 性能的同时提供高级的动态特性。

    使用方式

    在现代 Qt 开发中,moc 通常由构建系统自动调用:

    • qmake:自动生成规则调用 moc

    • CMake:通过 qt_wrap_cpp()AUTOMOC 选项自动处理

    将一些其他位置的接口文件添加到编译/构建

    手动qt5_wrap_cpp

    ...
    
    set(ICONTROL_HEADER 
        ${CMAKE_SOURCE_DIR}/src/App/IControl.h
    )
    
    qt5_wrap_cpp(MOC_ICONTROL_SRCS 
        ${ICONTROL_HEADER}
    )
    
    # 添加到目标(这才是真正使用)
    add_library(MyPlugin SHARED
        ${SOURCES}
        ${MOC_ICONTROL_SRCS}  # 必须包含生成的 moc 文件
    )
    
    target_link_libraries(MyPlugin Qt5::Core)

    AUTOMOC

    # 并且项目启用了 AUTOMOC
    set(CMAKE_AUTOMOC ON) 
    
    ...
    
    
    # 写法A
    file(GLOB HEADER
       ${CMAKE_SOURCE_DIR}/src/App/ITask.h
       ${CMAKE_SOURCE_DIR}/src/App/IProject.h
       ${CMAKE_SOURCE_DIR}/src/App/IMonitor.h
    )
    
    # 这些 HEADER 被直接用在了 add_library 中
    add_library(SomeTarget SHARED
        ${SOURCES}
        ${HEADER}   # ← 头文件列在 target 的源文件里
    )
    
    
    
    # 写法B
    include_directories(
        ${CMAKE_SOURCE_DIR}/src/App/
    )
    
    add_library(SomeTarget SHARED ${SOURCES})  # 自动处理
    
    
    
    

    修改 CMake Generator

    CMake针对不同平台,支持多种Generator生成器

    • Ninja:生成Ninja构建所需的所有文件
    • Unix Makefiles:生成Make构建所需的所有文件

    默认采用生成器为Ninja,可以修改为其他,比如Unix Makefiles,修改为:【Edit】->【Preferences…】->【Kits】

    默认ninja构建

    执行Cmake,输出打印信息:

    [cmake] Running C:\Program Files\CMake\bin\cmake.exe -S F:/qt_project/HelloQt -B F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug "-DCMAKE_C_COMPILER:FILEPATH=C:/Qt/Tools/mingw1310_64/bin/gcc.exe" "-DCMAKE_BUILD_TYPE:STRING=Debug" "-DQT_MAINTENANCE_TOOL:FILEPATH=C:/Qt/MaintenanceTool.exe" "-DQT_QMAKE_EXECUTABLE:FILEPATH=C:/Qt/6.10.2/mingw_64/bin/qmake.exe" "-DCMAKE_CXX_FLAGS_INIT:STRING=-DQT_QML_DEBUG" "-DCMAKE_CXX_COMPILER:FILEPATH=C:/Qt/Tools/mingw1310_64/bin/g++.exe" "-DCMAKE_GENERATOR:STRING=Ninja" "-DCMAKE_PREFIX_PATH:PATH=C:/Qt/6.10.2/mingw_64" "-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON" "-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=F:\qt_project\HelloQt\build\Desktop_Qt_6_10_2_MinGW_64_bit-Debug/.qtc/package-manager/auto-setup.cmake" in F:\qt_project\HelloQt\build\Desktop_Qt_6_10_2_MinGW_64_bit-Debug.
    [cmake] -- The CXX compiler identification is GNU 13.1.0
    [cmake] -- Detecting CXX compiler ABI info
    [cmake] -- Detecting CXX compiler ABI info - done
    [cmake] -- Check for working CXX compiler: C:/Qt/Tools/mingw1310_64/bin/g++.exe - skipped
    [cmake] -- Detecting CXX compile features
    [cmake] -- Detecting CXX compile features - done
    [cmake] -- Performing Test HAVE_STDATOMIC
    [cmake] -- Performing Test HAVE_STDATOMIC - Success
    [cmake] -- Configuring done (2.2s)
    [cmake] -- Generating done (0.1s)
    [cmake] -- Build files have been written to: F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug
    [cmake] 
    [cmake] Elapsed time: 00:02.

    点击【构建】,观察到编译构建信息:

    00:18:12: Starting: "C:\Program Files\CMake\bin\cmake.exe" --build F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug --target all
    [1/5 0.9/sec] Automatic MOC and UIC for target HelloQt
    [2/5 0.4/sec] Building CXX object CMakeFiles/HelloQt.dir/main.cpp.obj
    [3/5 0.7/sec] Building CXX object CMakeFiles/HelloQt.dir/HelloQt_autogen/mocs_compilation.cpp.obj
    [4/5 0.9/sec] Building CXX object CMakeFiles/HelloQt.dir/mywidget.cpp.obj
    [5/5 1.0/sec] Linking CXX executable HelloQt.exe
    00:18:17: The command "C:\Program Files\CMake\bin\cmake.exe --build F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug --target all" finished successfully.
    00:18:17: Elapsed time: 00:05.

    改为make构建

    修改为Make构建,也就是Generator指定为 “Unix Makefiles”。
    此时,执行CMake配置,输出打印信息,如下:

    [cmake] Running C:\Program Files\CMake\bin\cmake.exe -S F:/qt_project/HelloQt -B F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug "-DCMAKE_BUILD_TYPE:STRING=Debug" "-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=F:\qt_project\HelloQt\build\Desktop_Qt_6_10_2_MinGW_64_bit-Debug/.qtc/package-manager/auto-setup.cmake" "-DCMAKE_CXX_FLAGS_INIT:STRING=-DQT_QML_DEBUG" "-DCMAKE_PREFIX_PATH:PATH=C:/Qt/6.10.2/mingw_64" "-DQT_MAINTENANCE_TOOL:FILEPATH=C:/Qt/MaintenanceTool.exe" "-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON" "-DCMAKE_GENERATOR:STRING=Unix Makefiles" "-DQT_QMAKE_EXECUTABLE:FILEPATH=C:/Qt/6.10.2/mingw_64/bin/qmake.exe" "-DCMAKE_C_COMPILER:FILEPATH=C:/Qt/Tools/mingw1310_64/bin/gcc.exe" "-DCMAKE_CXX_COMPILER:FILEPATH=C:/Qt/Tools/mingw1310_64/bin/g++.exe" in F:\qt_project\HelloQt\build\Desktop_Qt_6_10_2_MinGW_64_bit-Debug.
    [cmake] -- The CXX compiler identification is GNU 13.1.0
    [cmake] -- Detecting CXX compiler ABI info
    [cmake] -- Detecting CXX compiler ABI info - done
    [cmake] -- Check for working CXX compiler: C:/Qt/Tools/mingw1310_64/bin/g++.exe - skipped
    [cmake] -- Detecting CXX compile features
    [cmake] -- Detecting CXX compile features - done
    [cmake] -- Performing Test HAVE_STDATOMIC
    [cmake] -- Performing Test HAVE_STDATOMIC - Success
    [cmake] -- Configuring done (3.6s)
    [cmake] -- Generating done (0.1s)
    [cmake] -- Build files have been written to: F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug
    [cmake] 
    [cmake] Elapsed time: 00:04.

    点击【构建】,观察到编译构建信息:

    00:36:03: Running steps for project HelloQt...
    00:36:03: Starting: "C:\Program Files\CMake\bin\cmake.exe" --build F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug --target all
    [  0%] Built target HelloQt_autogen_timestamp_deps
    [ 20%] Automatic MOC and UIC for target HelloQt
    [ 20%] Built target HelloQt_autogen
    [ 40%] Building CXX object CMakeFiles/HelloQt.dir/HelloQt_autogen/mocs_compilation.cpp.obj
    [ 60%] Building CXX object CMakeFiles/HelloQt.dir/main.cpp.obj
    [ 80%] Building CXX object CMakeFiles/HelloQt.dir/mywidget.cpp.obj
    [100%] Linking CXX executable HelloQt.exe
    [100%] Built target HelloQt
    00:36:15: The command "C:\Program Files\CMake\bin\cmake.exe --build F:/qt_project/HelloQt/build/Desktop_Qt_6_10_2_MinGW_64_bit-Debug --target all" finished successfully.
    00:36:15: Elapsed time: 00:12.

    运行设置

    点击左侧的【Projects】,可以打开当前项目的运行设置界面,如下:

    如果指定了命令行参数,可以在main.cpp中,添加如下代码来打印命令行参数,如下:

    qDebug() << "参数个数:" << argc;
    qDebug() << "参1:" << argv[0];
    qDebug() << "参2:" << argv[1];
    qDebug() << "参3:" << argv[2];

    执行结果:

    参数个数: 3
    参1: F:\qt_project\HelloQt\debug\HelloQt.exe
    参2: 123
    参3: 456

    更多推荐