SDL2_image::SDL2_image target was not found when installed with vcpkg

I am trying to migrate my CMakeLists.txt from FetchContent to find_package, so I don’t have to build all my dependencies on every rebuild. When I install SDL2 and SDL2_image via Pacman, my project builds. But when I install the packages through vcpkg (and pass my vcpkg path to CMAKE_TOOLCHAIN_FILE), it downloads all my dependencies but then can’t find the target SDL2_image::SDL2_image.s

vcpkg.json

{
  "dependencies": [
    "sdl2",
    "sdl2-image"
  ],
  "builtin-baseline": "1b65197e9393b9ca312c95731ebf9c53d776b8d2"
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.21)
project(Sdl2App)

find_package(SDL2 CONFIG REQUIRED)
find_package(SDL2_image CONFIG REQUIRED)
add_executable(Sdl2App 
    "./main.cpp"
)

target_link_libraries(Sdl2App PRIVATE
    SDL2::SDL2
    SDL2_image::SDL2_image
)

Output CMake

➜  sdl2-build-error cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=/home/ascendise/Dev/vcpkg/scripts/buildsystems/vcpkg.cmake
-- Running vcpkg install
Detecting compiler hash for triplet x64-linux...
All requested packages are currently installed.
Total install time: 390 ns
sdl2 provides CMake targets:

    find_package(SDL2 CONFIG REQUIRED)
    target_link_libraries(main
        PRIVATE
        $<TARGET_NAME_IF_EXISTS:SDL2::SDL2main>
        $<IF:$<TARGET_EXISTS:SDL2::SDL2>,SDL2::SDL2,SDL2::SDL2-static>
    )

sdl2-image provides CMake targets:

    find_package(SDL2_image CONFIG REQUIRED)
    target_link_libraries(main PRIVATE $<IF:$<TARGET_EXISTS:SDL2_image::SDL2_image>,SDL2_image::SDL2_image,SDL2_image::SDL2_image-static>)

-- Running vcpkg install - done
-- Configuring done (0.8s)
CMake Error at CMakeLists.txt:10 (target_link_libraries):
  Target "Sdl2App" links to:

    SDL2_image::SDL2_image

  but the target was not found.  Possible reasons include:

    * There is a typo in the target name.
    * A find_package call is missing for an IMPORTED target.
    * An ALIAS target is missing.



-- Generating done (0.0s)
CMake Generate step failed.  Build files cannot be regenerated correctly.

One thing to note is, that my project builds fine when linking to SDL2_image::SDL2_image-static (even tho no images are rendered then, but that might be out of scope of this topic)
So I checked the vcpkg_directory and saw, that I only have libSDL2.a, libSDL2main.a and libSDL2_image.a. So only static libraries? But why? Some other dependencies I have do come as shared library so why not SDL2 and SDL2_image? And why am I able to link to SDL2::SDL2 when there is no libSDL2.so? Because if find_package would fallback to the library installed with pacman, then it would also find the SDL2_image target…

So you see, there is some weirdness going on and I just try to understand this mess a bit more.
It’s also not like my sample CMakeLists.txt on the top does anything crazy. It is very similar to other people’s CMakeLists.txt…

Thank you very much in advance.

TL;DR use the command provided by vcpkg to link SDL_image:

target_link_libraries(main PRIVATE $<IF:$<TARGET_EXISTS:SDL2_image::SDL2_image>,SDL2_image::SDL2_image,SDL2_image::SDL2_image-static>

There’s a small difference between the CMake implementation of the main SDL project and its satellite libraries.

Starting SDL 2.0.18, the main library always exports SDL2::SDL2 which is either the shared library or an alias to the static library (SDL2::SDL2-static).

On the other hand, satellite libraries all have either SDL2_xxx::SDL2_xxx for the shared library or SDL2_xxx::SDL2_xxx-static for the static library.

One thing to note about vcpkg is that it’s defaulting to shared libraries on Windows, and static libraries on Linux and macOS, hence the funky target_link_libraries call vcpkg recommends:

target_link_libraries(main PRIVATE $<IF:$<TARGET_EXISTS:SDL2_image::SDL2_image>,SDL2_image::SDL2_image,SDL2_image::SDL2_image-static>

This expression can be broken down into:

if(TARGET SDL2_image::SDL2_image)
  target_link_libraries(main PRIVATE SDL2_image::SDL2_image)
else()
  target_link_libraries(main PRIVATE SDL2_image::SDL2_image-static)
endif()

As a side note, for SDL3, this will be much simplified as all SDL libraries will always offer the SDL3_xxx::SDL3_xxx target.

Hopefully this clears it up!

2 Likes

wow, thank you very much. This explains some of the weirdness I encountered. I was very confused, because most of the guides in the internet linked to a specific target. Also explains why I wasn’t able to reproduce the error on Windows… Would there be a way to force vcpkg to build shared libraries for SDL or is this not how the tool/the library is intended to be used?
As if I want to create a release for the project, I would have liked to build with dynamic linking so SDL wouldn’t be compiled into the app and the app would just use the SDL installation of the user.

You can tell vcpkg to build shared libraries by using the right triplet for your platform, for example:

  • ARCH-linux-dynamic for Linux
  • ARCH-osx-dynamic for macOS

Do note that shared libraries work differently outside Windows. If you place all your .so/dylib next to your executable, they won’t be picked up out of the box (unlike on Windows). You will need to play around with RPATH/RUNPATH, but CMake lets you configure that. Also, libraries built with vcpkg have their runpath already set, so they can easily be copied around.

1 Like