Developing with Objective Pascal

Part 8: Creating a Multi-Architecture Static Library (Objective C)


Contents

Introduction
Parsing the Objective C Header Files
Compiling the Objective C Classes
Using the Static Library in a Pascal App


Introduction

These notes describe how to compile Objective C classes into a static library that you can use in an Objective Pascal iOS app. The example given is for the popular ASIHTTPRequest classes, which are available here:

http://allseeing-i.com/ASIHTTPRequest


Parsing the Objective C Header Files

Before going much further, make sure you can parse the Objective C header files into equivalent Objective Pascal declarations. With a simple class that has only a few methods, you could probably just transliterate them manually, but with a large number of classes like ASIHTTPRequest, you'll want to use the latest FPC header parser, available here:

iOS_6_Parsing_Status.html

The parser includes all of the files needed to parse the ASIHTTPRequest header files and compile the Pascal Asihttp unit. To set up the parser for other header files, see Part 9.


Compiling the Objective C Classes

The easiest way to compile the Objective C classes is to create an Xcode project to do it.

  1. Start Xcode and choose File | New | New Project. On the Framework & Library tab, select Cocoa Touch Static Library and click Next.

  2. Enter the name to use for the library in Product Name. In this example, the Pascal Asihttp unit expects a library named libAsihttp.a, so enter Asihttp - Xcode will add the "lib" prefix to whatever you enter, per convention. Click Next and save the new project wherever you want. The name you entered will also be used to name the project folder.

  3. You could copy all of the Objective C .h (header) and .m (source) files into the project's source folder and then add them to the project, but it's easier just to add them from wherever they're located. Choose File | Add Files to do that. Note that "adding" does not copy anything, but just points the project to the added files.

    Important! With the ASIHTTPRequest example, be sure to add all of the .h files and .m files from both the ASIHTTPRequest Classes folder as well as the External/Reachability folder.

  4. Set the project's iOS Deployment Target to the earliest version of iOS that your app(s) will target to ensure that the classes are not using features that won't be available. You set this on the project's Info tab.

  5. On the project target's Build Phases tab, click Add Build Phase | Add Run Script, then copy and paste this script into the box for the run script:

    if [ $PLATFORM_NAME = "iphonesimulator" ]; then
      cp $BUILT_PRODUCTS_DIR/$EXECUTABLE_PATH $PROJECT_DIR/$EXECUTABLE_PATH
    else
      $DEVROOT/usr/bin/lipo $BUILT_PRODUCTS_DIR/$EXECUTABLE_PATH $PROJECT_DIR/$EXECUTABLE_PATH -create -output $PROJECT_DIR/$EXECUTABLE_PATH
    fi
    
    This script will combine the Simulator and ARM .a (archive) files into a single .a file.

  6. We want a multi-architecture library that includes support for i386, armv6 and armv7. Beginning with Xcode 4.2, the "standard" ARM architecture is now armv7, whereas in earlier versions "standard" included both armv6 and armv7. So with Xcode 4.2 and later, change the ARCHS setting on the project target's Build Settings tab from "Standard (armv7)" to "armv6 armv7".

  7. To compile, select Simulator for your iOS deployment target and choose Product | Build. Then select iOS Device and choose Product | Build again. Be sure to compile for Simulator first, then for the device (ARM) since the script assumes that order.

  8. Check that the .a file (libAsihttp.a) has been created okay and contains all architectures. Note that the script creates the .a file in the project's top level folder instead of burying it under ~/Library/Developer/Xcode/DerivedData along with the other compiled files. Change to this folder and use the file command. For example:

    file libAsihttp.a
    libAsihttp.a: Mach-O universal binary with 3 architectures
    libAsihttp.a (for architecture armv6):	current ar archive random library
    libAsihttp.a (for architecture armv7):	current ar archive random library
    libAsihttp.a (for architecture i386):	current ar archive random library
    

Using the Static Library in a Pascal App

  1. Add the Pascal interface unit (Asihttp) to your app's uses. If the unit's compiled files (Asihttp.o / Asihttp.ppu) are not where FPC can find them, add to the compiler's unit search path using the -Fu switch.

    Tip: Depending on how your app's Xcode project is set up, you can add switches either to its build script or, if the script uses them, to user-defined settings on the project target's Build Settings tab.

  2. Use the FPC -Fo switch to add the path to the library (libAsihttp.a) to the compiler's object search path.

  3. Test the library. For example, you can test the ASIHTTPRequest class with this simple code:

    var
      url     : NSURL;
      request : ASIHTTPRequest;
      error   : NSError;
    begin
      url := NSURL.URLWithString(NSSTR('http://jaiku.com/feed/json'));
      request := ASIHTTPRequest.requestWithURL(url);
      request.startSynchronous;
      error := request.error_;
      if not Assigned(error) then
        NSLog(request.responseString);  //output JSON to console
    

Copyright 2011 by Phil Hess.

macpgmr (at) fastermac (dot) net

First posted Nov. 9, 2011; last edited May 9, 2013.