Yesterday I was working on a forthcoming update to Chimey and I noticed something odd. Chimey of course makes use of SparklePlus for automatic updates, and after a test run of my build-for-release script, Sparkle was looking a little odd.
Normally a framework has one or more binaries, with a symbolic link pointing to the current version. From the command line you'd expect something like this:
$ find Sparkle.framework/ -name Sparkle -exec ls -l {} \;
lrwxr-xr-x 1 tph wheel 24 Nov 21 11:20 Sparkle.framework/
/Sparkle -> Versions/Current/Sparkle
-rwxr-xr-x 1 tph wheel 233088 Nov 21 11:20 Sparkle.framework/
/Versions/A/Sparkle
Instead I was seeing this:
find Sparkle.framework/ -name Sparkle -exec ls -l {} \;
-rwxr-xr-x 1 tph wheel 242928 Nov 21 11:20 Sparkle.framework/
/Sparkle
-rwxr-xr-x 1 tph wheel 233088 Nov 21 11:20 Sparkle.framework/
/Versions/A/Sparkle
Yow, how the hell did that happen? I thought it might have something to do with copying the framework, either when compiling or when building the disk image, but that wouldn't account for the different file sizes. A quick check on the current version of Chimey showed that this was something new, not something I'd been doing all along without realizing it.
So what was different? My build-for-release script now signs my code using Leopard code signing.
Apple's documentation on code signing indicates that "You should sign every program in your product, including applications, tools, hidden helper tools, utilities and so forth." Chimey's main bundle includes a preference pane and two helper tools, so I was making sure to sign all of them. The main documentation doesn't mention frameworks specifically, but the Code Signing Release notes indicate that "You may also sign any libraries, frameworks, plugins, and scripts you ship, whether they are delivered with an application or separately." Framework signatures don't get checked yet but might be in the future. I had made my script as future-proof as possible by signing the Sparkle framework now.
But if you sign a framework, the codesign tool modifies the structure of the framework, as I found with Sparkle. Just for sanity's sake I made sure that this affects any Mac OS X framework and is not some kind of Sparkle-specific behavior.
And the file sizes? I can guess what's going on, but I made sure:
$ codesign -vvv Sparkle.framework/Sparkle
Sparkle.framework/Sparkle: valid on disk
$ codesign -vvv Sparkle.framework/Versions/A/Sparkle
Sparkle.framework/Versions/A/Sparkle: code object is not signed
Not only is codesign changing the framework structure, it's also leaving the framework in an inconsistent state with regard to whether it's signed. Instead of one binary I've got two, and even though I signed the framework, one of those two is still unsigned.
At the same time, checking on the framework bundle still returns a valid signature, despite the presence of unsigned code in there:
$ codesign -vvv Sparkle.framework
Sparkle.framework: valid on disk
It's a good thing that Leopard doesn't currently check on framework signatures. For now it seems it's probably best not to bother signing a framework. Although codesign leaves you with something that should work, it's not clear that it's actually doing anything useful, and it's bloating the framework size in the process.
This has been filed as bug #5609522 with Apple, in case anyone from Apple reads this.
Bookmark/Search this post with:
Submitted by Tom Harrington on Wed, 11/21/2007 - 12:46.