【问题标题】:Issue Including SDL2 and SDL2_image With CMake使用 CMake 包含 SDL2 和 SDL2_image 的问题
【发布时间】:2021-06-17 00:14:13
【问题描述】:

问题

  • SDL2_image 无法从 SDL2 中找到 SDL.h
  • 项目文件中对 SDL2 的引用能够找到 SDL2 和 SDL2_image。

CMakeLists.txt

# Minimum CMAKE Version Requirement
cmake_minimum_required(VERSION 3.20.3)

# Find Modules - SDL2
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

# Project Fields - TEST PLATFORM
project(library_test
    LANGUAGES C
    VERSION 0.1.0
)

set(SDL2_LIBRARY "C:/lib/SDL2-2.0.14/i686-w64-mingw32/bin")
set(SDL2_INCLUDE_DIR "C:/lib/SDL2-2.0.14/i686-w64-mingw32/include")

set(SDL2_IMAGE_LIBRARY "C:/lib/SDL2_image-2.0.5/i686-w64-mingw32/bin")
set(SDL2_IMAGE_INCLUDE_DIR "C:/lib/SDL2_image-2.0.5/i686-w64-mingw32/include")

find_package(SDL2 REQUIRED)
find_package(SDL2_image REQUIRED)

# C99 Standard Requirement
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED YES)
set(CMAKE_C_EXTENSIONS OFF)

# RESET Library Content
add_library(reset STATIC)
target_link_libraries(reset SDL2::Main SDL2::Image)
target_include_directories(reset PUBLIC include/reset)
add_subdirectory(src)

# Test Platform Content
add_executable(test_platform test_platform/test_platform.c)
target_link_libraries(test_platform STATIC reset)

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -lmingw32 -lSDL2main -lSDL2 -lSDL2_image -ggdb")

CMake 构建输出

在此处查看完整输出:

[main] Building folder: reset 
[build] Starting build
[proc] Executing command: "C:\Program Files\CMake\bin\cmake.EXE" --build c:/C99/reset/build --config Debug --target all -j 6 --
[build] -- Configuring done
[build] -- Generating done
[build] -- Build files have been written to: C:/C99/reset/build
[build] Consolidate compiler generated dependencies of target reset
[build] [ 10%] Building C object CMakeFiles/reset.dir/src/data/provider.c.obj
[build] [ 20%] Building C object CMakeFiles/reset.dir/src/data/rrcon.c.obj
[build] [ 30%] Building C object CMakeFiles/reset.dir/src/internal/rsetup.c.obj
[build] [ 40%] Building C object CMakeFiles/reset.dir/src/spatial/rlevelmap.c.obj
[build] [ 50%] Building C object CMakeFiles/reset.dir/src/spatial/rtilemap.c.obj
[build] [ 60%] Building C object CMakeFiles/reset.dir/src/visual/rfocus.c.obj
[build] In file included from C:/C99/reset/include/reset/depn.h:12:0,
[build]                  from C:/C99/reset/include/reset/provider.h:13,
[build]                  from C:\C99\reset\src\data\provider.c:2:
[build] C:/lib/SDL2_image-2.0.5/i686-w64-mingw32/include/SDL2/SDL_image.h:27:17: fatal error: SDL.h: No such file or directory
[build]  #include "SDL.h"
[build]                  ^
[build] compilation terminated.
[build] In file included from C:/C99/reset/include/reset/depn.h:12:0,
[build]                  from C:/C99/reset/include/reset/rrcon.h:15,
[build]                  from C:\C99\reset\src\data\rrcon.c:4:
[build] C:/lib/SDL2_image-2.0.5/i686-w64-mingw32/include/SDL2/SDL_image.h:27:17: fatal error: SDL.h: No such file or directory
[build]  #include "SDL.h"
[build]                  ^
[build] compilation terminated.
[build] CMakeFiles\reset.dir\build.make:75: recipe for target 'CMakeFiles/reset.dir/src/data/provider.c.obj' failed
[build] mingw32-make.exe[2]: *** [CMakeFiles/reset.dir/src/data/provider.c.obj] Error 1
[build] mingw32-make.exe[2]: *** Waiting for unfinished jobs....
[build] CMakeFiles\reset.dir\build.make:90: recipe for target 'CMakeFiles/reset.dir/src/data/rrcon.c.obj' failed
[build] mingw32-make.exe[2]: *** [CMakeFiles/reset.dir/src/data/rrcon.c.obj] Error 1
[build] In file included from C:/C99/reset/include/reset/depn.h:12:0,
[build]                  from C:/C99/reset/include/reset/rsetup.h:11,
[build]                  from C:\C99\reset\src\internal\rsetup.c:2:
[build] C:/lib/SDL2_image-2.0.5/i686-w64-mingw32/include/SDL2/SDL_image.h:27:17: fatal error: SDL.h: No such file or directory
[build]  #include "SDL.h"
[build]                  ^
[build] compilation terminated.
[build] CMakeFiles\reset.dir\build.make:120: recipe for target 'CMakeFiles/reset.dir/src/internal/rsetup.c.obj' failed
[build] mingw32-make.exe[2]: *** [CMakeFiles/reset.dir/src/internal/rsetup.c.obj] Error 1
[build] In file included from C:/C99/reset/include/reset/depn.h:12:0,
[build]                  from C:/C99/reset/include/reset/rlevelmap.h:5,
[build]                  from C:\C99\reset\src\spatial\rlevelmap.c:2:
[build] C:/lib/SDL2_image-2.0.5/i686-w64-mingw32/include/SDL2/SDL_image.h:27:17: fatal error: SDL.h: No such file or directory
[build]  #include "SDL.h"
[build]                  ^
[build] compilation terminated.
[build] CMakeFiles\reset.dir\build.make:135: recipe for target 'CMakeFiles/reset.dir/src/spatial/rlevelmap.c.obj' failed
[build] mingw32-make.exe[2]: *** [CMakeFiles/reset.dir/src/spatial/rlevelmap.c.obj] Error 1
[build] In file included from C:/C99/reset/include/reset/depn.h:12:0,
[build]                  from C:/C99/reset/include/reset/rtilemap.h:9,
[build]                  from C:\C99\reset\src\spatial\rtilemap.c:2:
[build] C:/lib/SDL2_image-2.0.5/i686-w64-mingw32/include/SDL2/SDL_image.h:27:17: fatal error: SDL.h: No such file or directory
[build]  #include "SDL.h"
[build]                  ^
[build] compilation terminated.
[build] CMakeFiles\reset.dir\build.make:150: recipe for target 'CMakeFiles/reset.dir/src/spatial/rtilemap.c.obj' failed
[build] mingw32-make.exe[2]: *** [CMakeFiles/reset.dir/src/spatial/rtilemap.c.obj] Error 1
[build] In file included from C:/C99/reset/include/reset/depn.h:12:0,
[build]                  from C:/C99/reset/include/reset/rfocus.h:11,
[build]                  from C:\C99\reset\src\visual\rfocus.c:2:
[build] C:/lib/SDL2_image-2.0.5/i686-w64-mingw32/include/SDL2/SDL_image.h:27:17: fatal error: SDL.h: No such file or directory
[build]  #include "SDL.h"
[build]                  ^
[build] compilation terminated.
[build] CMakeFiles\reset.dir\build.make:165: recipe for target 'CMakeFiles/reset.dir/src/visual/rfocus.c.obj' failed
[build] mingw32-make.exe[2]: *** [CMakeFiles/reset.dir/src/visual/rfocus.c.obj] Error 1
[build] CMakeFiles\Makefile2:169: recipe for target 'CMakeFiles/reset.dir/all' failed
[build] mingw32-make.exe[1]: *** [CMakeFiles/reset.dir/all] Error 2
[build] Makefile:89: recipe for target 'all' failed
[build] mingw32-make.exe: *** [all] Error 2
[build] Build finished with exit code 2

当前的 CMake 设置解决了我之前遇到的 #include <SDL.h> 导致文件未找到错误的问题,但现在在 SDL_image 尝试访问 SDL 时出现此问题。请注意,错误的来源是SDL_image.h,因为它尝试#include "SDL.h"

目前,使用我在此页面上找到的一些 FindSDL2 cmake 文件找到 SDL 包:https://edgarluque.com/blog/sdl2-cmake

这也是我发现的第一页,它实际上解决了我以前遇到的任何错误。我在 windows 而不是 linux 上,所以自然有问题。

我确实尝试为 SDL 组件添加 -l 编译器参数,但这些似乎没有效果。

尝试的解决方案

我尝试更改 CMake_lists.txt 文件中的最后一行(编译器标志):

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -lmingw32 -lSDL2main -lSDL2 -lSDL2_image -ggdb -IC:/lib/SDL2-2.0.14/i686-w64-mingw32/include/SDL2")

这产生了一个不同的错误:

[main] Building folder: reset 
[build] Starting build
[proc] Executing command: "C:\Program Files\CMake\bin\cmake.EXE" --build c:/C99/reset/build --config Debug --target all -j 6 --
[build] -- Configuring done
[build] -- Generating done
[build] -- Build files have been written to: C:/C99/reset/build
[build] Consolidate compiler generated dependencies of target reset
[build] [ 10%] Building C object CMakeFiles/reset.dir/src/data/provider.c.obj
[build] [ 20%] Building C object CMakeFiles/reset.dir/src/data/rrcon.c.obj
[build] [ 30%] Building C object CMakeFiles/reset.dir/src/data/rvector.c.obj
[build] [ 40%] Building C object CMakeFiles/reset.dir/src/internal/rsetup.c.obj
[build] [ 50%] Building C object CMakeFiles/reset.dir/src/spatial/rlevelmap.c.obj
[build] [ 60%] Building C object CMakeFiles/reset.dir/src/spatial/rtilemap.c.obj
[build] [ 70%] Building C object CMakeFiles/reset.dir/src/visual/rfocus.c.obj
[build] [ 80%] Linking C static library libreset.a
[build] [ 80%] Built target reset
[build] Consolidate compiler generated dependencies of target test_platform
[build] [ 90%] Building C object CMakeFiles/test_platform.dir/test_platform/test_platform.c.obj
[build] [100%] Linking C executable test_platform.exe
[build] c:/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../../mingw32/bin/ld.exe: cannot find -lSDL2main
[build] c:/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../../mingw32/bin/ld.exe: cannot find -lSDL2
[build] c:/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../../mingw32/bin/ld.exe: cannot find -lSDL2_image
[build] CMakeFiles\test_platform.dir/objects.a(test_platform.c.obj): In function `main':
[build] C:/C99/reset/test_platform/test_platform.c:18: multiple definition of `main'
[build] c:/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../libmingw32.a(main.o):(.text.startup+0x0): first defined here
[build] c:/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../../mingw32/bin/ld.exe: cannot find -lSTATIC
[build] c:/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../../mingw32/bin/ld.exe: cannot find C:/lib/SDL2_image-2.0.5/i686-w64-mingw32/bin: Permission denied
[build] c:/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../../mingw32/bin/ld.exe: cannot find C:/lib/SDL2-2.0.14/i686-w64-mingw32/bin: Permission denied
[build] collect2.exe: error: ld returned 1 exit status
[build] CMakeFiles\test_platform.dir\build.make:101: recipe for target 'test_platform.exe' failed
[build] mingw32-make.exe[2]: *** [test_platform.exe] Error 1
[build] CMakeFiles\Makefile2:195: recipe for target 'CMakeFiles/test_platform.dir/all' failed
[build] mingw32-make.exe[1]: *** [CMakeFiles/test_platform.dir/all] Error 2
[build] Makefile:89: recipe for target 'all' failed
[build] mingw32-make.exe: *** [all] Error 2
[build] Build finished with exit code 2

这里也是test_platform.c文件,因为和新的错误有关:

//#define SDL_MAIN_HANDLED

#include "depn.h"
#include "rsetup.h"
#include "rrcon.h"
#include "provider.h"
#include "rfocus.h"
#include "rvector.h"
#include "rtilemap.h"
#include "rlevelmap.h"

#undef main

/// Main Function

int main ( int argc, char ** argv )
{
    fprintf ( stderr, "Received %d argument%s:\n", argc, argc == 1 ? "" : "s" );

    forsi ( argc ) fprintf ( stderr, "\t%s\n", argv [ ix ] );

    CFG_WIN cfg =
    {
        1920, 1080,
        SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
        "Reset"
    };

    r_sdlset(); // SDL2 module init

    DATA_WIN display = r_dispset ( cfg );

    RRCON rrcon = rrcon_inst ( display.renderer, TEXTURE );
    register_directory ( "tile" );
    rrcon_import ( rrcon, "grass", "grass.png" );

    RTILEMAP tilemap = rtilemap_static ( );
//    RTILEMAP tilemap = rtilemap_dynamic ( 72, 72 );
    RTILE tile = rtile_inst ( "grass" );

    VEC2U pos = { 0, 0 };
    VEC2U pos2 = { 63, 31 };

    rtilemap_set ( tilemap, tile, pos );
    rtilemap_set ( tilemap, tile, pos2 );

//    RFOCUS focus = rfocus_inst ( F_FLAT_TILEMAP );
//
//    focus -> tilemap = tilemap;

    VEC2I tilemap_start = { 30, 0 };

    SDL_Event ev;

    while ( 1 )
    {
        if ( SDL_WaitEvent ( &ev ) )
        {
            if ( ev.type == SDL_QUIT )
            {
                rrcon_clr ( rrcon );

                SDL_DestroyRenderer ( display.renderer );
                SDL_DestroyWindow ( display.window );
                SDL_Quit ();
                IMG_Quit ();

                return EXIT_SUCCESS;
            }
        }

        // SDL_SetRenderDrawColor ( display.renderer, 0, 0, 0, 255 );
        SDL_RenderClear ( display.renderer );

        rtilemap_render_tiles ( tilemap, rrcon, tilemap_start, 1.0 );

        SDL_RenderPresent ( display.renderer );
    }

    return 0;
}

【问题讨论】:

  • CMAKE_C_FLAGS != CMAKE_LINK_FLAGS 无论如何使用link_libraries()。无论如何,尝试使用变量而不是 SDL2::Image 像 ex。 here。使用find_package(.. PATHS the/path/to/library)
  • @KamilCuk 使用link_libraries() 怎么样?而不是target_link_libraries()?我不确定应该为链接器和编译器提供哪些标志才能使其正常工作。也不确定如何使用变量而不是 SDL2::Image,因为我不知道 SDL2::Image 实际代表什么。我对 cmake 很陌生。
  • Use link_libraries() how? Istead of set(CMAKE_SOMETHING -lsomething) 在定义可执行文件或库之前更喜欢link_libraries(something),或者更好的是,使用target_link_librarieswhat SDL2::Image actually represents 一个接口目标。我给出的链接有一个例子,试试target_link_libraries(Exe ${SDL2_LIBRARIES} ${SDL2_IMAGE_LIBRARIES})
  • @KamilCuk 在库和可执行文件之前使用link_libraries 会产生与定义库reset 之后的初始target_link_libraries 相同的错误输出(SDL_image 找不到 SDL)。我会仔细看看你的编辑。
  • SDL.h [通常] 在 SDL2 子目录下(例如,/usr/include/SDL2 用于 posix 系统)。所以,你必须做(1)#include <SDL2/SDL.h>或(2)将/SDL2添加到SDL2_INCLUDE_DIR的末尾我对cmake不太熟悉,但添加包应该能够设置必要的目录无需您手动将它们硬连线(例如,它将使用 pkg-config 的等效项让包说明在哪里查找并类似地查找 lib 目录)

标签: c cmake sdl-2


【解决方案1】:

查看您的信息和模块文档后,我发现了以下问题:

CMAKE_C_FLAGS:

强烈建议在现代 CMake 解决方案中避免直接操作这一点。 CMake 提供了专门的函数来定义编译器标志、链接器库等以及它们与项目中特定目标的关系,这使它能够更仔细地管理事物。

SDL2_变量:

根据https://github.com/aminosbh/sdl2-cmake-modules 的文档,这些应该是缓存变量而不是本地变量。我不确定这是否真的重要,但出于故障排除目的可能值得注意。一般来说,对这类事情使用缓存变量也是一个好主意,因为人们可以在 CMake 命令行或cmake-gui 中覆盖它们。

请注意,缓存变量值存储在构建目录中的 CMakeCache.txt 文件中,如果您想使用不同的值,可能需要将其删除。

我还应该在这里指出,模块的文档建议您应该能够只设置SDL2_PATHSDL2_IMAGE_PATH。但是,这显然要求库在您的安装中位于lib/ 下,而不是bin/ 下。

SDL2_LIBRARY/SDL2_IMAGE_LIBRARY:

如果您选择坚持直接定义这些,我认为您可能需要将它们指向实际库文件的完整路径和文件名,而不仅仅是包含目录。

SDL2_INCLUDE_DIR/SDL2_IMAGE_INCLUDE_DIR:

这些似乎是指向包含实际库头文件的SDL2 目录(例如SDL.h),而不是指向包含SDL2 目录的父目录。这可能是 SDL2_image 在编译期间找不到 SDL.h 的原因。

这也意味着您应该在自己的代码中从#include 指令中省略SDL2/ 路径前缀;但是,您可以使用 target_include_directories${SDL2_INCLUDE_DIR}/.. 等添加到您正在构建的每个依赖目标中,以便最终在编译器的头文件搜索路径中使用两个目录级别。

SDL::CoreSDL::Main

模块文档建议您正在构建的任何依赖于 SDL 的库(例如 reset)必须链接到 SDL::Core,而不是 SDL::Main

只有您正在构建的依赖于 SDL 的可执行文件(例如 test_platform)应该链接到 SDL::Main,因为这表示将您的 main()(或类似的特定于操作系统的)函数与 SDL 的主要函数包装在一起的库。

请注意,如果您只构建应用程序而不构建库,则只需链接 SDL::Main,因为该模块定义了对 SDL::Core 的内部依赖。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-14
    相关资源
    最近更新 更多