Adventures in Cocotron

October 27th, 2008 by glen

The Promise

The promise of Cocotron is a big one. Wrote a Cocoa app? Just add a new Xcode target, hit compile and out shoots a Windows version. Your mountains of Objective-C code now cross compiles and is no longer stranded on the Mac. You put your feet up, having just shipped a Windows app without ever touching a PC. Your cat brings you a freshly brewed cup of coffee. Read on for our journey from app to exe.

     

The Goal

Back in August, we decided that we should have a Windows version of our FileMagnet Uploader, a Mac application which connects to the iPhone via Bonjour and moves files back and forth between the desktop and our FileMagnet iPhone app. If you’ve been in this situation before, you know how much fun a line-by-line Windows port can be. Not only do you have to spend weeks hunched over Visual Studio, re-writing your entire program in a different language, but when you’re done you now have two separate code bases to manage. When a friend recommended that we check out Cocotron as an alternative, we were quite skeptical but agreed to try it out.

The Proof

Skip forward two months. We are now shipping a Windows version of our FileMagnet Uploader, built completely with Xcode from the same source files as the Mac version. Visual Studio was never opened. But wait… 2 months?

The Details

Let’s back up a bit. What is Cocotron? I’ll quote from the website:

      “The Cocotron is an open source project which aims to implement a cross-platform Objective-C API similar to that described by Apple Inc.’s Cocoa documentation. This includes the AppKit, Foundation, Objective-C runtime and support APIs such as CoreGraphics and CoreFoundation.”

In addition to this, you get a modified version of the gcc toolchain, allowing all this to be done from your Mac. The project has an MIT License.

It’s important to point out that Cocotron is targeting more than just Windows. All of the platform specific code is nicely abstracted using a bridge pattern. The Foundation project is implemented for linux too.

Cross Platform?

Let’s back up even more…

Get a couple of Mac software engineers together around a table of Chinese food and eventually they’ll start to debate the best way to do a cross-platform app. Usually, the nicest results come from using a combination of a cross-compiling core and platform specific UI code (a la Safari, Skype, PhotoShop, etc.) Anyone who’s tried to use most cross-compiling UI libraries knows that eventually what you end up with is an app that’s ugly and unruly on both platforms. At least with Cocotron, you end up with a beautiful Mac app, and hey, Windows apps are kind of ugly anyway so there’s no loss there.

Cocotron’s potential usefulness extends beyond user interface. It also includes a reimplementation of the Foundation framework. Foundation provides the powerful data structures, string handling, threading, I/O, etc., which is what makes Cocoa great for rapidly and robustly coding an app’s core logic. It would be a shame to have to use C++ for an app’s core instead of Foundation just because you need it to be cross platform. I can imagine a cross platform app which combines an Objective-C core (using Cocotron’s port of Foundation) with separate Mac and Windows native UI implementations.

Back to Cocotron

Simply follow the instructions to install Cocotron. Now, eagerly add the new Windows target to your Xcode project. Now, hit compile. Now, wait while the errors pile up like fan-boys at the Apple Store on a release day.

What’s wrong? Whoops! It turns out that your app isn’t only Cocoa after all. Okay, I’ll wait here while you go and #ifdef out all of that Mac specific code. That’s right… go find all the Carbon and other Mac-only routines (any Frameworks you’re using outside of Cocoa, such as AddressBook, CoreData, IOKit, CoreAudio, etc.) You’ll have to figure out how to port that stuff later.

Once your app is compiling, you’ll quickly realize that some methods appear at first glance to exist, but are actually just stubbed out for future implementation. Ever want to implement a Cocoa class method? Here’s your chance!

The Reality

The majority of Cocotron is spot-on brilliant, but here are some examples of the kind of things that we did to get FileMagnet up and running on Windows:

• Added unicode path support to the NSFileManager class.
• Added support for displaying truncated strings.
• Added support for drawing unicode strings. (Not very pretty support.)
• Fixed some issues with the NSSocket implementation.
• Worked around or fixed a number of UI bugs. (It was similar to trying to get a Cocoa UI to look right in both OS X 10.4 and 10.5.)
• Since Cocotron is not a complete implementation, we had to implement some methods ourselves, filling in the Windows implementation of the required Cocoa routines. A few examples:
– [NSPropertyList dataFromPropertyList:] (for binary property lists)
– [NSImage TIFFRepresentation]
– [NSFileManager subpathsAtPath:]
– [NSWorkspace iconForFile:]
– [NSMutableString replaceOccurrencesOfString:withString:option:]
• Additionally, Ken posted a few issues/requests to the Cocotron Google Group, and the team responded amazingly fast; they even implemented some functionality that we needed.

Now that the app has shipped, we’ll be merging our additions and fixes back into the Cocotron project as soon as possible.

The primary shortcoming of the Cocotron project may be the lack of a flagship product to drive the effort. It became apparent once we started the port, that the creators weren’t actively using it to create a shipping application. For comparison, take the Cappuccino project. They’re drinking their own Cocoa by using their new framework to make the awesome 280 Slides presentation tool. Cocotron desperately needs something in this vein to flush out bugs and unearth crucial but missing functionality.

I’m a PC

It’s true that we do build our app from Xcode, but we still needed to have Windows around for actually running, debugging and testing the app. However, in this day and age you don’t need to hop to a different machine. We simply used VMware Fusion.

One unexpected bonus was the ability to do source-level debugging of our Cocotron app. The website provides detailed step-by-step instructions for installing Insight-GDB. Once it’s all set up, just one click has you stepping through your Objective-C code on the Windows system. You can even step into the Cocotron framework’s source. (Don’t you wish you could do that with Cocoa?)

Also, I should point out that Windows users expect an installer, so you still do have to sit down on Windows and figure out how Windows installers and code signing work. Finally, don’t forget to struggle through Vista compatibility. Our app didn’t exactly work like a dream the first time we tried Vista. In fact, it didn’t even install.

Cocotron Evolution

Today we asked Cocotron co-creator Chris Lloyd about what the team has in store for us:

      “Cocotron development going forward will continue to focus on the needs of developers who use the project. This will revolve around completion of the existing frameworks and the addition of more frameworks. Some of the larger pieces under active development are a complete high quality Quartz 2D (CoreGraphics) rasterizer, AppKit support on Linux via X11 and a Windows cross-debugger which works with Xcode. There has been interest and some work on CoreData so hopefully we can expand on that component too. The more people use it, report bugs and submit patches the better it will become.”

It’s amazing what this team has been able to accomplish, and it sounds like they’ll continue to crank out new goodness.

In Conclusion

Good stuff, but be prepared to roll up your sleeves and join in the fun! But as Geordi La Forge would say, you don’t have to take our word for it. Try it out yourself! Our next Cocotron adventure will be a breeze now that we’ve fought through the jungle and know just what to expect. Expect it to work, but don’t expect it to be super fun.


20 Responses to “Adventures in Cocotron”

  1. Dr Nic Says:

    Awesome project. Glad its coming together.

  2. jasonrm Says:

    I read the entire post here and thought “wow, this is really awesome”. I then went over to the cocotron site and read over the various pages and thought “if I had not already known what cocotron can do, I never would have know what the heck this thing is supposed to do”…

    Seriously, someone please tell the cocotron folks to steal the line “The promise of Cocotron is a big one. Wrote a Cocoa app? Just add a new Xcode target, hit compile and out shoots a Windows version.”

  3. Scott Guelich Says:

    I’d seen Cocotron but hadn’t run across any real-life stories, so I always wondered how complete and usable it really was.

    Thanks for writing up your experience!

  4. Winawer Says:

    Great post; I hadn’t heard of Cocotron before, but now I’m going to check it out. How does this compare with something like GNUstep?

  5. David Leppik Says:

    I remember back in the NeXTSTEP days when Windows was a supported platform. Rather than doing a simple cross-compile, you would have separate NIB files for Windows and NeXT. That way, with a little extra effort, you got a native look-and-feel for both platforms.

    I wonder how much Cocotron apps feel like ports the Windows side. Do they feel a little off, like Windows ports or Java applications on the Mac? Or do your users feel right at home, in part because Windows apps in general have less UI consistency?

  6. Houman Says:

    This sounds great, do you think you’ll run into any issues using Mac frameworks on a Windows machine? What I mean is do you think Apple will allow it? I hope they do

  7. Alex Kac Says:

    We actually used some of the Cocotron stuff in some of our projects as well and provided bug-fixes back. I’m really quite excited about the though that Cocotron can grow and improve allowing us to perhaps eventually do some really neat things :)

  8. Aaron VonderHaar Says:

    Wow, this looks fantastic! I’ll look forward to playing around with this and trying to port some of my cocoa apps.

  9. Gregory Casamento Says:

    I’m forced to point out that GNUstep already has all of the methods on all of the classes mentioned in your article and has had them for some time.

    I also must point out that it is also possible to build xcode projects on Windows using GNUstep with a tool called “pbxbuild.” As yet pbxbuild is still in beta, but it’s improving rapidly.

    Later, GC

  10. Antonio Cangiano Says:

    This is truly interesting. ISVs can develop native Mac apps and have a Windows version at no extra cost. And this will probably facilitate the creation of open source software that runs on Mac, Windows and Linux, as well. On Linux in particular, there is a great need for applications whose UI have been paid particular attention to.

  11. Mike Says:

    Amazing! The only thing funny is the name Cocotron. I will explain. In Portuguese, coco, or better, cocô, is shit. So the name sounds like shitTron what in fact is perfect, as you are compiling for windows…haha

  12. Keith Bauer Says:

    You explicitly mention threading, yet Cocotron is very un-thread-safe — how do you handle that, or does your app not have multiple threads?

  13. ken Says:

    @Keith: Yes, we do use threads. It seemed to work just fine. Why do you think it’s un-thread-safe?

    @Mike: That’s really funny.

  14. Keith Bauer Says:

    I remembered reading it somewhere, so I took a look at the source. I don’t think I’m reading this wrong…

    -retain and -release aren’t atomic, so if two threads retain/release the same object at once I see nothing preventing the retain count from getting out of synch.

    The retain count is stored in a global hashtable which is mutated on -retain and -release, without locking; I see nothing that would suggest that this is in the least safe from corruption due to concurrent modification.

    http://cocotron.googlecode.com/svn/trunk/Foundation/NSZone/NSZone.m

    +initialize isn’t locked, so if the same class is used first from two different threads simultaneously, it could be called twice.

    http://cocotron.googlecode.com/svn/trunk/Foundation/objc/ObjCClass.m

    There may be more, but those were the things I thought to check.

  15. ken Says:

    @Keith: Thanks for the info. Threading was not one of the areas that caused us any grief. However, from what you say it sounds like some race condition issues do exist.

  16. glen Says:

    @David Leppik: There’s definitely a bit of “ported”-looking UI in the app! Since we don’t have have Windows background, we didn’t see it. But as soon as we showed the app to some Windows users, they immediately pointed out, for example, that the dialog boxes looked non-standard. Some of that can probably be fixed within the Cocotron framework. For more complicated apps, a separate nib file would probably be in order.

  17. Alexei Says:

    So you were adding/fixing things in Cocotron and sitting on your changes, rather than submitting patches to Cocotron as you progress? Why?

    For instance, I implemented “[NSWorkspace iconForFile:]” for Win32 in the current Cocotron tree. But you say you’ve implemented this.

    So either you’re taking credit for my work, or more likely you implemented this back when it wasn’t yet in Cocotron, and sat on your changes without submitting a patch. Then, since I didn’t know of your changes, I re-implemented this which was added to Cocotron. A duplication of effort!

    Please submit fixes/features as patches when you have them ready, rather than sitting on them for months and causing others to duplicate the effort.

  18. glen Says:

    Hi Alexei: No, our changes are not in yet. You should see some of them start coming through the group this week. As for iconForFile:, I just took a look at your version, and let’s just say I don’t think mine will ever see the light of day, as it’s many more levels of nasty!

  19. James Says:

    The most glaring “looks ported” feel will be that Mac apps have OK to the right of Cancel, where Windows users expect OK on the left. Does NSAlert alertWithMessageText: put the default button on the left?

  20. Iain Says:

    That’s Levar Burton, not Geordi LaForge. Cool project, anyway. I wonder how foreign a complex Cocoa application would feel on Windows.

Leave a Reply