首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在windows中使用cmake链接SDL_ttf和SDL_image库?

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

Stack Overflow用户
提问于 2022-02-04 17:57:50
回答 2查看 963关注 0票数 1

我在将SDL_ttfSDL_image链接到我的项目时遇到了问题。我有一个cmake文件,它只适用于SDLSDL_gfx。我想问题是来自cmake文件。在构建该项目时,我遇到了几个错误:undefined reference to `FUNCTION'

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

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

代码语言:javascript
运行
复制
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 :

代码语言:javascript
运行
复制
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})
EN

Stack Overflow用户

发布于 2022-02-05 16:21:14

简单地说,您使用的库是不兼容的,因为SDL2_ttf和SDL2_image是针对较新版本的SDL2构建的,而不是您在存档中使用的(链接有问题)。获得更新的SDL2,或者更旧的SDL2_ttf和SDL2_image,那么您就不必改变任何东西。在写完冗长的说明后,我注意到,在您的存档中,即使是同一个库的静态和动态版本也有不同的版本;我建议从SDL网站重新下载全部内容,因为您拥有的是一片混乱。

请注意,我的答案没有涵盖您的CMakeLists.txt。您所拥有的是非常特定于windows的;如果您不关心其他系统,请按您的方式来做。您的程序可以使用CMakeLists构建,您在最初的问题思考,这不是您的问题来源。

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

对图书馆不兼容的解释(很长,相当技术性,而且大多是特定的/gcc的;如果您对这些细节不感兴趣,只需在最后查看最后的注释):

您在问题中提到了undefined reference to 'FUNCTION',但是哪个FUNCTION非常重要;如果您曾经有过这样的问题,请不要忽略未来问题中的信息。幸运的是,您后来提供了一个指向完整库归档的链接,我们可以自己看到构建尝试的结果,即:

代码语言:javascript
运行
复制
../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函数,其他功能都可以找到。为什么在您的构建中找不到这些功能?林克说没有这个名字的函数,是吗?由于您使用了混合工具链,您应该可以访问比编译器更多的工具,例如nm工具(在控制台中):

代码语言:javascript
运行
复制
> nm -a sdl2/sdl-libs/libSDL2.a | grep SDL_RWseek
>

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

让我们从例如SDL_RWseek开始。在SDL2中有一个具有该名称的函数,我们可以在https://github.com/libsdl-org/SDL/blob/120c76c84bbce4c1bfed4e9eb74e10678bd83120/include/SDL_rwops.h#L401上查看它(只在github上搜索函数名并打开一个头文件)。该函数之前的注释有一个答案: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显然是为更新的东西而构建的,这已经是一个函数了。

好吧,那么SDL2_image使用的数学函数呢?好的,github搜索再次指向https://github.com/libsdl-org/SDL/blob/120c76c84bbce4c1bfed4e9eb74e10678bd83120/include/SDL_stdinc.h#L572,它似乎说它是在2.0.2添加的;不幸的是,注释只包含SDL_acos函数,而其他函数没有注释。但是,如果您将github视图切换为“指责”(顺便说一句,这并不是github特有的),以查看每一行是何时修改的,那么您可以看到,许多这些数学函数都是通过不同的提交和跨年添加的。还没有发现什么呢?4年前添加的SDL_fmodf,第一个版本是2.0.8。所有其他“未定义”函数也是如此。

因此,这些库需要SDL2 2.0.10和2.0.8。你有什么版本的?我看不出有一种快速的检查方法可以确定,但是有一个SDL_GetVersion函数,为什么不使用最小的程序来调用它:

代码语言:javascript
运行
复制
#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的一个内容),

代码语言:javascript
运行
复制
2.0.7

噢。所以是的,它不可能与那个版本一起工作,也没有它想要调用的函数。

在您自己的回答中,您说您是通过添加到libSDL2_ttf.dll.alibSDL2_image.dll.a的链接来构建它的,这可能是由于图书馆的订购。首先,库顺序只对dinamic库很重要(甚至对每个链接器实现来说也是如此),所以不是这样的。但它为什么要建造呢?我们将在这里使用“导入库”的概念来窗口特定的区域;.dll.a正是这样一个存根,其中包含“这将在运行时稍后加载”的符号。它所做的是使您的结果程序依赖于例如SDL2_ttf.dll。动态库非常类似于可执行文件,实际上它们本身也有依赖列表(静态库没有--这就是为什么cmakelist中有长长的SDL2依赖项列表),因此在SDL2_ttf.dll中有一个条目表示它依赖于SDL2.dll。再一次,您可以使用可靠的编译器工具链来检查这一点:

代码语言:javascript
运行
复制
> ldd sdl2/sdl2-ttf-bin/SDL2_ttf.dll | grep SDL2
        SDL2.dll => /c/WINDOWS/SYSTEM32/SDL2.dll (0x5ccb0000)

这意味着它取决于SDL2.dll,如果我在当前环境中启动它,它将使用我默认的dll搜索路径中的C:\Windows\system32\SDL2.dll (您的环境可能有所不同)。如果您使用相同的ldd工具检查生成的exe,您将看到您现在依赖于SDL2_ttf.dll,但正因为如此-也依赖于SDL2.dll。因此,现在您已经在程序中静态地链接了SDL2,但是由于依赖关系,还可以拉出动态SDL2.dll。因此,它构建,甚至运行,但很难想象它会像预期的那样工作。我很肯定,当你真的尝试去做纹理或字体处理的时候,它都会崩溃。

在编写所有我计算出的SDL2.dll时,实际上是2.0.20,而libSDL2.a是2.0.7。也许最好的做法是对整个图书馆的档案进行核弹,并从SDL网站重新下载所有内容。

票数 1
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70990839

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档