You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用SFML与C++20模块时GCC编译出现ODR违反错误的解决求助

SFML与C++20模块时GCC编译出现ODR违反错误的解决求助

我正在尝试用SFML和C++20模块搭建一个跨编译器项目,需要同时兼容MSVC和GCC 14.2。目前我梳理的现状(如果有错误欢迎指正):

  • SFML官方暂未支持模块(不过有一个活跃的PR在推进相关支持,GCC存在例外兼容情况)
  • GCC目前不支持头单元

所以我想了个折中方案:项目内部完全采用模块开发,通过全局模块片段引入SFML和标准库的内容(后续如果编译速度变慢再考虑预编译头优化)。

但搭建好项目后,在使用依赖std::string的SFML类sf::Font时,GCC编译直接抛出了ODR(单定义规则)违反错误。其中一个典型的错误日志如下:

[build] C:/.../bin/ld.exe: CMakeFiles/.../src/Game.cpp.obj: in function std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Alloc_hider::~_Alloc_hider()': [build] C:/.../lib/gcc/x86_64-w64-mingw32/14.2.0/include/c++/bits/basic_string.h:186: multiple definition of std::__cxx11::basic_string<char, std::char_traits, std::allocator >::_Alloc_hider::~_Alloc_hider()'; CMakeFiles/.../src/main.cpp.obj:C:/.../lib/gcc/x86_64-w64-mingw32/14.2.0/include/c++/bits/basic_string.h:186: first defined here

我把问题简化成了最小复现代码:

main.cpp

import Game;

int main() {
    Game game;
    game.run();
}

Game.ixx

module;
#include <SFML/Graphics.hpp>
export module Game;

export class Game {
public:
    Game();
    void run();
private:
    sf::RenderWindow m_window;
    sf::Font m_font;
};

Game.cpp

module;
#include <SFML/Graphics.hpp>
module Game;

Game::Game()
    : m_window(sf::VideoMode({1920u, 1080u}), "My Game"),
      m_font("Sansation.tff") {
}

void Game::run() {
}

注:我保留了sf::RenderWindow成员,因为它并没有引发类似的错误。

我的CMakeLists.txt配置如下:

set(CMAKE_CXX_STANDARD 20)
project(MyGame LANGUAGES CXX)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

set(FETCHCONTENT_FULLY_DISCONNECTED ON)
include(FetchContent)
FetchContent_Declare(SFML
    GIT_REPOSITORY https://github.com/SFML/SFML.git
    GIT_TAG 3.0.1
    GIT_SHALLOW ON
    EXCLUDE_FROM_ALL
    SYSTEM)
FetchContent_MakeAvailable(SFML)

file(GLOB_RECURSE MODULE_INTERFACE_FILES CONFIGURE_DEPENDS "src/*.ixx")
file(GLOB_RECURSE MODULE_IMPLEMENTATION_FILES CONFIGURE_DEPENDS "src/*.cpp")

add_executable(${PROJECT_NAME})
target_sources(${PROJECT_NAME}
    PUBLIC src/main.cpp)
target_sources(${PROJECT_NAME}
    PUBLIC
        FILE_SET cxx_modules TYPE CXX_MODULES
        FILES ${MODULE_INTERFACE_FILES}
    PRIVATE ${MODULE_IMPLEMENTATION_FILES}
)
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20)
target_link_libraries(${PROJECT_NAME} PRIVATE SFML::Graphics)

我现在完全摸不着头脑——从错误信息看,像是std::string这类标准库类的析构函数被重复定义了,但这看起来完全不符合常理。我猜测可能是模块上下文里的头文件包含守卫机制出了问题?但如果不在模块接口单元和实现单元中都引入SFML头文件,项目连基础编译都无法通过。

有没有大佬能帮忙分析下问题根源,或者给出可行的解决思路?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 10:23:10