【问题标题】:Linking SDL2 with CMake [duplicate]将 SDL2 与 CMake 链接 [重复]
【发布时间】:2020-06-29 18:31:30
【问题描述】:

我在将 SDL2 链接到我的项目时遇到问题,这可能是因为我是 CMake 新手,而且我不完全知道如何使用它创建新项目。我尝试解决此问题的每次和方法都导致以下问题之一:

  1. “找不到 WinMain@16”
  2. 多个未定义的引用错误
  3. 对 `SDL_main` 的未定义引用

我尝试使用 find_package,直接链接到文件,链接到库文件,遵循教程(例如 https://trenki2.github.io/blog/2017/06/02/using-sdl2-with-cmake/),搜索答案(他们中的大多数人都在谈论使用 find_package,但我无法开始工作) (例如Using SDL2 with CMake)。

项目依赖

SDL 2.0.12、CMake 3.17.0、7-Zip、mingw32-make、wget

该项目应该是跨平台的,但主要 devenv 是 Windows 10。所有脚本都从根文件夹“vivaria”运行。

项目结构

vivaria/
├── build/
│   └── [cmake build files]
├── buildtools/
│   └── SDL2/SDL2-2.0.12/lib/x86 (and x64)
│                            ├── SDL2.lib
│                            └── SDL2main.libs
├── deploy/
├── resources/
├── scripts/
│   ├── build_windows_debug_x86.bat
│   └── install_buildtools_windows.bat
└── src/
    ├── CMakeLists.txt
    └── vivaria.cpp

build_windows_debug_x86.bat

cmake -G "MinGW Makefiles" -S .\src\ -B .\build\ -DCMAKE_BUILD_TYPE=Debug
cd .\build\
mingw32-make

vivaria.cpp

#include <iostream>
#include "SDL.h"

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

CMakeLists.txt:对 SDL_main 的未定义引用

cmake_minimum_required(VERSION 3.17)
project(Vivaria VERSION 1.0.0)

set(CMAKE_CXX_GLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -lmingw32")
# set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++")

set(INCLUDE_DIR "${CMAKE_SOURCE_DIR}/../buildtools")
set(SDL2_DIR "${INCLUDE_DIR}/SDL2/SDL2-2.0.12")

set(SDL2_INCLUDE_DIRS "${SDL2_DIR}/include")
set(CMAKE_BINARY_DIR "${CMAKE_SOURCE_DIR}/../deploy")

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

# link dependencies
include_directories(${SDL2_INCLUDE_DIRS})
link_directories(${SDL2_LIBRARIES})

# Project files and linking
set(SOURCES vivaria.cpp)
add_executable(${PROJECT_NAME} vivaria.cpp)
target_link_libraries(${PROJECT_NAME} ${SDL2_LIBRARIES})

控制台输出

F:\Koodit\Vivaria\build>mingw32-make
[ 50%] Linking CXX executable Vivaria.exe
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: F:/Koodit/Vivaria/src/../buildtools/SDL2/SDL2-2.0.12/lib/x86/SDL2main.lib(Win32/Release/SDL_windows_main.obj):(.text[_main_getcmdline]+0xd1): undefined reference to `SDL_main'
collect2.exe: error: ld returned 1 exit status
CMakeFiles\Vivaria.dir\build.make:104: recipe for target 'Vivaria.exe' failed
mingw32-make[2]: *** [Vivaria.exe] Error 1
CMakeFiles\Makefile2:91: recipe for target 'CMakeFiles/Vivaria.dir/all' failed
mingw32-make[1]: *** [CMakeFiles/Vivaria.dir/all] Error 2
Makefile:99: recipe for target 'all' failed
mingw32-make: *** [all] Error 2

install_buildtools_windows.bat

set SDL2=SDL2-devel-2.0.12-VC.zip
set DOWNLOAD_DIR=%cd%\buildtools
set OUTPUT_DIR=%cd%\buildtools\SDL2

wget "https://libsdl.org/release/%SDL2%" -P "%DOWNLOAD_DIR%"

7z x "%DOWNLOAD_DIR%\%SDL2%" -y -o%OUTPUT_DIR%

del /F /Q %DOWNLOAD_DIR%\%SDL2%

如您所见,我对 CMake 仍然“有点”新手,但我正在努力学习。

【问题讨论】:

  • 您检查过that question 是否有类似的错误?它的答案讲述了在源文件中设置SDL_MAIN_HANDLED 宏。

标签: c++ cmake sdl-2


【解决方案1】:

哎呀。关于你的 CMakeLists 的一切都是错误的。

  1. 永远不要在你的 CMakeLists.txt 中设置 CMAKE_CXX_FLAGS
  2. 永远不要使用include_directorieslink_directories
  3. 永远不要在没有可见性说明符的情况下使用target_link_libraries
  4. 永远不要手动设置库的路径。
  5. 不要将您的目标名称设置为与项目名称相同。这是毫无意义的复杂性和糟糕的风格。

这就是你所需要的:

cmake_minimum_required(VERSION 3.16)
project(Vivaria VERSION 1.0.0)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED YES)
set(CMAKE_CXX_EXTENSIONS OFF)

find_package(SDL2 REQUIRED)

add_executable(Vivaria vivaria.cpp)
target_link_libraries(Vivaria PRIVATE SDL2::SDL2)

您的代码也有错误。您需要将此行添加到文件的顶部

#define SDL_MAIN_HANDLED

首先,使用 vcpkg 安装 SDL2。然后,通过上述更改,它可以使用以下命令为我编译和运行:

> mkdir build
> cd build
> cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=X:/path/to/vcpkg.cmake ..

【讨论】:

  • 我安装了 Ninja,将工具链更改为 vcpkg 并像你提到的那样清除了我的 cmakelists,但是在尝试运行构建后出现以下错误:“通过在 CMAKE_MODULE_PATH 中不提供“FindSDL2.cmake”,这个项目有要求CMake查找“SDL2”提供的包配置文件,但CMake没有找到“。如果我将 vcpkg 安装指定为 x64,find_package 会找到该软件包,但不认为它是正确的。将 -A 设置为 x64/x86 或设置 -DCMAKE_GENERATOR_PLATFORM=x86 或 x64 都没有帮助(打印不支持的平台)。
  • 您需要运行 vcvars 或处于开发人员命令提示符下。确保您确实通过vcpkg install sdl2:x64-windows 从 vcpkg 安装了 sdl2
  • @SuperTasche - 我不明白你的问题。我的指导方针都没有与供应您的依赖项或将安装依赖项的负担转移到用户身上相冲突。 CMake 中有很好的解决依赖关系的解决方案:ExternalProject(即超级构建)、FetchContent、git submodules + add_subdirectory 等。
  • @AlexReinking 感谢您的提示,我一定会检查的!不过,在扩展您的指南时,它可能会帮助 cmake 的初学者理解他们的错误。过去几周我一直在与 cmake 打交道,并且在没有任何合理理由的情况下继续阅读诸如“你永远不应该做 XYZ”之类的教条。对于主要目标是开始使用 C++ 编写项目的人来说,这是一个真正的痛苦。
  • @SuperTasche - 我认为这需要比 StackOverflow 评论或不同问题的答案更多的细节。如果您希望我解释原因,如果您愿意提出一个新的 SO 问题,我会很乐意这样做。
【解决方案2】:

感谢Tsyvarev! 在源文件中设置宏SDL_MAIN_HANDLED 解决了这个问题。

#define SDL_MAIN_HANDLED // insert this
#include <iostream>
#include "SDL.h"

int main() {
    if (SDL_Init(SDL_INIT_VIDEO) != 0){
        std::cout << "Hello world" << std::endl;
        return 1;
    }
    
        std::cout << "Hello world 2" << std::endl;

    SDL_Quit();
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-13
    • 2015-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多