Thursday, March 14, 2013

Building Growl 2.0.1 to Save $4.99


Today I figured it was time that I bit the bullet and upgraded my instillation of Growl from 1.2.2 to the latest - 2.0.1.  I resisted upgrading before because 1.2.2 was the last free compiled version available.   I am way too cheap to pay for an Open Source project but I never had the ambition to build it.  Hello Mr. Ambition!

Building Growl...how hard can it be?  The Growl developers even have a little write up here on how to do it.  Let's find out.

Requirements


The official build notes list the following requirements:

  • OS X Lion - 10.8
  • Xcode
  • A tool to pull down a clone of the repo, the mercurial client
  • A working Git client
  • A working subversion client

How many different version control systems does one project need?  I'm running OS X Lion 10.7.5 so it looks like I meet all the requirements.  No version of Xcode is recommended so I'm going with the latest that I have - 4.6 (4H127).

Source Code


Getting the source code couldn't be easier...

 $> export LC_ALL="en_US.UTF-8"  
 $> hg clone https://code.google.com/p/growl/  
 $> cd growl  

...search the tags to find the version I want...

 $> hg tags | grep 2.0.1  
 Growl SDK 2.0.1       7311:a28480ee445b  
 HardwareGrowler 2.0.1 7309:7812af68ed41  
 Growl.app 2.0.1       7303:5dc3156fecbd  
 GrowlTunes 2.0b1      6178:fe8985232975  

...and update.

 $> hg update "Growl.app 2.0.1"  

Compiling


I open up Growl.xcodeproj in Xcode and the currently selected scheme is Growl.app > My Mac 64-bit.  Seems legit.  No mention in the build notes if I should use 64 or 32-bit scheme.  64-bit it is!  I went through all the Targets to make sure that all the Base SDK options are set to 10.7.  I also modified the schema (⌘<) to set the Build Configuration to Release.

Kicked off a build and waited for the magic to happen.

John Hancock


I got three errors - all dealing with code signing.  Now the official build notes did mention that this was going to happen so I wasn't too surprised.

Code Signing Errors

We just need to create a self signed certificate.  Open up Keychain Access and go to Keychain Access->Certificate Assistant->Create A Certificate.  Use the identity in the error as the name when creating the certificate.  Don't forget to set the Certificate Type to Code Signing.

Create Certificate

I restarted Xcode and tried the build again.  I clicked 'Always Allow' on the request to use the newly created certificate.

Casting Couch


The code signing errors are gone but there are two new errors in GrowlDisplayWindowController.m.


Plugins/Displays/GrowlDisplayWindowController.m


The errors are complaining about casting from a void* to NSInteger (long).  Most libraries, like NSMapTable in this case, take a void* to allow user-provided data.  You usually pass in a pointer to your data and everyone is happy.  But the developers here took a shortcut by passing in the NSInteger value as the pointer to save themselves from allocating a buffer just to hold an integer value.  This is a pretty common 'trick' that you will find in a lot of code.  What happens when void* and NSInteger are not the same size? Bugs!  For my target machine void* and NSInteger are the same size.

Guess I'm using a newer version of Xcode than the Growl developers and it has a slightly lower tolerance for stuff like this.  There are two quick ways that I can get around this problem.  First, remove the cast to NSInteger...

 NSInteger startPercentage = NSMapGet(startTimes, transition);  
 NSInteger endPercentage = NSMapGet(endTimes, transition);  

...or just make Xcode a little less bitchy. Go into GrowlPlugins Target - Build Settings and remove, -Wbad-function-cast, from Other Warning Flags.

For all the lazy people out there, here is a quick sed one-liner for you...

 $> sed -e "400,401s/(NSInteger) //" -i '' Plugins/Displays/GrowlDisplayWindowController.m  

If you ever get this type of error in your own code, please do not ignore - it is a bug waiting to happen.  And for God's sake, don't fix it the way I'm suggesting here.

Time to try another build.

Format What?


Only one error this time!  Winning!  The wrong format specifier is used - "%u" instead of "%lu".

 $> sed -e "141s/\"%u\"/\"%lu\"/" -i '' Plugins/Actions/SMS/GrowlSMSDisplay.m  

Update 04/14/2013 - If you are using Xcode 4.6.1 (4H512) you need to use "%ld" instead of "%lu".

 $> sed -e "141s/\"%u\"/\"%ld\"/" -i '' Plugins/Actions/SMS/GrowlSMSDisplay.m  

Success


Another build. Success!

Move the freshly minted Growl.app from your Xcode DerivedData directory, usually ~/Library/Developer/Xcode/DerivedData/Growl-xxxx/Build/Products/Release, into your Applications directory.

What Old Version?


To delete the old version of Growl, I simply followed the developer provided instructions.

Running


I noticed that the version listed in the GUI is wrong - 2.0b6 instead of 2.0.1.




Looks like GrowlVersion.h was never updated before being tagged.  I could care less.

Follow-up


After building I started poking around the source more and I noticed that I could have used rake, Release/rakefile, to build.  Something like the following would have probably worked:

 $> cd Release  
 $> VERSION=2.0.1 rake setup  
 $> VERSION=2.0.1 rake build:growl  

Probably would have fixed my version problem too.

No comments:

Post a Comment