From 5ec2d46f476f5019d1d0bb8345b7f6f79222d0c1 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Fri, 3 Jun 2022 20:12:52 +0200 Subject: [PATCH] cmake: make SDL2Config.cmake compatible with autotools' sdl2-config.cmake --- CMakeLists.txt | 50 ++++++++++++------ SDL2Config.cmake | 122 -------------------------------------------- SDL2Config.cmake.in | 60 ++++++++++++++++++++++ 3 files changed, 93 insertions(+), 139 deletions(-) delete mode 100644 SDL2Config.cmake create mode 100644 SDL2Config.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index a1bb36477..e434a8acd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -287,7 +287,7 @@ if(MSVC) endif() endif() -# Those are used for pkg-config and friends, so that the SDL2.pc, sdl2-config, +# Those are used for pkg-config and friends, so that the sdl2.pc, sdl2-config, # etc. are created correctly. set(SDL_LIBS "-lSDL2") set(SDL_CFLAGS "") @@ -312,7 +312,7 @@ if(CYGWIN) HAVE_GCC_NO_CYGWIN) set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS}) if(HAVE_GCC_NO_CYGWIN) - list(APPEND EXTRA_LDFLAGS "-mno-cygwin") + list(APPEND EXTRA_LDFLAGS_BUILD "-mno-cygwin") list(APPEND SDL_LIBS "-mno-cygwin") endif() set(SDL_CFLAGS "${SDL_CFLAGS} -I/usr/include/mingw") @@ -612,15 +612,16 @@ if(USE_GCC OR USE_CLANG) endif() if(APPLE) - list(APPEND EXTRA_LDFLAGS "-Wl,-undefined,error") - list(APPEND EXTRA_LDFLAGS "-Wl,-compatibility_version,${DYLIB_COMPATIBILITY_VERSION}") - list(APPEND EXTRA_LDFLAGS "-Wl,-current_version,${DYLIB_CURRENT_VERSION}") + # FIXME: use generator expression instead of appending to EXTRA_LDFLAGS_BUILD + list(APPEND EXTRA_LDFLAGS_BUILD "-Wl,-undefined,error") + list(APPEND EXTRA_LDFLAGS_BUILD "-Wl,-compatibility_version,${DYLIB_COMPATIBILITY_VERSION}") + list(APPEND EXTRA_LDFLAGS_BUILD "-Wl,-current_version,${DYLIB_CURRENT_VERSION}") elseif(NOT OPENBSD) set(CMAKE_REQUIRED_FLAGS "-Wl,--no-undefined") check_c_compiler_flag("" HAVE_NO_UNDEFINED) set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS}) if(HAVE_NO_UNDEFINED AND NOT (USE_CLANG AND WINDOWS)) - list(APPEND EXTRA_LDFLAGS "-Wl,--no-undefined") + list(APPEND EXTRA_LDFLAGS_BUILD "-Wl,--no-undefined") endif() endif() @@ -1838,8 +1839,6 @@ elseif(WINDOWS) file(GLOB VERSION_SOURCES ${SDL2_SOURCE_DIR}/src/main/windows/*.rc) file(GLOB SDLMAIN_SOURCES ${SDL2_SOURCE_DIR}/src/main/windows/*.c) if(MINGW OR CYGWIN) - list(APPEND EXTRA_LIBS mingw32) - list(APPEND EXTRA_LDFLAGS "-mwindows") list(APPEND SDL_LIBS "-lmingw32" "-mwindows") if(NOT SDL2_DISABLE_SDL2MAIN) set(SDL_CFLAGS "${SDL_CFLAGS} -Dmain=SDL_main") @@ -2850,7 +2849,7 @@ endif() message(STATUS "") message(STATUS " CFLAGS: ${CMAKE_C_FLAGS}") message(STATUS " EXTRA_CFLAGS: ${EXTRA_CFLAGS}") -message(STATUS " EXTRA_LDFLAGS: ${EXTRA_LDFLAGS}") +message(STATUS " EXTRA_LDFLAGS: ${EXTRA_LDFLAGS} ${EXTRA_LDFLAGS_BUILD}") message(STATUS " EXTRA_LIBS: ${EXTRA_LIBS}") message(STATUS "") message(STATUS " Build Shared Library: ${SDL_SHARED}") @@ -2897,6 +2896,14 @@ if(NOT WINDOWS_STORE AND NOT SDL2_DISABLE_SDL2MAIN) if (WIN32) target_link_libraries(SDL2main PRIVATE shell32) endif() + if(MINGW OR CYGWIN) + cmake_minimum_required(VERSION 3.13) + if(CMAKE_SIZEOF_VOID_P EQUAL 4) + target_link_options(SDL2main PUBLIC "-Wl,--undefined=_WinMain@16") + else() + target_link_options(SDL2main PUBLIC "-Wl,--undefined=WinMain") + endif() + endif() if (NOT ANDROID) set_target_properties(SDL2main PROPERTIES DEBUG_POSTFIX "${SDL_CMAKE_DEBUG_POSTFIX}") endif() @@ -2945,11 +2952,17 @@ if(SDL_SHARED) endif() set_target_properties(SDL2 PROPERTIES STATIC_LIBRARY_FLAGS "/NODEFAULTLIB") endif() - target_link_libraries(SDL2 PRIVATE ${EXTRA_LIBS} ${EXTRA_LDFLAGS}) + # FIXME: if CMAKE_VERSION >= 3.13, use target_link_options for EXTRA_LDFLAGS + target_link_libraries(SDL2 PRIVATE ${EXTRA_LIBS} ${EXTRA_LDFLAGS} ${EXTRA_LDFLAGS_BUILD}) target_include_directories(SDL2 BEFORE PRIVATE "${SDL2_BINARY_DIR}/include") target_include_directories(SDL2 PUBLIC "$;$;$") # This picks up all the compiler options and such we've accumulated up to here. target_link_libraries(SDL2 PRIVATE $) + if(MINGW OR CYGWIN) + if(NOT CMAKE_VERSION VERSION_LESS "3.13") + target_link_options(SDL2 PRIVATE -static-libgcc) + endif() + endif() if(NOT ANDROID) set_target_properties(SDL2 PROPERTIES DEBUG_POSTFIX "${SDL_CMAKE_DEBUG_POSTFIX}") endif() @@ -2963,12 +2976,11 @@ if(SDL_STATIC) add_library(SDL2-static STATIC ${SOURCE_FILES}) # alias target for in-tree builds add_library(SDL2::SDL2-static ALIAS SDL2-static) - if (NOT SDL_SHARED OR NOT WIN32 OR MINGW) + if(MSVC OR (WATCOM AND (WIN32 OR OS2))) + # Avoid conflict between the dll import library and the static library + set_target_properties(SDL2-static PROPERTIES OUTPUT_NAME "SDL2-static") + else() set_target_properties(SDL2-static PROPERTIES OUTPUT_NAME "SDL2") - # Note: Apparently, OUTPUT_NAME must really be unique; even when - # CMAKE_IMPORT_LIBRARY_SUFFIX or the like are given. Otherwise - # the static build may race with the import lib and one will get - # clobbered, when the suffix is realized via subsequent rename. endif() set_target_properties(SDL2-static PROPERTIES POSITION_INDEPENDENT_CODE ${SDL_STATIC_PIC}) # Note: The clang toolset for Visual Studio does not support /NODEFAULTLIB. @@ -2979,7 +2991,7 @@ if(SDL_STATIC) endif() # TODO: Win32 platforms keep the same suffix .lib for import and static # libraries - do we need to consider this? - target_link_libraries(SDL2-static PRIVATE ${EXTRA_LIBS} ${EXTRA_LDFLAGS}) + target_link_libraries(SDL2-static PRIVATE ${EXTRA_LIBS} ${EXTRA_LDFLAGS} ${EXTRA_LDFLAGS_BUILD}) target_include_directories(SDL2-static BEFORE PRIVATE "${SDL2_BINARY_DIR}/include") target_include_directories(SDL2-static PUBLIC "$" $ $) # This picks up all the compiler options and such we've accumulated up to here. @@ -3047,6 +3059,10 @@ if(NOT SDL2_DISABLE_INSTALL) endif () include(CMakePackageConfigHelpers) + configure_package_config_file(SDL2Config.cmake.in "${CMAKE_BINARY_DIR}/SDL2Config.cmake" + PATH_VARS CMAKE_INSTALL_PREFIX CMAKE_INSTALL_FULL_BINDIR CMAKE_INSTALL_FULL_INCLUDEDIR CMAKE_INSTALL_FULL_LIBDIR + INSTALL_DESTINATION ${PKG_PREFIX} + ) write_basic_package_version_file("${CMAKE_BINARY_DIR}/SDL2ConfigVersion.cmake" VERSION ${SDL_VERSION} COMPATIBILITY AnyNewerVersion @@ -3086,7 +3102,7 @@ if(NOT SDL2_DISABLE_INSTALL) install( FILES - ${CMAKE_CURRENT_SOURCE_DIR}/SDL2Config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/SDL2Config.cmake ${CMAKE_BINARY_DIR}/SDL2ConfigVersion.cmake DESTINATION ${PKG_PREFIX} COMPONENT Devel diff --git a/SDL2Config.cmake b/SDL2Config.cmake deleted file mode 100644 index 39be60b63..000000000 --- a/SDL2Config.cmake +++ /dev/null @@ -1,122 +0,0 @@ -if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL2Targets.cmake") - include("${CMAKE_CURRENT_LIST_DIR}/SDL2Targets.cmake") -endif() -if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL2mainTargets.cmake") - include("${CMAKE_CURRENT_LIST_DIR}/SDL2mainTargets.cmake") -endif() -if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL2staticTargets.cmake") - include("${CMAKE_CURRENT_LIST_DIR}/SDL2staticTargets.cmake") -endif() -if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL2testTargets.cmake") - include("${CMAKE_CURRENT_LIST_DIR}/SDL2testTargets.cmake") -endif() - -# on static-only builds create an alias -if(NOT TARGET SDL2::SDL2 AND TARGET SDL2::SDL2-static) - if(CMAKE_VERSION VERSION_LESS "3.18") - # Aliasing local targets is not supported on CMake < 3.18, so make it global. - set_target_properties(SDL2::SDL2-static PROPERTIES IMPORTED_GLOBAL TRUE) - endif() - add_library(SDL2::SDL2 ALIAS SDL2::SDL2-static) -endif() - -# provide ${SDL2_LIBRARIES}, ${SDL2_INCLUDE_DIRS} etc, like sdl2-config.cmake does, -# for compatibility between SDL2 built with autotools and SDL2 built with CMake - -# the following seems to work on Windows for both MSVC and MINGW+MSYS and with both SDL2Config/Target.cmake -# from vcpkg and from building myself with cmake from latest git -# AND on Linux when building SDL2 (tested current git) with CMake - -# the headers are easy - but note that this adds both .../include/ and .../include/SDL2/ -# while the SDL2_INCLUDE_DIRS of sdl2-config.cmake only add ...include/SDL2/ -# But at least if building worked with sdl2-config.cmake it will also work with this. -get_target_property(SDL2_INCLUDE_DIRS SDL2::SDL2 INTERFACE_INCLUDE_DIRECTORIES) - -# get the paths to the files to link against (.lib or .dll.a on Windows, .so or .a on Unix, ...) for both SDL2 and SDL2main - -# for the "normal"/release build they could be in lots of different properties.. -set(relprops IMPORTED_IMPLIB_RELEASE IMPORTED_IMPLIB_NOCONFIG IMPORTED_IMPLIB IMPORTED_IMPLIB_MINSIZEREL IMPORTED_IMPLIB_RELWITHDEBINFO - IMPORTED_LOCATION_RELEASE IMPORTED_LOCATION_NOCONFIG IMPORTED_LOCATION IMPORTED_LOCATION_MINSIZEREL IMPORTED_LOCATION_RELWITHDEBINFO) - -# fewer possibilities for debug builds -set(dbgprops IMPORTED_IMPLIB_DEBUG IMPORTED_LOCATION_DEBUG) - -foreach(prop ${relprops}) - get_target_property(sdl2implib SDL2::SDL2 ${prop}) - if(sdl2implib) - #message("set sdl2implib from ${prop}") - break() - endif() -endforeach() - -foreach(prop ${relprops}) - get_target_property(sdl2mainimplib SDL2::SDL2main ${prop}) - if(sdl2mainimplib) - #message("set sdl2mainimplib from ${prop}") - break() - endif() -endforeach() - -foreach(prop ${dbgprops}) - get_target_property(sdl2implibdbg SDL2::SDL2 ${prop}) - if(sdl2implibdbg) - #message("set sdl2implibdbg from ${prop}") - break() - endif() -endforeach() - -foreach(prop ${dbgprops}) - get_target_property(sdl2mainimplibdbg SDL2::SDL2main ${prop}) - if(sdl2mainimplibdbg) - #message("set sdl2mainimplibdbg from ${prop}") - break() - endif() -endforeach() - -if( sdl2implib AND sdl2mainimplib AND sdl2implibdbg AND sdl2mainimplibdbg ) - # we have both release and debug builds of SDL2 and SDL2main, so use this ugly - # generator expression in SDL2_LIBRARIES to support both in MSVC, depending on build type configured there - set(SDL2_LIBRARIES $,${sdl2mainimplibdbg},${sdl2mainimplib}> $,${sdl2implibdbg},${sdl2implib}>) -else() - if( (NOT sdl2implib) AND sdl2implibdbg ) # if we only have a debug version of the lib - set(sdl2implib ${sdl2implibdbg}) - endif() - if( (NOT sdl2mainimplib) AND sdl2mainimplibdbg ) # if we only have a debug version of the lib - set(sdl2mainimplib ${sdl2mainimplibdbg}) - endif() - - if( sdl2implib AND sdl2mainimplib ) - set(SDL2_LIBRARIES ${sdl2mainimplib} ${sdl2implib}) - elseif(WIN32 OR APPLE) # I think these platforms have a non-dummy SDLmain? - message(FATAL_ERROR, "SDL2::SDL2 and/or SDL2::SDL2main don't seem to contain any kind of IMPORTED_IMPLIB* or IMPORTED_LOCATION*") - elseif(sdl2implib) # on other platforms just libSDL2 will hopefully do? - set(SDL2_LIBRARIES ${sdl2implib}) - message(STATUS, "No SDL2main lib not found, I hope you don't need it..") - else() - message(FATAL_ERROR, "SDL2::SDL2 doesn't seem to contain any kind of lib to link against in IMPORTED_IMPLIB* or IMPORTED_LOCATION*") - endif() - - # TODO: should something like INTERFACE_LINK_LIBRARIES be appended? or wherever -mwindows and things like that - # might be defined (if they were defined by the CMake build at all; autotools has @SDL_RLD_FLAGS@ @SDL_LIBS@)? - # LINK_DEPENDS? LINK_FLAGS? - -endif() - -get_filename_component(SDL2_LIBDIR ${sdl2implib} PATH) - -# NOTE: SDL2_LIBRARIES now looks like "c:/path/to/SDL2main.lib;c:/path/to/SDL2.lib" -# which is different to what it looks like when coming from sdl2-config.cmake -# (there it's more like "-L${SDL2_LIBDIR} -lSDL2main -lSDL2" - and also -lmingw32 and -mwindows) -# This seems to work with both MSVC and MinGW though, while the other only worked with MinGW -# On Linux it looks like "/tmp/sdl2inst/lib/libSDL2main.a;/tmp/sdl2inst/lib/libSDL2-2.0.so.0.14.1" which also seems to work - -# the exec prefix is one level up from lib/ - TODO: really, always? at least on Linux there's /usr/lib/x86_64-bla-blub/libSDL2-asdf.so.0 .. -get_filename_component(SDL2_EXEC_PREFIX ${SDL2_LIBDIR} PATH) -set(SDL2_PREFIX ${SDL2_EXEC_PREFIX}) # TODO: could this be somewhere else? parent dir of include or sth? - -unset(sdl2implib) -unset(sdl2mainimplib) -unset(sdl2implibdbg) -unset(sdl2mainimplibdbg) -unset(relprops) -unset(dbgprops) diff --git a/SDL2Config.cmake.in b/SDL2Config.cmake.in new file mode 100644 index 000000000..99344b287 --- /dev/null +++ b/SDL2Config.cmake.in @@ -0,0 +1,60 @@ +# sdl2 cmake project-config input for CMakeLists.txt script + +include(FeatureSummary) +set_package_properties(SDL2 PROPERTIES + URL "https://www.libsdl.org/" + DESCRIPTION "low level access to audio, keyboard, mouse, joystick, and graphics hardware" +) + +@PACKAGE_INIT@ + +set(SDL2_FOUND TRUE) + +if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL2Targets.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/SDL2Targets.cmake") + set(SDL2_SDL2_FOUND TRUE) +endif() +if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL2staticTargets.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/SDL2staticTargets.cmake") + set(SDL2_SDL2-static_FOUND TRUE) +endif() +if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL2mainTargets.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/SDL2mainTargets.cmake") + set(SDL2_SDL2main_FOUND TRUE) +endif() +if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL2testTargets.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/SDL2testTargets.cmake") + set(SDL2_SDL2test_FOUND TRUE) +endif() + +check_required_components(SDL2) + +# Create SDL2::SDL2 alias for static-only builds +if(NOT TARGET SDL2::SDL2 AND TARGET SDL2::SDL2-static) + if(CMAKE_VERSION VERSION_LESS "3.18") + # Aliasing local targets is not supported on CMake < 3.18, so make it global. + set_target_properties(SDL2::SDL2-static PROPERTIES IMPORTED_GLOBAL TRUE) + endif() + add_library(SDL2::SDL2 ALIAS SDL2::SDL2-static) +endif() + +# For compatibility with autotools sdl2-config.cmake, provide SDL2_* variables. + +set(SDL2_PREFIX "@PACKAGE_CMAKE_INSTALL_PREFIX@") +set(SDL2_EXEC_PREFIX "@PACKAGE_CMAKE_INSTALL_PREFIX@") +set(SDL2_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_FULL_INCLUDEDIR@/SDL2") +set(SDL2_INCLUDE_DIRS "@PACKAGE_CMAKE_INSTALL_FULL_INCLUDEDIR@;@PACKAGE_CMAKE_INSTALL_FULL_INCLUDEDIR@/SDL2") +set(SDL2_BINDIR "@PACKAGE_CMAKE_INSTALL_FULL_BINDIR@") +set(SDL2_LIBDIR "@PACKAGE_CMAKE_INSTALL_FULL_LIBDIR@") +set(SDL2_LIBRARIES SDL2::SDL2) +set(SDL2_STATIC_LIBRARIES SDL2::SDL2-static) +set(SDL2_STATIC_PRIVATE_LIBS) + +set(SDL2MAIN_LIBRARY) +if(TARGET SDL2::SDL2main) + set(SDL2MAIN_LIBRARY SDL2::SDL2main) + list(INSERT SDL2_LIBRARIES 0 SDL2::SDL2main) + list(INSERT SDL2_STATIC_LIBRARIES 0 SDL2::SDL2main) +endif() + +set(SDL2TEST_LIBRARY SDL2::SDL2test)