在Windows用MinGW编译Linux编写的Qt5应用报错求助
问题
我在RHEL8系统上用Qt5.15.2开发了名为AGM_COMPTA的Qt应用,现在尝试在Windows10的Qt Creator中用MinGW编译该项目时出现大量错误,典型错误如下:
C:\Qt\Tools\mingw810_64\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\bits\fs_path.h:237: erreur : no match for 'operator!=' (operand types are 'std::filesystem::__cxx11::path' and 'std::filesystem::__cxx11::path') In file included from C:/Qt/Tools/mingw810_64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/filesystem:37, from C:/Users/brd.LAPTOP-716I0O3B/Documents/app/AGM_COMPTA/datab.cpp:4: C:/Qt/Tools/mingw810_64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/fs_path.h: In member function 'std::filesystem::__cxx11::path& std::filesystem::__cxx11::path::operator/=(const std::filesystem::__cxx11::path&)': C:/Qt/Tools/mingw810_64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/fs_path.h:237:47: error: no match for 'operator!=' (operand types are 'std::filesystem::__cxx11::path' and 'std::filesystem::__cxx11::path') || (__p.has_root_name() && __p.root_name() != root_name())) ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~
导入项目的操作步骤:
- 在Qt Creator中选择「文件->打开文件或项目」,选中CMakeLists.txt并收到警告;
- 配置环节勾选MinGW 64位并继续;
- 打开项目后编译出现大量上述错误。
项目CMakeLists.txt包含SQLiteCpp和OpenXLSX两个子项目库,内容如下:
cmake_minimum_required(VERSION 3.5) project(AGM_COMPTA VERSION 0.1 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) add_subdirectory(static_lib/SQLiteCpp) add_subdirectory(static_lib/OpenXLSX) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Core console) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets) find_package(Qt${QT_VERSION_MAJOR}Sql REQUIRED) find_package(Qt5Network REQUIRED) find_package(OpenSSL REQUIRED) set(PROJECT_SOURCES main.cpp mainwindow.cpp mainwindow.h mainwindow.ui dialogdocumentline.h dialogdocumentline.cpp dialogdocumentline.ui settingdialog.h settingdialog.cpp settingdialog.ui operationassociationdialog.h operationassociationdialog.cpp operationassociationdialog.ui dialogcashboxline.h dialogcashboxline.cpp dialogcashboxline.ui ressources.qrc datab.cpp datab.h Importer.cpp Importer.h OperationLine.h QStyledItemDelegateNoElide.h tools.h DocumentLine.h CashboxLine.h exportTools.h) if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) qt_add_executable(AGM_COMPTA MANUAL_FINALIZATION ${PROJECT_SOURCES} ) # Define target properties for Android with Qt 6 as: # set_property(TARGET AGM_COMPTA APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR # ${CMAKE_CURRENT_SOURCE_DIR}/android) # For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation else() if(ANDROID) add_library(AGM_COMPTA SHARED ${PROJECT_SOURCES} ) # Define properties for Android with Qt 5 after find_package() calls as: # set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android") else() add_executable(AGM_COMPTA ${PROJECT_SOURCES} ) endif() endif() target_link_libraries(AGM_COMPTA PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Sql SQLiteCpp sqlite3 OpenXLSX::OpenXLSX Qt5::Network OpenSSL::SSL stdc++fs) set_target_properties(AGM_COMPTA PROPERTIES MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} MACOSX_BUNDLE TRUE WIN32_EXECUTABLE TRUE ) if(QT_VERSION_MAJOR EQUAL 6) qt_finalize_executable(AGM_COMPTA) endif()
测试新建基础Qt项目可正常编译,请问问题出在哪里?该如何排查定位错误?
问题定位与解决方法
核心问题分析
错误源于std::filesystem::path的运算符匹配失败,本质是MinGW 8.1.0对C17/C20标准库的std::filesystem支持不完善,再加上CMake配置中的C++标准版本冲突、子项目兼容性问题,共同导致编译失败。
具体排查修复步骤
统一C++标准版本
CMakeLists中先后设置了C17和C20,会导致主项目与子项目(SQLiteCpp、OpenXLSX)的编译标准不一致,触发ABI兼容性问题。建议统一使用C++17(Qt5.15对其支持更稳定,且适配MinGW8.1的特性):# 移除后续的set(CMAKE_CXX_STANDARD 20),保留并强化开头的设置 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON)修复MinGW下
std::filesystem的链接逻辑
Windows MinGW环境中,GCC9.0以下版本使用std::filesystem必须显式链接stdc++fs库,且要确保所有依赖该库的目标(包括子项目)都正确链接。修改主项目的链接配置,增加版本判断逻辑:target_link_libraries(AGM_COMPTA PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Sql SQLiteCpp sqlite3 OpenXLSX::OpenXLSX Qt5::Network OpenSSL::SSL $<$<AND:$<CXX_COMPILER_ID:GNU>,$<VERSION_LESS:$<CXX_COMPILER_VERSION>,9.0>>:stdc++fs> )同时强制子项目继承主项目的C++标准,在
add_subdirectory前添加:set(CMAKE_CXX_STANDARD 17 CACHE INTERNAL "" FORCE) set(CMAKE_CXX_STANDARD_REQUIRED ON CACHE INTERNAL "" FORCE)锁定Qt版本为Qt5
原CMake配置同时兼容Qt5和Qt6,但Windows环境下可能自动切换到Qt6,与你在RHEL8上开发的Qt5.15项目存在兼容性差异。强制指定Qt5:find_package(QT NAMES Qt5 REQUIRED COMPONENTS Widgets Core console)清理CMake缓存并重新配置
导入项目时的警告大概率是残留了Linux环境的缓存配置,导致编译逻辑混乱:- 关闭Qt Creator,删除项目目录下的
build-*文件夹; - 重新打开项目,选择MinGW 64位配置,确保配置过程无警告。
- 关闭Qt Creator,删除项目目录下的
验证流程
修改完成后,先单独编译SQLiteCpp和OpenXLSX子项目,确认无错误后再编译主项目。若仍有问题,检查datab.cpp中std::filesystem的使用:是否包含<filesystem>头文件、是否正确使用std::filesystem命名空间。
内容的提问来源于stack exchange,提问作者Brandonn

