将SDL2与CMake一起使用

时间:2015-02-08 15:38:06

标签: c++ cmake sdl-2

我尝试使用CLion创建SDL2项目。 问题是在使用#include时无法找到SDL标头。

我的CMakeLists.txt文件:

cmake_minimum_required(VERSION 2.8.4)
project(ChickenShooter)

set(SDL2_INCLUDE_DIR C:/SDL/SDL2-2.0.3/include)
set(SDL2_LIBRARY C:/SDL/SDL2-2.0.3/lib/x64)

include_directories(${SDL2_INCLUDE_DIR})
set(SOURCE_FILES main.cpp)

add_executable(ChickenShooter ${SOURCE_FILES})
target_link_libraries(ChickenShooter ${SDL2_LIBRARY})

我的测试main.cpp:

#include <iostream>
#include "SDL.h" /* This one can't be found */

int main(){
    if (SDL_Init(SDL_INIT_VIDEO) != 0){
        std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
        return 1;
    }
    SDL_Quit();
    return 0;
}

感谢您提供任何帮助。

编辑: 我使用Windows并且CLion配置为使用cygwin64。

12 个答案:

答案 0 :(得分:16)

不要手动设置SDL2的路径。使用正确的find命令,该命令使用FindSDL。应该是这样的:

find_file(SDL2_INCLUDE_DIR NAME SDL.h HINTS SDL2)
find_library(SDL2_LIBRARY NAME SDL2)
add_executable(ChickenShooter main.cpp)
target_include_directories(ChickenShooter ${SDL2_INCLUDE_DIR})
target_link_libraries(ChickenShooter ${SDL2_LIBRARY})    

如果未找到SDL2,则必须将SDL2的路径添加到CMAKE_PREFIX_PATH,这是CMake查找已安装软件的位置。

如果您可以使用Pkg-config,它的使用可能会更容易,请参阅How to use SDL2 and SDL_image with cmake

如果您觉得使用类似于CMake提供的FindSDL.cmake的FindSDL2.cmake文件感觉更舒服,请参阅https://brendanwhitfield.wordpress.com/2015/02/26/using-cmake-with-sdl2/

答案 1 :(得分:10)

此博客文章介绍了如何执行此操作:Using SDL2 with CMake

在Linux上,您可以使用最新的CMake(例如版本3.7),并且使用SDL2即可开箱即用。

cmake_minimum_required(VERSION 3.7)
project(SDL2Test)

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

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

在Windows下,您可以下载SDL2开发包,将其解压缩到某处,然后在提取的位置创建一个sdl-config.cmake文件,其中包含以下内容:

set(SDL2_INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}/include")

# Support both 32 and 64 bit builds
if (${CMAKE_SIZEOF_VOID_P} MATCHES 8)
  set(SDL2_LIBRARIES "${CMAKE_CURRENT_LIST_DIR}/lib/x64/SDL2.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x64/SDL2main.lib")
else ()
  set(SDL2_LIBRARIES "${CMAKE_CURRENT_LIST_DIR}/lib/x86/SDL2.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x86/SDL2main.lib")
endif ()

string(STRIP "${SDL2_LIBRARIES}" SDL2_LIBRARIES)

当您现在在CMake-GUI应用程序内部配置时,将有一个SDL2_DIR变量。您必须将它指向SDL2目录,在该目录中您解压缩开发包并重新配置,然后一切都应该工作。

然后,您只需撰写#include "SDL.h"即可包含SDL2标头。

答案 2 :(得分:1)

您似乎没有生成make文件的CMake错误。但我认为您的问题是,SDL标题位于名为&#34; SDL2&#34;的子文件夹中。

更改您的CMakeLists.txt以包含

C:/SDL/SDL2-2.0.3/include/SDL2

而不是

C:/SDL/SDL2-2.0.3/include

答案 3 :(得分:1)

使用我开发的SDL2 CMake module,您可以轻松地以现代且可移植的方式集成SDL2库。

您应该只在项目中的cmake/sdl2中复制模块(或仅克隆模块存储库):

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

然后在您的CMakeLists.txt中添加以下行:

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/sdl2)
find_package(SDL2 REQUIRED)
target_link_libraries(${PROJECT_NAME} SDL2::Main)

注意::如果CMake在Windows中找不到SDL2库,我们可以按以下方式指定CMake选项SDL2_PATH

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

有关更多详细信息,请阅读README.md文件。

SDL2 CMake模块支持其他相关的库:SDL2_image,SDL2_ttf,SDL2_mixer,SDL2_net和SDL2_gfx。

您可以在此处找到使用这些模块的示例/示例和项目的列表:https://github.com/aminosbh/sdl-samples-and-projects

答案 4 :(得分:0)

到我回答时,SDL2提供了 sdl2-config 可执行文件(据我所知,开发人员称他为“实验性”)。 在SDL2的“make install”之后,您可以尝试从终端调用它 sdl2-config --cflags --libs了解它的输出结果。

然后你可以在你的makefile中添加对它的调用:

set(PROJECT_NAME SomeProject)

project(${PROJECT_NAME})

execute_process(COMMAND /usr/local/bin/sdl2-config --libs RESULT_VARIABLE CMD_RES OUTPUT_VARIABLE SDL2_CFLAGS_LIBS ERROR_VARIABLE ERR_VAR OUTPUT_STRIP_TRAILING_WHITESPACE)
message("SDL2_CFLAGS_LIBS=${SDL2_CFLAGS_LIBS}; CMD_RES=${CMD_RES}; ERR_VAR=${ERR_VAR}")

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${SDL2_CFLAGS_LIBS}")

set(SOURCE_FILES main.cpp)
add_executable(${PROJECT_NAME} ${SOURCE_FILES})

这里我有一个问题 - 如果我只放一个没有路径的可执行文件名

execute_process(COMMAND sdl2-config --libs <...>

我收到错误“没有这样的文件”,即cmake不在当前路径中搜索,我现在不知道如何正确编写它。

还有一个注意事项:在我的makefile中,我没有使用--cflags选项,因为cmake发现包含正确,我不需要明确指定它们。

答案 5 :(得分:0)

我遇到了同样的问题,其他解决方案都没有。 但是我最终通过遵循这个解决方案来实现它:How to properly link libraries with cmake?

简而言之,问题是 SDL2库在我的CMakeLists.txt 中没有正确链接。通过将其写入文件,它可以工作(在另一个线程中有更多解释):

project (MyProgramExecBlaBla)  #not sure whether this should be the same name of the executable, but I always see that "convention"
cmake_minimum_required(VERSION 2.8)

ADD_LIBRARY(LibsModule 
    file1.cpp
    file2.cpp
)

target_link_libraries(LibsModule -lpthread)
target_link_libraries(LibsModule liblapack.a)
target_link_libraries(LibsModule -L/home/user/libs/somelibpath/)
ADD_EXECUTABLE(MyProgramExecBlaBla main.cpp)
target_link_libraries(MyProgramExecBlaBla LibsModule)

答案 6 :(得分:0)

cmake_minimum_required(VERSION 2.8.4)

project(ChickenShooter)

set(SDL2_INCLUDE_DIR C:/SDL/SDL2-2.0.3/include/SDL2)
set(SDL2_LIB_DIR C:/SDL/SDL2-2.0.3/lib/x64)

include_directories(${SDL2_INCLUDE_DIR})
link_directories(${SDL2_LIB_DIR})

set(SOURCE_FILES main.cpp)

add_executable(${PROJECT_NAME} ${SOURCE_FILES})
target_link_libraries(${PROJECT_NAME} SDL2main SDL2)

答案 7 :(得分:0)

您还可以将SDL源存储库作为子模块插入,并通过add_subdirectory()target_link_libraries()与主程序一起静态构建/链接它:

cmake_minimum_required( VERSION 3.7.0 )
project( sdl2-demo )

set( SDL_STATIC ON CACHE BOOL "" FORCE )
set( SDL_SHARED OFF CACHE BOOL "" FORCE )
add_subdirectory( external/sdl )

add_executable(
    sdl2-demo
    "src/main.cpp"
    )
target_link_libraries( sdl2-demo SDL2main SDL2-static )

(至少自release-2.0.9 tag起,可能更早。)

答案 8 :(得分:0)

重点介绍如何使用FindSDL2.cmake模块最终完成此操作的步骤:

  • 在下载页面的“开发库”部分下下载SDL2-devel-2.0.9-VC.zip(或发布此答案后的任何版本)。
  • 解压缩zip文件夹,您应该看到一个类似于“ SDL2-2.0.9”的文件夹。将此文件夹粘贴到C:\ Program Files(x86)\目录中。
  • 复制FindSDL2.cmake模块并将其放置在项目中的新“ cmake”目录中。我在“接受的答案” https://brendanwhitfield.wordpress.com/2015/02/26/using-cmake-with-sdl2/
  • 中引用的答案中找到了FindSDL2.cmake文件。
  • 在FindSDL2.cmake中找到Decodable行,并将复制的SDL2开发目录添加为新行:SET(SDL2_SEARCH_PATHS
  • 在我的CMakeLists.txt中,添加以下行:"/Program Files (x86)/SDL2-2.0.9" # Windows

在此之后,运行CMake对我有用。我将其余的CMakeList包括在内,以防进一步澄清我可能遗漏的内容:

set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)

希望这会在不久的将来对某人有所帮助。

答案 9 :(得分:0)

对于Windows中具有MinGW-w64的SDL2-2.0.9编译版本,以下配置对我有效:

find_package(SDL2 REQUIRED)

add_executable(sdl-test ${SOURCES})

target_link_libraries(sdl-test
  mingw32
  SDL2::SDL2main
  SDL2::SDL2
)

详细说明

通过阅读SDL2Targets.cmake文件,我了解到SDL2提供了几个目标:

  • SDL2::SDL2mainlib/libSDL2main.a
  • SDL2::SDL2lib/libSDL2.dll.a
  • SDL2::SDL2-staticlib/libSDL2-static.a

它们每个都定义了INTERFACE_INCLUDE_DIRECTORIES,这意味着我们不需要为SDL2手动指定include_directories

但是仅将SDL2::SDL2mainSDL2::SDL2添加为target_link_libraries是不够的。 g ++编译器可能会抱怨“对WinMain的未定义引用”。

通过检查编译器选项,我发现SDL2库被添加到-lmingw32选项之前。为了使-lmingw32选项先于SDL2库,我们还必须指定mingw32作为第一个target_link_libraries。这将使此配置正常工作。

我用来构建它的命令是:

$ mkdir build && cd build && cmake .. -G"MinGW Makefiles" && cmake --build .

这里唯一的小问题是在最终生成的编译器选项中,-lmingw32选项是重复的。但由于它不会影响链接过程,因此我暂时将其忽略。

答案 10 :(得分:0)

供您参考,在链接到SDL2源代码时,我能够成功构建和编译SDL2_ttf。

起初,由于cmake无法定位SDL2,即使在cmake中使用cmake中的SLD2_DIR变量指定了SDL2,我也遇到了错误。

似乎由于某些原因,cmake SDL2无法创建SDL2_ttf搜索的SDL2Targets.cmake文件。

在这种情况下,请从https://bugs.archlinux.org/task/57972获取SDL2Targets.cmake文件,并按如下所示修改文件:

您可以删除以下几行:

get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
if(_IMPORT_PREFIX STREQUAL "/")
    set(_IMPORT_PREFIX "")
endif()

并添加一个:

set(_IMPORT_PREFIX "C:/SDL2-2.0.12")

显然将文件路径更改为您解压缩SDL2源代码的位置

我不确定这是否正是您的问题,但是确实存在。

答案 11 :(得分:0)

我最近发现最新版本的SDL2(2.0.12版)现在带有所有必需的CMake配置/安装脚本,因此不再需要使用FindSDL。

我从https://www.libsdl.org/download-2.0.php下载了SDL源,然后从根文件夹运行了...

cmake -S . -B build/debug -G Ninja -DCMAKE_INSTALL_PREFIX=./install -DCMAKE_BUILD_TYPE=Debug
cmake --build build/debug --target install

这将构建并安装该库的调试版本,然后您还可以运行...

cmake -S . -B build/release -G Ninja -DCMAKE_INSTALL_PREFIX=./install -DCMAKE_BUILD_TYPE=Release
cmake --build build/release --target install

将构建并安装该库的发行版(并且由于SDL CMake脚本使用DEBUG_POSTFIX,因此该库的发行版不会覆盖调试版本,因为所有调试版本都在其名称后附加了“ d”)

然后在您的CMakeLists.txt文件中,只需执行以下操作:

find_package(SDL2 REQUIRED)

add_executable(${PROJECT_NAME} ...)

target_link_libraries(
    ${PROJECT_NAME} PRIVATE
    SDL2::SDL2
    SDL2::SDL2main

如果您使用示例中的自定义位置,则需要告诉您的应用程序在哪里可以找到SDL安装文件夹。为此,请在应用程序的根文件夹中运行:

cmake -S . -B build/debug -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH=</absolute/path/to/install/dir>
cmake --build build/debug

注意:您可以使用$(pwd)(* nix / macOS)或%cd%(Windows)创建混合的相对路径,这可能非常有用。

如果要将SDL安装到默认系统位置,则可以省略DCMAKE_INSTALL_PREFIXDCMAKE_PREFIX_PATH

在我选择使用Ninja生成器的示例中,因为它在macOS / Windows上是一致的-可以与MSVC / Visual Studio一起使用,只需确保运行此命令(路径可能会因年份/版本而略有不同)以将Ninja添加到您的路径。

C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat

更新:

我记得在Windows上有用的另一件事是能够将SDL .dll文件复制到应用程序二进制目录中,可以这样实现:

if (WIN32)
# copy the .dll file to the same folder as the executable
add_custom_command(
    TARGET ${PROJECT_NAME} POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
    $<TARGET_FILE:SDL2::SDL2>
    $<TARGET_FILE_DIR:${PROJECT_NAME}>
    VERBATIM)
endif()