Installation notes for EPICS on Mac OS X (Darwin)

# Building EPICS base

- To build base:
  1. Set the EPICS_HOST_ARCH environment variable to darwin-ppc, darwin-x86 or darwin-ppcx86. The scripts in the base/startup directory can automate this. For example, here's part of my Bash login script (~/.bash_login):

         #
         # EPICS
         #
         EPICS_BASE="${HOME}/src/EPICS/base"
         EPICS_EXTENSIONS="${HOME}/src/EPICS/extensions"
         . "${EPICS_BASE}"/startup/unix.sh

  2. `cd` to the EPICS base top-level source directory.
  3. Uncomment the appropriate line in the relevent EPICS_BASE/configure/os/CONFIG_SITE.Common.darwin-xxx file for your EPICS_HOST_ARCH value. Newer versions of OS X (e.g. Snow Leopard) may include only 64 bit versions of some OS libraries, so should only have the x86_64 ARCH_CLASS.
  4. Run `make`.
- As distributed, EPICS on Mac OS X uses the readline command line input routines. IOC applications are more pleasant to interact with if either the readline or libtecla library is used. The easiest way to get either or both of these libraries on to your system is to download and install them using the either the DarwinPorts distribution or the Fink package manager. If you don't want to install the readline library, set the COMMANDLINE_LIBRARY variable in one of the CONFIG_SITE files to EPICS.

  Information on DarwinPorts is available from the DarwinPorts project page. DarwinPorts binary packages are available from here.

  Fink may be downloaded from the Source Forge.

- If broadcasts are not seen locally, try adding "localhost" (127.0.0.1) to the EPICS_CA_ADDR_LIST.

# Building EPICS extensions

Many extensions build and run properly on OS X. To build and run medm, first obtain the X11 run-time and developer packages from Apple and the OpenMotif3 package from Fink.

# Objective-C and AppleScript

Code written in Objective-C can be included in host or IOC applications. Here are a couple of short Objective-C examples which can be used to send AppleScript events to other applications on the OS X machine.

    /*
     * exampleAppleScriptRecord.m
     *
     * Simple Objective-C/AppleScript subroutine record
     *
     * To use this record in an application:
     *
     * 1) Make the following changes to the application Makefile:
     *    - Add exampleAppleScriptRecord.m to the application SRCS.
     *    - Add -framework Foundation to the application LDFLAGS.
     * 2) Add the following line to the application database description:
     *      registrar(registerExampleAppleScript)
     * 3) Add a record to the application database:
     *      record(sub,"setVolume")
     *      {
     *          field(SNAM,"exampleAppleScriptProcess")
     *      }
     */
    #import <Foundation/Foundation.h>
    #include <registryFunction.h>
    #include <subRecord.h>
    #include <alarm.h>
    #include <errlog.h>
    #include <recGbl.h>
    #include <epicsExport.h>

    /*
     * Shim between EPICS and NSAppleScript class.
     */
    static long
    exampleAppleScriptProcess(struct subRecord *psub)
     {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSDictionary *err;
        NSAppleScript *nsa;

        nsa = [[NSAppleScript alloc] initWithSource:[NSString stringWithFormat:
                    @"tell application \"Finder\" to set volume %g\n", psub->a]];
        if ([nsa executeAndReturnError:&err] == nil) {
            errlogPrintf("Failed to run AppleScript: %s\n",
                            [[err objectForKey:NSAppleScriptErrorMessage] cString]);
            recGblSetSevr(psub, SOFT_ALARM, INVALID_ALARM);
        }
        [nsa release];
        [pool release];
        return 0;
    }

    static registryFunctionRef subRef[] = {
        {"exampleAppleScriptProcess",(REGISTRYFUNCTION)exampleAppleScriptProcess}
    };

    static void registerExampleAppleScript(void)
    {
        registryFunctionRefAdd(subRef,NELEMENTS(subRef));
    }
    epicsExportRegistrar(registerExampleAppleScript);

    ==============================================================================
    /*
     * runAppleScript.m
     *
     * Simple Objective-C/AppleScript shim to allow EPICS application to
     * send arbitrary AppleScript messages to other applications.
     *
     * To use this subroutine in an application make the following
     * changes to the application Makefile:
     * - Add runAppleScript.m to the application SRCS.
     * - Add -framework Foundation to the application LDFLAGS.
     */
    #import <Foundation/Foundation.h>
    #include <errlog.h>

    int
    runAppleScript(const char *format, ...)
    {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSString *script;
        NSMutableDictionary *err;
        NSAppleScript *nsa;
        va_list args;
        int ret = 0;

        va_start(args, format);
        script = [[NSString alloc] initWithFormat:
                                [NSString stringWithCString:format] arguments:args];
        va_end(args);
        err = [NSMutableDictionary dictionaryWithCapacity:10];
        nsa = [[NSAppleScript alloc] initWithSource:script];
        if ([nsa executeAndReturnError:&err] == nil) {
            errlogPrintf("Failed to run AppleScript: %s\n",
                            [[err objectForKey:NSAppleScriptErrorMessage] cString]);
            ret = -1;
        }
        [script release];
        [nsa release];
        [pool release];
        return ret;
    }