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