1

I am trying to use SDL and SDL_image as a subprojects in my project. Folder structure:

testRepos
├── build //build files inside
├── src
│   ├── main.cpp
│   ├── texture.png
│   └── CMakeLists.txt
├── third_party
│   ├── SDL //SDL repo inside
│   ├── SDL_image //SDL_image repo inside
│   └── CMakeLists.txt
└── CMakeLists.txt

main.cpp

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

using namespace std;

SDL_Window *m_window;
SDL_Renderer *m_renderer;

bool init();
void close();
SDL_Texture* loadTexture(const char* file_);
void renderTexture(SDL_Texture* tex_, int x_, int y_, int w_, int h_);
void renderTexture(SDL_Texture* tex_, int x_, int y_);

int SDL_main(int argc, char* args[])
{
    if (!init())
    {
        cout << "Cannot init SDL\n";
    }

    bool isRunning = true;
    SDL_Event e;

    SDL_Texture* tex = loadTexture("texture.png");

    while (isRunning)
    {
        while (SDL_PollEvent(&e))
        {
            if (e.type == SDL_QUIT)
                isRunning = false;
        }

        SDL_RenderClear(m_renderer);
        
        renderTexture(tex, 0, 0);

        SDL_RenderPresent(m_renderer);
    }

    close();
    system("pause");
    return 0;
}

bool init()
{
    if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
    {
        std::cout << "SDL initialization error: " << SDL_GetError() << std::endl;
        return false;
    }

    if ((IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG) != IMG_INIT_PNG)
    {
        std::cout << "IMG initialization error: " << SDL_GetError() << std::endl;
        return false;
    }

    m_window = SDL_CreateWindow("TestName", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1280, 720, SDL_WINDOW_SHOWN);
    if (m_window == NULL)
    {
        std::cout << "Window creation error: " << SDL_GetError() << std::endl;
        return false;
    }

    m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
    if (m_renderer == nullptr) {
        std::cout << "Renderer creation error: " << SDL_GetError() << std::endl;
        return false;
    }
}

void close()
{
    SDL_DestroyRenderer(m_renderer);
    SDL_DestroyWindow(m_window);
    IMG_Quit();
    SDL_Quit();
}

SDL_Texture* loadTexture(const char* file_)
{
    SDL_Texture* texture = IMG_LoadTexture(m_renderer, file_);
    if (!texture) {
        std::cout << "Texture loading problem: " << file_ << "  |  " << IMG_GetError() << std::endl;
    }
    return texture;
}

void renderTexture(SDL_Texture* tex_, int x_, int y_, int w_, int h_)
{
    SDL_Rect dst;

    dst.x = x_;
    dst.y = y_;
    dst.w = w_;
    dst.h = h_;

    SDL_RenderCopy(m_renderer, tex_, NULL, &dst);
}

void renderTexture(SDL_Texture* tex_, int x_, int y_)
{
    int w, h;
    SDL_QueryTexture(tex_, NULL, NULL, &w, &h);
    renderTexture(tex_, x_, y_, w, h);
}

testRepos/CMakeLists.txt

cmake_minimum_required (VERSION 3.8)
 
project (ProjectRoot)

add_subdirectory (third_party)
add_subdirectory (src)

testRepos/third_party/CMakeLists.txt

cmake_minimum_required (VERSION 3.8)

project(third_party)

add_subdirectory(SDL)
set(SDL_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}/SDL/include)

add_subdirectory(SDL_image)
set(SDL_IMAGE_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}/SDL_image)

testRepos/src/CMakeLists.txt

cmake_minimum_required (VERSION 3.8)
 
project(main)
 
add_executable (main main.cpp)
 
# Connecting the library, specify where to get the header files
target_include_directories(main PUBLIC ${SDL_INCLUDE_DIR} ${SDL_IMAGE_INCLUDE_DIR})
# And also we specify dependence on static library
target_link_libraries(main SDL2main SDL2-static SDL2_image)

It works perfectly fine without SDL_image (ofc without SDL_image code in sources). After adding SDL_image, it still builds, but requires to manually add SDL2_image.dll, SDL2d.dll , zlibd1.dll and libpng16d.dll and fails after running .exe with this:

WARN:

Assertion failure at SDL_CreateTextureFromSurface_REAL (T:\testRepos\third_party\SDL\src\render\SDL_render.c:1252), triggered 1 time:
  'renderer && renderer->magic == &renderer_magic'

Texture loading problem: texture.png  |
WARN:

Assertion failure at SDL_QueryTexture_REAL (T:\testRepos\third_party\SDL\src\render\SDL_render.c:1390), triggered 1 time:
  'texture && texture->magic == &texture_magic'

WARN:

Assertion failure at SDL_RenderCopyF_REAL (T:\testRepos\third_party\SDL\src\render\SDL_render.c:3199), triggered 1 time:
  'texture && texture->magic == &texture_magic'

It fails inside the IMG_LoadTexture, so everything definitely was initialized properly. Since I use libraries as a subprojects, I cannot use solution with packages. How can I solve this problem?

SavedowW
  • 39
  • 5
  • This seems like a duplicate asking how to put `dll` near executable automatically. See [Building of executable and shared library with cmake, runtimelinker does not find dll](https://stackoverflow.com/a/26513002/15971564). TL;DR `set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)` – Kaihaku Sep 19 '21 at 11:56
  • Does this answer your question? [Building of executable and shared library with cmake, runtimelinker does not find dll](https://stackoverflow.com/questions/23323741/building-of-executable-and-shared-library-with-cmake-runtimelinker-does-not-fin) – Kaihaku Sep 19 '21 at 11:56
  • @Kaihaku, that part about dll is not the main problem. I just mentioned it because it could clarify the problem: .exe somehow finds .dll if i build without SDL_image, otherwise it requires everything, including SDL dll that was found automatically in the first case – SavedowW Sep 19 '21 at 12:06

0 Answers0