From f8a578178560452aaafa18eb875903b1b8ee45cf Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Sat, 9 May 2026 23:31:18 -0400
Subject: [PATCH] stub: Add a stub library option.
Now you can link against a library that has all of SDL_net's functions, but
all those functions will fail.
This is useful to build something for a platform that doesn't have real
network sockets at the moment, like MS-DOS or Emscripten, without having to
sprinkle `#ifdef` all over your code.
Fixes #160.
---
CMakeLists.txt | 14 +++++++++-
src/SDL_net_stub_only.c | 58 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 71 insertions(+), 1 deletion(-)
create mode 100644 src/SDL_net_stub_only.c
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 07c96f16..ec0c8fa6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -104,7 +104,19 @@ endif()
set(PC_LIBS)
set(PC_REQUIRES)
-add_library(${sdl3_net_target_name} src/SDL_net.c)
+set(PLATFORM_UNSUPPORTED False)
+if (DOS OR EMSCRIPTEN) # These either don't have networking at all, or have needs we don't currently meet.
+ set(PLATFORM_UNSUPPORTED True)
+endif()
+
+option(SDLNET_STUB_ONLY "Build a stub library that does nothing" ${PLATFORM_UNSUPPORTED})
+if(SDLNET_STUB_ONLY)
+ message(WARNING "Only building a stub library. The functions will be there but all of them will fail!")
+ add_library(${sdl3_net_target_name} src/SDL_net_stub_only.c)
+else()
+ add_library(${sdl3_net_target_name} src/SDL_net.c)
+endif()
+
add_library(SDL3_net::${sdl3_net_target_name} ALIAS ${sdl3_net_target_name})
if("c_std_99" IN_LIST CMAKE_C_COMPILE_FEATURES)
target_compile_features(${sdl3_net_target_name} PRIVATE c_std_99)
diff --git a/src/SDL_net_stub_only.c b/src/SDL_net_stub_only.c
new file mode 100644
index 00000000..04294f4d
--- /dev/null
+++ b/src/SDL_net_stub_only.c
@@ -0,0 +1,58 @@
+/*
+ SDL_net: A simple networking library for use with SDL
+ Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "SDL3_net/SDL_net.h"
+
+// don't do anything. Sorry!
+int NET_Version(void) { return SDL_NET_VERSION; }
+bool NET_Init(void) { return true; }
+void NET_Quit(void) {}
+NET_Address * NET_ResolveHostname(const char *host) { SDL_Unsupported(); return NULL; }
+NET_Status NET_WaitUntilResolved(NET_Address *address, Sint32 timeout) { SDL_Unsupported(); return NET_FAILURE; }
+NET_Status NET_GetAddressStatus(NET_Address *address) { SDL_Unsupported(); return NET_FAILURE; }
+const char * NET_GetAddressString(NET_Address *address) { SDL_Unsupported(); return NULL; }
+NET_Address *NET_RefAddress(NET_Address *address) { SDL_Unsupported(); return NULL; }
+void NET_UnrefAddress(NET_Address *address) {}
+void NET_SimulateAddressResolutionLoss(int percent_loss) {}
+int NET_CompareAddresses(const NET_Address *a, const NET_Address *b) { return 0; }
+NET_Address **NET_GetLocalAddresses(int *num_addresses) { SDL_Unsupported(); return NULL; }
+void NET_FreeLocalAddresses(NET_Address **addresses) {}
+NET_StreamSocket * NET_CreateClient(NET_Address *address, Uint16 port) { SDL_Unsupported(); return NULL; }
+NET_Status NET_WaitUntilConnected(NET_StreamSocket *sock, Sint32 timeout) { SDL_Unsupported(); return NET_FAILURE; }
+NET_Server * NET_CreateServer(NET_Address *addr, Uint16 port) { SDL_Unsupported(); return NULL; }
+bool NET_AcceptClient(NET_Server *server, NET_StreamSocket **client_stream) { SDL_Unsupported(); return false; }
+void NET_DestroyServer(NET_Server *server) {}
+NET_Address * NET_GetStreamSocketAddress(NET_StreamSocket *sock) { SDL_Unsupported(); return NULL; }
+NET_Status NET_GetConnectionStatus(NET_StreamSocket *sock) { SDL_Unsupported(); return NET_FAILURE; }
+bool NET_WriteToStreamSocket(NET_StreamSocket *sock, const void *buf, int buflen) { SDL_Unsupported(); return false; }
+int NET_GetStreamSocketPendingWrites(NET_StreamSocket *sock) { SDL_Unsupported(); return -1; }
+int NET_WaitUntilStreamSocketDrained(NET_StreamSocket *sock, Sint32 timeout) { SDL_Unsupported(); return -1; }
+int NET_ReadFromStreamSocket(NET_StreamSocket *sock, void *buf, int buflen) { SDL_Unsupported(); return -1; }
+void NET_SimulateStreamPacketLoss(NET_StreamSocket *sock, int percent_loss) {}
+void NET_DestroyStreamSocket(NET_StreamSocket *sock) {}
+NET_DatagramSocket * NET_CreateDatagramSocket(NET_Address *addr, Uint16 port) { SDL_Unsupported(); return NULL; }
+bool NET_SendDatagram(NET_DatagramSocket *sock, NET_Address *address, Uint16 port, const void *buf, int buflen) { SDL_Unsupported(); return false; }
+bool NET_ReceiveDatagram(NET_DatagramSocket *sock, NET_Datagram **dgram) { SDL_Unsupported(); return false; }
+void NET_DestroyDatagram(NET_Datagram *dgram) {}
+void NET_SimulateDatagramPacketLoss(NET_DatagramSocket *sock, int percent_loss) {}
+void NET_DestroyDatagramSocket(NET_DatagramSocket *sock) {}
+int NET_WaitUntilInputAvailable(void **vsockets, int numsockets, Sint32 timeout) { SDL_Unsupported(); return -1; }
+