【问题标题】:Using SDL2 with CMake将 SDL2 与 CMake 一起使用
【发布时间】:2015-04-08 08:52:36
【问题描述】:

我正在尝试使用 CLion 创建一个 SDL2 项目。 问题是使用#include时找不到SDL headers。

我的 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。

【问题讨论】:

    标签: c++ cmake sdl-2


    【解决方案1】:

    这篇博文展示了如何做到这一点: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 标头。

    【讨论】:

    • 这不适用于 Windows 上的 Mingw。 SDL2 Mingw包中的库目录和文件名不同。
    • 只是为了补充这一点。查找包的配置文件名称应为 sdl2-config.cmake
    【解决方案2】:

    不要手动设置 SDL2 的路径。使用使用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/

    【讨论】:

    • 我有一个Unknown CMake command "find"。但我可以改用find_library(SDL)。
    • @charlesrockbass:感谢提示,应该是 find_package。
    • SDL 不与 SDL2 相同,默认 FindSDL.cmake 不查找 SDL2。
    • @FRR 好问题,但与此答案无关。请提出问题,我会很乐意回答。
    【解决方案3】:

    您还可以将 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 开始,可能更早。)

    【讨论】:

    • 请注意,如果项目路径包含空格(至少在 Mac OS 上),此 cmake 脚本可能会失败。除此之外,它确实是一种静态链接到 SDL2 的简单方法。
    【解决方案4】:
    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)
    

    【讨论】:

      【解决方案5】:

      我最近发现最新版本的 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_PREFIX 和 DCMAKE_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()
      

      【讨论】:

      【解决方案6】:

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

      你应该在你的项目中复制 cmake/sdl2 中的模块(或者只是克隆模块 repo):

      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 没有找到 SDL2 库(在 Windows 中),我们可以指定 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

      【讨论】:

        【解决方案7】:

        在 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::SDL2main (lib/libSDL2main.a)
        • SDL2::SDL2 (lib/libSDL2.dll.a)
        • SDL2::SDL2-static (lib/libSDL2-static.a)

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

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

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

        我用来构建它的命令是:

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

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

        【讨论】:

          【解决方案8】:

          您在生成 make 文件时似乎没有出现 CMake 错误。但我认为您的问题是,SDL 标头位于名为“SDL2”的子文件夹中。

          更改您的 CMakeLists.txt 以包含

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

          代替

          C:/SDL/SDL2-2.0.3/include
          

          【讨论】:

            【解决方案9】:

            在 Linux 上,在 Clion 中,这是可行的:

            cmake_minimum_required(VERSION 3.20)
            project(first_game)
            
            set(CMAKE_CXX_STANDARD 14)
            
            find_package(SDL2 REQUIRED)
            include_directories(${SDL2_INCLUDE_DIRS})
            
            add_executable(${PROJECT_NAME} main.cpp)
            target_link_libraries(${PROJECT_NAME} ${SDL2_LIBRARIES})
            

            【讨论】:

              【解决方案10】:

              在我回答时,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 可以正确找到包含,我不需要明确指定它们。

              【讨论】:

                【解决方案11】:

                我遇到了同样的问题,其他解决方案都不起作用。 但我终于按照这个解决方案让它工作了:How to properly link libraries with cmake?

                简而言之,问题在于我的 CMakeLists.txt 中的 SDL2 库没有正确链接。通过将其写入文件,它起作用了(其他线程中有更多解释):

                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)
                

                【讨论】:

                  【解决方案12】:

                  强调我是如何使用 FindSDL2.cmake 模块最终完成此任务的步骤:

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

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

                  cmake_minimum_required(VERSION 2.8.4)
                  project(Test_Project)
                  
                  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
                  
                  # includes cmake/FindSDL2.cmake
                  set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
                  
                  set(SOURCE_FILES src/main.cpp src/test.cpp)
                  add_executable(test ${SOURCE_FILES})
                  
                  # The two lines below have been removed to run on my Windows machine
                  #INCLUDE(FindPkgConfig)
                  #PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2)
                  find_package(SDL2 REQUIRED)
                  
                  INCLUDE_DIRECTORIES(${SDL2_INCLUDE_DIR})
                  TARGET_LINK_LIBRARIES(chip8 ${SDL2_LIBRARY})
                  

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

                  【讨论】:

                  • 它是${SDL2_LIBRARIES}(复数)。单数可能有用,但那是偶然的。
                  【解决方案13】:

                  供您参考,在链接到 SDL2 源代码时,我能够成功地 cmake 并编译 SDL2_ttf。

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

                  似乎由于某种原因,cmaking 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 源代码的位置

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

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2014-09-10
                    • 2014-08-10
                    • 1970-01-01
                    • 1970-01-01
                    • 2019-01-07
                    相关资源
                    最近更新 更多