Update doc/README-* for header-only SDL_main

This commit is contained in:
Daniel Gibson 2022-12-12 23:27:58 +01:00 committed by Sam Lantinga
parent c3bf253b09
commit ab554c8392
8 changed files with 38 additions and 23 deletions

View file

@ -83,8 +83,8 @@ If you already have a project that uses CMake, the instructions change somewhat:
2. Edit "<project>/app/build.gradle" to comment out or remove sections containing ndk-build
and uncomment the cmake sections. Add arguments to the CMake invocation as needed.
3. Edit "<project>/app/jni/CMakeLists.txt" to include your project (it defaults to
adding the "src" subdirectory). Note that you'll have SDL3, SDL3_main and SDL3-static
as targets in your project, so you should have "target_link_libraries(yourgame SDL3 SDL3_main)"
adding the "src" subdirectory). Note that you'll have SDL3 and SDL3-static
as targets in your project, so you should have "target_link_libraries(yourgame SDL3)"
in your CMakeLists.txt file. Also be aware that you should use add_library() instead of
add_executable() for the target containing your "main" function.

View file

@ -59,20 +59,11 @@ if(MYGAME_VENDORED)
else()
# 1. Look for a SDL3 package, 2. look for the SDL3 component and 3. fail if none can be found
find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3)
# 1. Look for a SDL3 package, 2. Look for the SDL3_maincomponent and 3. DO NOT fail when SDL3_main is not available
find_package(SDL3 REQUIRED CONFIG COMPONENTS SDL3_main)
endif()
# Create your game executable target as usual
add_executable(mygame WIN32 mygame.c)
# SDL3::SDL3_main may or may not be available. It is e.g. required by Windows GUI applications
if(TARGET SDL3::SDL3_main)
# It has an implicit dependency on SDL3 functions, so it MUST be added before SDL3::SDL3 (or SDL3::SDL3-static)
target_link_libraries(mygame PRIVATE SDL3::SDL3_main)
endif()
# Link to the actual SDL3 library. SDL3::SDL3 is the shared SDL library, SDL3::SDL3-static is the static SDL libarary.
target_link_libraries(mygame PRIVATE SDL3::SDL3)
```
@ -87,7 +78,6 @@ The following components are available, to be used as an argument of `find_packa
|----------------|--------------------------------------------------------------------------------------------|
| SDL3 | The SDL3 shared library, available through the `SDL3::SDL3` target [^SDL_TARGET_EXCEPTION] |
| SDL3-static | The SDL3 static library, available through the `SDL3::SDL3-static` target |
| SDL3_main | The SDL3_main static library, available through the `SDL3::SDL3_main` target |
| SDL3_test | The SDL3_test static library, available through the `SDL3::SDL3_test` target |

View file

@ -25,7 +25,7 @@ The Windows GDK port supports the full set of Win32 APIs, renderers, controllers
* Initializing/uninitializing the game runtime, and initializing Xbox Live services
* Creating a global task queue and setting it as the default for the process. When running any async operations, passing in `NULL` as the task queue will make the task get added to the global task queue.
* An implementation on `WinMain` that performs the above GDK setup that you can use by #include'ing SDL_main.h in the source file that includes your standard main() function. If you are unable to do this, you can instead manually call `SDL_GDKRunApp` from your entry point, passing in your `SDL_main` function and `NULL` as the parameters. To use `SDL_GDKRunApp`, `#define SDL_MAIN_HANDLED` before `#include <SDL3/SDL_main.h>`.
* An implementation on `WinMain` that performs the above GDK setup that you can use by #include'ing SDL_main.h in the source file that includes your standard main() function. If you are unable to do this, you can instead manually call `SDL_RunApp` from your entry point, passing in your `SDL_main` function and `NULL` as the parameters. To use `SDL_RunApp`, `#define SDL_MAIN_HANDLED` before `#include <SDL3/SDL_main.h>`.
* Global task queue callbacks are dispatched during `SDL_PumpEvents` (which is also called internally if using `SDL_PollEvent`).
* You can get the handle of the global task queue through `SDL_GDKGetTaskQueue`, if needed. When done with the queue, be sure to use `XTaskQueueCloseHandle` to decrement the reference count (otherwise it will cause a resource leak).
@ -73,7 +73,7 @@ While the Gaming.Desktop.x64 configuration sets most of the required settings, t
### 4. Setting up SDL_main ###
Rather than using your own implementation of `WinMain`, it's recommended that you instead `#include <SDL3/SDL_main.h>` and declare a standard main function. If you are unable to do this, you can instead manually call `SDL_GDKRunApp` from your entry point, passing in your `SDL_main` function and `NULL` as the parameters; in that case `#define SDL_MAIN_HANDLED` before including SDL_main.h
Rather than using your own implementation of `WinMain`, it's recommended that you instead `#include <SDL3/SDL_main.h>` and declare a standard main function. If you are unable to do this, you can instead manually call `SDL_RunApp` from your entry point, passing in your `SDL_main` function and `NULL` as the parameters; in that case `#define SDL_MAIN_HANDLED` before including SDL_main.h
### 5. Required DLLs ###

View file

@ -203,7 +203,7 @@ This target requires Xcode 11 or later. The target will simply fail to build if
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.
This means that iOS apps which used the statically-linked libSDL3.lib and now link with the xcframwork can just `#include <SDL3/SDL_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_RunApp()` 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:

View file

@ -9,10 +9,6 @@ SDL headers should now be included as `#include <SDL3/SDL.h>`. Typically that's
CMake users should use this snippet to include SDL support in their project:
```
find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3)
find_package(SDL3 REQUIRED CONFIG COMPONENTS SDL3_main)
if(TARGET SDL3::SDL3_main)
target_link_libraries(mygame PRIVATE SDL3::SDL3_main)
endif()
target_link_libraries(mygame PRIVATE SDL3::SDL3)
```
@ -28,7 +24,9 @@ CFLAGS += $(shell pkg-config sdl3 --cflags)
LDFLAGS += $(shell pkg-config sdl3 --libs)
```
The SDL3main and SDL3test libraries have been renamed SDL3_main and SDL3_test, respectively.
The SDL3test library has been renamed SDL3_test.
There is no static SDLmain library anymore, it's now header-only, see below in the SDL_main.h section.
## SDL_cpuinfo.h
@ -63,6 +61,34 @@ SDL_GetEventState used to be a macro, now it's a real function, but otherwise fu
Removed SDL_GameControllerGetSensorDataWithTimestamp(), if you want timestamps for the sensor data, you should use the sensor_timestamp member of SDL_CONTROLLERSENSORUPDATE events.
## SDL_main.h
SDL3 doesn't have a static libSDLmain to link against anymore.
Instead SDL_main.h is now a header-only library **and not included by SDL.h anymore**.
Using it is really simple: Just `#include <SDL3/SDL_main.h>` in the source file with your standard
`int main(int argc, char* argv[])` function.
The rest happens automatically: If your target platform needs the SDL_main functionality,
your `main` function will be renamed to `SDL_main` (with a macro, just like in SDL2),
and the real main-function will be implemented by inline code from SDL_main.h - and if your target
platform doesn't need it, nothing happens.
Like in SDL2, if you want to handle the platform-specific main yourself instead of using the SDL_main magic,
you can `#define SDL_MAIN_HANDLED` before `#include <SDL3/SDL_main.h>` - don't forget to call `SDL_SetMainReady()`!
If you need SDL_main.h in another source file (that doesn't implement main()), you also need to
`#define SDL_MAIN_HANDLED` there, to avoid that multiple main functions are generated by SDL_main.h
There is currently one platform where this approach doesn't always work: WinRT.
It requires WinMain to be implemented in a C++ source file that's compiled with `/ZW`. If your main
is implemented in plain C, or you can't use `/ZW` on that file, you can add another .cpp
source file that just contains `#include <SDL3/SDL_main.h>` and compile that with `/ZW` - but keep
in mind that the source file with your standard main also needs that include!
See [README-winrt.md](./README-winrt.md) for more details.
Furthermore, the different `SDL_*RunApp()` functions (SDL_WinRtRunApp, SDL_GDKRunApp, SDL_UIKitRunApp)
have been unified into just `int SDL_RunApp(int argc, char* argv[], void * reserved)` (which is also
used by additional platforms that didn't have a SDL_RunApp-like function before).
## SDL_platform.h

View file

@ -22,7 +22,7 @@ cmake --install build
## Notes
- Currently only software rendering is supported.
- SDL3_main should be used to ensure ROMFS is enabled.
- SDL3_main should be used to ensure ROMFS is enabled - this is done with `#include <SDL3/SDL_main.h>` in the source file that contains your main function.
- By default, the extra L2 cache and higher clock speeds of the New 2/3DS lineup are enabled. If you wish to turn it off, use `osSetSpeedupEnable(false)` in your main function.
- `SDL_GetBasePath` returns the romfs root instead of the executable's directory.
- The Nintendo 3DS uses a cooperative threading model on a single core, meaning a thread will never yield unless done manually through the `SDL_Delay` functions, or blocking waits (`SDL_LockMutex`, `SDL_SemWait`, `SDL_CondWait`, `SDL_WaitThread`). To avoid starving other threads, `SDL_SemTryWait` and `SDL_SemWaitTimeout` will yield if they fail to acquire the semaphore, see https://github.com/libsdl-org/SDL/pull/6776 for more information.

View file

@ -49,7 +49,6 @@ There are two basic ways of building SDL at the moment:
src/video/dummy/*.c
src/haptic/dummy/*.c
src/joystick/dummy/*.c
src/main/dummy/*.c
src/thread/generic/*.c
src/timer/dummy/*.c
src/loadso/dummy/*.c

View file

@ -292,7 +292,7 @@ To include these files for C/C++ projects:
app's project. This is to make sure that Visual C++'s linker builds a 'Windows
Metadata' file (.winmd) for your app. Not doing so can lead to build errors.**
For non-C++ projects, you will need to call SDL_WinRTRunApp from your language's
For non-C++ projects, you will need to call SDL_RunApp from your language's
main function, and generate SDL3-WinRTResources.res manually by using `rc` via
the Developer Command Prompt and including it as a <Win32Resource> within the
first <PropertyGroup> block in your Visual Studio project file.