【学写LibreCAD】Win11下在MSYS2 UCRT64环境中搭建Qt+Rust混合开发环境(VSCode)完整笔记

一、前言与选择

今天决定在Windows 11上搭建一个Qt+Rust的混合开发环境。经过研究,我选择了MSYS2的UCRT64环境,而不是传统的MINGW64。主要原因是UCRT(Universal C Runtime)是Windows 10/11的现代C运行时库,与系统兼容性更好,能避免一些潜在的兼容性问题。

二、环境准备与安装

1. 安装MSYS2并切换环境

我首先从MSYS2官网下载并安装了MSYS2。安装完成后,我注意到开始菜单中有多个终端快捷方式:

  • MSYS2 UCRT64 - 这是我今天要用的环境
  • MSYS2 MINGW64 - 传统的64位环境
  • MSYS2 MSYS - 模拟Unix的环境

我点击打开了"MSYS2 UCRT64"终端。

2. 在UCRT64环境中安装必要组件

在UCRT64终端中,我执行了以下命令:

bash 复制代码
# 首先更新包数据库和系统(MSYS2的常规操作)
pacman -Syu

# 安装Qt6开发包(我选择了Qt6,因为它更现代)
pacman -S mingw-w64-ucrt-x86_64-qt6-base mingw-w64-ucrt-x86_64-qt6-tools mingw-w64-ucrt-x86_64-qt6-declarative

# 安装Rust工具链
pacman -S mingw-w64-ucrt-x86_64-rust

# 安装构建工具
pacman -S mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-ninja mingw-w64-ucrt-x86_64-gcc

# 安装调试器
pacman -S mingw-w64-ucrt-x86_64-gdb

安装完成后,我验证了安装是否成功:

bash 复制代码
# 检查各组件版本
rustc --version  # 输出: rustc 1.91.1 (MSYS2 UCRT64环境)
g++ --version    # 输出: g++.exe (Rev8, Built by MSYS2 project) 15.2.0
qmake --version  # 输出: QMake version 3.1
cmake --version  # 输出: cmake version 4.2.0

3. 安装VSCode及必要扩展

在Windows 11上,我打开VSCode并安装了以下扩展:

  • C/C++ (Microsoft) - 用于C++代码智能感知
  • rust-analyzer - 用于Rust代码分析
  • CMake Tools - 用于CMake项目支持
  • Qt Configure - 可选,Qt项目辅助工具

三、VSCode项目配置

我创建了一个新的项目文件夹 qt_rust_mixed,并在其中进行配置。

1. 配置C++智能感知

在项目根目录创建 .vscode 文件夹,然后创建 c_cpp_properties.json

json 复制代码
{
    "configurations": [
        {
            "name": "MSYS2_UCRT64",
            "includePath": [
                "${workspaceFolder}/**",
                "C:/msys64/ucrt64/include/**",
                "C:/msys64/ucrt64/include/qt6/**",
                "C:/msys64/ucrt64/include/c++/12.2.0/**"
            ],
            "defines": [
                "QT_CORE_LIB",
                "QT_GUI_LIB", 
                "QT_WIDGETS_LIB",
                "UNICODE",
                "_UNICODE"
            ],
            "compilerPath": "C:/msys64/ucrt64/bin/g++.exe",
            "cStandard": "c17",
            "cppStandard": "c++17",
            "intelliSenseMode": "windows-gcc-x64",
            "configurationProvider": "ms-vscode.cmake-tools"
        }
    ],
    "version": 4
}

2. 配置VSCode使用UCRT64终端

为了确保所有命令都在统一环境下运行,我修改了VSCode的用户设置(通过Ctrl+Shift+P,输入"Preferences: Open User Settings (JSON)"):

json 复制代码
{
    "git.ignoreMissingGitWarning": true,
    
    "terminal.integrated.profiles.windows": {
        "MSYS2 UCRT64": {
            "path": "C:\\msys64\\usr\\bin\\bash.exe",
            "args": ["--login", "-i"],
            "env": {
                "MSYSTEM": "UCRT64",
                "CHERE_INVOKING": "1"
            },
            "icon": "terminal-bash"
        }
    },
    "terminal.integrated.defaultProfile.windows": "MSYS2 UCRT64",
    "terminal.integrated.cursorStyle": "line"
}

3. 配置CMake

在项目根目录创建 CMakeLists.txt,这是混合项目的构建核心:

cmake 复制代码
cmake_minimum_required(VERSION 3.20)
project(QtRustMixed LANGUAGES CXX)

# 设置C++标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 查找Qt6组件
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)

# 设置Rust构建
# 这里假设Rust部分会通过Cargo构建为静态库
# 实际项目中可能需要更复杂的集成

# 添加可执行文件
add_executable(qt_rust_mixed main.cpp)

# 链接Qt库
target_link_libraries(qt_rust_mixed 
    Qt6::Core 
    Qt6::Gui 
    Qt6::Widgets
)

# 在Windows上链接必要的库
if(WIN32)
   # Windows可能需要额外的库
    # target_link_libraries(qt_rust_mined)  # 这是错误行,已删除
endif()

4. 配置调试环境

.vscode/launch.json 中配置调试:

json 复制代码
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Debug - UCRT64",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/build/qt_rust_mixed.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [
                {
                    "name": "PATH",
                    "value": "C:/msys64/ucrt64/bin;C:/msys64/ucrt64/lib;${env:PATH}"
                }
            ],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerPath": "C:/msys64/ucrt64/bin/gdb.exe",
            "setupCommands": [
                {
                    "description": "为 gdb 启用整齐打印",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "CMake: build",
            "logging": {
                "engineLogging": false
            }
        }
    ]
}

.vscode/tasks.json 中配置构建任务:

json 复制代码
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "CMake: build",
            "type": "shell",
            "command": "cmake",
            "args": [
                "--build",
                "${workspaceFolder}/build",
                "--config",
                "Debug"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": [],
            "detail": "使用CMake构建项目"
        }
    ]
}

四、验证环境配置

1. 验证C++/Qt环境

我创建了一个简单的Qt测试程序 main.cpp

cpp 复制代码
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QLabel>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    
    QWidget window;
    window.setWindowTitle("Qt + Rust 测试环境");
    window.resize(400, 300);
    
    QVBoxLayout *layout = new QVBoxLayout(&window);
    
    QLabel *label = new QLabel("环境配置成功!");
    label->setAlignment(Qt::AlignCenter);
    layout->addWidget(label);
    
    QPushButton *button = new QPushButton("点击我");
    layout->addWidget(button);
    
    QObject::connect(button, &QPushButton::clicked, [label]() {
        label->setText("按钮被点击了!");
    });
    
    window.show();
    return app.exec();
}

然后在UCRT64终端中测试编译(qt_rust_mixed目录下):

bash 复制代码
# 创建构建目录
mkdir -p build
cd build

# 配置CMake
cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Debug ..

# 构建
cmake --build .

构建成功后,我运行了程序:

bash 复制代码
./qt_rust_mixed.exe

程序正常启动,显示了一个带有按钮的窗口,点击按钮功能正常。

2. 验证Rust环境

我创建了一个简单的Rust库来测试。首先在项目根目录创建 rust-lib 文件夹:

bash 复制代码
cargo new rust_lib --lib
cd rust_lib

然后编辑 rust-lib/Cargo.toml

toml 复制代码
[package]
name = "rust_lib"
version = "0.1.0"
edition = "2024"

[lib]
name = "rust_lib"
crate-type = ["staticlib", "cdylib"]  # 静态库和动态库

[dependencies]

编辑 rust-lib/src/lib.rs

rust 复制代码
#![allow(unused)]

#[unsafe(no_mangle)]
pub extern "C" fn add_numbers(a: i32, b: i32) -> i32 {
    a + b
}

#[unsafe(no_mangle)]
pub extern "C" fn greet(name: *const std::os::raw::c_char) {
    unsafe {
        if !name.is_null() {
            let c_str = std::ffi::CStr::from_ptr(name);
            if let Ok(rust_str) = c_str.to_str() {
                println!("你好, {}!", rust_str);
            }
        }
    }
}

在UCRT64终端中构建Rust库:

bash 复制代码
cd rust-lib
cargo build --release

构建成功,在 target/release 目录下生成了 librust_lib.a(静态库)和 rust_lib.dll(动态库)。

3. 验证混合调用

为了测试Qt和Rust的混合调用,我修改了 main.cpp

cpp 复制代码
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QLabel>
#include <QMessageBox>

// 声明Rust函数
extern "C" {
    int add_numbers(int a, int b);
    void greet(const char* name);
}

int main(int argc, char *argv[]) {
    // 测试Rust函数
    int result = add_numbers(10, 20);
    greet("Qt+Rust开发者");
    
    QApplication app(argc, argv);
    
    QWidget window;
    window.setWindowTitle("Qt + Rust 混合环境测试");
    window.resize(500, 400);
    
    QVBoxLayout *layout = new QVBoxLayout(&window);
    
    QLabel *label = new QLabel(QString("Rust计算 10 + 20 = %1").arg(result));
    label->setAlignment(Qt::AlignCenter);
    layout->addWidget(label);
    
    QPushButton *rustBtn = new QPushButton("调用Rust函数");
    layout->addWidget(rustBtn);
    
    QPushButton *quitBtn = new QPushButton("退出");
    layout->addWidget(quitBtn);
    
    QObject::connect(rustBtn, &QPushButton::clicked, [label]() {
        static int count = 0;
        count++;
        int new_result = add_numbers(count * 10, count * 5);
        label->setText(QString("Rust计算 %1*10 + %1*5 = %2").arg(count).arg(new_result));
        greet("VSCode用户");
    });
    
    QObject::connect(quitBtn, &QPushButton::clicked, &app, &QApplication::quit);
    
    window.show();
    return app.exec();
}

更新CMakeLists.txt以链接Rust库:

cmake 复制代码
cmake_minimum_required(VERSION 3.20)
project(QtRustMixed)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)

find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)

# 设置Rust库路径
set(RUST_LIB "${CMAKE_CURRENT_SOURCE_DIR}/rust_lib/target/release/librust_lib.a")

add_executable(qt_rust_mixed main.cpp)

target_link_libraries(qt_rust_mixed 
    Qt6::Widgets
    Qt6::Gui
    Qt6::Core
    "${RUST_LIB}"
    ws2_32
    ntdll
    advapi32
    userenv
)

# ============================================
# Windows平台:自动部署依赖
# ============================================
if(WIN32)
    # 获取MSYS2 UCRT64安装路径
    if(DEFINED ENV{MSYSTEM_PREFIX})
        set(MSYS2_PREFIX "$ENV{MSYSTEM_PREFIX}")
    else()
        # 默认路径(适用于标准安装)
        set(MSYS2_PREFIX "C:/msys64/ucrt64")
    endif()
    
    message(STATUS "MSYS2 prefix: ${MSYS2_PREFIX}")
    
    # 输出目录
    set(OUTPUT_DIR "$<TARGET_FILE_DIR:qt_rust_mixed>")
    
    # 函数:安全复制文件(检查文件是否存在)
    function(safe_copy_dll target src dest_dir)
        if(EXISTS "${src}")
            add_custom_command(TARGET ${target} POST_BUILD
                COMMAND ${CMAKE_COMMAND} -E copy_if_different
                "${src}"
                "${dest_dir}"
                COMMENT "复制: $(notdir ${src})"
            )
            message(STATUS "已配置: $(notdir ${src})")
        else()
            message(WARNING "文件不存在: ${src}")
        endif()
    endfunction()
    
    # 1. Qt6核心DLL
    set(QT6_CORE_DLLS
        "${MSYS2_PREFIX}/bin/Qt6Core.dll"
        "${MSYS2_PREFIX}/bin/Qt6Gui.dll"
        "${MSYS2_PREFIX}/bin/Qt6Widgets.dll"
    )
    
    # 2. Qt6图形和字体依赖(必须的)
    set(QT6_GRAPHICS_DLLS
        "${MSYS2_PREFIX}/bin/libfreetype-6.dll"
        "${MSYS2_PREFIX}/bin/libharfbuzz-0.dll"
        "${MSYS2_PREFIX}/bin/libb2-1.dll"
        "${MSYS2_PREFIX}/bin/libdouble-conversion.dll"
        "${MSYS2_PREFIX}/bin/libpcre2-16-0.dll"
        "${MSYS2_PREFIX}/bin/libzstd.dll"
        "${MSYS2_PREFIX}/bin/zlib1.dll"  # 注意:不是libz.dll
    )
    
    # 3. ICU国际化支持(可选,但如果Qt编译时包含ICU则需要)
    set(ICU_DLLS
        "${MSYS2_PREFIX}/bin/libicuin78.dll"
        "${MSYS2_PREFIX}/bin/libicuuc78.dll"
        "${MSYS2_PREFIX}/bin/libicudt78.dll"
    )
    
    # 4. MSYS2运行时
    set(MSYS2_RUNTIME_DLLS
        "${MSYS2_PREFIX}/bin/libstdc++-6.dll"
        "${MSYS2_PREFIX}/bin/libgcc_s_seh-1.dll"
        "${MSYS2_PREFIX}/bin/libwinpthread-1.dll"
    )
    
    # 复制所有DLL
    message(STATUS "配置Windows依赖部署...")
    
    # 创建部署列表
    set(ALL_DLLS 
        ${QT6_CORE_DLLS}
        ${QT6_GRAPHICS_DLLS}
        ${MSYS2_RUNTIME_DLLS}
    )
    
    # 检查并添加ICU DLL(如果存在)
    if(EXISTS "${MSYS2_PREFIX}/bin/libicuin78.dll")
        list(APPEND ALL_DLLS ${ICU_DLLS})
        message(STATUS "包含ICU国际化支持")
    else()
        message(STATUS "跳过ICU库(未找到)")
    endif()
    
    # 复制每个DLL
    foreach(DLL ${ALL_DLLS})
        safe_copy_dll(qt_rust_mixed "${DLL}" "${OUTPUT_DIR}")
    endforeach()
    
    # Rust DLL(如果存在)
    set(RUST_DLL "${CMAKE_CURRENT_SOURCE_DIR}/rust_lib/target/release/rust_lib.dll")
    if(EXISTS "${RUST_DLL}")
        safe_copy_dll(qt_rust_mixed "${RUST_DLL}" "${OUTPUT_DIR}")
    else()
        message(WARNING "Rust DLL未找到: ${RUST_DLL}")
        message(WARNING "请先运行: cd rust_lib && cargo build --release")
    endif()
    
    # 平台插件
    set(PLATFORM_PLUGIN "${MSYS2_PREFIX}/share/qt6/plugins/platforms/qwindows.dll")
    if(EXISTS "${PLATFORM_PLUGIN}")
        # 创建platforms目录
        add_custom_command(TARGET qt_rust_mixed POST_BUILD
            COMMAND ${CMAKE_COMMAND} -E make_directory
            "${OUTPUT_DIR}/platforms"
        )
        
        # 复制平台插件
        safe_copy_dll(qt_rust_mixed
            "${PLATFORM_PLUGIN}"
            "${OUTPUT_DIR}/platforms/"
        )
    else()
        message(WARNING "Qt平台插件未找到: ${PLATFORM_PLUGIN}")
    endif()
    
    # 可选:创建快捷运行脚本
    file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/run_app.bat" CONTENT "@echo off
set PATH=${MSYS2_PREFIX}/bin;%PATH%
$<TARGET_FILE_NAME:qt_rust_mixed>
pause")
    
    message(STATUS "Windows部署配置完成")
endif()

# ============================================
# 清理构建的辅助目标
# ============================================
add_custom_target(clean-all
    COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}
    COMMENT "完全清理构建目录"
)

重新构建并运行程序,成功实现了Qt界面调用Rust函数的功能。

五、配置代码分析功能

1. 验证代码跳转功能

现在测试VSCode的核心代码分析功能:

  1. C++代码跳转 :在 main.cpp 中,将光标放在 QApplication 上,按F12,成功跳转到Qt的头文件定义。
  2. 查找所有引用 :在 main.cpp 中,右键点击 add_numbers 函数,选择"查找所有引用",成功找到所有调用位置。
  3. 调用层次结构 :右键点击 greet 函数,选择"显示调用层次结构",成功显示调用关系图。

2. Rust代码分析

rust-lib/src/lib.rs 中:

  1. 将光标放在 add_numbers 函数上,按F12,跳转到定义。
  2. 使用Shift+F12查找所有对 add_numbers 的引用。
  3. rust-analyzer 扩展提供了完整的代码补全、类型提示和内联错误检查。

3. 跨语言调用分析

我注意到一个有用的技巧:通过创建虚拟的C++头文件来描述Rust函数的接口,可以改善C++端的代码分析体验。

创建 rust_interface.h

cpp 复制代码
// rust_interface.h
#ifndef RUST_INTERFACE_H
#define RUST_INTERFACE_H

#ifdef __cplusplus
extern "C" {
#endif

int add_numbers(int a, int b);
void greet(const char* name);

#ifdef __cplusplus
}
#endif

#endif // RUST_INTERFACE_H

然后在 main.cpp 中包含这个头文件,而不是直接使用 extern "C" 声明。这样C/C++扩展就能更好地理解这些函数。

六、遇到的问题与解决方案

1. 问题:VSCode的C++扩展找不到Qt头文件

现象:在VSCode中打开Qt头文件时出现红色波浪线错误。

解决 :我检查了 c_cpp_properties.json,确保 includePath 正确指向了UCRT64的Qt路径。还需要注意Qt6和Qt5的路径不同。

2. 问题:调试时找不到DLL

现象:程序编译成功,但运行时崩溃,提示缺少DLL。

解决 :在 launch.jsonenvironment 部分正确设置PATH,包含UCRT64的bin目录和Qt的bin目录。

3. 问题:rust-analyzer有时不工作

现象:Rust文件没有代码补全和错误提示。

解决

  1. 检查VSCode右下角,确保rust-analyzer已激活。
  2. 在UCRT64终端中运行 cargo check,确保Rust项目本身能编译。
  3. 重启rust-analyzer:在VSCode中按Ctrl+Shift+P,输入"Rust Analyzer: Restart Server"。

七、环境优化

1. 创建环境检查脚本

我创建了一个 check_env.sh 脚本来自动化环境检查:

bash 复制代码
#!/bin/bash

echo "=== MSYS2 UCRT64 Qt+Rust 环境检查 ==="
echo ""

echo "1. 检查基本工具:"
command -v g++ && g++ --version | head -1
command -v cmake && cmake --version | head -1
command -v rustc && rustc --version
command -v cargo && cargo --version
echo ""

echo "2. 检查Qt安装:"
find /ucrt64 -name "qmake.exe" 2>/dev/null | head -1
if [ -f "/ucrt64/bin/qmake.exe" ]; then
    /ucrt64/bin/qmake.exe --version | head -1
fi
echo ""

echo "3. 检查关键路径是否存在:"
echo "Qt头文件路径:"
ls -d /ucrt64/include/qt* 2>/dev/null
echo ""
echo "Rust工具链:"
rustup toolchain list
echo ""

echo "=== 检查完成 ==="

2. 配置VSCode工作区设置

.vscode/settings.json 中,我添加了项目特定设置:

json 复制代码
{
    "cmake.configureSettings": {
        "CMAKE_BUILD_TYPE": "Debug",
        "CMAKE_C_COMPILER": "C:/msys64/ucrt64/bin/gcc.exe",
        "CMAKE_CXX_COMPILER": "C:/msys64/ucrt64/bin/g++.exe"
    },
    "rust-analyzer.checkOnSave.command": "clippy",
    "rust-analyzer.cargo.target": "x86_64-pc-windows-gnu",
    "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
    "files.associations": {
        "*.rs": "rust",
        "*.cpp": "cpp",
        "*.h": "cpp",
        "*.hpp": "cpp"
    }
}

八、总结

经过一天的配置和测试,我成功在Windows 11上搭建了基于MSYS2 UCRT64环境的Qt+Rust混合开发环境。主要收获:

  1. UCRT64环境选择正确:与Windows 11的兼容性确实更好,运行时问题更少。
  2. VSCode配置是关键 :正确配置 c_cpp_properties.json、终端设置和调试环境是成功的前提。
  3. 混合编程可行:通过C接口,Qt和Rust可以很好地协作,各自发挥优势。
  4. 代码分析功能完整:两个语言的代码跳转、查找引用、查看调用层次结构功能都工作正常。

这个环境现在完全满足我的开发需求,可以同时享受Qt强大的GUI能力和Rust的内存安全与高性能。


最后更新时间 :2025年12月
环境状态 :稳定可用
下次优化方向:探索更深入的Qt+Rust集成模式,如使用CXX-Qt等高级绑定库。

相关推荐
粉红色回忆13 小时前
用链表实现了简单版本的malloc/free函数
数据结构·c++
写代码的小球14 小时前
C++计算器(学生版)
c++·算法
k***921614 小时前
【C++】继承和多态扩展学习
java·c++·学习
wadesir15 小时前
掌握Rust并发数据结构(从零开始构建线程安全的多线程应用)
数据结构·安全·rust
序属秋秋秋15 小时前
《Linux系统编程之进程控制》【进程等待】
linux·c语言·c++·进程·系统编程·进程控制·进程等待
l木本I15 小时前
Reinforcement Learning for VLA(强化学习+VLA)
c++·人工智能·python·机器学习·机器人
strive programming16 小时前
Effective C++_异常(解剖挖掘)
c++
wregjru16 小时前
【读书笔记】Effective C++ 条款1~2 核心编程准则
java·开发语言·c++
青岛少儿编程-王老师17 小时前
CCF编程能力等级认证GESP—C++1级—20251227
java·c++·算法
微露清风18 小时前
系统性学习C++进阶-第十四讲-二叉搜索树
开发语言·c++·学习