Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[macOS] SDL2::SDL2main target is not defined. #6119

Closed
FtZPetruska opened this issue Aug 23, 2022 · 6 comments · Fixed by #6120
Closed

[macOS] SDL2::SDL2main target is not defined. #6119

FtZPetruska opened this issue Aug 23, 2022 · 6 comments · Fixed by #6120

Comments

@FtZPetruska
Copy link
Contributor

Starting version 2.24.0, the CMake target SDL2::SDL2main is no longer defined on macOS even when the library itself is present.

I have already seen a few reports of that issue from other macOS users in the discord server and one on the discourse forum.

The error happens when using SDL2 packaged from homebrew (uses autotools and installs a libSDL2main.a file), as well as the official release using the Apple framework.

Here is a sample project to reproduce the issue and the exact error message:

# CMakeLists.txt
cmake_minimum_required(VERSION 3.0.0)
project(main VERSION 0.1.0)

add_executable(main main.cpp)

find_package(SDL2 CONFIG REQUIRED)

target_link_libraries(main PRIVATE SDL2::SDL2 SDL2::SDL2main)
/* main.cpp */
#include "SDL.h"

int main(int, char**) {
    SDL_Log("Hello world.\n");
    return 0;
}
CMake Error at CMakeLists.txt:8 (target_link_libraries):
   Target "main" links to:
 
     SDL2::SDL2main
 
   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.
@madebr
Copy link
Contributor

madebr commented Aug 23, 2022

Indeed, SDL2::SDL2main is only created when "SDL2main" is present in the link argument.

SDL/sdl2-config.cmake.in

Lines 62 to 73 in 50c5d23

if(_sdl2_libraries MATCHES ".*SDL2main.*")
list(INSERT SDL2_LIBRARIES 0 SDL2::SDL2main)
list(INSERT SDL2_STATIC_LIBRARIES 0 SDL2::SDL2main)
set(_sdl2main_library ${SDL2_LIBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}SDL2main${CMAKE_STATIC_LIBRARY_SUFFIX})
if(EXISTS "${_sdl2main_library}")
set(SDL2MAIN_LIBRARY SDL2::SDL2main)
if(NOT TARGET SDL2::SDL2main)
add_library(SDL2::SDL2main STATIC IMPORTED)
set_target_properties(SDL2::SDL2main
PROPERTIES
IMPORTED_LOCATION "${_sdl2main_library}"
)

This should probably be changed to something behaving as follows (removing the if(1) indent in the final code):

if(_sdl2_libraries MATCHES ".*SDL2main.*")
  list(INSERT SDL2_LIBRARIES 0 SDL2::SDL2main)
  list(INSERT SDL2_STATIC_LIBRARIES 0 SDL2::SDL2main)
endif()
if(1)
  set(_sdl2main_library ${SDL2_LIBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}SDL2main${CMAKE_STATIC_LIBRARY_SUFFIX})
  if(EXISTS "${_sdl2main_library}")
    set(SDL2MAIN_LIBRARY SDL2::SDL2main)
    if(NOT TARGET SDL2::SDL2main)
      add_library(SDL2::SDL2main STATIC IMPORTED)
      set_target_properties(SDL2::SDL2main
        PROPERTIES
          IMPORTED_LOCATION "${_sdl2main_library}"
      )

@madebr
Copy link
Contributor

madebr commented Aug 23, 2022

The error happens when using SDL2 packaged from homebrew (uses autotools and installs a libSDL2main.a file), as well as the official release using the Apple framework.

When I last extracted the dmg (I don't own a Mac), I only saw a single SDL2 thing which I presumed to be the SDL2 shared library.
Does it actually contain the SDL2main library?
And if so, how do you link to it?

FYI, this is how the SDL2::SDL2 target is created for the Apple framework dmg:

if(NOT TARGET SDL2::SDL2)
add_library(SDL2::SDL2 INTERFACE IMPORTED)
set_target_properties(SDL2::SDL2
PROPERTIES
INTERFACE_COMPILE_OPTIONS "SHELL:-F \"${SDL2_FRAMEWORK_PARENT_PATH}\""
INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INCLUDE_DIR}"
INTERFACE_LINK_OPTIONS "SHELL:-F \"${SDL2_FRAMEWORK_PARENT_PATH}\";SHELL:-framework SDL2"
COMPATIBLE_INTERFACE_BOOL "SDL2_SHARED"
INTERFACE_SDL2_SHARED "ON"
)
endif()

@FtZPetruska
Copy link
Contributor Author

Indeed, SDL2::SDL2main is only created when "SDL2main" is present in the link argument.

SDL/sdl2-config.cmake.in

Lines 62 to 73 in 50c5d23

if(_sdl2_libraries MATCHES ".*SDL2main.*")
list(INSERT SDL2_LIBRARIES 0 SDL2::SDL2main)
list(INSERT SDL2_STATIC_LIBRARIES 0 SDL2::SDL2main)
set(_sdl2main_library ${SDL2_LIBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}SDL2main${CMAKE_STATIC_LIBRARY_SUFFIX})
if(EXISTS "${_sdl2main_library}")
set(SDL2MAIN_LIBRARY SDL2::SDL2main)
if(NOT TARGET SDL2::SDL2main)
add_library(SDL2::SDL2main STATIC IMPORTED)
set_target_properties(SDL2::SDL2main
PROPERTIES
IMPORTED_LOCATION "${_sdl2main_library}"
)

This should probably be changed to something behaving as follows (removing the if(1) indent in the final code):

if(_sdl2_libraries MATCHES ".*SDL2main.*")
  list(INSERT SDL2_LIBRARIES 0 SDL2::SDL2main)
  list(INSERT SDL2_STATIC_LIBRARIES 0 SDL2::SDL2main)
endif()
if(1)
  set(_sdl2main_library ${SDL2_LIBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}SDL2main${CMAKE_STATIC_LIBRARY_SUFFIX})
  if(EXISTS "${_sdl2main_library}")
    set(SDL2MAIN_LIBRARY SDL2::SDL2main)
    if(NOT TARGET SDL2::SDL2main)
      add_library(SDL2::SDL2main STATIC IMPORTED)
      set_target_properties(SDL2::SDL2main
        PROPERTIES
          IMPORTED_LOCATION "${_sdl2main_library}"
      )

I can confirm that this patch works for the homebrew version.

The error happens when using SDL2 packaged from homebrew (uses autotools and installs a libSDL2main.a file), as well as the official release using the Apple framework.

When I last extracted the dmg (I don't own a Mac), I only saw a single SDL2 thing which I presumed to be the SDL2 shared library. Does it actually contain the SDL2main library? And if so, how do you link to it?

SDL2main does nothing on macOS and it's not shipped in the framework. If you build from source the library just defines a main that calls SDL_main. What's new with 2.24.0 is that CMake config files are now shipped with the framework.

@madebr
Copy link
Contributor

madebr commented Aug 24, 2022

I can confirm that this patch works for the homebrew version.

I'll create a pr for it. It's very small and probably a candidate for 2.24.x.

SDL2main does nothing on macOS and it's not shipped in the framework. If you build from source the library just defines a main that calls SDL_main.

We can't create an imported cmake target for a library that does not exist.
I think we have 3 ways to fix this:

  1. Create a dummy, empty SDL2::SDL2main library:
    add_library(SDL2::SDL2main INTERFACE IMPORTED)
  2. Create a target compiling a trivial sdl2main.c source, and create a library for it.
    # Untested code!
    if(NOT TARGET SDL2::SDL2main)
        set(_sdl2main_src [[
            #include "SDL2.h"
            #if defined(main)
            #undef main
            #endif
            int main(int argc, char *argv[]) {
                return SDL_main(argc, argv);
            }
        ]])
        add_custom_command(OUTPUT sdl_main.c COMMAND "${CMAKE_COMMAND}" -E echo "${_sdl2main_src}" >sdl_main.c)
        add_library(_sdl2main STATIC EXCLUDE_FROM_ALL "${CMAKE_CURRENT_BINARY_DIR}/sdl_main.c")
        target_link_libraries(_sdl2main PRIVATE SDL2::SDL2)
        add_library(SDL2::SDL2main ALIAS _sdl2main)
    endif()
  3. Do nothing!
    Users of SDL2 should not expect SDL2main to be available.
    This means linking to SDL2 becomes a little more complicated:
    target_link_libraries(my_executable PRIVATE $<$<TARGET_EXISTS:SDL2::SDL2main>:SDL2::SDL2main> SDL2::SDL2)
    (equivalent to)
    if(TARGET SDL2::SDL2main)
        target_link_libraries(my_executable PRIVATE SDL2::SDL2main)
    endif()
    target_link_libraries(my_executable PRIVATE SDL2::SDL2)

I think(!) the reason the dmg does not ship an SDL2main static library is because Macos does not need it. Neither SDL_MAIN_NEEDED or SDL_MAIN_AVAILABLE are defined in SDL_main.h for this platform.

In the CMake test, it is not assumed SDL2::SDL2main is available.

@FtZPetruska
Copy link
Contributor Author

I can confirm that this patch works for the homebrew version.

I'll create a pr for it. It's very small and probably a candidate for 2.24.x.

SDL2main does nothing on macOS and it's not shipped in the framework. If you build from source the library just defines a main that calls SDL_main.

We can't create an imported cmake target for a library that does not exist. I think we have 3 ways to fix this:

1. Create a dummy, empty `SDL2::SDL2main` library:
   ```cmake
   add_library(SDL2::SDL2main INTERFACE IMPORTED)
   ```

2. Create a target compiling a trivial sdl2main.c source, and create a library for it.
   ```cmake
   # Untested code!
   if(NOT TARGET SDL2::SDL2main)
       set(_sdl2main_src [[
           #include "SDL2.h"
           #if defined(main)
           #undef main
           #endif
           int main(int argc, char *argv[]) {
               return SDL_main(argc, argv);
           }
       ]])
       add_custom_command(OUTPUT sdl_main.c COMMAND "${CMAKE_COMMAND}" -E echo "${_sdl2main_src}" >sdl_main.c)
       add_library(_sdl2main STATIC EXCLUDE_FROM_ALL "${CMAKE_CURRENT_BINARY_DIR}/sdl_main.c")
       target_link_libraries(_sdl2main PRIVATE SDL2::SDL2)
       add_library(SDL2::SDL2main ALIAS _sdl2main)
   endif()
   ```

3. Do nothing!
   Users of SDL2 should not expect SDL2main to be available.
   This means linking to SDL2 becomes a little more complicated:
   ```cmake
   target_link_libraries(my_executable PRIVATE $<$<TARGET_EXISTS:SDL2::SDL2main>:SDL2::SDL2main> SDL2::SDL2)
   ```
   
   
       
         
       
   
         
       
   
       
     
   (equivalent to)
   ```cmake
   if(TARGET SDL2::SDL2main)
       target_link_libraries(my_executable PRIVATE SDL2::SDL2main)
   endif()
   target_link_libraries(my_executable PRIVATE SDL2::SDL2)
   ```

I think(!) the reason the dmg does not ship an SDL2main static library is because Macos does not need it. Neither SDL_MAIN_NEEDED or SDL_MAIN_AVAILABLE are defined in SDL_main.h for this platform.

In the CMake test, it is not assumed SDL2::SDL2main is available.

Previously, if you were trying to find the framework through CMake you'd have to use ${SDL2_LIBRARIES} since there was no CMake config/target file. On other platforms, that variable would implicitly include SDL2main if available. Moreover, until now on all platforms SDL2::SDL2main could be used even when the platform didn't need it.

With that in mind, I would tend to say that the target should remain available to avoid breaking existing projects.

Looking at the framework's headers, it should be safe to simply create a dummy SDL2::SDL2main target (option 1). Doing the following patch to the framework's config file fixed build on the projects people have reported issues with:

if(NOT TARGET SDL2::SDL2main)
    add_library(SDL2::SDL2main INTERFACE IMPORTED)
endif()

@madebr
Copy link
Contributor

madebr commented Aug 24, 2022

With that in mind, I would tend to say that the target should remain available to avoid breaking existing projects.

Looking at the framework's headers, it should be safe to simply create a dummy SDL2::SDL2main target (option 1). Doing the following patch to the framework's config file fixed build on the projects people have reported issues with:

if(NOT TARGET SDL2::SDL2main)
    add_library(SDL2::SDL2main INTERFACE IMPORTED)
endif()

I'll add that to the pr :)

glebm added a commit to glebm/devilutionX that referenced this issue Aug 25, 2022
SDL2 2.24.0 has a bug in its cmake for macOS: libsdl-org/SDL#6119

This bug has already been fixed upstream. This is a workaround until the
next version of SDL2 is released.
StephenCWills pushed a commit to StephenCWills/devilutionX that referenced this issue Aug 25, 2022
SDL2 2.24.0 has a bug in its cmake for macOS: libsdl-org/SDL#6119

This bug has already been fixed upstream. This is a workaround until the
next version of SDL2 is released.
glebm added a commit to diasurgical/devilutionX that referenced this issue Aug 25, 2022
SDL2 2.24.0 has a bug in its cmake for macOS: libsdl-org/SDL#6119

This bug has already been fixed upstream. This is a workaround until the
next version of SDL2 is released.
artifacts-storage pushed a commit to artifacts-storage/devilutionx-artifacts that referenced this issue Aug 25, 2022
SDL2 2.24.0 has a bug in its cmake for macOS: libsdl-org/SDL#6119

This bug has already been fixed upstream. This is a workaround until the
next version of SDL2 is released.
artifacts-storage pushed a commit to artifacts-storage/devilutionx-artifacts that referenced this issue Feb 13, 2023
SDL2 2.24.0 has a bug in its cmake for macOS: libsdl-org/SDL#6119

This bug has already been fixed upstream. This is a workaround until the
next version of SDL2 is released.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants