Category Archives: Open Source

Dynamic Development Team

The first Xcode 8 beta was released at WWDC, and includes a major revision to the way code signing is handled by default. You can watch the video or read the slides on Apple’s WWDC Videos page.

A major change from Xcode 7 is that Xcode now requires that every target in your project specify a development team, even when the manual code signing option is selected.

This is a nuisance to developers who have fine-tuned their code signing process such that signing is configured elsewhere: for example, in a centralized Xcode configuration file that imparts signing information to all projects in an organization.

The problem is worse for open source projects, where a project may be expected to be checked out and built by a variety of organizations. In this scenario, each organization will have to somehow automate the insertion of a valid team name and ID in the project file after every checkout or update.

The DevelopmentTeam and DevelopmentTeamName values are stored in the Xcode project file, so they can’t be defined in Xcode configuration files the way so many other settings that affect build behaviors can.

Xcode needs some mechanism for providing these values without manually, permanently altering the affected project files. I would welcome either a mechanism for specifying the values in the Xcode configuration file specified for the project, or a wildcard type value that can be selected to indicate the “default team” should be used.

(Radar #26892618)

Update: It turns out my wishes are already answered. The new PROVISIONING_PROFILE_SPECIFIER build setting will impart the desired team information to Xcode, even if provisioning profiles are not used. So, something like this in my Xcode configuration file:

PROVISIONING_PROFILE_SPECIFIER = 493CVA9A35/

Quiets all of Xcode’s gripes about requiring a team name, and doesn’t require that I tediously update every last target with explicit team information. This doesn’t exactly solve the challenge for open source projects, because organizations using an open source project will still have to override the configuration file or build settings for the projects they check out. As far as I know there is no way to define PROVISIONING_PROFILE_SPECIFIER generically, the way you can specify code signing identities as e.g. “Mac Developer”. It would be great if open source projects could declare a PROVISIONING_PROFILE_SPECIFIER (when needed) as:

PROVISIONING_PROFILE_SPECIFIER = Automatic/

And allow the host project’s prevailing team identity automatically apply. But, I am satisfied to know this at least doesn’t need to be manually set everywhere in order to continue building my projects successfully.

WebKit Hacking From The Bleeding Edge

As the developer of an app that depends heavily upon Apple’s WebKit technologies, I have often been grateful that the software is open source. It is by no means easy to wrap one’s head around, but when faced with a vexing problem, I can browse, even build and run a custom copy of WebKit on my system, to step through code and try to reason more clearly about its behavior. I’ve even filed my share of bug reports and patches.

While I am very interested in the evolution of WebKit, I am even more concerned with the evolution of OS X. For this reason, I typically install OS X beta releases far earlier than many of my colleagues. This gives me the opportunity to work day to day with the latest changes coming from Apple, and makes it that much more likely I will spot issues with my apps, concerns with the OS, etc., before my customers do.

As an open source project, I initially believed I could build and run WebKit wherever I choose. After all, isn’t that what “open source” is supposed to be all about? But ah, there’s a catch. At least when it comes to building and running WebKit on OS X releases, there is a dependency on a small, binary-only static library which provides key system-specific linkages to WebKit. Usually this binary is added to the open source project around the time the system release goes public, but not much sooner.

The long and short of it? If you want to build WebKit and you don’t work at Apple, you need to do so from publicly released versions of OS X.

For years, I have found this personally annoying, but also philosophically distasteful. It seems like a problem for Apple, too: it’s in their best interest to have as many WebKit developers as possible staying up to date, building the latest versions, testing, submitting patches, etc. And it’s in their interest to have as many OS X developers running the latest betas of the OS, providing feedback, preparing their apps for the public, etc.

A single developer, with a single Mac, running a single installation of OS X cannot simultaneously be a diligent, interested WebKit developer and a dedicated OS X beta tester. This seems like a problem to me, so I finally reported a bug. Radar 21703162: “Beta OS X releases should facilicate building/running WebKit from source.”

Taking the Shine Off

I have used Sparkle, the open source project for automating in-app updates to Mac apps, for years. It’s been an invaluable gift to myself and hundreds if not thousands of other developers.

It’s precisely because of this popularity that I want to share a convoluted scenario in which catastrophic data loss may occur.

Sparkle’s basic operation consists of checking for an updated version of the host app, downloading it, replacing the host app, and relaunching the freshly-installed version. To achieve this, it makes use of a secondary helper app called finish_installation.app. The app is built and bundled into the Sparkle.framework which a host app links to and bundles in the Frameworks folder of its own app bundle.

If, for any reason, finish_installation.app cannot be located at update time, the host app’s entire application support folder is wiped out.

The very good news is it’s extremely unlikely your app would find itself unable to locate the finish_installation.app in Sparkle’s bundle. Three obvious scenarios jump to mind for how this could happen in practice:

  1. The helper app could be removed from the Sparkle bundle after your app is downloaded and installed on a user’s Mac. This could involve a user fishing around inside your app and deciding that the helper app is not needed, or perhaps a misguided utility app deciding that the helper should be deleted.
  2. The NSBundle-based code for dynamically locating the Sparkle bundle and its contents could fail at runtime. For this to happen I think that there would need to be some bug in Apple’s bundle registration, or change in the expected behavior of either -[NSBundle bundleWithIdentifier:] or -[NSBundle pathForResource:ofType:]. This scenario seems extremely unlikely but nonetheless worth guarding against.
  3. The helper app could be missing from the Sparkle bundle because it was omitted at build time. If in the course of your own mucking about with Sparkle’s Xcode project, you make some change that causes the helper to be removed from the Copy Files phase that normally adds it to Sparkle’s bundle, you would end up with a copy of Sparkle that exhibits the bug.

Why do I know about this bug? Because I fell for scenario #3 above. While merging changes from another version of Sparkle with my own repository, something happened to cause the file to come off the Copy Files list. This sounds unlikely, but anybody who has used Xcode extensively knows that sometimes little changes, a drag here or there, can cause unexpected side effects to membership in targets or copy phase lists.

How does the bug manifest, exactly? During the previously described process of updating an app, Sparkle gets to the point where it wants to run the helper. Before running, it copies it into the host app’s Application Support folder. At least, that’s what it intends to do. It determines the destination path based on the name of the helper app found in the Sparkle bundle. But when that name is nil, the constructed path consists only the host’s Application Support folder:

“Library/Application Support/YourApp” + (nil) = Library/Application Support/YourApp

It then proceeds to try copying from “nil” to the target folder, and … you can probably guess how well that turns out.

The simple fix that prevents catastrophic damage in all cases is to simply skip that copying process whenever the source path comes up nil. For any reason whatsoever. This will cause Sparkle to fall into another failure mode which displays a somewhat cryptic error message, but which at least doesn’t wipe out all of your user’s data for your app.

You can find my patch for addressing the bug on GitHub.