将 SDL2 与 CMake 结合使用
Using SDL2 with CMake
我正在尝试使用 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。
您在生成 make 文件时似乎没有出现 CMake 错误。但我认为您的问题是,SDL Header 位于名为 "SDL2".
的子文件夹中
将您的CMakeLists.txt更改为包含
C:/SDL/SDL2-2.0.3/include/SDL2
而不是
C:/SDL/SDL2-2.0.3/include
不要手动设置 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/
在我回答时,SDL2 提供了 sdl2-config 可执行文件(据我了解,开发人员称他为 "experimental")。
在 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 <...>
我收到错误 "No such file",即 cmake 不在当前路径中搜索,我现在不知道如何正确编写它。
另外请注意:在我的 makefile 中我没有使用 --cflags
选项,因为 cmake 发现正确包含并且我不需要明确指定它们。
此博客 post 展示了如何做到这一点: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 headers
我遇到了同样的问题,none 其他解决方案有效。
但我终于按照这个解决方案让它工作了: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)
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)
您还可以将 SDL 源存储库作为子模块引入,并通过 add_subdirectory()
和 target_link_libraries()
:
build/link 将其与您的主程序一起静态引入
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 开始,可能更早。)
强调我最终如何使用 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 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没有找到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。
您可以在此处找到 examples/samples 和使用这些模块的项目的列表:https://github.com/aminosbh/sdl-samples-and-projects
在 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++ 编译器可能会抱怨 "undefined reference to `WinMain'".
通过检查编译器选项,我发现在 -lmingw32
选项之前添加了 SDL2 库。为了使 -lmingw32
选项出现在 SDL2 库之前,我们还必须指定 mingw32
作为第一个 target_link_libraries
。这将使此配置有效。
我用来构建它的命令是:
$ mkdir build && cd build && cmake .. -G"MinGW Makefiles" && cmake --build .
这里唯一的小问题是在最终生成的编译器选项中,-lmingw32
选项是重复的。但由于它不影响链接过程,所以我暂时忽略它。
供您参考,我能够在链接到 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 源代码的位置
我不确定这是否正是您的问题,但确实如此。
我最近发现最新版本的 SDL2(版本 2.0.12)现在附带了所有必需的 CMake config/install 脚本,因此不再需要使用 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
Note: You can use $(pwd)
(*nix/macOS) or %cd%
(Windows) to create a hybrid relative path which can be very useful.
如果要将 SDL 安装到默认系统位置,可以省略 DCMAKE_INSTALL_PREFIX
和 DCMAKE_PREFIX_PATH
。
在示例中,我选择使用 Ninja 生成器,因为它在 macOS/Windows 中是一致的 - 它可以与 MSVC/Visual Studio 一起使用,只需确保 运行 这个(路径可能略有不同,具体取决于 year/version)将 Ninja 添加到您的路径中。
C:\Program Files (x86)\Microsoft Visual Studio19\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()
在 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})
我正在尝试使用 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。
您在生成 make 文件时似乎没有出现 CMake 错误。但我认为您的问题是,SDL Header 位于名为 "SDL2".
的子文件夹中将您的CMakeLists.txt更改为包含
C:/SDL/SDL2-2.0.3/include/SDL2
而不是
C:/SDL/SDL2-2.0.3/include
不要手动设置 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/
在我回答时,SDL2 提供了 sdl2-config 可执行文件(据我了解,开发人员称他为 "experimental")。
在 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 <...>
我收到错误 "No such file",即 cmake 不在当前路径中搜索,我现在不知道如何正确编写它。
另外请注意:在我的 makefile 中我没有使用 --cflags
选项,因为 cmake 发现正确包含并且我不需要明确指定它们。
此博客 post 展示了如何做到这一点: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"
.
我遇到了同样的问题,none 其他解决方案有效。 但我终于按照这个解决方案让它工作了: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)
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)
您还可以将 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 开始,可能更早。)
强调我最终如何使用 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 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没有找到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。
您可以在此处找到 examples/samples 和使用这些模块的项目的列表:https://github.com/aminosbh/sdl-samples-and-projects
在 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++ 编译器可能会抱怨 "undefined reference to `WinMain'".
通过检查编译器选项,我发现在 -lmingw32
选项之前添加了 SDL2 库。为了使 -lmingw32
选项出现在 SDL2 库之前,我们还必须指定 mingw32
作为第一个 target_link_libraries
。这将使此配置有效。
我用来构建它的命令是:
$ mkdir build && cd build && cmake .. -G"MinGW Makefiles" && cmake --build .
这里唯一的小问题是在最终生成的编译器选项中,-lmingw32
选项是重复的。但由于它不影响链接过程,所以我暂时忽略它。
供您参考,我能够在链接到 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 源代码的位置
我不确定这是否正是您的问题,但确实如此。
我最近发现最新版本的 SDL2(版本 2.0.12)现在附带了所有必需的 CMake config/install 脚本,因此不再需要使用 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
Note: You can use
$(pwd)
(*nix/macOS) or%cd%
(Windows) to create a hybrid relative path which can be very useful.
如果要将 SDL 安装到默认系统位置,可以省略 DCMAKE_INSTALL_PREFIX
和 DCMAKE_PREFIX_PATH
。
在示例中,我选择使用 Ninja 生成器,因为它在 macOS/Windows 中是一致的 - 它可以与 MSVC/Visual Studio 一起使用,只需确保 运行 这个(路径可能略有不同,具体取决于 year/version)将 Ninja 添加到您的路径中。
C:\Program Files (x86)\Microsoft Visual Studio19\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()
在 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})