docs: Modernized README-macosx.md and cleaned up the Markdown a little.

Reference #960.
This commit is contained in:
Ryan C. Gordon 2021-11-09 10:50:18 -05:00
parent 0f2bf62935
commit cfdbd6acca
No known key found for this signature in database
GPG Key ID: FA148B892AB48044
1 changed files with 281 additions and 240 deletions

View File

@ -1,240 +1,281 @@
Mac OS X # Mac OS X (aka macOS).
==============================================================================
These instructions are for people using Apple's Mac OS X (pronounced
These instructions are for people using Apple's Mac OS X (pronounced "ten"), which in newer versions is just referred to as "macOS".
"ten").
From the developer's point of view, macOS is a sort of hybrid Mac and
From the developer's point of view, OS X is a sort of hybrid Mac and Unix system, and you have the option of using either traditional
Unix system, and you have the option of using either traditional command line tools or Apple's IDE Xcode.
command line tools or Apple's IDE Xcode.
# Command Line Build
Command Line Build
================== To build SDL using the command line, use the standard configure and make
process:
To build SDL using the command line, use the standard configure and make
process: ```bash
mkdir build
./configure cd build
make ../configure
sudo make install make
sudo make install
You can also build SDL as a Universal library (a single binary for both ```
32-bit and 64-bit Intel architectures), on Mac OS X 10.7 and newer, by using
the gcc-fat.sh script in build-scripts: CMake is also known to work, although it continues to be a work in progress:
mkdir mybuild ```bash
cd mybuild mkdir build
CC=$PWD/../build-scripts/gcc-fat.sh CXX=$PWD/../build-scripts/g++-fat.sh ../configure cd build
make cmake -DCMAKE_BUILD_TYPE=Release ..
sudo make install make
sudo make install
This script builds SDL with 10.5 ABI compatibility on i386 and 10.6 ```
ABI compatibility on x86_64 architectures. For best compatibility you
should compile your application the same way.
You can also build SDL as a Universal library (a single binary for both
Please note that building SDL requires at least Xcode 4.6 and the 10.7 SDK 64-bit Intel and ARM architectures), by using the build-scripts/clang-fat.sh
(even if you target back to 10.5 systems). PowerPC support for Mac OS X has script.
been officially dropped as of SDL 2.0.2.
```bash
To use the library once it's built, you essential have two possibilities: mkdir build
use the traditional autoconf/automake/make method, or use Xcode. cd build
CC=$PWD/../build-scripts/clang-fat.sh ../configure
============================================================================== make
Caveats for using SDL with Mac OS X sudo make install
============================================================================== ```
Some things you have to be aware of when using SDL on Mac OS X: This script builds SDL with 10.6 ABI compatibility on 64-bit Intel and 11.0
ABI compatibility on ARM64 architectures. For best compatibility you
- If you register your own NSApplicationDelegate (using [NSApp setDelegate:]), should compile your application the same way.
SDL will not register its own. This means that SDL will not terminate using
SDL_Quit if it receives a termination request, it will terminate like a Please note that building SDL requires at least Xcode 4.6 and the 10.7 SDK
normal app, and it will not send a SDL_DROPFILE when you request to open a (even if you target back to 10.6 systems). PowerPC support for Mac OS X has
file with the app. To solve these issues, put the following code in your been officially dropped as of SDL 2.0.2. 32-bit Intel, using an older Xcode
NSApplicationDelegate implementation: release, is still supported at the time of this writing, but current Xcode
releases no longer support it, and eventually neither will SDL.
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender To use the library once it's built, you essential have two possibilities:
{ use the traditional autoconf/automake/make method, or use Xcode.
if (SDL_GetEventState(SDL_QUIT) == SDL_ENABLE) {
SDL_Event event;
event.type = SDL_QUIT; # Caveats for using SDL with Mac OS X
SDL_PushEvent(&event);
} If you register your own NSApplicationDelegate (using [NSApp setDelegate:]),
SDL will not register its own. This means that SDL will not terminate using
return NSTerminateCancel; SDL_Quit if it receives a termination request, it will terminate like a
} normal app, and it will not send a SDL_DROPFILE when you request to open a
file with the app. To solve these issues, put the following code in your
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename NSApplicationDelegate implementation:
{
if (SDL_GetEventState(SDL_DROPFILE) == SDL_ENABLE) {
SDL_Event event; ```objc
event.type = SDL_DROPFILE; - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
event.drop.file = SDL_strdup([filename UTF8String]); {
return (SDL_PushEvent(&event) > 0); if (SDL_GetEventState(SDL_QUIT) == SDL_ENABLE) {
} SDL_Event event;
event.type = SDL_QUIT;
return NO; SDL_PushEvent(&event);
} }
============================================================================== return NSTerminateCancel;
Using the Simple DirectMedia Layer with a traditional Makefile }
==============================================================================
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
An existing autoconf/automake build system for your SDL app has good chances {
to work almost unchanged on OS X. However, to produce a "real" Mac OS X binary if (SDL_GetEventState(SDL_DROPFILE) == SDL_ENABLE) {
that you can distribute to users, you need to put the generated binary into a SDL_Event event;
so called "bundle", which basically is a fancy folder with a name like event.type = SDL_DROPFILE;
"MyCoolGame.app". event.drop.file = SDL_strdup([filename UTF8String]);
return (SDL_PushEvent(&event) > 0);
To get this build automatically, add something like the following rule to }
your Makefile.am:
return NO;
bundle_contents = APP_NAME.app/Contents }
APP_NAME_bundle: EXE_NAME ```
mkdir -p $(bundle_contents)/MacOS
mkdir -p $(bundle_contents)/Resources # Using the Simple DirectMedia Layer with a traditional Makefile
echo "APPL????" > $(bundle_contents)/PkgInfo
$(INSTALL_PROGRAM) $< $(bundle_contents)/MacOS/ An existing autoconf/automake build system for your SDL app has good chances
to work almost unchanged on macOS. However, to produce a "real" Mac binary
You should replace EXE_NAME with the name of the executable. APP_NAME is what that you can distribute to users, you need to put the generated binary into a
will be visible to the user in the Finder. Usually it will be the same so called "bundle", which is basically a fancy folder with a name like
as EXE_NAME but capitalized. E.g. if EXE_NAME is "testgame" then APP_NAME "MyCoolGame.app".
usually is "TestGame". You might also want to use `@PACKAGE@` to use the package
name as specified in your configure.ac file. To get this build automatically, add something like the following rule to
your Makefile.am:
If your project builds more than one application, you will have to do a bit
more. For each of your target applications, you need a separate rule. ```make
bundle_contents = APP_NAME.app/Contents
If you want the created bundles to be installed, you may want to add this APP_NAME_bundle: EXE_NAME
rule to your Makefile.am: mkdir -p $(bundle_contents)/MacOS
mkdir -p $(bundle_contents)/Resources
install-exec-hook: APP_NAME_bundle echo "APPL????" > $(bundle_contents)/PkgInfo
rm -rf $(DESTDIR)$(prefix)/Applications/APP_NAME.app $(INSTALL_PROGRAM) $< $(bundle_contents)/MacOS/
mkdir -p $(DESTDIR)$(prefix)/Applications/ ```
cp -r $< /$(DESTDIR)$(prefix)Applications/
You should replace `EXE_NAME` with the name of the executable. `APP_NAME` is
This rule takes the Bundle created by the rule from step 3 and installs them what will be visible to the user in the Finder. Usually it will be the same
into "$(DESTDIR)$(prefix)/Applications/". as `EXE_NAME` but capitalized. E.g. if `EXE_NAME` is "testgame" then `APP_NAME`
usually is "TestGame". You might also want to use `@PACKAGE@` to use the
Again, if you want to install multiple applications, you will have to augment package name as specified in your configure.ac file.
the make rule accordingly.
If your project builds more than one application, you will have to do a bit
more. For each of your target applications, you need a separate rule.
But beware! That is only part of the story! With the above, you end up with
a bare bone .app bundle, which is double clickable from the Finder. But If you want the created bundles to be installed, you may want to add this
there are some more things you should do before shipping your product... rule to your Makefile.am:
1) The bundle right now probably is dynamically linked against SDL. That ```make
means that when you copy it to another computer, *it will not run*, install-exec-hook: APP_NAME_bundle
unless you also install SDL on that other computer. A good solution rm -rf $(DESTDIR)$(prefix)/Applications/APP_NAME.app
for this dilemma is to static link against SDL. On OS X, you can mkdir -p $(DESTDIR)$(prefix)/Applications/
achieve that by linking against the libraries listed by cp -r $< /$(DESTDIR)$(prefix)Applications/
```
sdl-config --static-libs
This rule takes the Bundle created by the rule from step 3 and installs them
instead of those listed by into "$(DESTDIR)$(prefix)/Applications/".
sdl-config --libs Again, if you want to install multiple applications, you will have to augment
the make rule accordingly.
Depending on how exactly SDL is integrated into your build systems, the
way to achieve that varies, so I won't describe it here in detail But beware! That is only part of the story! With the above, you end up with
a barebones .app bundle, which is double-clickable from the Finder. But
2) Add an 'Info.plist' to your application. That is a special XML file which there are some more things you should do before shipping your product...
contains some meta-information about your application (like some copyright
information, the version of your app, the name of an optional icon file, 1. The bundle right now probably is dynamically linked against SDL. That
and other things). Part of that information is displayed by the Finder means that when you copy it to another computer, *it will not run*,
when you click on the .app, or if you look at the "Get Info" window. unless you also install SDL on that other computer. A good solution
More information about Info.plist files can be found on Apple's homepage. for this dilemma is to static link against SDL. On OS X, you can
achieve that by linking against the libraries listed by
As a final remark, let me add that I use some of the techniques (and some ```bash
variations of them) in Exult and ScummVM; both are available in source on sdl-config --static-libs
the net, so feel free to take a peek at them for inspiration! ```
instead of those listed by
==============================================================================
Using the Simple DirectMedia Layer with Xcode ```bash
============================================================================== sdl-config --libs
```
These instructions are for using Apple's Xcode IDE to build SDL applications.
Depending on how exactly SDL is integrated into your build systems, the
- First steps way to achieve that varies, so I won't describe it here in detail
The first thing to do is to unpack the Xcode.tar.gz archive in the 2. Add an 'Info.plist' to your application. That is a special XML file which
top level SDL directory (where the Xcode.tar.gz archive resides). contains some meta-information about your application (like some copyright
Because Stuffit Expander will unpack the archive into a subdirectory, information, the version of your app, the name of an optional icon file,
you should unpack the archive manually from the command line: and other things). Part of that information is displayed by the Finder
when you click on the .app, or if you look at the "Get Info" window.
cd [path_to_SDL_source] More information about Info.plist files can be found on Apple's homepage.
tar zxf Xcode.tar.gz
This will create a new folder called Xcode, which you can browse As a final remark, let me add that I use some of the techniques (and some
normally from the Finder. variations of them) in [Exult](https://github.com/exult/exult) and
[ScummVM](https://github.com/scummvm/scummvm); both are available in source on
- Building the Framework the net, so feel free to take a peek at them for inspiration!
The SDL Library is packaged as a framework bundle, an organized
relocatable folder hierarchy of executable code, interface headers, # Using the Simple DirectMedia Layer with Xcode
and additional resources. For practical purposes, you can think of a
framework as a more user and system-friendly shared library, whose library These instructions are for using Apple's Xcode IDE to build SDL applications.
file behaves more or less like a standard UNIX shared library.
## First steps
To build the framework, simply open the framework project and build it.
By default, the framework bundle "SDL.framework" is installed in The first thing to do is to unpack the Xcode.tar.gz archive in the
/Library/Frameworks. Therefore, the testers and project stationary expect top level SDL directory (where the Xcode.tar.gz archive resides).
it to be located there. However, it will function the same in any of the Because Stuffit Expander will unpack the archive into a subdirectory,
following locations: you should unpack the archive manually from the command line:
~/Library/Frameworks ```bash
/Local/Library/Frameworks cd [path_to_SDL_source]
/System/Library/Frameworks tar zxf Xcode.tar.gz
```
- Build Options
There are two "Build Styles" (See the "Targets" tab) for SDL. This will create a new folder called Xcode, which you can browse
"Deployment" should be used if you aren't tweaking the SDL library. normally from the Finder.
"Development" should be used to debug SDL apps or the library itself.
## Building the Framework
- Building the Testers
Open the SDLTest project and build away! The SDL Library is packaged as a framework bundle, an organized
relocatable folder hierarchy of executable code, interface headers,
- Using the Project Stationary and additional resources. For practical purposes, you can think of a
Copy the stationary to the indicated folders to access it from framework as a more user and system-friendly shared library, whose library
the "New Project" and "Add target" menus. What could be easier? file behaves more or less like a standard UNIX shared library.
- Setting up a new project by hand To build the framework, simply open the framework project and build it.
Some of you won't want to use the Stationary so I'll give some tips: By default, the framework bundle "SDL.framework" is installed in
* Create a new "Cocoa Application" /Library/Frameworks. Therefore, the testers and project stationary expect
* Add src/main/macosx/SDLMain.m , .h and .nib to your project it to be located there. However, it will function the same in any of the
* Remove "main.c" from your project following locations:
* Remove "MainMenu.nib" from your project
* Add "$(HOME)/Library/Frameworks/SDL.framework/Headers" to include path * ~/Library/Frameworks
* Add "$(HOME)/Library/Frameworks" to the frameworks search path * /Local/Library/Frameworks
* Add "-framework SDL -framework Foundation -framework AppKit" to "OTHER_LDFLAGS" * /System/Library/Frameworks
* Set the "Main Nib File" under "Application Settings" to "SDLMain.nib"
* Add your files ## Build Options
* Clean and build
There are two "Build Styles" (See the "Targets" tab) for SDL.
- Building from command line "Deployment" should be used if you aren't tweaking the SDL library.
Use pbxbuild in the same directory as your .pbproj file "Development" should be used to debug SDL apps or the library itself.
- Running your app ## Building the Testers
You can send command line args to your app by either invoking it from
the command line (in *.app/Contents/MacOS) or by entering them in the Open the SDLTest project and build away!
"Executables" panel of the target settings.
## Using the Project Stationary
- Implementation Notes
Some things that may be of interest about how it all works... Copy the stationary to the indicated folders to access it from
* Working directory the "New Project" and "Add target" menus. What could be easier?
As defined in the SDL_main.m file, the working directory of your SDL app
is by default set to its parent. You may wish to change this to better ## Setting up a new project by hand
suit your needs.
* You have a Cocoa App! Some of you won't want to use the Stationary so I'll give some tips:
Your SDL app is essentially a Cocoa application. When your app
starts up and the libraries finish loading, a Cocoa procedure is called, * Create a new "Cocoa Application"
which sets up the working directory and calls your main() method. * Remove "main.c" from your project
You are free to modify your Cocoa app with generally no consequence * Remove "MainMenu.nib" from your project
to SDL. You cannot, however, easily change the SDL window itself. * Add "$(HOME)/Library/Frameworks/SDL.framework/Headers" to include path
Functionality may be added in the future to help this. * Add "$(HOME)/Library/Frameworks" to the frameworks search path
* Add "-framework SDL -framework Foundation -framework AppKit" to "OTHER_LDFLAGS"
* Set the "Main Nib File" under "Application Settings" to "SDLMain.nib"
Known bugs are listed in the file "BUGS.txt". * Add your files
* Clean and build
## Building from command line
Use `xcode-build` in the same directory as your .pbxproj file
## Running your app
You can send command line args to your app by either invoking it from
the command line (in *.app/Contents/MacOS) or by entering them in the
Executables" panel of the target settings.
# Implementation Notes
Some things that may be of interest about how it all works...
## Working directory
In SDL 1.2, the working directory of your SDL app is by default set to its
parent, but this is no longer the case in SDL 2.0. SDL2 does change the
working directory, which means it'll be whatever the command line prompt
that launched the program was using, or if launched by double-clicking in
the finger, it will be "/", the _root of the filesystem_. Plan accordingly!
You can use SDL_GetBasePath() to find where the program is running from and
chdir() there directly.
## You have a Cocoa App!
Your SDL app is essentially a Cocoa application. When your app
starts up and the libraries finish loading, a Cocoa procedure is called,
which sets up the working directory and calls your main() method.
You are free to modify your Cocoa app with generally no consequence
to SDL. You cannot, however, easily change the SDL window itself.
Functionality may be added in the future to help this.
# Bug reports
Bugs are tracked at [the GitHub issue tracker](https://github.com/libsdl-org/SDL/issues/).
Please feel free to report bugs there!