使用CMake构建SFML共享库时遭遇多重定义错误的技术问询
解决动态库转换后的multiple definition错误
原本使用静态库时构建正常,将库改为SHARED类型后,构建项目出现multiple definition error。问题根源是SFML被重复链接,但移除任意一方的SFML链接后,对应项目又无法找到SFML头文件,以下是解决方法:
原CMake配置
库(arcade-lib)配置
add_library(arcade-lib SHARED src/button.cpp src/menu.cpp src/random.cpp) target_include_directories(arcade-lib PUBLIC include) target_link_libraries(arcade-lib PRIVATE sfml-window sfml-graphics)
可执行文件(snake-game)配置
add_executable(snake-game WIN32 snake-game.cpp src/field.cpp src/food.cpp src/level.cpp src/menu.cpp src/snake.cpp) target_link_libraries(snake-game PRIVATE arcade-lib sfml-graphics sfml-window sfml-system sfml-main) target_include_directories(snake-game PRIVATE include)
错误信息
cmd.exe /C "cd . && C:\PROGRA~1\JETBRA~1\CLION2~1.2\bin\mingw\bin\G__~1.EXE -g -static -static-libgcc -mwindows snake-game/CMakeFiles/snake-game.dir/snake-game.cpp.obj snake-game/CMakeFiles/snake-game.dir/src/field.cpp.obj snake-game/CMakeFiles/snake-game.dir/src/food.cpp.obj snake-game/CMakeFiles/snake-game.dir/src/level.cpp.obj snake-game/CMakeFiles/snake-game.dir/src/menu.cpp.obj snake-game/CMakeFiles/snake-game.dir/src/snake.cpp.obj snake-game/CMakeFiles/snake-game.dir/src/witch_level.cpp.obj -o snake-game\bin\snake-game.exe -Wl,--out-implib,snake-game\lib\libsnake-game.dll.a -Wl,--major-image-version,0,--minor-image-version,0 arcade-games-lib/libarcade-lib.dll.a C:/projects/snake-game/arcade-games/sfml/MinGW/lib/libsfml-graphics-s-d.a C:/projects/snake-game/arcade-games/sfml/MinGW/lib/libsfml-window-s-d.a C:/projects/snake-game/arcade-games/sfml/MinGW/lib/libsfml-system-s-d.a C:/projects/snake-game/arcade-games/sfml/MinGW/lib/libsfml-main-d.a -lOpenGL32 -lwinmm -lgdi32 C:/projects/snake-game/arcade-games/sfml/MinGW/lib/libfreetype.a -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ." C:\Program Files\JetBrains\CLion 2022.3.2\bin\mingw\bin/ld.exe: C:/projects/snake-game/arcade-games/sfml/MinGW/lib/libsfml-graphics-s-d.a(Color.cpp.obj): in function `sf::Color::Color(unsigned char, unsigned char, unsigned char, unsigned char)': D:/Programming/C++/Contrib/SFML/src/SFML/Graphics/Color.cpp:60: multiple definition of `sf::Color::Color(unsigned char, unsigned char, unsigned char, unsigned char)'; arcade-games-lib/libarcade-lib.dll.a(d000781.o):(.text+0x0): first defined here collect2.exe: error: ld returned 1 exit status
解决步骤
1. 修改库的SFML链接属性为PUBLIC
将arcade-lib中target_link_libraries的PRIVATE改为PUBLIC,这样CMake会自动将SFML的依赖传递给所有链接该库的目标(比如snake-game),同时保证库和可执行文件都能找到SFML的头文件:
add_library(arcade-lib SHARED src/button.cpp src/menu.cpp src/random.cpp) target_include_directories(arcade-lib PUBLIC include) # 改为PUBLIC,让依赖自动传递 target_link_libraries(arcade-lib PUBLIC sfml-window sfml-graphics)
2. 移除可执行文件中的重复SFML链接项
由于库已经将SFML作为PUBLIC依赖传递,snake-game不需要再手动链接sfml-graphics和sfml-window,只保留独有的sfml-system和sfml-main即可:
add_executable(snake-game WIN32 snake-game.cpp src/field.cpp src/food.cpp src/level.cpp src/menu.cpp src/snake.cpp) # 仅链接arcade-lib和独有的SFML组件 target_link_libraries(snake-game PRIVATE arcade-lib sfml-system sfml-main) target_include_directories(snake-game PRIVATE include)
原理说明
静态SFML库的代码不能被多次链接到不同模块(动态库和可执行文件),否则会触发重复定义错误。通过将库的SFML依赖设为PUBLIC,CMake会统一管理依赖传递,确保SFML静态库只被链接一次到最终可执行文件,同时所有依赖模块都能正确访问SFML的头文件。
内容的提问来源于stack exchange,提问作者Vinograd
相关产品推荐
相关产品推荐

