如何使用cmake与SDL2和SDL_image

38

我正在寻找使用SDL2SDL_image编译c++程序的最简单方法,需要使用cmake。

在经过数小时的搜索后,这是我做出的最佳尝试:

CMakeLists.txt

project(shooter-cmake2)

cmake_minimum_required(VERSION 2.8)

set(SOURCES
shooter.cpp
classes.cpp
utils.cpp
)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")

add_executable(${PROJECT_NAME} ${SOURCES})

INCLUDE(FindPkgConfig)
PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2)
PKG_SEARCH_MODULE(SDL2_image REQUIRED sdl2_image)
INCLUDE_DIRECTORIES(${SDL2_INCLUDE_DIRS} ${SDL2IMAGE_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${SDL2_LIBRARIES} ${SDL2IMAGE_LIBRARY})

我遇到了这些错误:

In function `loadTexture(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, SDL_Renderer*)':
undefined reference to `IMG_LoadTexture'
collect2: ld returned 1 exit status

这里是函数调用:

#include "SDL.h"
#include "SDL_image.h"

SDL_Texture* loadTexture(const std::string &file, SDL_Renderer *ren){
    SDL_Texture *texture = IMG_LoadTexture(ren, file.c_str());
    texture != nullptr or die("LoadTexture");
    return texture;
}

1
请记住,SDL是C库,而不是C++库。因此,使用C++类作为参数,如std::string,很可能无法正常工作。 - Some programmer dude
另外,由于您是在SO上新手,如果您有关于构建(编译器或链接器)错误的问题,请在您的问题中包含完整未编辑的错误日志,包括导致错误的代码(最好是最小化,完整和可验证的示例)。在您的情况下,请编辑您的问题以包含调用IMG_LoadTexture的代码以及足够理解代码的上下文(如变量声明等)。 - Some programmer dude
1
不知道cmake的具体情况,但是你应该也要添加${SDL2_IMAGE_LIBRARIES}吧? - keltar
@keltar 我尝试了:相同的错误。(我编辑了我的帖子) - Carl Lemaire
6个回答

57

我认为以下内容应该是可行的,因为它可以在我的Ubuntu系统上找到所需的库文件并且您提供的示例函数可以被链接:

project(shooter-cmake2)

cmake_minimum_required(VERSION 2.8)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")

add_executable(${PROJECT_NAME} src/test.cpp)

INCLUDE(FindPkgConfig)

PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2)
PKG_SEARCH_MODULE(SDL2IMAGE REQUIRED SDL2_image>=2.0.0)

INCLUDE_DIRECTORIES(${SDL2_INCLUDE_DIRS} ${SDL2IMAGE_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${SDL2_LIBRARIES} ${SDL2IMAGE_LIBRARIES})

如果使用 --debug-output 参数运行 cmake,则会输出:

-- Found PkgConfig: /usr/bin/pkg-config (found version "0.26") 
Called from: [2]    /usr/share/cmake-2.8/Modules/FindPkgConfig.cmake
            [1] $USER/stack-overflow/cmake-sdl2-image/CMakeLists.txt
-- checking for one of the modules 'sdl2'
Called from: [1]    $USER/stack-overflow/cmake-sdl2-image/CMakeLists.txt
-- checking for one of the modules 'SDL2_image>=2.0.0'
Called from: [1]    $USER/stack-overflow/cmake-sdl2-image/CMakeLists.txt
这让我检查了一下

的内容


/usr/lib/x86_64-linux-gnu/pkgconfig/sdl2.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/SDL2_image.pc

我注意到SDL2_image.pc中包含了Name: SDL2_image,我认为这应该与PKF_SEARCH_MODULE的第三个参数匹配,以便于使用此库。


我没有使用任何参考资料,只是从您使用的模块的源代码中读取了一些信息,并且根据我对 .pc 文件工作原理的了解进行了更新。我已经在答案中添加了额外的信息。 :) - wojciii
谢谢你的编辑!但是 --debug-output 怎么帮助到你了呢?我只是想了解你是如何解决问题的。 - Carl Lemaire
3
自 CMake 3.1 起,set(CMAKE_CXX_STANDARD yy) 已经取代修改 CMAKE_CXX_FLAGS,成为首选方法。 - emlai
你应该肯定地改进这个答案。 ;) - wojciii
太棒了!谢谢! - sinner
显示剩余4条评论

11

这里有两篇关于此问题的博客文章:

使用 CMake 使用 SDL2

使用 CMake 使用 SDL2_image

你需要一个 FindSDL2.cmakeFindSDL2_image.cmake 模块。它们可以基于已经包含在 CMake 中用于 SDL 1.2 的模块。使用这些 Find 模块也适用于 Windows。

如果您在 Linux 上,并且只需要 SDL2,则不需要 FindSDL2.cmake,因为以下内容已经可以工作:

cmake_minimum_required(VERSION 3.7)

project(SDL2Test)

find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})

add_executable(SDL2Test Main.cpp)
target_link_libraries(SDL2Test ${SDL2_LIBRARIES})

这在Linux上如何工作?(我看到它可以。)在Linux上安装了CMake的FindSDL2.cmake吗? - user2023370
1
当前CMake(v3.12)的模块列表此处似乎不包括SDL2支持,那么这该怎么办呢? - user2023370
1
SDL2在Linux下包含一个CMake配置文件。这样就可以不需要FindSDL2模块来工作了。 - trenki
它在Mac上也可以使用brew运行。 - sofuslund

6

我对这些答案感到困惑,我认为cmake改变了导入目标的方式。根据@trenki博客文章,我需要更改我的CMakeLists.txt如下:

project(SDL2Test)
find_package(SDL2 REQUIRED COMPONENTS SDL2::SDL2)
add_executable(SDL2Test main.cpp)
target_link_libraries(SDL2Test SDL2::SDL2)

目前,Arch Linux 可以直接使用此功能。


我也看到了一些类似的双冒号的东西,但是在使用SDL2_image时无法使其工作。这完全取决于您的系统上是否存在不同风格的特定“查找”配置文件。CMake需要您的耐心。我们能否都同意将我们的文件放在同一个地方 :) - user2023370

5

我介绍了一种现代且便携的方法来链接SDL2和SDL2_image。这些SDL2 CMake模块允许您按以下方式构建SDL2和SDL2_image项目:

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/sdl2)

find_package(SDL2 REQUIRED)
find_package(SDL2_image REQUIRED)
target_link_libraries(${PROJECT_NAME} SDL2::Main SDL2::Image)

你只需要在你的项目中克隆该仓库:

git clone https://github.com/aminosbh/sdl2-cmake-modules cmake/sdl2

注意: 如果CMake在Windows中没有找到SDL2/SDL2_image库,我们可以按照以下方式指定CMake选项SDL2_PATHSDL2_IMAGE_PATH:

cmake .. -DSDL2_PATH="/path/to/sdl2" -DSDL2_IMAGE_PATH="/path/to/sdl2-image"

它还支持其他相关库:SDL2_ttf,SDL2_net,SDL2_mixer和SDL2_gfx。有关更多详细信息,请阅读README.md文件。
您可以在此处找到使用这些模块的示例/样本列表和项目:https://github.com/aminosbh/sdl-samples-and-projects

3
自2.6版本以来,SDL2_image安装已经附带了CMake配置脚本SDL2_imageConfig.cmake/SDL2_image-config.cmake
因此,find_package(SDL2_image)无需任何其他FindSDL2_image.cmake模块,会创建IMPORTED目标SDL2_image::SDL2_image
find_package(SDL2_image REQUIRED)
target_link_libraries(<executable-target> SDL2_image::SDL2_image)

请注意,像SDL2_IMAGE_LIBRARIESSDL2_IMAGE_INCLUDE_DIRS这样的变量在此情况下**未设置**,因此使用它们是没有意义的。

0

以下命令对我来说运行良好:

set(SDL_INCLUDE_DIR "/usr/include/SDL2")
set(SDL_LIBRARY "SDL2")
include(FindSDL)  

if(SDL_FOUND)  
  message(STATUS "SDL FOUND")
endif()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接