SDL: Make iOS/tvOS (uikit) SDL_main header-only

From 8e0693c982c40e282da864b6fc7af51cdf855926 Mon Sep 17 00:00:00 2001
From: Daniel Gibson <[EMAIL REDACTED]>
Date: Sun, 11 Dec 2022 05:08:15 +0100
Subject: [PATCH] Make iOS/tvOS (uikit) SDL_main header-only

Also adjusted iOS demo's includes to <SDL3/..> and explicit SDL_main.h

untested, I don't have Xcode (or a Mac, for that matter)

The xcode projects (for both Xcode-iOS/ and Xcode/) will probably
have to be adjusted for the SDL_main changes to work, but now at least
the iOS demo source should work as is :)
---
 Xcode-iOS/Demos/src/accelerometer.c |  3 ++-
 Xcode-iOS/Demos/src/common.c        |  2 +-
 Xcode-iOS/Demos/src/fireworks.c     |  5 +++--
 Xcode-iOS/Demos/src/happy.c         |  3 ++-
 Xcode-iOS/Demos/src/keyboard.c      |  3 ++-
 Xcode-iOS/Demos/src/mixer.c         |  3 ++-
 Xcode-iOS/Demos/src/rectangles.c    |  3 ++-
 Xcode-iOS/Demos/src/touch.c         |  3 ++-
 docs/README-ios.md                  | 23 ++++++----------------
 include/SDL3/SDL_main.h             |  8 ++++----
 include/SDL3/SDL_main_impl.h        | 30 ++++++++++++++++++++++++++++-
 src/main/uikit/SDL_uikit_main.c     | 20 +++----------------
 12 files changed, 58 insertions(+), 48 deletions(-)

diff --git a/Xcode-iOS/Demos/src/accelerometer.c b/Xcode-iOS/Demos/src/accelerometer.c
index 543a7b37f4cb..6231a72500b6 100644
--- a/Xcode-iOS/Demos/src/accelerometer.c
+++ b/Xcode-iOS/Demos/src/accelerometer.c
@@ -4,7 +4,8 @@
  *  use however you want
  */
 
-#include "SDL.h"
+#include <SDL3/SDL.h>
+#include <SDL3/SDL_main.h>
 #include <math.h>
 #include "common.h"
 
diff --git a/Xcode-iOS/Demos/src/common.c b/Xcode-iOS/Demos/src/common.c
index e15fb5ff1968..6baaa39b4e1c 100644
--- a/Xcode-iOS/Demos/src/common.c
+++ b/Xcode-iOS/Demos/src/common.c
@@ -5,7 +5,7 @@
  */
 
 #include "common.h"
-#include "SDL.h"
+#include <SDL3/SDL.h>
 #include <stdlib.h>
 
 /*
diff --git a/Xcode-iOS/Demos/src/fireworks.c b/Xcode-iOS/Demos/src/fireworks.c
index 43427b49e455..1f1282bedc88 100644
--- a/Xcode-iOS/Demos/src/fireworks.c
+++ b/Xcode-iOS/Demos/src/fireworks.c
@@ -4,8 +4,9 @@
  *  use however you want
  */
 
-#include "SDL.h"
-#include "SDL_opengles.h"
+#include <SDL3/SDL.h>
+#include <SDL3/SDL_main.h>
+#include <SDL3/SDL_opengles.h>
 #include "common.h"
 #include <math.h>
 #include <time.h>
diff --git a/Xcode-iOS/Demos/src/happy.c b/Xcode-iOS/Demos/src/happy.c
index 1bf183e15f26..197a1c6f269b 100644
--- a/Xcode-iOS/Demos/src/happy.c
+++ b/Xcode-iOS/Demos/src/happy.c
@@ -4,7 +4,8 @@
  *  use however you want
  */
 
-#include "SDL.h"
+#include <SDL3/SDL.h>
+#include <SDL3/SDL_main.h>
 #include "common.h"
 
 #define NUM_HAPPY_FACES 100     /* number of faces to draw */
diff --git a/Xcode-iOS/Demos/src/keyboard.c b/Xcode-iOS/Demos/src/keyboard.c
index 2439aa59a93a..2d243d53dca6 100644
--- a/Xcode-iOS/Demos/src/keyboard.c
+++ b/Xcode-iOS/Demos/src/keyboard.c
@@ -4,7 +4,8 @@
  *  use however you want
  */
 
-#include "SDL.h"
+#include <SDL3/SDL.h>
+#include <SDL3/SDL_main.h>
 #include "common.h"
 
 #define TEST_INPUT_RECT
diff --git a/Xcode-iOS/Demos/src/mixer.c b/Xcode-iOS/Demos/src/mixer.c
index 2ea1b861a0ea..642602c76449 100644
--- a/Xcode-iOS/Demos/src/mixer.c
+++ b/Xcode-iOS/Demos/src/mixer.c
@@ -4,7 +4,8 @@
  *  use however you want
  */
 
-#include "SDL.h"
+#include <SDL3/SDL.h>
+#include <SDL3/SDL_main.h>
 #include "common.h"
 
 #define NUM_CHANNELS 8          /* max number of sounds we can play at once */
diff --git a/Xcode-iOS/Demos/src/rectangles.c b/Xcode-iOS/Demos/src/rectangles.c
index 0f6cac95795d..a43914338ab5 100644
--- a/Xcode-iOS/Demos/src/rectangles.c
+++ b/Xcode-iOS/Demos/src/rectangles.c
@@ -4,7 +4,8 @@
  *  use however you want
 */
 
-#include "SDL.h"
+#include <SDL3/SDL.h>
+#include <SDL3/SDL_main.h>
 #include <time.h>
 #include "common.h"
 
diff --git a/Xcode-iOS/Demos/src/touch.c b/Xcode-iOS/Demos/src/touch.c
index 7c81390df97c..67459f41467f 100644
--- a/Xcode-iOS/Demos/src/touch.c
+++ b/Xcode-iOS/Demos/src/touch.c
@@ -4,7 +4,8 @@
  *  use however you want
  */
 
-#include "SDL.h"
+#include <SDL3/SDL.h>
+#include <SDL3/SDL_main.h>
 #include <math.h>
 #include "common.h"
 
diff --git a/docs/README-ios.md b/docs/README-ios.md
index 8e81f75bc18c..1575888579fa 100644
--- a/docs/README-ios.md
+++ b/docs/README-ios.md
@@ -22,10 +22,9 @@ Using the Simple DirectMedia Layer for iOS
 5. Select the project in the main view, go to the "Build Settings" tab, select "All", and edit "Header Search Path" and drag over the SDL "Public Headers" folder from the left
 6. Select the project in the main view, go to the "Build Phases" tab, select "Link Binary With Libraries", and add SDL3.framework from "Framework-iOS"
 7. Select the project in the main view, go to the "General" tab, scroll down to "Frameworks, Libraries, and Embedded Content", and select "Embed & Sign" for the SDL library.
-8. In the main view, expand SDL -> Library Source -> main -> uikit and drag SDL_uikit_main.c into your game files
-9. Add the source files that you would normally have for an SDL program, making sure to have #include "SDL.h" at the top of the file containing your main() function.
-10. Add any assets that your application needs.
-11. Enjoy!
+8. Add the source files that you would normally have for an SDL program, making sure to have #include "SDL.h" at the top of the file containing your main() function.
+9. Add any assets that your application needs.
+10. Enjoy!
 
 
 TODO: Add information regarding App Store requirements such as icons, etc.
@@ -202,19 +201,9 @@ The xcframework target builds into a Products directory alongside the SDL.xcodep
 
 This target requires Xcode 11 or later. The target will simply fail to build if attempted on older Xcodes.
 
-In addition, on Apple platforms, main() cannot be in a dynamically loaded library. This means that iOS apps which used the statically-linked libSDL3.lib and now link with the xcframwork will need to define their own main() to call SDL_UIKitRunApp(), like this:
-
-#ifndef SDL_MAIN_HANDLED
-#ifdef main
-#undef main
-#endif
-
-int
-main(int argc, char *argv[])
-{
-	return SDL_UIKitRunApp(argc, argv, SDL_main);
-}
-#endif /* !SDL_MAIN_HANDLED */
+In addition, on Apple platforms, main() cannot be in a dynamically loaded library.
+However, unlike in SDL2, in SDL3 SDL_main is implemented inline in SDL_main.h, so you don't need to link against a static libSDL3main.lib, and you don't need to copy a .c file from the SDL3 source either.
+This means that iOS apps which used the statically-linked libSDL3.lib and now link with the xcframwork can just `#include <SDL3/SDL3_main.h>` in the source file that contains their standard `int main(int argc; char *argv[])` function to get a header-only SDL_main implementation that calls the `SDL_UIKitRunApp()` with your standard main function.
 
 Using an xcFramework is similar to using a regular framework. However, issues have been seen with the build system not seeing the headers in the xcFramework. To remedy this, add the path to the xcFramework in your app's target ==> Build Settings ==> Framework Search Paths and mark it recursive (this is critical). Also critical is to remove "*.framework" from Build Settings ==> Sub-Directories to Exclude in Recursive Searches. Clean the build folder, and on your next build the build system should be able to see any of these in your code, as expected: 
 
diff --git a/include/SDL3/SDL_main.h b/include/SDL3/SDL_main.h
index 3a188d3aa60c..d26b866de9ea 100644
--- a/include/SDL3/SDL_main.h
+++ b/include/SDL3/SDL_main.h
@@ -65,9 +65,8 @@
 /* On iOS SDL provides a main function that creates an application delegate
    and starts the iOS application run loop.
 
-   If you link with SDL dynamically on iOS, the main function can't be in a
-   shared library, so you need to link with libSDL_main.a, which includes a
-   stub main function that calls into the shared library to start execution.
+   To use it, just #include SDL_main.h in the source file that contains your
+   main() function.
 
    See src/video/uikit/SDL_uikitappdelegate.m for more details.
  */
@@ -287,9 +286,10 @@ extern DECLSPEC void SDLCALL SDL_GDKSuspendComplete(void);
 
 #if !defined(SDL_MAIN_HANDLED) && !defined(_SDL_MAIN_NOIMPL)
 /* include header-only SDL_main implementations */
-#if defined(__WIN32__) || defined(__GDK__) /* TODO: other platforms */
+#if defined(__WIN32__) || defined(__GDK__) || defined(__IOS__) || defined(__TVOS__) /* TODO: other platforms */
 #include <SDL3/SDL_main_impl.h>
 #endif
+
 #endif /* SDL_MAIN_HANDLED */
 
 #endif /* SDL_main_h_ */
diff --git a/include/SDL3/SDL_main_impl.h b/include/SDL3/SDL_main_impl.h
index 6221e5731d90..c4646887f0a3 100644
--- a/include/SDL3/SDL_main_impl.h
+++ b/include/SDL3/SDL_main_impl.h
@@ -103,7 +103,35 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
 #define main    SDL_main
 
 /* end of __WIN32__ and __GDK__ impls */
-#elif 1 /* TODO: next platform */
+#elif defined(__IOS__) || defined(__TVOS__)
+
+#ifdef main
+#  undef main
+#endif /* main */
+
+#include <SDL3/begin_code.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int main(int argc, char *argv[])
+{
+    return SDL_UIKitRunApp(argc, argv, SDL_main);
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#include <SDL3/close_code.h>
+
+/* rename users main() function to SDL_main() so it can be called from the wrapper above */
+#define main    SDL_main
+
+/* end of __IOS__ and __TVOS__ impls */
+
+/* TODO: remaining platforms */
 
 #endif /* __WIN32__ etc */
 
diff --git a/src/main/uikit/SDL_uikit_main.c b/src/main/uikit/SDL_uikit_main.c
index 2b4b204778f4..fe418d565c94 100644
--- a/src/main/uikit/SDL_uikit_main.c
+++ b/src/main/uikit/SDL_uikit_main.c
@@ -1,22 +1,8 @@
 /*
     SDL_uikit_main.c, placed in the public domain by Sam Lantinga  3/18/2019
-*/
-#include <SDL3/SDL.h>
-#include <SDL3/SDL_main.h> /* until this SDL_main impl is converted to header-only.. */
-
-#if defined(__IOS__) || defined(__TVOS__)
-
-#ifndef SDL_MAIN_HANDLED
-#ifdef main
-#undef main
-#endif
 
-int main(int argc, char *argv[])
-{
-    return SDL_UIKitRunApp(argc, argv, SDL_main);
-}
-#endif /* !SDL_MAIN_HANDLED */
-
-#endif /* __IOS__ || __TVOS__ */
+    Nothing to do here, the code moved into SDL_main_impl.h
+    TODO: remove this file
+*/
 
 /* vi: set ts=4 sw=4 expandtab: */