SDL_net: Add CMake support

From 20f33294db42d9b75c89d9b236cca0f936c5d3ca Mon Sep 17 00:00:00 2001
From: Pierre Wendling <[EMAIL REDACTED]>
Date: Tue, 14 Jun 2022 17:55:37 -0400
Subject: [PATCH] Add CMake support

https://github.com/libsdl-org/SDL_net/pull/48

* Add CMake support.

Implementation is based off SDL2_Image.

* Add CMake tests to test-versioning.sh.

* Add CMake workflow

Changes link flags to fix mingw builds.

`showinterfaces` is disabled on MSVC workflow as the minimum version of SDL is too old for current MSVCRT and gives linker errors even when linking `legacy_stdio_definitions.lib`

* Apply suggestion from review

Only set `Compatible Interface Properties` for shared libraries.

Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com>

* CMake: Define SDL_MAIN_HANDLED for showinterfaces.

This removes the need for SDL2main as it is a console-only application.
MSVC workflow now builds showinterfaces.

* Apply suggestion from review.

The `mingw32` library is no longer needed as `showinterfaces` is a console app.

Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com>

* CMake: Update MSVC compiler flags.

Applied review suggestion to use `target_compile_options`.
Replaced `/wd4996` as `_WINSOCK_DEPRECATED_NO_WARNINGS` is enough.
Raise the warning level to `/W3` to be consistent with the solution in
`VisualC/`.

* Apply suggestions from code review.

- Set a different output name for static libraries on MSVC and WATCOM (cf. libsdl-org/SDL_image#275 and libsdl-org/SDL#5727)
- Fix `PKG_PREFIX` on Windows (cf. libsdl-org/SDL_image#274)

Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com>

* CMake: Fix missing parenthesis.

* CMake: Remove dead code.

SDL_net does not build any dependency, so we don't need to force
position independent code.

* CMake: Add config files for XCode Frameworks

* CMake: Generate cmake config when using autotools.

* CMake: Add config files for mingw devel archive.

* CMake: Add config files for VC devel archive.

* Regenerate autotools file with CMake support.

* autogen.sh + cmake integration test

* Don't force an installed SDL2_net::SDL2_net-static to link with a specific SDL2 sharedness library

* Update PrivateSdlFunctions.cmake

* Apply suggestion from review.

Fix option de-duplication issues when linking with SDL2 framework.

Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com>

* CMake: Escape framework parent path.

This is necessary if the framework has a space in its path.

* Apply suggestion from review.

Fix name mismatch between the bundled CMake config file for mingw and the generated config.

Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com>

* Apply suggestion from review.

Fix regex match.

Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com>

* Apply suggestion from review.

No longer set PKG_PREFIX on macOS.

Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com>

Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com>
Co-authored-by: Anonymous Maarten <anonymous.maarten@gmail.com>
---
 .github/fetch_sdl_vc.ps1                      |  40 +++
 .github/workflows/main.yml                    | 112 ++++++--
 CMakeLists.txt                                | 236 +++++++++++++++++
 Makefile.am                                   |  15 +-
 Makefile.in                                   |  87 ++++---
 SDL2_netConfig.cmake.in                       |  14 +
 .../cmake/sdl2_net-config-version.cmake       |  54 ++++
 .../pkg-support/cmake/sdl2_net-config.cmake   |  45 ++++
 Xcode/SDL_net.xcodeproj/project.pbxproj       |   4 +
 .../CMake/sdl2_net-config-version.cmake       |  48 ++++
 .../resources/CMake/sdl2_net-config.cmake     |  32 +++
 aclocal.m4                                    | 100 +++++++
 cmake/CommonFindSDL2.cmake                    |  22 ++
 cmake/FindPrivateSDL2.cmake                   |  48 ++++
 cmake/PrivateSdlFunctions.cmake               | 243 ++++++++++++++++++
 cmake/test/CMakeLists.txt                     |  47 ++++
 cmake/test/main.c                             |  18 ++
 configure                                     | 223 ++++++++++++----
 configure.ac                                  |  36 ++-
 .../cmake/sdl2_net-config-version.cmake       |  19 ++
 mingw/pkg-support/cmake/sdl2_net-config.cmake |  19 ++
 sdl2_net-config-version.cmake.in              |  12 +
 sdl2_net-config.cmake.in                      |  72 ++++++
 test-versioning.sh                            |  42 ++-
 24 files changed, 1483 insertions(+), 105 deletions(-)
 create mode 100644 .github/fetch_sdl_vc.ps1
 create mode 100644 CMakeLists.txt
 create mode 100644 SDL2_netConfig.cmake.in
 create mode 100644 VisualC/pkg-support/cmake/sdl2_net-config-version.cmake
 create mode 100644 VisualC/pkg-support/cmake/sdl2_net-config.cmake
 create mode 100644 Xcode/pkg-support/resources/CMake/sdl2_net-config-version.cmake
 create mode 100644 Xcode/pkg-support/resources/CMake/sdl2_net-config.cmake
 create mode 100644 cmake/CommonFindSDL2.cmake
 create mode 100644 cmake/FindPrivateSDL2.cmake
 create mode 100644 cmake/PrivateSdlFunctions.cmake
 create mode 100644 cmake/test/CMakeLists.txt
 create mode 100644 cmake/test/main.c
 create mode 100644 mingw/pkg-support/cmake/sdl2_net-config-version.cmake
 create mode 100644 mingw/pkg-support/cmake/sdl2_net-config.cmake
 create mode 100644 sdl2_net-config-version.cmake.in
 create mode 100644 sdl2_net-config.cmake.in

diff --git a/.github/fetch_sdl_vc.ps1 b/.github/fetch_sdl_vc.ps1
new file mode 100644
index 0000000..05b3d92
--- /dev/null
+++ b/.github/fetch_sdl_vc.ps1
@@ -0,0 +1,40 @@
+$ErrorActionPreference = "Stop"
+
+$project_root = "$psScriptRoot\.."
+Write-Output "project_root: $project_root"
+
+$sdl2_version = "2.0.0"
+$sdl2_zip = "SDL2-devel-$($sdl2_version)-VC.zip"
+
+$sdl2_url = "https://www.libsdl.org/release/$($sdl2_zip)"
+$sdl2_dlpath = "$($Env:TEMP)\$sdl2_zip"
+
+$sdl2_bindir = "$($project_root)"
+$sdl2_extractdir = "$($sdl2_bindir)\SDL2-$($sdl2_version)"
+$sdl2_root_name = "SDL2-devel-VC"
+
+echo "sdl2_bindir:     $sdl2_bindir"
+echo "sdl2_extractdir: $sdl2_extractdir"
+echo "sdl2_root_name:  $sdl2_root_name"
+
+echo "Cleaning previous artifacts"
+if (Test-Path $sdl2_extractdir) {
+    Remove-Item $sdl2_extractdir -Recurse -Force
+}
+if (Test-Path "$($sdl2_bindir)/$sdl2_root_name") {
+    Remove-Item "$($sdl2_bindir)/$sdl2_root_name" -Recurse -Force
+}
+if (Test-Path $sdl2_dlpath) {
+    Remove-Item $sdl2_dlpath -Force
+}
+
+Write-Output "Downloading $sdl2_url"
+Invoke-WebRequest -Uri $sdl2_url -OutFile $sdl2_dlpath
+
+Write-Output "Extracting archive"
+Expand-Archive $sdl2_dlpath -DestinationPath $sdl2_bindir
+
+Write-Output "Setting up SDL2 folder"
+Rename-Item $sdl2_extractdir $sdl2_root_name
+
+Write-Output "Done"
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 8ab48bc..a175531 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -15,9 +15,14 @@ jobs:
       fail-fast: false
       matrix:
         platform:
-        - { name: Windows (mingw32),      os: windows-latest, shell: 'msys2 {0}', msystem: mingw32, msys-env: mingw-w64-i686 }
-        - { name: Windows (mingw64),      os: windows-latest, shell: 'msys2 {0}', msystem: mingw64, msys-env: mingw-w64-x86_64 }
-        - { name: Linux (autotools),      os: ubuntu-20.04,   shell: sh }
+        - { name: Windows (MSVC+CMake),         os: windows-latest, shell: sh,   cmake: '-GNinja', msvc: 1, shared: 1, static: 0 }
+        - { name: Windows (mingw32+autotools),  os: windows-latest, shell: 'msys2 {0}', msystem: mingw32, msys-env: mingw-w64-i686, shared: 1, static: 1 }
+        - { name: Windows (mingw64+CMake),      os: windows-latest, shell: 'msys2 {0}', msystem: mingw64, msys-env: mingw-w64-x86_64, cmake: '-G "Ninja Multi-Config"', shared: 1, static: 0 }
+        - { name: Linux (autotools),            os: ubuntu-20.04,   shell: sh , shared: 1, static: 1 }
+        - { name: Linux (CMake),                os: ubuntu-20.04,   shell: sh,   cmake: '-GNinja', shared: 1, static: 0 }
+        - { name: 'Linux (CMake, static)',      os: ubuntu-20.04,   shell: sh,   cmake: '-DBUILD_SHARED_LIBS=OFF -GNinja', shared: 0, static: 1 }
+        - { name: macOS (autotools),            os: macos-latest,   shell: sh, shared: 1, static: 1 }
+        - { name: macOS (CMake),                os: macos-latest,   shell: sh,   cmake: '-GNinja', shared: 1, static: 0 }
 
     steps:
     - name: Set up MSYS2
@@ -28,9 +33,22 @@ jobs:
         install: >-
           ${{ matrix.platform.msys-env }}-SDL2
           ${{ matrix.platform.msys-env }}-autotools
+          ${{ matrix.platform.msys-env }}-cmake
           ${{ matrix.platform.msys-env }}-gcc
+          ${{ matrix.platform.msys-env }}-ninja
           ${{ matrix.platform.msys-env }}-pkg-config
 
+    - name: Setup macOS dependencies
+      if: runner.os == 'macOS'
+      run: |
+          brew install \
+            autoconf \
+            automake \
+            ninja \
+            pkg-config \
+            sdl2 \
+            ${NULL+}
+
     - name: Setup Linux dependencies
       if: runner.os == 'Linux'
       run: |
@@ -38,36 +56,100 @@ jobs:
         sudo apt-get -y install \
           autoconf \
           automake \
+          cmake \
           libsdl2-dev \
+          ninja-build \
           pkg-config \
           ${NULL+}
+
     - uses: actions/checkout@v2
 
+    - name: Setup MSVC dependencies
+      if: "matrix.platform.msvc"
+      shell: pwsh
+      run: |
+        .github/fetch_sdl_vc.ps1
+        echo "SDL2_DIR=$Env:GITHUB_WORKSPACE/SDL2-devel-VC" >> $Env:GITHUB_ENV
+    - name: Setup Ninja for MSVC
+      if: "matrix.platform.msvc"
+      uses: ashutoshvarma/setup-ninja@master
+      with:
+        version: 1.10.2
+    - uses: ilammy/msvc-dev-cmd@v1
+      if: "matrix.platform.msvc"
+      with:
+        arch: x64
+
     - name: Check that versioning is consistent
+      # We only need to run this once: arbitrarily use the Linux/CMake build
+      if: "runner.os == 'Linux' && matrix.platform.cmake"
       run: ./test-versioning.sh
 
-    - name: Configure Autotools
+    - name: Configure (CMake)
+      if: "matrix.platform.cmake"
       run: |
         set -eu
+        cmake -S . \
+          -B build-cmake \
+          -DBUILD_SHARED_LIBS=ON \
+          -DCMAKE_BUILD_TYPE=Release \
+          -DCMAKE_INSTALL_PREFIX=prefix_cmake \
+          -DSDL2NET_SHOWINTERFACES=ON \
+          ${{ matrix.platform.cmake }}
+
+    - name: Build (CMake)
+      if: "matrix.platform.cmake"
+      run: cmake --build build-cmake/ --config Release --parallel --verbose
+
+    - name: Install (CMake)
+      if: "matrix.platform.cmake"
+      run: |
+        set -eu
+        rm -rf prefix_cmake
+        cmake --install build-cmake/ --config Release --verbose
+        echo "SDL2_net_DIR=$(pwd)/prefix_cmake" >> $GITHUB_ENV
+        ( cd prefix_cmake; find . ) | LC_ALL=C sort -u
+
+    - name: Configure (Autotools)
+      if: "! matrix.platform.cmake"
+      run: |
+        set -eu
+        rm -fr build-autotools
+        mkdir build-autotools
         ./autogen.sh
-        ./configure
-    - name: Build with Autotools
+        set -- --prefix=$(pwd)/prefix_autotools
+        ( cd build-autotools && ../configure "$@" )
+
+    - name: Build (Autotools)
+      if: "! matrix.platform.cmake"
       run: |
         set -eu
         parallel="$(getconf _NPROCESSORS_ONLN)"
-        make -j"${parallel}" V=1
-    - name: Install with Autotools
+        make -j"${parallel}" -C build-autotools V=1
+
+    - name: Install (Autotools)
+      if: "! matrix.platform.cmake"
       run: |
         set -eu
         curdir="$(pwd)"
         parallel="$(getconf _NPROCESSORS_ONLN)"
-        rm -fr DESTDIR-autotools
-        mkdir DESTDIR-autotools
-        make -j"${parallel}" install DESTDIR="${curdir}/DESTDIR-autotools" V=1
-        ( cd DESTDIR-autotools; find ) | LC_ALL=C sort -u
-    - name: Distcheck with Autotools
-      if: "runner.os == 'Linux'"
+        rm -rf prefix_autotools
+        make -j"${parallel}" -C build-autotools install V=1
+        echo "SDL2_net_DIR=$(pwd)/prefix_autotools" >> $GITHUB_ENV
+        ( cd prefix_autotools; find . ) | LC_ALL=C sort -u
+
+    - name: Distcheck (Autotools)
+      if: "runner.os == 'Linux' && ! matrix.platform.cmake"
       run: |
         set -eu
         parallel="$(getconf _NPROCESSORS_ONLN)"
-        make -j"${parallel}" distcheck V=1
+        make -j"${parallel}" -C build-autotools distcheck V=1
+
+    - name: Verify CMake configuration files
+      run: |
+        cmake -S cmake/test -B cmake_config_build \
+          -DCMAKE_BUILD_TYPE=Release \
+          -DCMAKE_PREFIX_PATH="${{ env.SDL2_net_DIR }};${{ env.SDL2_DIR }}" \
+          -DTEST_SHARED=${{ matrix.platform.shared }} \
+          -DTEST_STATIC=${{ matrix.platform.static }}
+        cmake --build cmake_config_build --verbose
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..18cabd9
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,236 @@
+cmake_minimum_required(VERSION 3.16)
+
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
+
+# See release_checklist.md
+set(MAJOR_VERSION 2)
+set(MINOR_VERSION 1)
+set(MICRO_VERSION 0)
+set(SDL_REQUIRED_VERSION 2.0.0)
+
+set(DYLIB_COMPATIBILITY_VERSION "1")
+
+include(PrivateSdlFunctions)
+sdl_calculate_derived_version_variables()
+
+if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
+    message(FATAL_ERROR "Prevented in-tree built. Please create a build directory outside of the SDL_net source code and call cmake from there")
+endif()
+
+project(SDL2_net
+    LANGUAGES C
+    VERSION "${FULL_VERSION}"
+)
+
+# Set defaults preventing destination file conflicts
+set(SDL2NET_DEBUG_POSTFIX "d"
+    CACHE STRING "Name suffix for debug builds")
+mark_as_advanced(SDL2NET_DEBUG_POSTFIX)
+
+include(CMakePackageConfigHelpers)
+include(GNUInstallDirs)
+
+option(CMAKE_POSITION_INDEPENDENT_CODE "Build static libraries with -fPIC" ON)
+option(BUILD_SHARED_LIBS "Build the library as a shared library" ON)
+
+option(SDL2NET_INSTALL "Enable SDL2_net install target" ON)
+option(SDL2NET_SHOWINTERFACES "Build the showinterfaces test program" OFF)
+
+# Save BUILD_SHARED_LIBS variable
+set(SDL2NET_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})
+
+if(SDL2NET_BUILD_SHARED_LIBS)
+    set(sdl2_net_export_name SDL2_net)
+    set(sdl2_net_install_name_infix shared)
+    set(sdl2_target_name SDL2::SDL2)
+else()
+    set(sdl2_net_export_name SDL2_net-static)
+    set(sdl2_net_install_name_infix static)
+    set(sdl2_target_name SDL2::SDL2-static)
+endif()
+
+sdl_find_sdl2(${sdl2_target_name} ${SDL_REQUIRED_VERSION})
+
+add_library(SDL2_net
+    SDLnet.c
+    SDLnetselect.c
+    SDLnetTCP.c
+    SDLnetUDP.c
+)
+add_library(SDL2_net::${sdl2_net_export_name} ALIAS SDL2_net)
+target_include_directories(SDL2_net PUBLIC
+    "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
+    "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/SDL2>"
+)
+target_compile_definitions(SDL2_net PRIVATE
+    BUILD_SDL
+    SDL_BUILD_MAJOR_VERSION=${MAJOR_VERSION}
+    SDL_BUILD_MINOR_VERSION=${MINOR_VERSION}
+    SDL_BUILD_MICRO_VERSION=${MICRO_VERSION}
+)
+target_link_libraries(SDL2_net PRIVATE $<BUILD_INTERFACE:${sdl2_target_name}>)
+if(WIN32)
+    if (MSVC)
+        target_compile_options(SDL2_net PRIVATE /W3 /wd4244)
+    endif()
+    target_compile_definitions(SDL2_net PRIVATE _WINSOCK_DEPRECATED_NO_WARNINGS)
+    target_link_libraries(SDL2_net PRIVATE ws2_32 iphlpapi)
+    if(SDL2NET_BUILD_SHARED_LIBS)
+        target_sources(SDL2_net PRIVATE version.rc)
+    endif()
+endif()
+set_target_properties(SDL2_net PROPERTIES
+    DEFINE_SYMBOL DLL_EXPORT
+    PUBLIC_HEADER SDL_net.h
+    EXPORT_NAME ${sdl2_net_export_name}
+    C_VISIBILITY_PRESET "hidden"
+)
+if(NOT ANDROID)
+    set_target_properties(SDL2_net PROPERTIES
+        DEBUG_POSTFIX "${SDL2NET_DEBUG_POSTFIX}"
+    )
+    if(APPLE)
+        # the SOVERSION property corresponds to the compatibility version and VERSION corresponds to the current version
+        # https://cmake.org/cmake/help/latest/prop_tgt/SOVERSION.html#mach-o-versions
+        set_target_properties(SDL2_net PROPERTIES
+            SOVERSION "${DYLIB_COMPATIBILITY_VERSION}"
+            VERSION "${DYLIB_CURRENT_VERSION}"
+        )
+    else()
+        set_target_properties(SDL2_net PROPERTIES
+            SOVERSION "${LT_MAJOR}"
+            VERSION "${LT_VERSION}"
+        )
+    endif()
+endif()
+if(SDL2NET_BUILD_SHARED_LIBS AND (APPLE OR (UNIX AND NOT ANDROID)))
+    add_custom_command(TARGET SDL2_net POST_BUILD
+        COMMAND "${CMAKE_COMMAND}" -E create_symlink "$<TARGET_SONAME_FILE_NAME:SDL2_net>" "libSDL2_net$<$<CONFIG:Debug>:${SDL2NET_DEBUG_POSTFIX}>$<TARGET_FILE_SUFFIX:SDL2_net>"
+        WORKING_DIRECTORY "${PROJECT_BINARY_DIR}"
+    )
+endif()
+if(SDL2NET_BUILD_SHARED_LIBS)
+    if(WIN32 OR OS2)
+        set_target_properties(SDL2_net PROPERTIES
+            PREFIX ""
+        )
+    endif()
+    if(OS2)
+        # FIXME: OS/2 Makefile has a different LIBNAME
+        set_target_properties(SDL2_net PROPERTIES
+            OUTPUT_NAME "SDL2net"
+        )
+    elseif(UNIX AND NOT ANDROID)
+        set_target_properties(SDL2_net PROPERTIES
+            OUTPUT_NAME "SDL2_net-${LT_RELEASE}"
+        )
+    endif()
+else()
+    if(MSVC OR (WATCOM AND (WIN32 OR OS2)))
+        set_target_properties(SDL2_net PROPERTIES
+            OUTPUT_NAME "SDL2_net-static"
+        )
+    endif()
+endif()
+
+# Use `Compatible Interface Properties` to ensure a shared SDL2_net is built with a shared SDL2
+if(SDL2NET_BUILD_SHARED_LIBS)
+    set_target_properties(SDL2_net PROPERTIES 
+        INTERFACE_SDL2_SHARED ${SDL2NET_BUILD_SHARED_LIBS}
+        COMPATIBLE_INTERFACE_BOOL SDL2_SHARED
+    )
+endif()
+
+if(SDL2NET_BUILD_SHARED_LIBS)
+    sdl_target_link_options_no_undefined(SDL2_net)
+endif()
+
+if(SDL2NET_INSTALL)
+    install(
+        TARGETS SDL2_net
+        EXPORT SDL2NetExports
+        ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel
+        LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT library
+        RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT library
+        PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/SDL2" COMPONENT devel
+    )
+
+    if(WIN32 AND NOT MINGW)
+        set(PKG_PREFIX "cmake")
+    else()
+        set(PKG_PREFIX "${CMAKE_INSTALL_LIBDIR}/cmake/SDL2_net")
+    endif()
+
+    configure_package_config_file(SDL2_netConfig.cmake.in SDL2_netConfig.cmake
+        INSTALL_DESTINATION "${PKG_PREFIX}"
+    )
+    write_basic_package_version_file("${PROJECT_BINARY_DIR}/SDL2_netConfigVersion.cmake"
+        VERSION ${FULL_VERSION}
+        COMPATIBILITY AnyNewerVersion
+    )
+    install(
+        FILES
+            "${CMAKE_CURRENT_BINARY_DIR}/SDL2_netConfig.cmake"
+            "${CMAKE_CURRENT_BINARY_DIR}/SDL2_netConfigVersion.cmake"
+        DESTINATION "${PKG_PREFIX}"
+        COMPONENT devel
+    )
+    install(EXPORT SDL2NetExports
+        FILE SDL2_net-${sdl2_net_install_name_infix}-targets.cmake
+        NAMESPACE SDL2_net::
+        DESTINATION "${PKG_PREFIX}"
+        COMPONENT devel
+    )
+
+    if(SDL2NET_BUILD_SHARED_LIBS)
+        # Only create a .pc file for a shared SDL2_net
+        set(prefix "${CMAKE_INSTALL_PREFIX}")
+        set(exec_prefix "\${prefix}")
+        set(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
+        set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
+        set(PACKAGE "${PROJECT_NAME}")
+        set(VERSION "${FULL_VERSION}")
+        set(SDL_VERSION "${SDL_REQUIRED_VERSION}")
+        string(JOIN " " PC_REQUIRES ${PC_REQUIRES})
+        string(JOIN " " PC_LIBS ${PC_LIBS})
+        configure_file("${PROJECT_SOURCE_DIR}/SDL2_net.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/SDL2_net.pc.intermediate" @ONLY)
+        file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/SDL2_net-$<CONFIG>.pc" INPUT "${CMAKE_CURRENT_BINARY_DIR}/SDL2_net.pc.intermediate")
+
+        set(PC_DESTDIR)
+        if(CMAKE_SYSTEM_NAME MATCHES FreeBSD)
+            # FreeBSD uses ${PREFIX}/libdata/pkgconfig
+            set(PC_DESTDIR "libdata/pkgconfig")
+        else()
+            set(PC_DESTDIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
+        endif()
+        # Only install a SDL2_net.pc file in Release mode
+        install(CODE "
+            # FIXME: use file(COPY_FILE) if minimum CMake version >= 3.21
+            execute_process(COMMAND \"\${CMAKE_COMMAND}\" -E copy_if_different
+                \"${CMAKE_CURRENT_BINARY_DIR}/SDL2_net-$<CONFIG>.pc\"
+                \"${CMAKE_CURRENT_BINARY_DIR}/SDL2_net.pc\")
+            file(INSTALL DESTINATION \"\${CMAKE_INSTALL_PREFIX}/${PC_DESTDIR}\"
+                TYPE FILE
+                FILES \"${CMAKE_CURRENT_BINARY_DIR}/SDL2_net.pc\")" CONFIG Release COMPONENT devel)
+    endif()
+
+    if(SDL2NET_BUILD_SHARED_LIBS AND (APPLE OR (UNIX AND NOT ANDROID)))
+        install(
+            FILES
+                "${PROJECT_BINARY_DIR}/libSDL2_net$<$<CONFIG:Debug>:${SDL2NET_DEBUG_POSTFIX}>$<TARGET_FILE_SUFFIX:SDL2_net>"
+            DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+            COMPONENT devel
+        )
+    endif()
+
+    install(FILES "COPYING.txt"
+        DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/licenses/${PROJECT_NAME}"
+        COMPONENT library
+    )
+endif()
+
+if(SDL2NET_SHOWINTERFACES)
+    add_executable(showinterfaces showinterfaces.c)
+    target_compile_definitions(showinterfaces PRIVATE SDL_MAIN_HANDLED)
+    target_link_libraries(showinterfaces PRIVATE SDL2_net::${sdl2_net_export_name} ${sdl2_target_name})
+endif()
diff --git a/Makefile.am b/Makefile.am
index b5324f2..3dc0ee5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -28,7 +28,10 @@ EXTRA_DIST = CHANGES.txt COPYING.txt README.txt \
 	scroll_up.bmp		\
 	SDL2_net.spec		\
 	SDL2_net.spec.in	\
-	autogen.sh
+	autogen.sh	\
+	CMakeLists.txt	\
+	cmake	\
+	SDL2_netConfig.cmake.in
 
 libSDL2_net_la_LDFLAGS = 	\
 	-no-undefined		\
@@ -65,3 +68,13 @@ rpm: $(PACKAGE)-$(VERSION).tar.gz
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = SDL2_net.pc
+
+install-data-local:
+	$(MKDIR_P) $(DESTDIR)$(libdir)/cmake/SDL2_net
+	$(INSTALL) -m 644 sdl2_net-config.cmake $(DESTDIR)$(libdir)/cmake/SDL2_net
+	$(INSTALL) -m 644 sdl2_net-config-version.cmake $(DESTDIR)$(libdir)/cmake/SDL2_net
+
+uninstall-hook:
+	rm $(DESTDIR)$(libdir)/cmake/SDL2_net/sdl2_net-config.cmake
+	rm $(DESTDIR)$(libdir)/cmake/SDL2_net/sdl2_net-config-version.cmake
+	rm -r $(DESTDIR)$(libdir)/cmake/SDL2_net
diff --git a/Makefile.in b/Makefile.in
index 7613125..66cfd0b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -110,7 +110,8 @@ DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
 am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
  configure.lineno config.status.lineno
 mkinstalldirs = $(install_sh) -d
-CONFIG_CLEAN_FILES = SDL2_net.spec SDL2_net.pc
+CONFIG_CLEAN_FILES = sdl2_net-config.cmake \
+	sdl2_net-config-version.cmake SDL2_net.spec SDL2_net.pc
 CONFIG_CLEAN_VPATH_FILES =
 @HAVE_GUI_LIB_FALSE@am__EXEEXT_1 = showinterfaces$(EXEEXT)
 @HAVE_GUI_LIB_TRUE@am__EXEEXT_1 = showinterfaces$(EXEEXT) \
@@ -252,8 +253,10 @@ am__define_uniq_tagged_files = \
   done | $(am__uniquify_input)`
 AM_RECURSIVE_TARGETS = cscope
 am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/SDL2_net.pc.in \
-	$(srcdir)/SDL2_net.spec.in compile config.guess config.sub \
-	depcomp install-sh ltmain.sh missing
+	$(srcdir)/SDL2_net.spec.in \
+	$(srcdir)/sdl2_net-config-version.cmake.in \
+	$(srcdir)/sdl2_net-config.cmake.in compile config.guess \
+	config.sub depcomp install-sh ltmain.sh missing
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 distdir = $(PACKAGE)-$(VERSION)
 top_distdir = $(distdir)
@@ -383,6 +386,7 @@ build_cpu = @build_cpu@
 build_os = @build_os@
 build_vendor = @build_vendor@
 builddir = @builddir@
+cmake_prefix_relpath = @cmake_prefix_relpath@
 datadir = @datadir@
 datarootdir = @datarootdir@
 docdir = @docdir@
@@ -447,7 +451,10 @@ EXTRA_DIST = CHANGES.txt COPYING.txt README.txt \
 	scroll_up.bmp		\
 	SDL2_net.spec		\
 	SDL2_net.spec.in	\
-	autogen.sh
+	autogen.sh	\
+	CMakeLists.txt	\
+	cmake	\
+	SDL2_netConfig.cmake.in
 
 libSDL2_net_la_LDFLAGS = \
 	-no-undefined		\
@@ -503,6 +510,10 @@ $(top_srcdir)/configure:  $(am__configure_deps)
 $(ACLOCAL_M4):  $(am__aclocal_m4_deps)
 	$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
 $(am__aclocal_m4_deps):
+sdl2_net-config.cmake: $(top_builddir)/config.status $(srcdir)/sdl2_net-config.cmake.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
+sdl2_net-config-version.cmake: $(top_builddir)/config.status $(srcdir)/sdl2_net-config-version.cmake.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
 SDL2_net.spec: $(top_builddir)/config.status $(srcdir)/SDL2_net.spec.in
 	cd $(top_builddir) && $(SHELL) ./config.status $@
 SDL2_net.pc: $(top_builddir)/config.status $(srcdir)/SDL2_net.pc.in
@@ -588,43 +599,49 @@ $(am__depfiles_remade):
 am--depfiles: $(am__depfiles_remade)
 
 .c.o:
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
 
 .c.obj:
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
 
 .c.lo:
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
 
 .cpp.o:
-@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCXX_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
 
 .cpp.obj:
-@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCXX_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
 
 .cpp.lo:
-@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCXX_TRUE@	$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCXX_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
@@ -977,7 +994,7 @@ info: info-am
 
 info-am:
 
-install-data-am: install-libSDL2_netincludeHEADERS \
+install-data-am: install-data-local install-libSDL2_netincludeHEADERS \
 	install-pkgconfigDATA
 
 install-dvi: install-dvi-am
@@ -1034,8 +1051,9 @@ ps-am:
 
 uninstall-am: uninstall-libLTLIBRARIES \
 	uninstall-libSDL2_netincludeHEADERS uninstall-pkgconfigDATA
-
-.MAKE: install-am install-strip
+	@$(NORMAL_INSTALL)
+	$(MAKE) $(AM_MAKEFLAGS) uninstall-hook
+.MAKE: install-am install-strip uninstall-am
 
 .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles am--refresh check \
 	check-am clean clean-cscope clean-generic clean-libLTLIBRARIES \
@@ -1045,16 +1063,17 @@ uninstall-am: uninstall-libLTLIBRARIES \
 	distclean distclean-compile distclean-generic \
 	distclean-libtool distclean-tags distcleancheck distdir \
 	distuninstallcheck dvi dvi-am html html-am info info-am \
-	install install-am install-data install-data-am install-dvi \
-	install-dvi-am install-exec install-exec-am install-html \
-	install-html-am install-info install-info-am \
-	install-libLTLIBRARIES install-libSDL2_netincludeHEADERS \
-	install-man install-pdf install-pdf-am install-pkgconfigDATA \
-	install-ps install-ps-am install-strip installcheck \
-	installcheck-am installdirs maintainer-clean \
-	maintainer-clean-generic mostlyclean mostlyclean-compile \
-	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-	tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES \
+	install install-am install-data install-data-am \
+	install-data-local install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-libLTLIBRARIES \
+	install-libSDL2_netincludeHEADERS install-man install-pdf \
+	install-pdf-am install-pkgconfigDATA install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \
+	uninstall-hook uninstall-libLTLIBRARIES \
 	uninstall-libSDL2_netincludeHEADERS uninstall-pkgconfigDATA
 
 .PRECIOUS: Makefile
@@ -1070,6 +1089,16 @@ $(PACKAGE)-$(VERSION).tar.gz: distcheck
 rpm: $(PACKAGE)-$(VERSION).tar.gz
 	rpmbuild -ta $(PACKAGE)-$(VERSION).tar.gz
 
+install-data-local:
+	$(MKDIR_P) $(DESTDIR)$(libdir)/cmake/SDL2_net
+	$

(Patch may be truncated, please check the link at the top of this post.)