Search code examples
macosportingnsapplication

Building Mac OS X App instead of console


I have a port of my application, a game, running on Mac OS X. I build with make, and only added a few .mm files to access the necessities from NSApplication, NSWindow and NSOpenGLView.

  1. How do I "convert it" into a proper App as opposed to the current console form? Do I bundle it with something, if so how? Or is it some type of linker setting (as in Windows)? Do I have to build using XCode?
  2. Currently I just "tick" the system, i.e. poll it for events rather than utilizing OS X message pump properly. Could you point me to some basic sample or tutorial which shows me how to do it properly, while still being able to "tick" my own stuff at a fixed frame rate? I say "sample or tutorial", since I am blind when it comes to documentation.

Thanks!


Solution

  • For the creation of a proper Mac application, you'll have to create a Mac OS X bundle. You can find the great documentation on the Apple site, here. You can create them with standard tool (I did write a small python script to create a bundle from a simple .ini file that describe files to pack, and how to construct the Info.plist file).

    Basically, an application bundle is just a regular directory with a .app extension, and a fixed structure. The following file are required:

    Application.app/
      + Contents/
        + MacOS/
        | + <Executable>
        + Resources/
        | + <Icon>
        + Info.plist
    

    The Info.plist file is a standard property list file (either in XML or in the old format), that indicate what is the name of the executable file (CFBundleExecutable), what is the name of the icon file (CFBundleIconFile), the bundle type (CFBundleType with a value of APPL), and some other informations (file type supported, version string, development language, ...). Those file is the strict minimum required to have a basic Mac OS X application.

    For explanation of how the Mac OS X message pump work, I recommend the reading of this article by Matt Gallagher. He explains how the run message of the NSApplication class is implemented. You can then write this method runOnce that only iterate when there are pending messages. You'll then call this function periodically (it is really similar to the PeekMessage, TranslateMessage, and DispatchMessage sequence on Win32):

    - (void)runOnce
    {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
        [self finishLaunching];
    
        for (;;)
        {
            [pool release];
            pool = [[NSAutoreleasePool alloc] init];
    
            NSEvent *event =
                [self
                    nextEventMatchingMask:NSAnyEventMask
                    untilDate:nil
                    inMode:NSDefaultRunLoopMode
                    dequeue:YES];
    
            if (sender == nil)
                break;
    
            [self sendEvent:event];
            [self updateWindows];
        }
    
        [pool release];
    }