CMake静态链接SDL2_Image失败求助(Windows+MSYS2环境)
环境信息
- 系统:
Windows 11 22H2 - 工具链:
MSYS2 UCRT64
问题详情
使用如下CMakeLists.txt配置时,出现错误:"INTERFACE_SDL2_SHARED property not agree"
cmake_minimum_required(VERSION 3.16) project(sdl_test) set(CMAKE_CXX_STANDARD 23) find_package(SDL2 REQUIRED) find_package(SDL2_image REQUIRED) find_package(SDL2_ttf REQUIRED) find_package(SDL2_mixer REQUIRED) include_directories(${SDL2_INCLUDE_DIRS}) add_executable(sdl_test main.cpp sdl_bindings/window.cpp sdl_bindings/window.h sdl_bindings/renderer.cpp sdl_bindings/renderer.h sdl_bindings/texture.cpp sdl_bindings/texture.h sdl_bindings/surface.cpp sdl_bindings/surface.h sdl_bindings/image.cpp sdl_bindings/image.h sdl_bindings/font.cpp sdl_bindings/font.h) #include_directories( # "C:/clibs/SDL2_mingw/SDL2-2.28.5/include/SDL2" # "C:/clibs/SDL2_mingw/SDL2_image-2.6.3/x86_64-w64-mingw32/include/SDL2" # "C:/clibs/SDL2_mingw/SDL2_ttf-2.20.2/x86_64-w64-mingw32/include/SDL2" # "C:/clibs/SDL2_mingw/SDL2_mixer-2.6.3/x86_64-w64-mingw32/include/SDL2" #) # include dir above not correct and misleading, change to: include_directories( ${SDL2_INCLUDE_DIRS} ) target_link_libraries( sdl_test SDL2::SDL2main SDL2::SDL2 SDL2_image::SDL2_image SDL2_ttf::SDL2_ttf SDL2_mixer::SDL2_mixer )
动态链接时的错误日志
C:\packages\MSYS2\ucrt64\bin\cmake.exe -DCMAKE_BUILD_TYPE=Debug -DCMAKE_MAKE_PROGRAM=C:/packages/MSYS2/ucrt64/bin/mingw32-make.exe -DCMAKE_C_COMPILER=C:/packages/MSYS2/ucrt64/bin/gcc.exe -DCMAKE_CXX_COMPILER=C:/packages/MSYS2/ucrt64/bin/g++.exe -G "CodeBlocks - MinGW Makefiles" -S C:\workspace\cpp\sdl_test -B C:\workspace\cpp\sdl_test\cmake-build-debug-msys2 -- Configuring done CMake Error: The INTERFACE_SDL2_SHARED property of "SDL2_image::SDL2_image" does not agree with the value of SDL2_SHARED already determined for "sdl_test". -- Generating done CMake Generate step failed. Build files cannot be regenerated correctly.
静态链接尝试的错误
将链接目标改为SDL2::SDL2-static、SDL2_image::SDL2_image-static这类静态版本时,出现"target not found"错误:
C:\packages\MSYS2\ucrt64\bin\cmake.exe -DCMAKE_BUILD_TYPE=Debug -DCMAKE_MAKE_PROGRAM=C:/packages/MSYS2/ucrt64/bin/mingw32-make.exe -DCMAKE_C_COMPILER=C:/packages/MSYS2/ucrt64/bin/gcc.exe -DCMAKE_CXX_COMPILER=C:/packages/MSYS2/ucrt64/bin/g++.exe -G "CodeBlocks - MinGW Makefiles" -S C:\workspace\cpp\sdl_test -B C:\workspace\cpp\sdl_test\cmake-build-debug-msys2 -- Configuring done CMake Error at CMakeLists.txt:59 (target_link_libraries): Target "sdl_test" links to: SDL2_image::SDL2_image-static but the target was not found. Possible reasons include: * There is a typo in the target name. * An ALIAS target is missing.
静态库实际存在于C:\packages\MSYS2\ucrt64\lib目录,但不知道如何通过CMake正确链接,同时有两个疑问:
- 怎么知道链接目标要用
SDL2::SDL2-static这类命名,而非其他形式? - 不查看
FindSDL2.cmake等文件的话,怎么知道find_package(SDL2 REQUIRED)的返回结果和副作用?
解决方案与解释
1. 解决INTERFACE_SDL2_SHARED不匹配问题
这个错误是因为SDL主库和组件(SDL2_image、SDL2_ttf等)要求使用一致的链接类型(静态/动态),当前配置出现了混合冲突。在MSYS2 UCRT64环境中,默认SDL包同时包含静态和动态库,但CMake Find模块的默认选择可能导致组件间配置不一致。
方法一:强制使用动态库
在find_package前添加变量设置,统一所有SDL组件用动态链接:
set(SDL2_SHARED ON CACHE BOOL "Use shared SDL2 libraries" FORCE)
修改后的CMakeLists开头:
cmake_minimum_required(VERSION 3.16) project(sdl_test) set(CMAKE_CXX_STANDARD 23) # 强制所有SDL组件使用动态库,避免链接类型不匹配 set(SDL2_SHARED ON CACHE BOOL "Use shared SDL2 libraries" FORCE) find_package(SDL2 REQUIRED) find_package(SDL2_image REQUIRED) find_package(SDL2_ttf REQUIRED) find_package(SDL2_mixer REQUIRED)
方法二:强制使用静态库
如果要使用静态库,先在find_package前设置:
set(SDL2_SHARED OFF CACHE BOOL "Use shared SDL2 libraries" FORCE)
同时确保MSYS2中安装了静态库包:
pacman -S mingw-w64-ucrt-x86_64-SDL2-static mingw-w64-ucrt-x86_64-SDL2_image-static mingw-w64-ucrt-x86_64-SDL2_ttf-static mingw-w64-ucrt-x86_64-SDL2_mixer-static
安装后,CMake会自动识别静态目标,链接时直接用原目标名(如SDL2::SDL2)即可,不需要加-static后缀——因为SDL2_SHARED设为OFF后,SDL2::SDL2会自动指向静态库版本。
2. 关于链接目标命名的疑问
- 不需要手动指定
-static后缀,通过SDL2_SHARED变量就能切换静态/动态链接目标,SDL的Find模块会自动处理目标指向。 - 想查看
find_package生成的目标和变量,有两种方式:- 在CMake配置时添加
--debug-find参数,输出详细的查找过程和生成的目标信息; - 在CMakeLists中添加代码打印SDL相关变量:
get_cmake_property(_variableNames VARIABLES) list (FILTER _variableNames REGEX "^SDL2.*") foreach (_variableName ${_variableNames}) message(STATUS "${_variableName}=${${_variableName}}") endforeach() - 配置完成后进入构建目录,运行
cmake -L .查看所有已设置的变量,其中包含SDL相关的目标和路径信息。
- 在CMake配置时添加
3. CMakeLists优化建议
- 避免使用全局的
include_directories,改用目标导向的target_include_directories,更符合现代CMake规范:target_include_directories(sdl_test PRIVATE ${SDL2_INCLUDE_DIRS}) SDL2::SDL2main只需要链接一次,且仅针对可执行文件,无需添加到库目标中。
内容的提问来源于stack exchange,提问作者Kera
相关产品推荐
相关产品推荐

