Undefined IMG_Init and IMG_LoadTexture

I’ve installed SDL2 on my arch linux system. Here’s my CMakeLists.txt setup:

cmake_minimum_required(VERSION 3.12)

project(ChessEngine)

set(CMAKE_CXX_STANDARD 11)

# Add your source files
file(GLOB SOURCE_FILES "src/*.cpp" "src/*.h")

# Add the executable
add_executable(ChessEngine ${SOURCE_FILES})

# SDL2
find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})
target_link_libraries(ChessEngine ${SDL2_LIBRARIES})

And here’s my main.cpp file:

/**
 * @file main.cpp
 * @author Hashem A. Damrah
 * @brief Main file for the chess engine.
 * @copyright
 */

#include "./headers/renderWindow.h"

#include <iostream>

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

int main(int argc, char* args[]) {
  // Initialize SDL
  if (SDL_Init(SDL_INIT_EVERYTHING) > 0) {
    std::cerr
      << "SDL could not initialize! SDL_Error: "
      << SDL_GetError()
      << std::endl;
  }

  // Initialize SDL_image
  if (!(IMG_Init(IMG_INIT_PNG))) {
    std::cerr
      << "SDL_image could not initialize! SDL_image Error: "
      << SDL_GetError()
      << std::endl;
  }

  /**
   * @brief The window that the game is rendered in.
   */
  RenderWindow window("Chess", 700, 700);

  /**
   * @brief The event that is used to handle user input.
   */
  SDL_Event event;

  /**
   * @brief Variable that controls the main loop.
   */
  bool isRunning = true;

  // Main game loop
  while (isRunning) {
    // Check for user input
    while (SDL_PollEvent(&event)) {
      // Check if the user wants to quit
      if (event.type == SDL_QUIT) {
        // If so, exit the main loop
        isRunning = false;
      }
    }
  }

  window.cleanUp();
  SDL_Quit();

  return 0;
}

And here’s the renderWindow.cpp:

/**
 * @file renderWindow.cpp
 * @author Hashem A. Damrah
 * @brief Implementation file for the RenderWindow class.
 * @copyright
 */

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

#include <iostream>

#include "./headers/renderWindow.h"

RenderWindow::RenderWindow(const char *title, int p, int h)
    : window(NULL), renderer(NULL) {
  window = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED,
                            SDL_WINDOWPOS_UNDEFINED, p, h, SDL_WINDOW_SHOWN);

  if (window == NULL) {
    std::cerr << "Window failed to init. Error: " << SDL_GetError()
              << std::endl;
  }

  renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
}

SDL_Texture *RenderWindow::loadTexture(const char *filePath) {
  SDL_Texture *texture = NULL;
  texture = IMG_LoadTexture(renderer, filePath);

  if (texture == NULL) {
    std::cerr << "Failed to load texture. Error: " << SDL_GetError()
              << std::endl;
  }

  return texture;
}

void RenderWindow::cleanUp() {
  SDL_DestroyWindow(window);
}

Lastly, here’s the renderWindow.h:

/**
 * @file renderWindow.h
 * @author Hashem A. Damrah
 * @brief Header file for the RenderWindow class.
 * @copyright
 */

#pragma once
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

/**
 * @class RenderWindow
 * @brief A class that represents the window that the game is rendered in.
 *
 */
class RenderWindow {
 public:
    /**
     * @brief Construct a new Render Window object.
     *
     * @param title The title of the window.
     * @param w Width of the window.
     * @param h Height of the window.
     */
    RenderWindow(const char* title, int w, int h);

    /**
     * @brief Render the game.
     *
     * @param filePath The path to the image that is to be rendered.
     * @return SDL_Texture* The texture that is to be rendered.
     */
    SDL_Texture* loadTexture(const char* filePath);

    /**
     * @brief Destroy the Render Window object.
     */
    void cleanUp();

 private:
    /**
     * @brief The window that the game is rendered in.
     */
    SDL_Window* window;

    /**
     * @brief The renderer that renders the game.
     */
    SDL_Renderer* renderer;
};

But when I run mkdir build; cd build; cmake ..; make, I get the following errors:

/usr/bin/ld: CMakeFiles/ChessEngine.dir/src/main.cpp.o: in function `main':
main.cpp:(.text+0x7f): undefined reference to `IMG_Init'
/usr/bin/ld: CMakeFiles/ChessEngine.dir/src/renderWindow.cpp.o: in function `RenderWindow::loadTexture(char const*)':
renderWindow.cpp:(.text+0xfa): undefined reference to `IMG_LoadTexture'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/ChessEngine.dir/build.make:131: ChessEngine] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/ChessEngine.dir/all] Error 2
make: *** [Makefile:91: all] Error 2

Here’s the link to the repo if you need more info.

I don’t use cmake so I’m not 100% sure, but looking through your CMakeLists.txt file, I don’t see mention of SDL_image.
Does the compiled Makefile include any mention of SDL_image? → SDL_image is a separate library that you need to install and needs to be added to the compile command.

Hello,

After some little changes, cmake works perfectly. As wrote @GuildedDoughnut(Profile - GuildedDoughnut - Simple Directmedia Layer), you’re missing SDL2_image at link time + some other errors

See below :slight_smile:

  1. do NOT use the path for headers, but add the path in CMakeLists.txt (see the one I provided

  2. put renderWindow.h inside headers subdir, not in src (use clean rule : do not mix .h and .cpp)

  3. in your .cpp, replace

#include "./headers/renderWindow.h" 

with;

#include "renderWindow.h" 

Since you add headers in include_dir paths, g++ will find everything at compile time, as expected.

  1. you miss SDL2_image at link time.

Correct and fully working CMakeLists.txt now :slight_smile:

cmake_minimum_required(VERSION 3.12)

project(ChessEngine)

set(CMAKE_CXX_STANDARD 11)

# Add your source files
file(GLOB SOURCE_FILES "src/*.cpp" "src/*.h")

# Add the executable
add_executable(ChessEngine ${SOURCE_FILES})

# SDL2
find_package(SDL2 REQUIRED)

include_directories(headers ${SDL2_INCLUDE_DIRS})

# Do NOT forget to add SDL2_image at link time
target_link_libraries(ChessEngine ${SDL2_LIBRARIES} SDL2_image)

Last but not least, I’d suggest you to have a look at CMake Tutorial — CMake 3.28.1 Documentation

Hope this will help you

[EDIT] : I forgot yhe command line to create build directory.

e.g. type the following command line in the directory containing the CMakeLists.txt file (at the root of src and headers subdirs). Just do NOT forget the dot :wink:

cmake -BBuild_Linux .


ericb

1 Like