Tuesday, March 21, 2006

XCode - Linking Different Static Library Architectures

This had me scratching my head. If you have a static library you want to link into your universal binary, and the library comes in two different files of the same name but in different directories, one for PowerPC and one for Intel i386, then how do you add them both into XCode? Won't the linker find one version first and stop looking and later give an error about missing symbols? Well there are two solutions:

1) Use the lipo utility to join your two static libraries into one universal binary library. This is fine, but you either have to write a script to automate the process or you have to manually run lipo. This is what I did earlier with the gpc runtime library.

2) Make use of the CURRENT_ARCH environment variable. When a universal binary is being built, XCode will set this variable first to "i386", and then later to "ppc". You can use this to set (via XCode's project or target build configuration pane) your library pathnames properly for each half of the build, as in ../mylibs/$(CURRENT_ARCH) which will give a path to your ../mylibs/ppc directory during the PowerPC build and your ../mylibs/i386 directory during the Intel portion. Of course, this requires you arrange your environment in such a fashion. And the directory doesn't even have to be i386/ppc it could be mac_i386/mac_ppc if you used ../mylibs/mac_$(CURRENT_ARCH)

The same thing works for header paths.

One trick I figured out today, if you need to know an XCode environment variable, start a build and look at the beginning of the Build Results log. You'll see all the variables XCode sets. It's a lot faster than trying to guess what to google. A lot faster.

Sunday, March 05, 2006

Actual Cocoa Development

Back in graduate school we had two Macs in the lab. One Mac was fast (for 1993); the other had a CD drive. I wanted to use the fast one, but I also wanted to listen to my small CD collection. So I did what any geekish sort does, I wrote an AppleScript extension, audioCDgh, which allowed me to write short scripts to start the CD playing. That was sort of OK, but not very Mac-like running little scripts when a GUI application was possible. So I wrote my first C++ application, Remote Remote GH, which worked quite well, and started me on over a decade of semi-steady work writing C++ applications.

Well, version 0.19 of MythTV can be controlled via telnet with simple text commands, and I quickly decided it would be very cool to renovate the Remote Remote GH brand with a MythTV edition. So, my nights and weekends have been filled with glorious Cocoa development. Not the trudgery of making a living C++, but honest to goodness, delightfully simple and powerful Objective-C; it's been wonderful and reminded me of why I left chemistry for computers so long ago.

And I'm close to being done. Just this afternoon, I got the TCP socket code working, and have been sending keystrokes to the MythTV box on my local network; it's still very rough, but all the hard stuff is behind me, and just polish and completeness ahead of me. Look for it in a couple weeks.

I've written numerous multimedia controllers over the years, and the one thing I think people miss is that real CD players have buttons for play, stop, fast forward, etc. because they have no alternative; they are limited by their physicality. Computers are less limited. Therefore, RRgh for MythTV will have no such buttons, users will type to send the same commands you would from the Linux keyboard, or double click tables, or navigate via a popup menu; all things a physical CD player's designer could only imagine. Which is a partial shame, as I became quite good at designing play button icons.