Simple Directmedia Layer
1# macOS 2 3These instructions are for people using Apple's macOS. 4 5From the developer's point of view, macOS is a sort of hybrid Mac and 6Unix system, and you have the option of using either traditional 7command line tools or Apple's IDE Xcode. 8 9# Command Line Build 10 11To build SDL using the command line, use the CMake build script: 12 13```bash 14mkdir build 15cd build 16cmake .. -DCMAKE_OSX_DEPLOYMENT_TARGET=10.11 17cmake --build . 18sudo cmake --install . 19``` 20 21 22You can also build SDL as a Universal library (a single binary for both 2364-bit Intel and ARM architectures): 24 25```bash 26mkdir build 27cd build 28cmake .. "-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.11 29cmake --build . 30sudo cmake --install . 31``` 32 33Please note that building SDL requires at least Xcode 12.2 and the 11.0 SDK. 34PowerPC support for macOS has been officially dropped as of SDL 2.0.2. 3532-bit Intel and macOS 10.8 runtime support has been officially dropped as 36of SDL 2.24.0. 37 38To use the library once it's built, you essential have two possibilities: 39use the traditional autoconf/automake/make method, or use Xcode. 40 41 42# Caveats for using SDL with macOS 43 44If you register your own NSApplicationDelegate (using [NSApp setDelegate:]), 45SDL will not register its own. This means that SDL will not terminate using 46SDL_Quit if it receives a termination request, it will terminate like a 47normal app, and it will not send a SDL_EVENT_DROP_FILE when you request to open a 48file with the app. To solve these issues, put the following code in your 49NSApplicationDelegate implementation: 50 51 52```objc 53- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender 54{ 55 if (SDL_GetEventState(SDL_EVENT_QUIT) == SDL_ENABLE) { 56 SDL_Event event; 57 SDL_zero(event); 58 event.type = SDL_EVENT_QUIT; 59 SDL_PushEvent(&event); 60 } 61 62 return NSTerminateCancel; 63} 64 65- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename 66{ 67 if (SDL_GetEventState(SDL_EVENT_DROP_FILE) == SDL_ENABLE) { 68 SDL_Event event; 69 SDL_zero(event); 70 event.type = SDL_EVENT_DROP_FILE; 71 event.drop.file = SDL_strdup([filename UTF8String]); 72 return SDL_PushEvent(&event); 73 } 74 75 return NO; 76} 77``` 78 79# Using the Simple DirectMedia Layer with a traditional Makefile 80 81An existing build system for your SDL app has good chances to work almost 82unchanged on macOS, as long as you link with the SDL framework. However, 83to produce a "real" Mac binary that you can distribute to users, you need 84to put the generated binary into a so called "bundle", which is basically 85a fancy folder with a name like "MyCoolGame.app". 86 87To get this build automatically, add something like the following rule to 88your Makefile.am: 89 90```make 91bundle_contents = APP_NAME.app/Contents 92APP_NAME_bundle: EXE_NAME 93 mkdir -p $(bundle_contents)/MacOS 94 mkdir -p $(bundle_contents)/Resources 95 echo "APPL????" > $(bundle_contents)/PkgInfo 96 $(INSTALL_PROGRAM) $< $(bundle_contents)/MacOS/ 97``` 98 99You should replace `EXE_NAME` with the name of the executable. `APP_NAME` is 100what will be visible to the user in the Finder. Usually it will be the same 101as `EXE_NAME` but capitalized. E.g. if `EXE_NAME` is "testgame" then `APP_NAME` 102usually is "TestGame". You might also want to use `@PACKAGE@` to use the 103package name as specified in your configure.ac file. 104 105If your project builds more than one application, you will have to do a bit 106more. For each of your target applications, you need a separate rule. 107 108If you want the created bundles to be installed, you may want to add this 109rule to your Makefile.am: 110 111```make 112install-exec-hook: APP_NAME_bundle 113 rm -rf $(DESTDIR)$(prefix)/Applications/APP_NAME.app 114 mkdir -p $(DESTDIR)$(prefix)/Applications/ 115 cp -r $< /$(DESTDIR)$(prefix)Applications/ 116``` 117 118This rule takes the Bundle created by the rule from step 3 and installs them 119into "$(DESTDIR)$(prefix)/Applications/". 120 121Again, if you want to install multiple applications, you will have to augment 122the make rule accordingly. 123 124But beware! That is only part of the story! With the above, you end up with 125a barebones .app bundle, which is double-clickable from the Finder. But 126there are some more things you should do before shipping your product... 127 1281. You'll need to copy the SDL framework into the Contents/Frameworks 129 folder in your bundle, so it is included along with your application. 130 1312. Add an 'Info.plist' to your application. That is a special XML file which 132 contains some meta-information about your application (like some copyright 133 information, the version of your app, the name of an optional icon file, 134 and other things). Part of that information is displayed by the Finder 135 when you click on the .app, or if you look at the "Get Info" window. 136 More information about Info.plist files can be found on Apple's homepage. 137 138 139As a final remark, let me add that I use some of the techniques (and some 140variations of them) in [Exult](https://github.com/exult/exult) and 141[ScummVM](https://github.com/scummvm/scummvm); both are available in source on 142the net, so feel free to take a peek at them for inspiration! 143 144 145# Using the Simple DirectMedia Layer with Xcode 146 147These instructions are for using Apple's Xcode IDE to build SDL applications. 148 149## First steps 150 151The first thing to do is to unpack the Xcode.tar.gz archive in the 152top level SDL directory (where the Xcode.tar.gz archive resides). 153Because Stuffit Expander will unpack the archive into a subdirectory, 154you should unpack the archive manually from the command line: 155 156```bash 157cd [path_to_SDL_source] 158tar zxf Xcode.tar.gz 159``` 160 161This will create a new folder called Xcode, which you can browse 162normally from the Finder. 163 164## Building the Framework 165 166The SDL Library is packaged as a framework bundle, an organized 167relocatable folder hierarchy of executable code, interface headers, 168and additional resources. For practical purposes, you can think of a 169framework as a more user and system-friendly shared library, whose library 170file behaves more or less like a standard UNIX shared library. 171 172To build the framework, simply open the framework project and build it. 173By default, the framework bundle "SDL.framework" is installed in 174/Library/Frameworks. Therefore, the testers and project stationary expect 175it to be located there. However, it will function the same in any of the 176following locations: 177 178* ~/Library/Frameworks 179* /Local/Library/Frameworks 180* /System/Library/Frameworks 181 182## Build Options 183 184There are two "Build Styles" (See the "Targets" tab) for SDL. 185"Deployment" should be used if you aren't tweaking the SDL library. 186"Development" should be used to debug SDL apps or the library itself. 187 188## Building the Testers 189 190Open the SDLTest project and build away! 191 192## Using the Project Stationary 193 194Copy the stationary to the indicated folders to access it from 195the "New Project" and "Add target" menus. What could be easier? 196 197## Setting up a new project by hand 198 199Some of you won't want to use the Stationary so I'll give some tips: 200 201(this is accurate as of Xcode 12.5.) 202 203* Click "File" -> "New" -> "Project... 204* Choose "macOS" and then "App" from the "Application" section. 205* Fill out the options in the next window. User interface is "XIB" and 206 Language is "Objective-C". 207* Remove "main.m" from your project 208* Remove "MainMenu.xib" from your project 209* Remove "AppDelegates.*" from your project 210* Add "\$(HOME)/Library/Frameworks/SDL.framework/Headers" to include path 211* Add "\$(HOME)/Library/Frameworks" to the frameworks search path 212* Add "-framework SDL -framework Foundation -framework AppKit" to "OTHER_LDFLAGS" 213* Add your files 214* Clean and build 215 216## Building from command line 217 218Use `xcode-build` in the same directory as your .pbxproj file 219 220## Running your app 221 222You can send command line args to your app by either invoking it from 223the command line (in *.app/Contents/MacOS) or by entering them in the 224Executables" panel of the target settings. 225 226# Implementation Notes 227 228Some things that may be of interest about how it all works... 229 230## Working directory 231 232In SDL 1.2, the working directory of your SDL app is by default set to its 233parent, but this is no longer the case in SDL 2.0 and later. SDL2 does not 234change the working directory, which means it'll be whatever the command line 235prompt that launched the program was using, or if launched by double-clicking 236in the Finder, it will be "/", the _root of the filesystem_. Plan accordingly! 237You can use SDL_GetBasePath() to find where the program is running from and 238chdir() there directly. 239 240 241## You have a Cocoa App! 242 243Your SDL app is essentially a Cocoa application. When your app 244starts up and the libraries finish loading, a Cocoa procedure is called, 245which sets up the working directory and calls your main() method. 246You are free to modify your Cocoa app with generally no consequence 247to SDL. You cannot, however, easily change the SDL window itself. 248Functionality may be added in the future to help this. 249 250# Bug reports 251 252Bugs are tracked at [the GitHub issue tracker](https://github.com/libsdl-org/SDL/issues/). 253Please feel free to report bugs there! 254