繁体   English   中英

如何使用 windows 中的 cmake 链接 SDL_ttf 和 SDL_image 库?

[英]How to link SDL_ttf and SDL_image libraries using cmake in windows?

我无法将SDL_ttfSDL_image包含并链接到我的项目。 我有一个仅适用于 Clion 上的SDLSDL_gfx的 cmake 文件。 我想问题出在 cmake 文件中。 我在构建项目时遇到了几个错误: undefined reference to `FUNCTION'

我用于项目的库: https://github.com/satayyeb/sdl2-libraries

sdl2 文件夹(库文件所在的位置)树:

sdl2-|
     |-sdl2-image-include
     |    |-SDL_image.h
     |
     |-sdl2-image-lib
     |    |-libSDL2_image.a
     |    |-libSDL2_image.dll.a
     |    |-libSDL2_image.la
     |
     |-sdl2-ttf-include
     |    |-SDL_ttf.h
     |
     |-sdl2-ttf-lib
          |-libSDL2_ttf.a
          |-libSDL2_ttf.dll.a
          |-libSDL2_ttf.la

CMakeLists.txt:

set(SOURCE src/main.c)
set(PROJECT_NAME state.SAT)

cmake_minimum_required(VERSION 3.19)

project(${PROJECT_NAME} C)

set(CMAKE_C_STANDARD 11)

set(SDL2_INCLUDE_DIR     "${CMAKE_CURRENT_SOURCE_DIR}/sdl2/sdl2-include")
set(SDL2_LIB_DIR         "${CMAKE_CURRENT_SOURCE_DIR}/sdl2/sdl2-lib")

set(SDL2_GFX_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/sdl2/sdl2-gfx-include")
set(SDL2_GFX_LIB_DIR     "${CMAKE_CURRENT_SOURCE_DIR}/sdl2/sdl2-gfx-lib")

set(SDL2_IMAGE_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/sdl2/sdl2-image-include")
set(SDL2_IMAGE_LIB_DIR     "${CMAKE_CURRENT_SOURCE_DIR}/sdl2/sdl2-image-lib")

set(SDL2_TTF_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/sdl2/sdl2-ttf-include")
set(SDL2_TTF_LIB_DIR     "${CMAKE_CURRENT_SOURCE_DIR}/sdl2/sdl2-ttf-lib")

set(SDL2_FLAGS           "-mwindows -Wl,--no-undefined -static-libgcc")


add_library(SDL2       STATIC IMPORTED)
add_library(SDL2main   STATIC IMPORTED)
add_library(SDL2_GFX   STATIC IMPORTED)
add_library(SDL2_IMAGE STATIC IMPORTED)

add_library(SDL2_TTF   STATIC IMPORTED)

set_property(TARGET SDL2       PROPERTY IMPORTED_LOCATION "${SDL2_LIB_DIR}/libSDL2.a")
set_property(TARGET SDL2main   PROPERTY IMPORTED_LOCATION "${SDL2_LIB_DIR}/libSDL2main.a")
set_property(TARGET SDL2_GFX   PROPERTY IMPORTED_LOCATION "${SDL2_GFX_LIB_DIR}/libsdl-gfx.a")
set_property(TARGET SDL2_IMAGE PROPERTY IMPORTED_LOCATION "${SDL2_IMAGE_LIB_DIR}/libSDL2_image.a")
set_property(TARGET SDL2_TTF   PROPERTY IMPORTED_LOCATION "${SDL2_TTF_LIB_DIR}/libSDL2_ttf.a")


set(SDL2_LIBS SDL2 SDL2main SDL2_GFX SDL2_TTF SDL2_IMAGE m dinput8 dxguid dxerr8 user32 gdi32 winmm imm32 ole32 oleaut32 shell32 version uuid)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${SDL2_FLAGS}")

file(GLOB_RECURSE SOURCE "src/*.c" "src/*.h")
add_executable("${PROJECT_NAME}" "${SOURCE}")

include_directories(${SDL2_INCLUDE_DIR} ${SDL2_GFX_INCLUDE_DIR} ${SDL2_IMAGE_INCLUDE_DIR} ${SDL2_TTF_INCLUDE_DIR})
target_link_libraries(${PROJECT_NAME} ${SDL2_LIBS})

简短的回答是您使用的库不兼容,因为 SDL2_ttf 和 SDL2_image 是针对比您存档中的更新版本的 SDL2 构建的(有问题的链接)。 获取较新的 SDL2,或较旧的 SDL2_ttf 和 SDL2_image,则无需更改任何内容。 写了冗长的解释后更正我注意到在你的档案中,即使是 static 和同一库的动态版本也有不同的版本; 我建议从 SDL 网站重新下载全部内容,因为您拥有的是一团糟。

请注意,我的回答不包括您的 CMakeLists.txt。 你所拥有的是非常特定于 Windows 的; 如果您不关心其他系统 - 就按照您的方式吧。 您的程序可以使用您在原始问题中想到的 CMakeLists 构建,这不是您问题的根源。

首先是否要使用 static 库是值得怀疑的。 如果没有充分的理由专门使用 static 库,我建议您切换到动态库,即与.dll.a链接(或直接支持工具链的.dll链接), 这样,您就不需要dinput8 dxguid dxerr8 user32 gdi32 winmm imm32 ole32 oleaut32 shell32 version uuid的长列表,如果您不知道,它们是您使用的 SDL2 版本的依赖项。 这意味着如果您更新您的 static libSDL2.a,此列表可能会有所不同,因为它现在取决于更多的东西(这不是理论上的 - 最新的 SDL 2.0.20 实际上有更长的依赖列表)。

库不兼容性的解释(很长,技术性很强,而且主要是 mingw/gcc 特定的;如果您对这些细节不感兴趣,请查看最后的注释):

您在问题中提到undefined reference to 'FUNCTION' ,但是FUNCTION非常重要; 如果您有这些信息,请不要从您未来的问题中忽略这些信息。 谢天谢地,您后来提供了完整库存档的链接,我们可以自己查看构建尝试的结果,即:

../sdl2/sdl2-ttf-lib/libSDL2_ttf.a(libSDL2_ttf_la-SDL_ttf.o): In function `RWread':
/Users/valve/release/SDL_ttf/SDL2_ttf-2.0.18-source/foo-x64/../SDL_ttf.c:1583: undefined reference to `SDL_RWseek'
/Users/valve/release/SDL_ttf/SDL2_ttf-2.0.18-source/foo-x64/../SDL_ttf.c:1587: undefined reference to `SDL_RWread'
../sdl2/sdl2-ttf-lib/libSDL2_ttf.a(libSDL2_ttf_la-SDL_ttf.o): In function `TTF_CloseFont':
/Users/valve/release/SDL_ttf/SDL2_ttf-2.0.18-source/foo-x64/../SDL_ttf.c:2544: undefined reference to `SDL_RWclose'
../sdl2/sdl2-ttf-lib/libSDL2_ttf.a(libSDL2_ttf_la-SDL_ttf.o): In function `TTF_OpenFontIndexDPIRW':
/Users/valve/release/SDL_ttf/SDL2_ttf-2.0.18-source/foo-x64/../SDL_ttf.c:1614: undefined reference to `SDL_RWtell'
/Users/valve/release/SDL_ttf/SDL2_ttf-2.0.18-source/foo-x64/../SDL_ttf.c:1647: undefined reference to `SDL_RWsize'
/Users/valve/release/SDL_ttf/SDL2_ttf-2.0.18-source/foo-x64/../SDL_ttf.c:1603: undefined reference to `SDL_RWclose'
../sdl2/sdl2-image-lib/libSDL2_image.a(IMG_svg.o): In function `nsvg__vecang':
/Users/valve/release/SDL_image/SDL2_image-2.0.5-source/foo-x64/../nanosvg.h:2096: undefined reference to `SDL_acosf'
../sdl2/sdl2-image-lib/libSDL2_image.a(IMG_svg.o): In function `nsvg__addActive':
/Users/valve/release/SDL_image/SDL2_image-2.0.5-source/foo-x64/../nanosvgrast.h:873: undefined reference to `SDL_floorf'
/Users/valve/release/SDL_image/SDL2_image-2.0.5-source/foo-x64/../nanosvgrast.h:874: undefined reference to `SDL_floorf'
/Users/valve/release/SDL_image/SDL2_image-2.0.5-source/foo-x64/../nanosvgrast.h:871: undefined reference to `SDL_floorf'
../sdl2/sdl2-image-lib/libSDL2_image.a(IMG_svg.o): In function `nsvg__parseStrokeDashArray':
/Users/valve/release/SDL_image/SDL2_image-2.0.5-source/foo-x64/../nanosvg.h:1722: undefined reference to `SDL_fabsf'
../sdl2/sdl2-image-lib/libSDL2_image.a(IMG_svg.o): In function `nsvg__parseRect':
/Users/valve/release/SDL_image/SDL2_image-2.0.5-source/foo-x64/../nanosvg.h:2364: undefined reference to `SDL_fabsf'
../sdl2/sdl2-image-lib/libSDL2_image.a(IMG_svg.o): In function `nsvg__parseCircle':
/Users/valve/release/SDL_image/SDL2_image-2.0.5-source/foo-x64/../nanosvg.h:2413: undefined reference to `SDL_fabsf'
../sdl2/sdl2-image-lib/libSDL2_image.a(IMG_svg.o): In function `nsvg__pathArcTo':
/Users/valve/release/SDL_image/SDL2_image-2.0.5-source/foo-x64/../nanosvg.h:2112: undefined reference to `SDL_fabsf'
/Users/valve/release/SDL_image/SDL2_image-2.0.5-source/foo-x64/../nanosvg.h:2113: undefined reference to `SDL_fabsf'
../sdl2/sdl2-image-lib/libSDL2_image.a(IMG_svg.o):/Users/valve/release/SDL_image/SDL2_image-2.0.5-source/foo-x64/../nanosvg.h:2115: more undefined references to `SDL_fabsf' follow
../sdl2/sdl2-image-lib/libSDL2_image.a(IMG_svg.o): In function `nsvg__curveDivs':
/Users/valve/release/SDL_image/SDL2_image-2.0.5-source/foo-x64/../nanosvgrast.h:598: undefined reference to `SDL_acosf'
/Users/valve/release/SDL_image/SDL2_image-2.0.5-source/foo-x64/../nanosvgrast.h:599: undefined reference to `SDL_ceilf'
../sdl2/sdl2-image-lib/libSDL2_image.a(IMG_svg.o): In function `nsvg__roundJoin':
/Users/valve/release/SDL_image/SDL2_image-2.0.5-source/foo-x64/../nanosvgrast.h:548: undefined reference to `SDL_atan2f'
/Users/valve/release/SDL_image/SDL2_image-2.0.5-source/foo-x64/../nanosvgrast.h:549: undefined reference to `SDL_atan2f'
/Users/valve/release/SDL_image/SDL2_image-2.0.5-source/foo-x64/../nanosvgrast.h:556: undefined reference to `SDL_ceilf'
../sdl2/sdl2-image-lib/libSDL2_image.a(IMG_svg.o): In function `nsvg__flattenShapeStroke':
/Users/valve/release/SDL_image/SDL2_image-2.0.5-source/foo-x64/../nanosvgrast.h:786: undefined reference to `SDL_fmodf'

好的,实际上不是一个长列表。 那么什么是未定义的? 少数SDL_RW*函数和少数 SDL 数学函数。 请注意,这不是SDL2_ttf 和 SDL2_image 使用的唯一 SDL 函数,其他所有函数都可以找到。 为什么在您的构建中找不到该功能?.. Linker 说没有具有该名称的功能,嗯,有吗? 由于您使用 mingw 工具链,因此您应该可以访问更多工具,而不仅仅是编译器,例如nm工具(在控制台中):

> nm -a sdl2/sdl-libs/libSDL2.a | grep SDL_RWseek
>

(如果您没有grep ,请使用findstr )是的,不在那里。 好吧,我们有 SDL2 源代码,包括版本历史,让我们看看为什么会这样。

让我们从例如SDL_RWseek开始。 There is a function with that name in SDL2, which we can view at https://github.com/libsdl-org/SDL/blob/120c76c84bbce4c1bfed4e9eb74e10678bd83120/include/SDL_rwops.h#L401 (just did a search for function name on github并打开了 header 文件)。 function 之前的评论有一个答案: Prior to SDL 2.0.10, this function was a macro. ... This function is available since SDL 2.0.10. . 哦。 因此,无论您拥有什么,似乎都低于 2.0.10,并且 SDL2_ttf 显然是为更新的东西而构建的,这已经是 function。

好的,SDL2_image 使用的数学函数怎么样。 Well, github search again points to https://github.com/libsdl-org/SDL/blob/120c76c84bbce4c1bfed4e9eb74e10678bd83120/include/SDL_stdinc.h#L572 , which seems to say that it was added at 2.0.2; 不幸的是,评论仅涵盖SDL_acos function,其他未评论。 但是,如果您将 github 视图切换为“责备”(顺便说一下,这并不特定于 github)以查看每行最后一次修改的时间,您可以看到许多这些数学函数是通过不同的提交添加的,并且跨越多个 什么没找到? SDL_fmodf - 4 年前添加,第一个版本是 2.0.8。 对于所有其他“未定义”函数也是如此。

因此,这些库需要 SDL2 2.0.10 和 2.0.8。 你有什么版本? 我没有看到快速检查的方法,但是有一个SDL_GetVersion function,为什么不制作调用它的最小程序:

#include "SDL.h"
#include <stdio.h>

int main(int argc, char **argv) {
    SDL_version v = {};
    SDL_GetVersion(&v);
    printf("%d.%d.%d\n", v.major, v.minor, v.patch);
    return 0;
}

构建和执行(重要的是它必须在您拥有的相同环境中构建,因此,出于所有意图和目的,这是您的main.c的内容),

2.0.7

哦。 所以是的,它无法与该版本一起使用,它没有想要调用的函数。

在您自己的回答中,您说您已经通过添加指向libSDL2_ttf.dll.alibSDL2_image.dll.a的链接来构建它,大概是由于库顺序。 首先,图书馆顺序只对动态图书馆很重要(甚至在那里——不是每个 linker 实现),所以不是这样。 但它为什么建起来? 我们这里要到 windows 特定领域,其概念是“导入库”; .dll.a就是这样,一个包含“这将在运行时稍后加载”的符号的存根。 它的作用是使您的结果程序取决于例如SDL2_ttf.dll 动态库与可执行文件非常相似,并且实际上有自己的依赖项列表(静态库没有 - 这就是为什么您在 cmakelists 中有长长的 SDL2 依赖项列表的原因),因此 SDL2_ttf.dll 中有一个条目表示它依赖于 SDL2 .dll。 再一次,您可以使用值得信赖的编译器工具链进行检查:

> ldd sdl2/sdl2-ttf-bin/SDL2_ttf.dll | grep SDL2
        SDL2.dll => /c/WINDOWS/SYSTEM32/SDL2.dll (0x5ccb0000)

What it means is it depends on SDL2.dll , and if i launch it in my current environment, it'll use C:\Windows\system32\SDL2.dll that I have in my default dll search path (your environment could be different )。 如果您使用相同的ldd工具检查生成的 exe,您会看到您现在依赖于SDL2_ttf.dll ,但正因为如此 - 也依赖于SDL2.dll 因此,现在您在程序中静态链接了 SDL2,但由于依赖关系,还拉动了动态 SDL2.dll。 所以它可以构建,甚至可以运行,但很难想象它会按预期工作。 我很确定当您尝试实际进行纹理或字体处理时,它会全部崩溃。

在编写所有内容时,我发现您的 SDL2.dll 实际上是 2.0.20,但 libSDL2.a 是 2.0.7。 也许最好的做法是核对您的整个库存档并从 SDL 网站重新下载所有内容。

我发现了问题:

  1. sdl2-image-libsdl2-ttf-lib目录中有libSDL2_image.dll.alibSDL2_ttf.dll.a二进制文件必须链接。

  2. 顺序在链接中很重要 例如libSDL2_image.dll.a必须在 libSDL2_image.a 之前传递给libSDL2_image.a

我用于项目的库: https://github.com/satayyeb/sdl2-libraries

和修改后的CMakeLists.txt:

set(SOURCE src/main.c)
set(PROJECT_NAME state.SAT)
cmake_minimum_required(VERSION 3.19)
project(${PROJECT_NAME} C)
set(CMAKE_C_STANDARD 11)


set(SDL2_INCLUDE_DIR     "${CMAKE_CURRENT_SOURCE_DIR}/sdl2/sdl2-include")
set(SDL2_LIB_DIR         "${CMAKE_CURRENT_SOURCE_DIR}/sdl2/sdl2-lib")

set(SDL2_GFX_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/sdl2/sdl2-gfx-include")
set(SDL2_GFX_LIB_DIR     "${CMAKE_CURRENT_SOURCE_DIR}/sdl2/sdl2-gfx-lib")

set(SDL2_IMAGE_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/sdl2/sdl2-image-include")
set(SDL2_IMAGE_LIB_DIR     "${CMAKE_CURRENT_SOURCE_DIR}/sdl2/sdl2-image-lib")

set(SDL2_TTF_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/sdl2/sdl2-ttf-include")
set(SDL2_TTF_LIB_DIR     "${CMAKE_CURRENT_SOURCE_DIR}/sdl2/sdl2-ttf-lib")


set(SDL2_FLAGS   "-mwindows -Wl,--no-undefined -static-libgcc")


add_library(SDL2            STATIC IMPORTED)
add_library(SDL2main        STATIC IMPORTED)

add_library(SDL2_GFX        STATIC IMPORTED)

add_library(SDL2_IMAGE_DLL  STATIC IMPORTED)
add_library(SDL2_IMAGE      STATIC IMPORTED)

add_library(SDL2_TTF_DLL    STATIC IMPORTED)
add_library(SDL2_TTF        STATIC IMPORTED)




set_property(TARGET SDL2            PROPERTY IMPORTED_LOCATION "${SDL2_LIB_DIR}/libSDL2.a")
set_property(TARGET SDL2main        PROPERTY IMPORTED_LOCATION "${SDL2_LIB_DIR}/libSDL2main.a")

set_property(TARGET SDL2_GFX        PROPERTY IMPORTED_LOCATION "${SDL2_GFX_LIB_DIR}/libsdl-gfx.a")

set_property(TARGET SDL2_IMAGE_DLL  PROPERTY IMPORTED_LOCATION "${SDL2_IMAGE_LIB_DIR}/libSDL2_image.dll.a")
set_property(TARGET SDL2_IMAGE      PROPERTY IMPORTED_LOCATION "${SDL2_IMAGE_LIB_DIR}/libSDL2_image.a")

set_property(TARGET SDL2_TTF_DLL    PROPERTY IMPORTED_LOCATION "${SDL2_TTF_LIB_DIR}/libSDL2_ttf.dll.a")
set_property(TARGET SDL2_TTF        PROPERTY IMPORTED_LOCATION "${SDL2_TTF_LIB_DIR}/libSDL2_ttf.a")


# Order is important! SDL2_IMAGE_DLL must called before SDL2_IMAGE and SDL2_TTF_DLL before SDL2_TTF
set(SDL2_LIBS mingw32 SDL2 SDL2main SDL2_GFX SDL2_TTF_DLL SDL2_TTF SDL2_IMAGE_DLL SDL2_IMAGE m dinput8 dxguid dxerr8 user32 gdi32 winmm imm32 ole32 oleaut32 shell32 version uuid)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${SDL2_FLAGS}")
file(GLOB_RECURSE SOURCE "src/*.c" "src/*.h")
add_executable("${PROJECT_NAME}" "${SOURCE}")
include_directories(${SDL2_INCLUDE_DIR} ${SDL2_GFX_INCLUDE_DIR} ${SDL2_IMAGE_INCLUDE_DIR} ${SDL2_TTF_INCLUDE_DIR})
target_link_libraries(${PROJECT_NAME} ${SDL2_LIBS})

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM