AlexMax
AlexMax

Reputation: 1204

CMake - Imported Library has library dependency that must come first

I am yet another fool who is attempting to make a decent FindSDL2.cmake by trying to do things "the right way". However, I am banging my head against a wall when it comes to the following problem:

# SDL2main imported target.
add_library(SDL2::SDL2main UNKNOWN IMPORTED)
set_target_properties(SDL2::SDL2main PROPERTIES
                      IMPORTED_LOCATION "${SDL2_MAIN_LIBRARY}")

The trouble is, when compiling with MinGW, SDL2main needs -lmingw32 in order to locate WinMain. And it must come before SDL2main in the linker flags.

It seems like the happy path wants me to do this:

if(MINGW)
    set_target_properties(SDL2::SDL2main PROPERTIES
                          INTERFACE_LINK_LIBRARIES mingw32)
endif()

But that doesn't work, because mingw32 comes after SDL2main on the linker command. It needs to be before. I also would prefer not to burden targets with inserting it themselves.

Upvotes: 1

Views: 354

Answers (1)

AlexMax
AlexMax

Reputation: 1204

Okay, this took me a little bit to figure out - thanks to ngladitz on #cmake IRC for some clarifications.

I ended up with a three step workaround:

  1. Set up the SDL2main library as a new, separate target, in my case called SDL2::_SDL2main_detail.
  2. Link this separate target directly against SDL2::SDL2. This is important, otherwise CMake will mix up the link ordering of SDL2 and SDL2main.
  3. Create the SDL2::SD2main target that just points at mingw32 and links against SDL2::_SDL2main_detail.

Here is my code:

# SDL2main imported target.
if(MINGW)
    # Gross hack to get mingw32 first in the linker order.
    add_library(SDL2::_SDL2main_detail UNKNOWN IMPORTED)
    set_target_properties(SDL2::_SDL2main_detail PROPERTIES
                          IMPORTED_LOCATION "${SDL2_MAIN_LIBRARY}")

    # Ensure that SDL2main comes before SDL2 in the linker order.  CMake
    # isn't smart enough to keep proper ordering for indirect dependencies
    # so we have to spell it out here.
    target_link_libraries(SDL2::_SDL2main_detail INTERFACE SDL2::SDL2)

    add_library(SDL2::SDL2main INTERFACE IMPORTED)
    set_target_properties(SDL2::SDL2main PROPERTIES
                          IMPORTED_LIBNAME mingw32)
    target_link_libraries(SDL2::SDL2main INTERFACE SDL2::_SDL2main_detail)
else()
    add_library(SDL2::SDL2main UNKNOWN IMPORTED)
    set_target_properties(SDL2::SDL2main PROPERTIES
                          IMPORTED_LOCATION "${SDL2_MAIN_LIBRARY}")
endif()

Upvotes: 1

Related Questions