Conditionally Building Mac App Store Applications to Exclude Sparkle

A lot of developers are in the process of rebuilding their apps for the Mac App Store. One of the guidelines is not using any update mechanism and leaving the updating to the App Store. Like most developers we also use the Sparkle framework to do our non-App Store updates and figuring out how to build a version of your application without Sparkle can be frustrating. Some developers have already solved it in clever ways – our favorite being Gus Mueller from Flying Meat who uses a script to run a find and replace:

Then when my build script is run for App Store builds (-s) it’ll use /usr/bin/sed against Acorn’s project.pbxproj and replace all instances of Sparkle.framework with Noop.framework. Then the automated build takes place, and Noop.framework gets copied in instead of Sparkle.

But we feel there’s still space for another solution on how to conditionally include Sparkle:

1. You should have a configuration for the App Store. It can be created under the project settings “Configurations” tab. You should duplicate your Release configuration for these new settings.

2. Remove Sparkle from being automatically included in all linker calls. To do this remove it from under the Targets–>Link Binaries With Libraries.

3. Under all your regular configurations (Debug, Release, …) add Sparkle to the linker flags. Open the build setting and set “other linker flags” to “-framework Sparkle”.

OTHER_LDFLAGS = -framework Sparkle

4. You now need to remove Sparkle from the Mac App Store application folder after building it. Create a new custom script build phase to run at the end of your build (Custom Package Processing above) and make the script the following (do make sure that the value of $CONFIGURATION matches the name you set  your new configuration for Mac App Store releases):

#!/bin/sh
# Remove Sparkle Framework for MacAppStore
if [ $CONFIGURATION == MacAppStore ]
then
rm -rf "$TARGET_BUILD_DIR/$FRAMEWORKS_FOLDER_PATH/Sparkle.framework"
fi

The above takes care of the physical framework and linking but you still need to remove any code that calls the Sparkle framework. To do so set a variable in the Mac App Store build that you can use in your code to conditionally include Sparkle calls.

5. In your Mac App Store build setting set a flag, we use:

OTHER_CFLAGS = $(OTHER_CFLAGS) -DMacAppStore

6. Encapsulate all  your sparkle code with #ifdef preprocessor directives.

#ifndef MacAppStore
[[SUUpdater sharedUpdater] checkForUpdatesInBackground];
#endif

7. Don’t forget to update your interface if necessary. Remove any menus and check for update preferences. Include the menus programmatically for non-Mac App Store builds at applicationWillFinishLaunching:

#ifndef MacAppStore

// Insert Check For Updates menu
NSMenu *mainMenu = [NSApp mainMenu];
NSMenu *appMenu = [[mainMenu itemAtIndex:0] submenu];
NSMenuItem *uploadMenu = [[[NSMenuItem alloc] init] autorelease];
[uploadMenu setTitle:NSLocalizedStringWithDefaultValue(@"Check for Updates", nil, frameworkBundle, nil, nil)];
[uploadMenu setTarget:self];
[uploadMenu setAction:@selector(checkForUpdate:)];
[appMenu insertItem:uploadMenu atIndex:1];

#endif

The same method can be used for the eSellerate registration engine. The linker flags would be, “-lEWS -lValidateUniversal” and you would remove both the libEWS.a library and the compressed .zip version of the engine. Hoping the following proves useful to a few developers. Code on.

7 Responses to “Conditionally Building Mac App Store Applications to Exclude Sparkle”

  1. Thorsten Seitz Says:

    What about the entries in the .plist (SUPublicDSAKeyFile, SUFeedURL)?
    Do you remove them with a script, too?

  2. Conor Says:

    The .plist file entries don’t seem to be a problem for Apple so I leave them in on both versions.

  3. Robyn Says:

    I am not an advanced user. I just discovered Sparkle was installed, I guess, when I tried to install and run SMC Fan Control. I do not use the App Store on my Macbook Pro. Can you help me with removing Sparkle Framework from my Mac? I’d appreciate an answer a lot even though I am not advanced. Thanks!

  4. Conor Says:

    There is no need to remove Sparkle for apps that use it as a user. Only developer need to not include it when submitting apps to the App Store for sale. So unless your developing an app and planning to sell it on the Mac App Store you need not worry about uninstalling Sparkle.

  5. Chris Says:

    Can you explain this procedure for Xcode 4? I am looking at XC4 for the first time and it’s really baffling (the schemes and what appears like 4 new layers of stuff). I really want to use the process you have here but can’t figure it out.

  6. Conor Says:

    The procedure would be the same, except that new Xcode makes a lot of the setting harder to find. But most of them would be shown by selecting the project on the left side (would be the first file, blue Xcode icon). From there select the target project in the new inner sidebar. To change build settings (steps 3 and 5) would be the “build settings” tab. To remove frameworks and add a script (steps 2 and 4) would be under the “build phases”.

    Step one does become the complicated step as the new Xcode, as you mentioned, uses schemes. I myself have not figured those out either, I go in and edit the scheme and switch the build settings by hand on the test build each time I want to build the different configurations. I really haven’t been able to wrap my head on how to edit the build settings for each individual configuration. I think my projects are trapped in a limbo area where they can still use the old build settings but under a new scheme that imported them from Xcode 3. I have to sit down and read the documentation when I get some time.

  7. Edmond Major III Says:

    Thanks