Objective-C on Linux: Setting up GNUstep, clang (llvm), Objective-C 2.0, Blocks Runtime, GCD on Ubuntu 12.04

February 24th, 2013 · 19 Comments · Objective-C, Tutorials

I recently posted a couple of articles about how to use Cocotron for cross compiling Objective-C applications for Linux. In my opinion, what makes Cocotron great is that you can continue to work on the OS X platform and harness the conveniences of code editing with Xcode. However, there are a number of drawbacks that I did not yet manage to overcome. The main issue I have with Cocotron is that it’s still based on GCC and hence does not provide support for some nice modern features of Objective-C, most notably blocks and Grand Central Dispatch (GCD) (both require clang.) What is more, Cocotron doesn’t come with GUI support on Linux (only Windows is supported as of now.)

GNUstep appears to be a good alternative if you are willing to sacrifice the ability to work with an Xcode project, but is it feasible to set it up on Ubuntu with support for clang, blocks and GCD?

Turns out it is.

As information about this particular setup appears to be a bit scattered over the web, and there happens to be no defacto step-by-step guide on how to accomplish this easily, I decided to try and fill this gap.

So no more babbling, let’s just jump right in!

Things You Will Need

  • Ubuntu 12.04 (Desktop) installed on a (virtual) machine.
  • That’s it, really!
If you don’t want to carry out the steps listed below manually, I have prepared a shell script, which should do all the work for you.

Step 1: Get a Bunch of Packages

Open up a terminal session and enter the following command:

sudo apt-get install build-essential clang libblocksruntime-dev libkqueue-dev libpthread-workqueue-dev gobjc libxml2-dev libjpeg-dev libtiff-dev libpng12-dev libcups2-dev libfreetype6-dev libcairo2-dev libxt-dev libgl1-mesa-dev

Note: I am assuming that you start with a fresh Ubuntu instance, so I am listing all required packages to start from there. If you had libdispatch-dev installed previously, please remove it before proceeding with step 2. (It causes trouble when configuring GNUstep base.) We will re-install it later again.

Step 2: Download GNUstep and libobj2 Sources from the GNUstep Website

It’s important NOT to install the respective Ubuntu packages (gnustep-devel, libobjc2). Instead, download the following from the GNUstep resources site:

  1. GNUstep Make
  2. GNUstep Base
  3. GNUstep GUI
  4. GNUstep Backend

Additionally, get the latest libobjc2 sources from http://download.gna.org/gnustep/.

Finally, move the files into an install folder, and unpack them there. (I named mine ‘gnustep-dev’ and put it into my home directory.)

Step 3: Install libobjc2

Change into the unpacked libobjc2 directory and then type the following on your terminal:

export CC=clang
make
sudo make install

Note: It’s important to complete the following steps within this terminal session. Otherwise, you need to repeat export CC=clang (set the C compiler to clang instead of gcc) if you continue with a fresh session.

Step 4: Install the GNUstep Tools and Libraries

  1. Install GNUstep Make by changing into the unpacked gnustep-make-x.x.x directory and typing:
    ./configure
    sudo make install
    
  2. Install GNUstep Base by changing into the unpacked gnustep-base-x.x.x directory and typing:
    ./configure
    make
    sudo make install
    
  3. Install GNUstep GUI by changing into the unpacked gnustep-gui-x.x.x directory and typing:
    ./configure
    make
    sudo make install
    
  4. Install GNUstep Backend by changing into the unpacked gnustep-back-x.x.x directory and typing:
    ./configure
    make
    sudo make install
    

Step 5: Install libdispatch-dev

On the terminal, type:

sudo apt-get install libdispatch-dev

Step 6: Try it out

I have set up a simple test program and named it main.m:

Just download it to your Ubuntu machine.

On the terminal, go into the directory containing main.m and execute the following command to compile the source file:

clang `gnustep-config --objc-flags` -o main -x objective-c main.m -fconstant-string-class=NSConstantString -fobjc-nonfragile-abi -fblocks -lgnustep-base -lgnustep-gui -ldispatch -I/usr/include/GNUstep -L/usr/lib/GNUstep

Finally, execute the built binary by typing:

./main

If everything works correctly, you should see the following terminal output:

2013-02-24 01:08:20.981 main[6710] 21
Hello, world from a dispatch queue!

Additionally, an alert panel should pop up as seen in the screenshot above.

Sources

→ 19 CommentsTags:··

Creating an Objective-C based CLI for Ubuntu 12 using Cocotron

February 24th, 2013 · 2 Comments · Objective-C, Tutorials

In Part 1: Compiling Cocotron Foundation Framework For Ubuntu 12.04 I provided an updated step by step tutorial on how to compile the Cocotron Foundation framework for Ubuntu 12.04 using Xcode 4.

This post is an updated version of the old part 2 tutorial on how to cross compile a simple command line tool runnable on Ubuntu 12.

Step 1: Creating the Xcode Project

The first thing we will do is create a new command line tool Xcode project.

  1. Open up Xcode and create a new project by selecting “File” => “New” => “New Project…” from the main menu.
  2. Create a new command line tool project by selecting “Application” => “Command Line Tool” from the new project template wizard.
  3. Name the project “CocotronUbuntuCLI” and choose “Foundation” from the type dropdown.

Step 2: Replacing OS X with Linux Foundation Framework

The standard project template used by Xcode will reference Apple’s Foundation framework, which of course won’t run on Linux. Hence, we will have to replace it with the Cocotron Foundation framework that you built in part 1 of this tutorial.

  1. In the project navigator, expand the “Frameworks” item and remove “Foundation.framework” by selecting it and hitting backspace.
  2. To add the Foundation framework for Linux, right click on the project navigator, select “Add Files to CocotronUbuntuCLI…” from the contextual menu, and locate Cocotron’s Foundation.framework that you built in the last part of this tutorial. Usually this will be located at /Developer/Cocotron/1.0/Linux/i386/Frameworks/ Foundation.framework.
  3. Finally, click “Add”.

Step 3: Replacing Unsupported @autoreleasepool Statement

Unfortunately, Cocotron does not support some of the syntactic sugar provided by modern Objective-C versions.

In the main.m source file, change

@autoreleasepool {
    // your code
}

to

NSAutoreleasePool *pool = [NSAutoreleasePool alloc] init];
// your code
[pool release];

Step 4: Configuring the Target’s Build Settings

In order to make Xcode build the application correctly, we will have to change some build settings.

  1. From the project navigator, click on the “CocotronUbuntuCLI” project item. This will open up project settings in the editor.
  2. In the project settings editor, select the “CocotronUbuntuCLI” target from the tree control on the left. Then select “Build Settings” => “All”/”Combined” from the project settings editor’s tabs.
  3. Change “Architecture” to “32-bit Intel”.
  4. Change “Mac OS X Deployment Target” to “Compiler Default”.
  5. Change “Compiler for C/C++/Objective-C” to “Cocotron 1.0 Linux i386 gcc 4.3.1″.
  6. Change “Implicit Conversion to 32 Bit Type” to “No”.

Step 5: Installing and Testing the Command Line Interface on Ubuntu Linux

  1. Locate Cocotron’s Foundation.framework directory on your Mac (see step 2.2.)
  2. Copy the complete directory to /usr/lib on your Ubuntu Linux machine recursively. Make sure to preserve symlinks.
  3. Within your Linux system’s /usr/lib directory, create a symlink named “libFoundation.so” to /usr/lib/Foundation.framework/libFoundation.so.
  4. Copy the build product from step 5.4 to your user’s home directory on the Ubuntu Linux machine.
    Finally, open up a terminal on your Linux and execute the command line tool by typing ./CocotronUbuntuCLI (current working directory must be your home directory.) You should see an NSLog message saying “Hello, World!” if everything worked correctly!

Limitations

Unfortunately, Cocotron did not yet migrate to LLVM and does therefore not support some of the new compiler and language features of Objective-C.

Most notably, the following is NOT supported when cross compiling with Cocotron:

  • Blocks
  • Grand Central Dispatch (GCD)
  • ARC
  • @autoreleasepool, @synchronized, etc.

See what you can do about it!

→ 2 CommentsTags:···

Compiling Cocotron Foundation Framework for Ubuntu 12.04

February 20th, 2013 · 2 Comments · Objective-C, Tutorials

This article is an updated step by step guide on how to compile the Cocotron toolchain and Foundation framework for Ubuntu 12.04 (32 bit). Most instructions from the old article for Ubuntu 11 are still valid, however, there are a couple of changes, both for the Cocotron Developer Tools (CDT) and for the files needed from the Linux system to create a functional platform interface.

Things You Will Need

  • A Mac with the latest Xcode and developer tools installed; you will use this for cross compilation. I used Xcode 4.6 on OS X 10.8.2 to test the steps described in this article. Older versions of Xcode (4.x) and/or OS X (10.6+) should also work.
  • A machine with the target Linux system installed. We will use Ubuntu 12.04 32 bit here. Installing Ubuntu as a guest OS in a VM is fine. I suggest using VirtualBox.
  • The Cocotron source code (get it by typing “$ hg clone http://cocotron.googlecode.com/hg/ cocotron” on the terminal)

Note: the Cocotron Developer Tools are now included in the Cocotron source. There is no need to download them separately anymore.

Step 1: Create a Platform Interface for Cocotron Developer Tools

The CDT require some files from your target platform. We are going to get these in this step. Don’t worry, this is already the most complicated part of the story.

Note: As of Xcode 4.3, the /Developer folder is no longer used by the Apple toolchain. Cocotron still uses the root Developer folder, so you may need to create it manually.

  1. Create directory structure /Developer/Cocotron/1.0/PlatformInterfaces.
  2. In the PlatformInterfaces directory, create a subdirectory named i386-ubuntu-linux.
  3. From your Ubuntu machine, copy the /usr/include directory to /Developer/Cocotron/1.0/PlatformInterfaces/i386-ubuntu-linux/include on your Mac.
  4. Additionally, from your Ubuntu machine, copy the /usr/src/linux-headers-x.x.xx-x/arch/x86/include/asm diectory to /Developer/Cocotron/1.0/PlatformInterfaces/i386-ubuntu-linux/include/asm on your Mac.
  5. Then copy /usr/src/linux-headers-x.x.xx-x/include/linux/compiler.h from the Ubuntu machine to /Developer/Cocotron/1.0/PlatformInterfaces/i386-ubuntu-linux/include/linux on your Mac.
  6. On your Mac, move all files and directories inside /Developer/Cocotron/1.0/PlatformInterfaces/i386-ubuntu-linux/include/i386-linux-gnu folder to the parent folder omitting the asm directory.
  7. In the i386-ubuntu-linux directory, create a subdirectory named lib.
  8. From your Ubuntu Linux machine, copy the following files to that directory from /usr/lib/i386-linux-gnu:

    crt1.o
    crti.o
    crtn.o
    libc.a
    libc.so
    libc_nonshared.a
    libm.a
    libpthread_nonshared.a
    libpthread.a
    libpthread.so

    Edit: it’s important to not copy libdl.a here (see the issue discussed in this thread.)

  9. Additionally, copy the following files to lib from your Ubuntu’s /lib/i386-linux-gnu directory:

    libdl-2.15.so
    libm-2.15.so
    libc-2.15.so
    ld-2.15.so
    libpthread-2.15.so

  10. Create symlinks:

    libdl.so.2 -> libdl-2.15.so
    libdl.so -> libdl.so.2
    libm.so.6 -> libm-2.15.so
    libc.so.6 -> libc-2.15.so
    ld-linux.so.2 -> ld-2.15.so
    libpthread.so.0 -> libpthread-2.15.so

  11. Finally, edit libc.so and libpthread.so using a text editor and replace /usr/lib/i386-linux-gnu and /lib/i386-linux-gnu paths with /Developer/Cocotron/1.0/PlatformInterfaces/i386-ubuntu-linux/lib.

Step 2: Checkout the Cocotron Source

Open up a terminal session and change the working directory to the target directory which you want to contain the cocotron source folder. Then type:

$ hg clone http://cocotron.googlecode.com/hg/ cocotron

Step 3: Build and Install Cocotron Developer Tools

  1. Switch to the InstallCDT folder by typing:
    $ cd cocotron/InstallCDT
  2. Install the Cocotron Developer Tools for Linux by typing:
    $ sudo ./install.sh Linux i386

The script will build the Cocotron toolchain for Ubuntu Linux and install all required files to allow for cross compiling using Xcode.

Step 4: Compile the Cocotron Foundation.framework

Open Xcode and load Foundation.xcodeproj from the cocotron/Foundation folder. Choose ‘Foundation-Linux-i386′ as active scheme. Build the Cocotron Foundation framework by hitting Cmd+B. If you see ‘Build succeeded’, congratulations, you have taken the first step towards Objective-C on Linux.

You may continue by reading the second part of this tutorial: Creating an Objective-C based CLI for Ubuntu 12 using Cocotron.

→ 2 CommentsTags:···

Introducing the IcedCoffee Framework – A Basis for OpenGL ES 2 User Interfaces on iOS/Mac OS X

May 1st, 2012 · 1 Comment · Objective-C, Projects

Summary

IcedCoffee is an attempt towards a clean, minimalistic OpenGL based user interface framework written in Objective-C. It borrows some ideas and code snippets from cocos2d and cocos3d, but approaches stuff in a slightly different way. IcedCoffee is thought to be a basis for accelerated user interfaces – in games, apps or whatever you wish. Its current highlights are: shader based picking, a perspective projected UI, render to texture (with depth buffers, with picking support, even when nested), a basic view hierarchy (wip), and a minimalistic scene graph employing the visitor pattern to keep things clean.

IcedCoffee is in a really early stage. It’s not feature complete and some things won’t work, but I would really appreciate feedback on the core concept. A sneak preview can be grabbed here: IcedCoffee Framework on GitHub.

Warning: in what follows I wrote down the long story trying to justify why I decided to create another UI framework – in the end it boils down to “passion” and doesn’t tell you anything you couldn’t learn from IcedCoffee’s readme, but I’ve you are still interested, voilà:

Long Version: Why Another Framework?

I have always been in love with user interfaces. Ever since I had a computer with a graphical UI (I think that’s roughly 20 years ago) UI engineering and design became one of the things I was and still am really interested in. I have used and extended many UI frameworks, beginning with Visual Basic’s Form Editor, then C and the Win32 API (putting together dialogs and runloops manually was big fun, but I don’t miss it), continuing with the Microsoft Foundation Classes (MFC), then Qt for multi-platform UIs and finally arriving at Cocoa/CocoaTouch.

Back in the old days, I started many attempts to put together an own framework. My first try was named “VelvetUI”, a 2D user interface with some 3D capabilities built upon Microsoft’s DirectX. Velvet ended up being a polymorphic C++/XML monster, slow and bloated – I didn’t even want to use it myself after a while. I always had a talent for coding, but Velvet was the first time I over-engineered a project to death, endangered my ex-relationship by spending too much time on coding and gaining a hell lot of experience on what NOT to do when approaching a big engineering task.

However, there were a few nice things in Velvet, which I still liked, so I built “tlib”, Velvet’s sequil. tlib drove my Bachelor’s thesis. It was kind of Velvet light, and it worked. By the way, you can still download it, if you don’t know what to do with your time and want to dig a bit in the old codes: this is tlib (and my Bachelor’s thesis). When I finally started studying for my Master’s degree in 2006, I abandoned Microsoft and went on to using a Mac. tlib was history and I began using Carbon, then Cocoa, which I still love, then programming OpenGL.

Filling A Gap?

Whenever it came to OpenGL, pretty much everyone I know brew their own soup. If you implement a game you use OpenGL (or DirectX, or both) and probably either use an existing game engine or write your own. If you just want to implement a flashy GUI that goes beyond the standard set of possibilities you have with vendor-specific UI frameworks like MFC, WPF, Cocoa, gnome or whatever, you probably implement it on your own. If you are on the Mac or iOS, you may use cocos2d or similar frameworks to speed up development a bit. All of these are not really focussed on GUIs, but more on games. I once tried to create an editor for a 2D map with 3D objects on it, quite simple, but complex enough to make it really hard with cocos2d.

Finally, I decided to give it another try.

So, What’s In It?

I love Objective-C, so I decided to write the framework using that. I believe Objective-C paired with Apple’s Foundation framework constitute a quite solid basis for all the stuff you don’t want to think about too much: runloops, inter-thread communication, messaging, containers, strings, encodings, and so on.

What I like about cocos2d is the way they handle drawing, threading and OpenGL contexts. So I borrowed some pieces of code and some core principles from there. IcedCoffee performs drawing and event handling on a display link thread. The display link ensures frame updates are performed in sync with display refreshes. It is a courtesy of the CoreVideo framework on OS X and CoreAnimation on iOS. IcedCoffee re-routes events to that thread just like cocos does so as to ensure no inter-thread synchronization is required. Nearly all IcedCoffee resources are non-atomic by this means. However, IcedCoffee still allows asynchronous operations such as texture loading via GCD in a distinct OpenGL context (which has been inspired by cocos2d as well).

What I dislike about cocos2d is the way they rely on singletons. Cocos2d is full of singletons. Now I don’t want to say that singletons are a bad thing per se, but my intuition and experience tells me that they tend to cause trouble later on. So I decided to make IcedCoffee virtually singleton-free. Well, nearly, IcedCoffee has a few singletons, but it uses these only for stuff that really is “global” and “single” (globally) – I guess you know what I mean.

What I also dislike about cocos2d is the whole CCLayer stuff and the way user interaction and hit testing is performed. I personally don’t want to fiddle around with rects, priorities and so on. So I decided that a core component of IcedCoffee would be its ability to do color-based picking using shaders. This should work on the OpenGL view’s frame buffer and also on render texture FBOs, even when nested. It was a hell of a work, and it now does work, so I hope you like it as much as I do. As I liked the way Cocoa treats event processing with its responder chain, I decided to incorporate that into the framework and connect it with the picking. As a result, each node can receive mouse or touch events when someone clicks or taps on it.

What I like about cocos3d is the way they do visitation. The visitor pattern is really powerful when it comes to scene graphs, so I decided to implement visitors in IcedCoffee. The IcedCoffee framework ships with two default visitors: one for drawing and another one for picking. The drawing visitor is quite straight-forward, but the picking visitor does real magic. It allows for picking with nearly all custom nodes you could write up, you don’t need to care about it in 99% of the cases. It works with exactly the same efficiency as the drawing visitor does. So if you write up some kind of visibility detection and incorporate that into the visitors, your picking algorithm will automatically be as fast as your drawing algorithm – quite nice.

Another quite unique thing about IcedCoffee is its user interface camera. IcedCoffee uses a perspective projection that projects points on the world’s XY plane to pixels on the frame buffers and thus allows for flashy effects and (nearly) implicit retina display support.

IcedCoffee is still very basic. It does not feature any high level user interface controls. I am currently working on a control abstraction and some basic controls. Another focus for the next couple of weeks is font rendering and update scheduling. If you are interested, please have a look at IcedCoffee’s test cases and the code and add a comment to this post. Or send me an email. I really appreciate it!

→ 1 CommentTags:···

A Delegate-like Observer Mechanism in Objective-C using Forward Invocation

August 14th, 2011 · 9 Comments · Objective-C

The observer pattern is useful whenever you want a dynamic list of objects (observers) be notified when an event occurs in an observed object (also called the subject).

Cocoa provides several built-in ways to make use of this pattern. If you are interested in a profound comparison, Matt Gallagher has a great summary of the standard methods for observation and notification in Cocoa.

In this post I am going to contribute an implementation of the observer pattern that resembles the way delegates are implemented in Cocoa. In contrast to Cocoa built-in mechanisms (like NSNotificationCenter) the presented approach enables you to use arbitrary selectors in notification messages (just as is the case with delegates). What is more you won’t have to cope with the details how notification messages are dispatched by the broadcaster.

Note: for what it’s worth, I will call the broadcaster “observable” and the listener “observer” throughout this post. This is in line with the classes I’m providing in my sample code.

Basic Idea

We would like to be able to notify multiple observers about a certain event, giving them a chance to act as appropriate. Just like with delegates, this should be possible using arbitrary selectors.

Let’s take a look at a standard delegation example in Objective-C:

- (void)performTask
{
    // Check whether delegate implements -willPerformTask
    if ([delegate respondsToSelector: @selector(willPerformTask)]) {
        // Notify delegate that we're about to perform the task
        [delegate willPerformTask];
    }
}

The example above, of course, is limited to one delegate receiving notification messages from the delegator. Now, what we want in certain situations is a collection of observers (multiple “delegates”). All observers should receive the notification message.

It would be neat if the code in your observable object would look something like this:

- (void)performTask
{
     // Notify observers that we're about to perform the task
     [self.observers willPerformTask];
}

The idea here is that observers acts as a proxy broadcasting the willPerformTask message to all observer objects implementing the message’s selector.

This is exactly what the Observers class that I provide in the Observer sample code will do for you.

A Closer Look

Let’s take a closer look at what we’re talking about here.

The Observer sample provides two classes responsible for implementing observer registration and message broadcasting:

  • Observable: Abstract base class giving subclasses the ability to easily adopt the role of “generic” broadcasters. Observable maintains an Observers object and allows other objects to add and remove observers.
  • Observers: This class implements the actual broadcasting mechanism for Objective-C messages to arbitrary observer objects (must be Objective-C objects.) The basic idea here is that all messages sent to Observers are automatically broadcasted to all observers responding to a given selector (implementing/listing to a given notification message.)

An Example

For what follows, let’s assume the following example: we’d like to implement a simple contact manager that is capable of managing a collection of contact names. The contact manager provides two methods, -addContactWithName: and -removeContactWithName:. What is more, our contact manager should be observable, i.e. an arbitrary number of observers should be notified whenever a contact is being added or removed.

Implementing an Observable Contact Manager

Our contact manager is defined in the ContactManager class which inherits from Observable so as to provide for observation capabilities (see ContactManager.h in the sample code):

#import "Observable.h"
@interface ContactManager : Observable {
    NSMutableArray *contactNames;
}
- (void)addContactWithName:(NSString *)name;
- (void)removeContactWithName:(NSString *)name;
@end

By inheriting from Observable, ContactManager is equipped with an Observers object which is capable of maintaining a collection of observers and broadcasting messages to them.

As a consequence, within ContactManager‘s implementation of -addContactWithName: we can do the following (see ContactManager.m in the sample code):

- (void)addContactWithName:(NSString *)name
{
    [contactNames addObject:[name copy]];
    [self.observers contactManager:self
             didAddContactWithName:[name copy]];
}

-removeContactWithName: is implemented likewise:

- (void)removeContactWithName:(NSString *)name
{
    [contactNames removeObjectIdenticalTo:name];
    [self.observers contactManager:self
         willRemoveContactWithName:[name copy]];
}

Note: Observable provides two methods to add and remove observers:

  • -(void)addObserver:(id)observer; and
  • -(void)removeObserver:(id)observer;.

Since ContactManager is a Observable subclass, we can later wire observers to the contact manager by using these methods.

Implementing a Contact Manager Observer

The observer may be defined as a simple NSObject subclass providing implementations for the notification selectors it is interested in. Consider the following example (see ContactObserver.h and ContactObserver.m in the sample code):

@interface ContactObserver : NSObject
@end

@implementation ContactObserver
- (void)contactManager:(ContactManager *)manager
 didAddContactWithName:(NSString *)name
{
    NSLog(@"Observer got notification: contact manager added contact with name %@", name);
}

- (void)contactManager:(ContactManager*)manager
willRemoveContactWithName:(NSString *)name
{
    NSLog(@"Observer got notification: contact manager is about to remove contact with name %@", name);
}
@end

Wiring Observers with Observables

Finally, what we have to do to kick things off is wire the observer with the observable. In our example this looks as follows (see main.m in the sample code):

ContactManager *manager = [[ContactManager alloc] init];
ContactObserver *observer = [[ContactObserver alloc] init];
[manager addObserver:observer];
// [...]

Providing a Syntactically Correct Implementation with Protocols

While the code presented above will work, it is likely to cause compiler warnings due to the fact that observers are of type id. The compiler cannot know for sure that observers are going to respond to messages like contactManager:didAddContactWithName:, because id does not implement these methods.

The best solution here is to provide a protocol for each type of observer. This is not strictly necessary, but it tidies up your code and supports a good understanding of how things are structured.

It’s a good idea to add the protocol to the Observable’s header and name it accordingly.

In ContactManager.h, we add:

@protocol ContactManagerObserver
@optional
- (void)contactManager:(ContactManager *)manager
 didAddContactWithName:(NSString *)name;
- (void)contactManager:(ContactManager *)manager
willRemoveContactWithName:(NSString *)name;
@end

Consequently, the observer class should implement the newly defined protocol.

In ContactObserver.h we then have:

#import "ContactManager.h"
@interface ContactObserver : NSObject <ContactManagerObserver>
- (void)contactManager:(ContactManager *)manager
 didAddContactWithName:(NSString *)name;
- (void)contactManager:(ContactManager *)manager
willRemoveContactWithName:(NSString *)name;
@end

Finally, we need to change how ContactManager sends notification messages to observers.

In ContactManager.m, consider the “add contact” example employing the protocol as follows:

- (void)addContactWithName:(NSString *)name
{
    [contactNames addObject:[name copy]];
    [(id<ContactManagerObserver>)self.observers contactManager:self
                                         didAddContactWithName:[name copy]];
}

Viola, by telling the compiler that observers conform to the ContactManagerObserver protocol, there’s nothing to complain about anymore.

Characteristics of the Presented Observer Mechanism

There are some key characteristics of what you can do with observers when implementing them in the way discussed here:

  • Arbitrary method signatures: you may use selectors with arbitrary signatures for notification messages.
  • No obligation to handle all observer messages: it is not necessary to implement all methods for handling messages sent by the observable object. That is, in our example an observer may implement -contactManager:didAddContactWithName: only, omitting -contactManager:didRemoveContactWithName:.
  • Order of notification message dispatch undefined: you should keep in mind that the order in which notifications are sent to observers is not defined with this approach. As a consequence, you should avoid making assumptions on what other observers do in response to an observable notification.
  • Weak references to observers: the Observers class holds weak references to observer objects to avoid retain cycles. Consequently, you must take care of the observer vs. observable lifecycle on your own.

Limitations

There are some limitations with the presented approach:

  • Observer method implementations cannot return values: due to the nature of the broadcaster mechanism employed here, observer methods must exhibit a void return type.
  • Sample code is not optimized for performance: you should not use this approach for performance critical operations. The Observers class implements broadcasting in a fairly naive way, asking all registered observer objects whether they respond to the given selector. For large numbers of observer, this may represent a major performance hit. You should consider using another method in such cases.

Behind the Scenes: How Does Message Forwarding Work?

There is a plethora of documentation on Objective-C message forwarding, and I am not going to re-iterate on that here. However, to give you a basic understanding of what the code in the Observers class does, I provide a brief explanation here. And also there’s one little thing to add that has not yet been discussed profoundly on the web yet—swallowing selectors with an unknown method signature—but more on that later.

Message Forwarding and How To Swallow Messages With Unknown Signature

At the heart of the Observers message forwarding mechanism, there are two methods: methodSignatureForSelector: and forwardInvocation:.

These methods are called by the Objective-C runtime whenever a selector is sent to an object which is not implemented inside the compiled code of the receiver’s class.

Essentially, the runtime first calls methodSignatureForSelector:. If it gets back a valid method signature, it continues with calling forwardInvocation:. This gives custom code a chance to implement message forwarding for messages not implemented directly in the receiver’s class.

Be wary, that the runtime will cause an exception (unrecognized selector sent to instance) when methodSignatureForSelector: returns nil.

Let’s have a look at Observer implementation of methodSignatureForSelector: first:

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    NSMethodSignature *signature = [super methodSignatureForSelector:aSelector];
    if(!signature) {
        for(id observer in observers) {
            if([observer respondsToSelector:aSelector])
                return [observer methodSignatureForSelector:aSelector];
        }
        signature = [NSMethodSignature signatureWithObjCTypes: "@^v^c"];
    }
    return signature;
}

This method is called by the Objective-C runtime to request a method signature for a given selector. Observers implements this method so as to ask each registered observer whether it is capable of responding to the given selector. If so, the method signature is requested from the first observer exhibiting that capability.

If no observer capable of responding is found, we have to quietly bailout—without causing an exception.

This is exactly what the following line does:

signature = [NSMethodSignature signatureWithObjCTypes: "@^v^c"];

Recall that observables should be able to simply send an arbitrary observer selector to their observers. This means we may run into a situation where no observer implements the given selector. Usually this would cause the runtime to throw an exception, because an unrecognized selector is sent to an instance.

The key to resolving this situation without running into runtime errors is to provide an arbitrary method signature. That is, we just simply ignore that we have no clue about the selector’s designated method signature by returning a default signature. This is possible, because we just want to swallow the invocation later on, i.e. there is no invocation in response to the message being sent to the observers instance.

Finally, this is what the corresponding forwardInvocation: implementation looks like:

- (void)forwardInvocation:(NSInvocation*)anInvocation
{
    for(id observer in observers) {
        if([observer respondsToSelector:[anInvocation selector]]) {
            [anInvocation invokeWithTarget:observer];
        }
    }
}

This code checks whether there is a registered observer that responds to the given invocation’s selector. If there is one, we can be sure that methodSignatureForSelector: did successfully respond with the correct method signature for the required selector. If not, we simply do nothing. Thus, it is completely irrelevant whether the previously requested method signature was correct or not.

I found one single blog post about Elegant Delegation that explicitly discusses this issue. There is also a post by Matt Gallagher about collecting arbitrary messages using NSInvocation. While that post is great, the method provided there appears overly complex for the problem at hand in this case.

Sample Code

Download Observer Sample Code (22 KB)

→ 9 CommentsTags:·

Cocotron and Xcode4: How to Run Objective-C Apps on Linux (Part 2)

June 7th, 2011 · 10 Comments · Objective-C, Tutorials

An updated version of this article is available for Ubuntu Linux 12.04 (32 bit).

Part 2: Creating a Foundation-based CLI for Ubuntu

In Part 1: Cross Compiling Foundation I provided a step by step tutorial on how to compile the Cocotron Foundation framework for Ubuntu Linux using Xcode 4.

This post is intended to complete the tutorial by explaining how a simple command line tool can be created which will run on Ubuntu Linux using the previously compiled Foundation framework.

After completing this tutorial you will have:

  • a baseline project for compiling (GUI-less) Objective-C apps on Linux,
  • Foundation.framework installed on your Ubuntu Linux machine,
  • basic support for NSUserDefaults on the Linux machine.

The requirements for completing this tutorial are basically the same as those provided in the previous part. What is more, you need to complete part 1 successfully before you may start with part 2.

Step 1: Creating the Base Xcode Project

The first thing we will do is create a new command line tool Xcode project.

  1. Open up Xcode and create a new project by selecting “File” => “New” => “New Project…” from the main menu.
  2. Create a new command line tool project by selecting “Application” => “Command Line Tool” from the new project template wizard.
  3. Name the project “CocotronUbuntuCLI” and choose “Foundation” from the type dropdown.

Step 2: Replacing OS X with Linux Foundation Framework

The standard project template used by Xcode will reference Apple’s Foundation framework, which of course won’t run on Linux. Hence, we will have to replace it with the Cocotron Foundation framework that you built in part 1 of this tutorial.

  1. In the project navigator, expand the “Frameworks” item and remove “Foundation.framework” by selecting it and hitting backspace.
  2. To add the Foundation framework for Linux, right click on the project navigator, select “Add Files to CocotronUbuntuCLI…” from the contextual menu, and locate Cocotron’s Foundation.framework that you built in the last part of this tutorial. Usually this will be located at /Developer/Cocotron/1.0/Linux/i386/Frameworks/ Foundation.framework.
  3. Finally, click “Add”.

Step 3: Configuring the Target’s Build Settings

In order to make Xcode build the application correctly, we will have to change some build settings.

  1. From the project navigator, click on the “CocotronUbuntuCLI” project item. This will open up project settings in the editor.
  2. In the project settings editor, select the “CocotronUbuntuCLI” target from the tree control on the left. Then select “Build Settings” => “All”/”Combined” from the project settings editor’s tabs.
  3. Change “Architecture” to “32-bit Intel”.
  4. Change “Mac OS X Deployment Target” to “Compiler Default”.
  5. Change “C/C++ Compiler Version” to “System default (LLVM GCC 4.2)”.
  6. Change “Implicit Conversion to 32 Bit Type” to “No”.

Step 4: Configuring the Target’s Build Rules and Building the Source

Additionally, we have to add a build rule for C source files, so Xcode uses the correct compiler tool chain to build our command line tool for Linux.

  1. In the project settings editor, select the “CocotronUbuntuCLI” target from the tree control on the left. Then select “Build Rules” => “Target” from the project settings editor’s tabs.
  2. Click the “Add Build Rule” button on the lower right corner of the Xcode window. A new build rule is added to the target.
  3. From the “Process” dropdown select “C source files”; from the “Using” dropdown, select “Cocotron 1.0 Linux i386 gcc default (4.3.1)”.
  4. Finally, build the command line tool by hitting Cmd+B.

Step 5: Installing libm.so.6 on Your OS X Machine

The last step to set up the project for proper building is to get a Foundation framework dependency from your Ubuntu machine, namely libm.so.6. This library was not needed in part 1, but is required when linking against Cocotron’s Foundation.framework. In fact, libm.so.6 is a symlink pointing to libm-2.13.so.

  1. Locate libm-2.13.so on your Ubuntu Linux machine. It is usually located at /lib/i386-linux-gnu/libm-2.13.so.
  2. Copy libm-2.13.so to /Developer/Cocotron/1.0/Linux/i386/gcc-4.3.1/i386-ubuntu-linux/lib.
  3. Create a symlink libm.so.6 -> libm-2.13.so in that directory.
  4. Finally, build the command line tool by hitting Cmd+B.

Step 6: Installing and Testing the Command Line Interface on Ubuntu Linux

  1. Locate Cocotron’s Foundation.framework directory on your Mac (see step 2.2.)
  2. Copy the complete directory to /usr/lib on your Ubuntu Linux machine recursively. Make sure to preserve symlinks.
  3. Within your Linux system’s /usr/lib directory, create a symlink named “libFoundation.so” to /usr/lib/Foundation.framework/libFoundation.so.
  4. Copy the build product from step 5.4 to your user’s home directory on the Ubuntu Linux machine.
    Finally, open up a terminal on your Linux and execute the command line tool by typing ./CocotronUbuntuCLI (current working directory must be your home directory.) You should see an NSLog message saying “Hello, World!” if everything worked correctly!

Beyond Porting(?)

I hope this tutorial was helpful for you, what ever you intend to do with Objective-C on Linux.

Of course, porting OS X based code over to Linux is the most obvious use case here. As outlined in my previous post I see great potential in combining both platforms in a client/server manner. Thanks to the Cocotron project, this is now perfectly possible.

However, there are still a number of things I would love to have:

  • a GUI library (not necessarily an exact Cocoa ripoff) on Linux – this is not currently provided by Cocotron,
  • the compiler tool chain for building the complete Cocotron frameworks and apps based on that on Linux,
  • an IDE for developing Objective-C apps on Linux,
  • and, finally, 64 bit support for Objective-C apps on Linux.

If there are others out there who think that these tools are really needed, please don’t hesitate to contact me. I’m willing to invest some of my free time to contribute to one or two of these projects, if there are fellow devs willing to do the same!

→ 10 CommentsTags:···

Cocotron and Xcode4: How to Run Objective-C Apps on Linux

May 1st, 2011 · 14 Comments · Objective-C, Tutorials

An updated version of this article is available for Ubuntu Linux 12.04 (32 bit).

This is part one of a two part tutorial. The first part focusses on cross compiling the Cocotron Foundation framework. The second part explains how to get an exemplary CLI app up and running on Linux.

Part 1: Cross Compiling Foundation

Everyone who knows me knows I’m an advocate of Objective-C, the Foundation framework, and Cocoa. Luckily, in recent years Objective-C has gained wide-spread popularity by virtue of the iPhone/iPad hype. However, there has always been a lack of integration with operating systems not originating from Apple. There are numerous reasons one would want to compile Objective-C based code on Linux, for instance. Imagine you are writing an iPhone multiplayer game and you need a custom server solution for that. Chances are you will want to reuse parts of your client code, but you won’t run an OS X based server farm. If so, you will quickly feel the need for porting lots of Objective-C code over to another language, say C/C++, simply because there is no (easy) way to get your original code working on the server platform.

Fortunately, I am not the only one thinking in that direction and so Christopher Lloyd came up with his great Cocotron project. Cocotron provides an open source implementation of the most important frameworks used with Objective-C on the Mac and iOS platforms. What is more, it comes with a cross compiler integration for Xcode. This allows you to build Objective-C based apps for a number of operating systems, e.g. Windows or Linux.

Both Cocotron and Apple are working constantly, so there is need for a good tutorial of how to get started with Cocotron and the newest Apple developer tools on Linux. This is what this article is all about.

Things You Will Need

  • A Mac with OS X 10.6.7+ and Xcode4 (latest developer tools from Apple) installed; you will use this for cross compilation
  • A machine with your target Linux OS installed (we will use Ubuntu 11.04 32-bit here)
  • The Cocotron source code (get it by typing “$ hg clone http://cocotron.googlecode.com/hg/ cocotron” on the terminal)
  • The Cocotron Developer Tools (CDT)

Step 1: Install Cocotron Developer Tools (CDT)

Cocotron’s InstallCDT provides an automatized setup and Xcode integration of tool chains for Objective-C cross compilation. Download the latest InstallCDT package and unzip it to a directory on your Mac.

Step 2: Create a Platform Interface for Cocotron Developer Tools

Installing CDT requires some files from your target platform. We are going to get these in this step. Don’t worry, this is already the most complicated part of the story.

  1. Create directory structure /Developer/Cocotron/1.0/PlatformInterfaces.
  2. In the PlatformInterfaces directory, create a subdirectory named i386-ubuntu-linux.
  3. From your Ubuntu machine, copy the /usr/include directory to /Developer/Cocotron/1.0/PlatformInterfaces/i386-ubuntu-linux/include on your Mac.
  4. Additionally, from your Ubuntu machine, copy the /usr/src/linux-headers-x.x.xx-x/arch/x86/include/asm diectory to /Developer/Cocotron/1.0/PlatformInterfaces/i386-ubuntu-linux/include/asm on your Mac.
  5. In the i386-ubuntu-linux directory, create a subdirectory named lib.
  6. From your Ubuntu Linux machine, copy the following files to that directory from /usr/lib/i386-linux-gnu:

    crt1.o
    crti.o
    crtn.o
    libc.a
    libc.so
    libc_nonshared.a
    libdl.a
    libdl.so
    libm.a
    libm.so
    libpthread_nonshared.a
    libpthread.a
    libpthread.so

  7. Additionally, copy the following files to lib from your Ubuntu’s lib/i386-linux-gnu directory:

    libc-2.13.so
    libc.so.6 -> libc-2.13.so
    ld-2.13.so
    ld-linux.so.2 -> ld-2.13.so
    libdl-2.13.so
    libdl.so.2 -> libdl-2.13.so
    libpthread-2.13.so
    libpthread.so.0 -> libpthread-2.13.so

  8. Edit libc.so and libpthread.so using a text editor and replace /usr/lib/i386-linux-gnu and /lib/i386-linux-gnu paths with /Developer/Cocotron/1.0/PlatformInterfaces/i386-ubuntu-linux/lib. [Source]
  9. Run install.sh from your InstallCDT directory as follows:
    $ sudo install.sh Linux i386
  10. Finally, change ownership of the /Developer/Cocotron directory as follows:
    $ sudo chown -R YOUR_USER_NAME:admin /Developer/Cocotron

    This will recursively change ownership of /Developer/Cocotron to your user (needed for use with Xcode4.)

Step 3: Getting the Cocotron Source

You can get the Cocotron source by typing the following in a terminal session:

$ hg clone http://cocotron.googlecode.com/hg/ cocotron

Step 4: Compiling Foundation

As an example, let’s compile the Cocotron Foundation project for Ubuntu. Open Xcode4 and load Foundation.xcodeproj from the Cocotron source code. Choose ‘Foundation-Linux-i386′ as active scheme. Build the Cocotron Foundation framework by hitting Cmd+B. If you see ‘Build succeeded’, congratulations, you have taken the first step towards Objective-C on Linux.

Note: the steps described here relate to Ubuntu Linux (11.04). Creating a CDT platform interface for a different platform may require other steps. For more information see Creating a Platform Interface for CDT.

In the next post I am going to make this tutorial complete by explaining how to set up a Cocotron based Xcode project from scratch. That tutorial will also cover installing and running your first Objective-C binary on Ubuntu Linux.

→ 14 CommentsTags:···

Installing Mercurial on a Shared Web Server without Root Access (HostEurope)

April 12th, 2010 · 20 Comments · Server

SVN did a great job for me for at least four years now. Lately, I stumbled upon Mercurial and decided to have a closer look. It turned out that Mercurial (also called “hg”) comes with some great advantages, namely:

  • Not a “Version Control System” (VCS), but a “Distributed Version Control System” (DVCS) enabling you to check in changes locally (offline, without an internet connection). The advantages of this one are also discussed in detail in PEP 374 (Python Foundation).
  • Available in pure Python, therefore installable on a standard shared web server without root access (not a virtual server, just a “web host”). Thereby cutting my costs of maintaining a root server on my own or being charged by a specialized host for an SVN/VPS plan.

This post is a small guide on how to accomplish the mission of installing Mercurial (the pure Python version) on a shared web host. In this exemplary case a “WebPack Pro” that we rent from our ISP of choice, HostEurope, is going to be used. However, what is described herein should basically work for any web hosting plan that fulfills the following requirements. This article is therefore most interesting for people who already own a shared web hosting plan and wish to use that plan for hg hosting also.

Requirements

  • Source version of Mercurial
  • A shared web server at an arbitrary web host enabling execution of CGI scripts written in Python (HostEurope provides Python 2.4 which appears to be sufficient).
  • mod_python or mod_wsgi (better).
  • SSH access to that host. This is required to setup Mercurial on your shared web server. No need for root privileges.

Installation (Step by Step)

  1. Unpack the Mercurial source tarball on your local system.
  2. Create a temporary directory on your web server and transfer the extracted Mercurial source tree to that directory. You can do so via SSH or FTP.
  3. SSH into the server (if you did not so already) and create a top-level directory named “python”. This is going to hold all the Python modules you would like to use, but which are not currently installed on the server’s root Python distribution.
  4. Change to the Mercurial source directory and build the module in pure Python mode (instructions adopted from Mercurial Wiki) :
    $ python setup.py --pure build_py -c -d . build_ext -i build_mo --force
    
  5. Likewise, install the module. Here, it is essential to enter the correct prefix path, as you want an alternate installation following the prefix scheme, not a standard installation. Please specify the path to your “python” directory, which you created in step 3 (in my case this is “../../python”):
    $ python setup.py --pure install --prefix ../../python --force
    
  6. If everything went well setup.py has installed the Mercurial module files to python/lib/python2.4/site-packages and the hg binary to python/bin.
  7. In order to get the hg binary running via SSH you have to export your custom PYTHONPATH so Python knows where to look for the hg modules. Via SSH go to your home directory on the web host and create a .bash_profile file as follows:
    $ cd ~
    $ touch .bash_profile
    

    Open the file in a text editor and add the following line to it (adjust the path so that it fits your configuration):

    export PYTHONPATH=/is/htdocs/wpXXXXX_XXX/python/lib/python2.4/site-packages
    

    In order to make hg accessible from any directory within the shell, add the following line (adjust path corresponding to your environment again):

    export PATH=/is/htdocs/wpXXXXX_XXX/python/bin:$PATH
    
  8. Logout and login again via SSH. Type hg. If you get the Mercurial Distribution SCM help screen you now have finished installation and are ready to go for setting up Mercurial web access.

Setting up hgwebdir.cgi

  1. First of all, create a directory on your webspace for hg. This directory must be reachable via HTTP. You may also want to set up a subdomain, e.g. hg.yourdomain.com and link that to your hg web directory.
  2. Get hgwebdir.cgi from the root of the Mercurial source tree or download hgwebdir.cgi from the Mercurial website, upload it to your hg directory and rename it to index.cgi.
  3. Make sure your web host is configured appropriately to handle .cgi files and index.cgi files. (You should be able to configure these settings in the scripts settings of your ISP’s administrative UI.)
  4. Open index.cgi using your text editor of choice. It is a good idea to check the script environment statement that is located in the first line of the file. It should look like the following:
    #!/usr/bin/env python
    

    This should work on most servers. However, if your python binary is not linked (or located) in /usr/bin/python you may have to correct for this.

  5. Find the following comment # enable importing on demand to reduce startup time. Beneath the comment line there should be two commented lines. Change these lines to something like this:
    import sys
    sys.path.insert(0, "/is/htdocs/wpXXXXX_XXX/python/lib/python2.4/site-packages")
    

    Replace the absolute path to the site-packages directory with your own one.

  6. If everything works as intended, the script should now be callable via HTTP. Enter the address of your hg web directory into your web browser and check whether the script runs correctly.

Setting Up Your First Repository and Configuring hgweb.config

  1. Via SSH you can setup a first test repository like this:
    $ cd /path/to/www/hg
    $ hg init test
    

    hg will create a directory named test and place a .hg subdirectory in it containing repository-specific configuration and payload data.

  2. hgwebdir.cgi has to know which repositories to serve. You tell this by creating a file named hgweb.config. Simply put the config file into the directory of hgwebdir.cgi.
  3. Open the config file with a text editor and add the following lines:
    [paths]
    test=test
    

    Note: more info on how to configure hgwebdir.cgi can be found on HgWebDirStepByStep (in the Mercurial Wiki).

  4. Finally, the repository itself needs some configuration. In test/.hg create a new file named hgrc and add the following lines to it:
    [ui]
    user = Firstname Lastname 
    
    [web]
    push_ssl = false
    allow_push = *
    

    This will register a first user, allow for HTTP pushing, and allow pushing for everyone (we will take care of security later on).

  5. That’s it. Your first repository is served via Mercurial on your shared web host.

Testing the Whole Thing

You may want to do a simple test to check whether your repository is working and you are able to pull and push changes as intended. You can do so by opening a terminal and type something like the following:

$ hg clone http://hg.yourdomain.com/index.cgi/test
$ cd test
$ touch testfile
$ echo "This is just a test" > testfile
$ hg add testfile
$ hg commit -m 'Testing...' -u username
$ hg push

If everything went right, this should add the file testfile to the repository root and push it to the web server.

For now, you hopefully have a working Mercurial repository directory service up and running on your shared web host. However, there are two major flaws. Firstly, the repository address is not as beautiful as it could be, because of the index.cgi contained in any path. Secondly, the repositories are accessible for everyone. We will fix these issues in what follows.

Beautifying hgwebdir Paths

In order to strip index.cgi from the repository URLs we will have to use mod_rewrite (and your server needs to support that apache module).

Go to your hg webdir root directory and create a file named .htaccess. Open the file in a text editor and add the following lines:

# Taken and adapted from http://www.pmwiki.org/wiki/Cookbook/CleanUrls#samedir
# Used at http://ggap.sf.net/hg/
RewriteEngine On
#write base depending on where the base url lives
RewriteBase /
RewriteRule ^$ index.cgi  [L]
# Send requests for files that exist to those files.
RewriteCond %{REQUEST_FILENAME} !-f
# Send requests to hgwebdir.cgi, appending the rest of url.
RewriteRule (.*) index.cgi/$1  [QSA,L]

Note: this apache script rewrites URLs so that any directory queried in the form hg.yourdomain.com/directory is automatically rewritten to hg.yourdomain.com/index.cgi/directory internally. Consequently, users can omit disturbing repetitive typing of index.cgi in hg repository URLs. Please note that you may have to adapt RewriteBase to your specific server environment. If you do not serve hg repositories via a subdomain you should specify the relative base directory of your hg webdir here instead (this may e.g. be /hg if you serve hg repositories via www.yourdomain.com/hg). The approach is also discussed in PublishingMultipleRepositories on the Mercurial Wiki.

Securing hgwebdir

You can secure your hg web directory in multiple ways. You may want to allow pulling by anyone and pushing only to specific core developers. Detailed information about hg authentication can be found on PublishingMultipleRepositories.

However, my intention is to have private repositories, which I share only with my friends (no public pulling). Me and my friends will use HTTP authentication and I will create a user and password for everyone who is allowed to pull and push. Fortunately, this scenario is relatively simple to configure for everyone who knows about apache authentication configuration using htaccess files.

First of all, use htpasswd to create a password file for hg users. Name the file .hgusers and place it in a location that is not accessible via HTTP. For example, you may want to do it this way:

$ cd /private-path
$ htpasswd -c hgusers username
Enter password twice, etc...

Since we already have a .htaccess file, it is even more simple. Re-open the file using a text editor and add the following lines at the end of the file:

# Authentication
AuthName "Please enter your username and password."
AuthType Basic
Require valid-user
AuthUserFile /is/htdocs/wpXXXXX_XXX/.hgusers

Please change the path to the .hgusers file conforming to your server environment.

Congratulations! You now have a running, secured, beautified, pure-python hg repository server on your cheap web hosting account.

Remarks
Building Mercurial in pure Python may have drawbacks in terms of performance. This has more thoroughly been discussed on the Mercurial mailing list, see mailing list archive on pure python Mercurial.

→ 20 CommentsTags:····

WhyNotUnmount 0.3 Beta

December 18th, 2008 · 1 Comment · Projects

WhyNotUnmountWhyNotUnmount 0.3 is out now. Version 0.3 provides a number of stability improvements (multi-threading issues were fixed), improved unmounting of volumes, automatic list updating on device mounting / unmounting, and finally, several updated user interface details.

WhyNotUnmount works on Mac OS X 10.4 (Tiger) and 10.5 (Leopard) and comes as a Universal Binary.

For more information on what the application does, please see the original post on WhyNotUnmount.

Download WhyNotUnmount (DMG, 315 KB, Freeware)

→ 1 CommentTags:·

openFrameworks 005 Python Binding for OS X 10.5 Leopard

December 17th, 2008 · 5 Comments · Creative Coding

A new openFrameworks-Python Binding for OS X 10.5 is finally available for download. The new binding comes with an Xcode project including the openFrameworks 005 source code and required libraries plus an example of how to use the binding. As in the previous versions, after building the binding using Xcode, you may run the test example as follows: open up a terminal, go to the build/release directory of the binding and type: ‘python animation.py’. The example script should run out of the box. If it does not please don’t hesitate to contact me.

Note: for those who want to build the binding for OS X 10.4, please see the readme file contained in the package. It contains hints on how to build the project using the 10.4 SDK.

Requirements: OS X 10.5.5, Xcode 3.1.1+, SWIG, Python 2.5(+)
Download openFrameworks-Python Binding for OS X 10.5

→ 5 CommentsTags:····

© 2013 Tobis Lensing. All rights reserved. Powered by Wordpress — based upon Cutline by Chris Pearson. This page reflects the personal opinion of the author and is in no way linked to institutions the author is working or has worked for. For more information, see the disclaimer.