<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Basil Shkara</title>
 <link href="http://neat.io/posts/atom.xml" rel="self"/>
 <link href="http://neat.io/posts"/>
 <updated>2011-11-25T11:02:06+11:00</updated>
 <id>http://neat.io/posts</id>
 <author>
   <name>Basil Shkara</name>
   <email>basil@neat.io</email>
 </author>

 
 <entry>
   <title>Automated OTA iOS App Distribution</title>
   <link href="http://neat.io/posts//2010/10/27/automated-ota-ios-app-distribution.html"/>
   <updated>2010-10-27T00:00:00+11:00</updated>
   <id>/2010/10/27/automated-ota-ios-app-distribution</id>
   <content type="html">&lt;p&gt;I&amp;#8217;ve been spending some time setting up &lt;a href='http://hudson-ci.org'&gt;Hudson&lt;/a&gt; on a Mac Pro for continuous integration of Xcode projects. It&amp;#8217;s worked out better than I expected. I started with a goal to allow over-the-air (OTA) distributions of iOS ad hoc builds and am pleased to say that this goal was accomplished.&lt;/p&gt;

&lt;p&gt;OTA distribution is a new feature particular to iOS4, so users on versions prior to this will not be able to take advantage of the feature, however they are still catered for as I&amp;#8217;ll share further down. The primary advantage of having your build server take care of distributing your builds to your beta testers is that you do not have to be concerned with creating correctly signed .ipa files, zipping them up together with the right provisioning profile and then emailing the result to your testers. It streamlines your development process by getting rid of one of the most annoying processes of iOS development: the beta release cycle.&lt;/p&gt;

&lt;p&gt;For OTA distribution, you cannot simply create an ad hoc signed build, zip it up manually and give it the .ipa extension. If the user attempts to install this build and s/he doesn&amp;#8217;t have the same provisioning profile you signed the build with, the installation will fail. Until recently, I thought the only way of creating a valid OTA build was via Xcode&amp;#8217;s &amp;#8216;Build and Archive&amp;#8217; feature which performs some trickery and embeds the provisioning profile somehow into the resulting .ipa. This allows users to install the app and during this installation process, the provisioning profile also gets installed onto the device automatically.&lt;/p&gt;

&lt;p&gt;So what if you want this process automated? Turns out there is a command-line utility which allows you to do the exact same thing as the &amp;#8216;Build and Archive&amp;#8217; tool. In fact, it&amp;#8217;s what gets run when you hit &amp;#8216;Build and Archive&amp;#8217;.&lt;/p&gt;

&lt;h2 id='the_setup'&gt;The Setup&lt;/h2&gt;

&lt;p&gt;All our code is kept on a locally hosted &lt;a href='http://gitorious.org'&gt;Gitorious&lt;/a&gt; instance on a virtual machine somewhere. Hudson is installed on a Mac Pro running Snow Leopard. The rest is just configuration.&lt;/p&gt;

&lt;p&gt;I created a parameterized build in Hudson which just means that you get to supply a lot of environment variables to your running script if you want. I hosted my build scripts in my VCS and I recommend anyone to do the same. Then it&amp;#8217;s just a matter of having the following execute in Hudson: &lt;pre&gt;
bash -c &quot;$(curl -fsS http://github.com/baz/ios-build-scripts/raw/master/build_ipa.sh)&quot;
&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;The script in its entirety is below:&lt;/p&gt;
&lt;pre class='prettyprint'&gt;
#!/bin/bash
# Below are required environment variables with some example content:
# SDK='iphoneos4.1'
# FORMATTED_TARGET_LIST='-alltargets'
# CONFIGURATION='Ad Hoc'
# DISTRIBUTION_CERTIFICATE='iPhone Distribution: Your Company Pty Ltd'
# PROVISIONING_PROFILE_PATH='/Users/tomcat/Library/MobileDevice/Provisioning Profiles/Your_Company_Ad_Hoc.mobileprovision'
# GIT_BINARY='/usr/local/git/bin/git'
# REMOTE_HOST='your.remote.host.com'
# REMOTE_PARENT_PATH='/www/docs/ios_builds'
# MANIFEST_SCRIPT_LOCATION='http://github.com/baz/ios-build-scripts/raw/master/generate_manifest.py'
# ROOT_DEPLOYMENT_ADDRESS='http://your.remote.host.com/ios_builds'
# ARCHIVE_FILENAME='beta_archive.zip'
# KEYCHAIN_LOCATION='/Users/tomcat/Library/Keychains/Your Company.keychain'
# KEYCHAIN_PASSWORD='Password'

# Build project
security default-keychain -s &quot;$KEYCHAIN_LOCATION&quot;
security unlock-keychain -p $KEYCHAIN_PASSWORD &quot;$KEYCHAIN_LOCATION&quot;
xcodebuild -sdk &quot;$SDK&quot; $FORMATTED_TARGET_LIST -configuration &quot;$CONFIGURATION&quot; clean build

GIT_HASH=&quot;$($GIT_BINARY log --pretty=format:'' | wc -l)-$($GIT_BINARY rev-parse --short HEAD)&quot;
GIT_HASH=${GIT_HASH//[[:space:]]}
BUILD_DIRECTORY=&quot;$(pwd)/build/${CONFIGURATION}-iphoneos&quot;
cd &quot;$BUILD_DIRECTORY&quot; || die &quot;Build directory does not exist.&quot;
MANIFEST_SCRIPT=$(curl -fsS $MANIFEST_SCRIPT_LOCATION)
MANIFEST_OUTPUT_HTML_FILENAME='index.html'
MANIFEST_OUTPUT_MANIFEST_FILENAME='manifest.plist'
for APP_FILENAME in *.app; do
	APP_NAME=$(echo &quot;$APP_FILENAME&quot; | sed -e 's/.app//')
	IPA_FILENAME=&quot;$APP_NAME.ipa&quot;
	DSYM_FILEPATH=&quot;$APP_FILENAME.dSYM&quot;

	/usr/bin/xcrun -sdk iphoneos PackageApplication -v &quot;$APP_FILENAME&quot; -o &quot;$BUILD_DIRECTORY/$IPA_FILENAME&quot; --sign &quot;$DISTRIBUTION_CERTIFICATE&quot; --embed &quot;$PROVISIONING_PROFILE_PATH&quot;

	# Create legacy archive for pre iOS4.0 users
	cp &quot;$PROVISIONING_PROFILE_PATH&quot; .
	PROVISIONING_PROFILE_FILENAME=$(basename &quot;$PROVISIONING_PROFILE_PATH&quot;)
	zip &quot;$ARCHIVE_FILENAME&quot; &quot;$IPA_FILENAME&quot; &quot;$PROVISIONING_PROFILE_FILENAME&quot;
	rm &quot;$PROVISIONING_PROFILE_FILENAME&quot;

	# Output of this is index.html and manifest.plist
	python -c &quot;$MANIFEST_SCRIPT&quot; -f &quot;$APP_FILENAME&quot; -d &quot;$ROOT_DEPLOYMENT_ADDRESS/$APP_NAME/$GIT_HASH/$MANIFEST_OUTPUT_MANIFEST_FILENAME&quot; -a &quot;$ARCHIVE_FILENAME&quot;

	# Create tarball with .ipa, dSYM directory, legacy build and generated manifest files and scp them all across
	PAYLOAD_FILENAME='payload.tar'
	tar -cf $PAYLOAD_FILENAME &quot;$IPA_FILENAME&quot; &quot;$DSYM_FILEPATH&quot; &quot;$ARCHIVE_FILENAME&quot; &quot;$MANIFEST_OUTPUT_HTML_FILENAME&quot; &quot;$MANIFEST_OUTPUT_MANIFEST_FILENAME&quot;

	QUOTE='&quot;'
	ssh $REMOTE_HOST &quot;cd $REMOTE_PARENT_PATH; rm -rf ${QUOTE}$APP_NAME${QUOTE}/$GIT_HASH; mkdir -p ${QUOTE}$APP_NAME${QUOTE}/$GIT_HASH;&quot;
	scp &quot;$PAYLOAD_FILENAME&quot; &quot;$REMOTE_HOST:$REMOTE_PARENT_PATH/${QUOTE}$APP_NAME${QUOTE}/$GIT_HASH&quot;
	ssh $REMOTE_HOST &quot;cd $REMOTE_PARENT_PATH/${QUOTE}$APP_NAME${QUOTE}/$GIT_HASH; tar -xf $PAYLOAD_FILENAME; rm $PAYLOAD_FILENAME&quot;

	# Clean up
	rm &quot;$IPA_FILENAME&quot;
	rm &quot;$ARCHIVE_FILENAME&quot;
	rm &quot;$MANIFEST_OUTPUT_HTML_FILENAME&quot;
	rm &quot;$MANIFEST_OUTPUT_MANIFEST_FILENAME&quot;
	rm &quot;$PAYLOAD_FILENAME&quot;
done
&lt;/pre&gt;
&lt;p&gt;Feel free to use and modify the above script. Both scripts I use are located &lt;a href='http://github.com/baz/ios-build-scripts'&gt;here&lt;/a&gt;. The script above expects quite a lot of environment variables to be set so it knows what to do. The expectation is that this script is run in an automated fashion, so you just need to set it up the one time. The environment variables listed at the top of the file are all parameters set in Hudson. This way you can easily change any of the settings should you decide to switch provisioning profiles or server locations.&lt;/p&gt;

&lt;p&gt;The most interesting line is possibly this one: &lt;pre&gt;
/usr/bin/xcrun -sdk iphoneos PackageApplication -v &quot;$APP_FILENAME&quot; -o &quot;$BUILD_DIRECTORY/$IPA_FILENAME&quot; --sign &quot;$DISTRIBUTION_CERTIFICATE&quot; --embed &quot;$PROVISIONING_PROFILE_PATH&quot;
&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;This will create the .ipa for you, codesign it correctly and embed the provisioning profile into the .ipa so that when your beta testers install the build OTA - the profile will be installed automatically as part of the installation. How did I discover this command? &lt;a href='https://devforums.apple.com/message/311711'&gt;This&lt;/a&gt; lonely thread on the Apple developer forums. Turns out if you watch the Console whilst you run &amp;#8216;Build and Archive&amp;#8217; from within Xcode, you&amp;#8217;ll see the command that it runs.&lt;/p&gt;

&lt;p&gt;There is also a &lt;a href='http://github.com/baz/ios-build-scripts/blob/master/generate_manifest.py'&gt;Python script&lt;/a&gt; which gets executed: &lt;pre&gt;
python -c &quot;$MANIFEST_SCRIPT&quot; -f &quot;$APP_FILENAME&quot; -d &quot;$ROOT_DEPLOYMENT_ADDRESS/$APP_NAME/$GIT_HASH/$MANIFEST_OUTPUT_MANIFEST_FILENAME&quot; -a &quot;$ARCHIVE_FILENAME&quot;
&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;This generates the required manifest file (which is just a plist describing your app) and the web page presented to your users. The template for the web page was taken from the &lt;a href='http://github.com/HunterHillegas/iOS-BetaBuilder'&gt;iOS Beta Builder&lt;/a&gt; project.&lt;/p&gt;

&lt;p&gt;The end result is this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Hudson polls the VCS and ensures it has the latest copy of your codebase.&lt;/li&gt;

&lt;li&gt;If a change is detected in the codebase, it initiates a build using the above bash script.&lt;/li&gt;

&lt;li&gt;An .ipa is then created from the built app and the provisioning profile is embedded.&lt;/li&gt;

&lt;li&gt;A .zip file is created with the .ipa and the provisioning profile for legacy iOS3 users.&lt;/li&gt;

&lt;li&gt;The plist manifest file and the index.html web page is generated.&lt;/li&gt;

&lt;li&gt;All of these files plus the .dSYM directory are then copied across to your web server and versioned by the current Git hash.&lt;/li&gt;
&lt;/ol&gt;</content>
 </entry>
 
 <entry>
   <title>App Sales Machine - pulls, parses, stores and emails App Store reports</title>
   <link href="http://neat.io/posts//2009/09/05/app-sales-machine.html"/>
   <updated>2009-09-05T00:00:00+10:00</updated>
   <id>/2009/09/05/app-sales-machine</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;[UPDATE 20090910] Now parsing the Top 200 rankings.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[UPDATE 20090909] App Sales Machine now automatically generates graphs using &lt;a href='http://code.google.com/p/graphy/'&gt;Graphy&lt;/a&gt; and also sends HTML formatted emails.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I recently spent a couple days writing an &lt;a href='http://code.google.com/appengine/'&gt;App Engine&lt;/a&gt; application using the &lt;a href='http://code.google.com/appengine/docs/python/tools/webapp/'&gt;webapp&lt;/a&gt; framework. App Sales Machine does the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Imports a tarball of your existing sales reports and stores them in the datastore.&lt;/li&gt;

&lt;li&gt;Logs into iTunes Connect every morning, downloads your latest sales report and stores it in the datastore.&lt;/li&gt;

&lt;li&gt;Parses the downloaded report and stores the parsed data in the datastore.&lt;/li&gt;

&lt;li&gt;Converts the reported income revenue of your sales to a configurable currency and stores that.&lt;/li&gt;

&lt;li&gt;Pulls the rankings for your app every 8 hours (configurable) and stores that in the datastore.&lt;/li&gt;

&lt;li&gt;Emails a report to a select group of recipients every morning with the latest cumulative figures, as well as the last downloaded report&amp;#8217;s figures.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It utilises the &lt;a href='http://code.google.com/appengine/docs/python/taskqueue/'&gt;task queues API&lt;/a&gt; to fetch your rankings asynchronously in a staggered approach. And if the daily sales report pull times out, it will add that task to the task queue to keep trying until it is downloaded.&lt;/p&gt;

&lt;p&gt;All of this was made possible because of the following pieces of open software:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='http://code.google.com/p/itunes-connect-scraper/'&gt;itunes-connect-scraper&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href='http://www.rogueamoeba.com/utm/2009/05/04/itunesconnectarchiver/'&gt;iTunesConnectArchiver&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href='http://benchatelain.com/2009/03/05/scraping-app-store-rankings-around-the-world/'&gt;app_rank.pl&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href='http://www.crummy.com/software/BeautifulSoup/'&gt;Beautiful Soup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I made some modifications to &lt;code&gt;itunes-connect-scraper&lt;/code&gt; to use the &lt;a href='http://code.google.com/appengine/docs/python/urlfetch/overview.html'&gt;URL Fetch API&lt;/a&gt; so I could increase the connection timeout to the maximum currently allowed on App Engine (10 seconds).&lt;/p&gt;

&lt;p&gt;The data parsing and currency converting code is borrowed and modified from &lt;code&gt;iTunesConnectArchiver&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I also ported the &lt;code&gt;app_rank.pl&lt;/code&gt; Perl script to Python. It was originally written by &lt;a href='http://benchatelain.com/'&gt;Ben Chatelain&lt;/a&gt; but it seems to have been taken down, however it still lives on in other forms albeit still in Perl (read the comments in his original blog post).&lt;/p&gt;

&lt;p&gt;The variety of scripts available to download and parse your own report data is just an indication of the poor state of tools that Apple has provided iPhone developers with which to monitor their sales. In fact an entire ecosystem has sprung up to capitalise on this void (appFigures, heartbeat, TapMetrics, Appstatz, AppViz, My App Sales).&lt;/p&gt;

&lt;p&gt;There &lt;em&gt;are&lt;/em&gt; some free tools (as well as the above scripts) available such as &lt;a href='http://majicjungle.com/majicrank.html'&gt;MajicRank&lt;/a&gt; and &lt;a href='http://github.com/caffo/appsales-mobile/tree/master'&gt;AppSalesMobile&lt;/a&gt; but nothing really comparable to the kind of reporting you get from one of the above paid tools. App Sales Machine isn&amp;#8217;t really comparable either at this stage and I don&amp;#8217;t know if it ever will be.&lt;/p&gt;

&lt;p&gt;There&amp;#8217;s nothing wrong with any of the above tools, in fact I used appFigures for a while and was quite happy with it. App Sales Machine was inspired by their functionality but I just wanted to be in control of my own data.&lt;/p&gt;

&lt;p&gt;In its current state App Sales Machine may offer all the functionality you require. It does for me currently but there is certainly room for extending it&amp;#8217;s current feature set. There is currently a very minimal frontend interface which consists of just a file upload field to upload your existing sales reports. It wouldn&amp;#8217;t be hard to integrate nice charts as email attachments (e.g. &lt;a href='http://code.google.com/p/graphy/'&gt;Graphy&lt;/a&gt;) or even as part of a frontend interface.&lt;/p&gt;

&lt;h2 id='how_to_install'&gt;How to install&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Sign up for a free &lt;a href='http://appengine.google.com/'&gt;Google App Engine&lt;/a&gt; account if you don&amp;#8217;t already have one and create a new GAE application.&lt;/li&gt;

&lt;li&gt;Clone my Git repository. &lt;pre&gt;
git clone git://github.com/baz/app-sales-machine.git
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;Configure &lt;code&gt;settings.py&lt;/code&gt; located in the root directory. I&amp;#8217;ve commented this file thoroughly to indicate which values need to be changed to be specific to the current app(s) you have on the App Store.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class='prettyprint'&gt;
# SKU of the app when you uploaded it to the App Store
&quot;&amp;lt;&amp;lt;SKU&amp;gt;&amp;gt;&quot;: {
	# Human-readable app name which corresponds to the above SKU
	&quot;name&quot;: &quot;&amp;lt;&amp;lt;app name&amp;gt;&amp;gt;&quot;,

	# App ID (can be found from the GET param of your iTunes URL i.e. ?id=xxxxxxxxx)
	&quot;app_id&quot;: &quot;&amp;lt;&amp;lt;app id&amp;gt;&amp;gt;&quot;,

	# Make sure your category name and corresponding ID exists in jobs/app_store_codes.py
	&quot;category_name&quot;: &quot;&amp;lt;&amp;lt;category name&amp;gt;&amp;gt;&quot;,

	# Is your app free?
	&quot;paid&quot;: False,

	# List of dictionaries which represent the human-readable version number and the
	# date the version was released on the App Store
	&quot;versions&quot;: [{'name': 'v1.0', 'date': datetime.date(2009, 6, 22)},
			{'name': 'v1.1', 'date': datetime.date(2009, 7, 18)}],

	# This must be the email address of a registered administrator for the application due to
	# mail API restrictions
	&quot;from_address&quot;: &quot;My Name &amp;lt;sender@example.com&amp;gt;&quot;,

	# List of email addresses you would like the daily reports sent to
	&quot;to_addresses&quot;: [
		'Recipient Name &amp;lt;recipient@example.com&amp;gt;',
	]
}
&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;You can specify more than one product SKU. It is just another key in this dictionary structure. Note: I have not tested App Sales Machine with more than one product as I only have one app in the App Store at the moment. However I designed it to accommodate multiple products so theoretically it should all just work.&lt;/li&gt;

&lt;li&gt;I discovered the App Store category IDs in the &lt;code&gt;app_rank.pl&lt;/code&gt; script were wrong/had changed whilst I was porting it. As such, &lt;code&gt;lib/app_store_codes.py&lt;/code&gt; only contains category IDs for the &amp;#8220;Top 100&amp;#8221; and &amp;#8220;Lifestyle&amp;#8221; categories (categories I am monitoring for my current app). If you use App Sales Machine, you will have to update the &lt;code&gt;CATEGORIES&lt;/code&gt; dictionary with your app&amp;#8217;s particular category. From &lt;a href='http://benchatelain.com/2009/03/05/scraping-app-store-rankings-around-the-world/'&gt;Ben&amp;#8217;s blog entry&lt;/a&gt; on this: &lt;pre&gt;
http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewTop?id=$categoryID&amp;amp;popId=xx
$categoryID is the category id your app is in
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;The only other file you may want to configure is &lt;code&gt;cron.yaml&lt;/code&gt; which describes the schedule of events. It is fairly self-explanatory but for more info, read &lt;a href='http://code.google.com/appengine/docs/python/config/cron.html'&gt;this&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class='prettyprint'&gt;
cron:
- description: Daily report pull
  url: /jobs/pull_report
  schedule: every day 06:00
  timezone: Australia/Sydney

- description: Rankings pull
  url: /jobs/pull_rankings
  # Must be larger than 1 hour, see email_report.py
  schedule: every 8 hours
  timezone: Australia/Sydney

- description: Daily report email push
  url: /jobs/email_report
  schedule: every day 07:00
  timezone: Australia/Sydney
&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Note: ensure your cron pull time is a time that occurs after the previous day&amp;#8217;s report is made available on iTunes Connect otherwise your pull report job will fail for obvious reasons.&lt;/li&gt;

&lt;li&gt;Visit the root URL of your App Engine application and upload a tarball with your existing iTunes Connect reports if you have any.&lt;/li&gt;

&lt;li&gt;Then the only thing left to do is modify your &lt;code&gt;app.yaml&lt;/code&gt; file to correspond to the App Engine application name you created and upload it using the command-line tool or the &lt;a href='http://code.google.com/p/google-appengine-mac-launcher/'&gt;Mac Launcher&lt;/a&gt; tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='what_you_get'&gt;What you get&lt;/h2&gt;

&lt;p&gt;If all goes well, the scheduled email task should push a daily report to your inbox that looks something like this:&lt;/p&gt;
&lt;pre&gt;
Hello,

Here is your daily report for &amp;lt;&amp;lt;app name&amp;gt;&amp;gt;
--

Yesterday's (2009-09-03) download figures:
       - xx

Yesterday's (2009-09-03) upgrade figures:
       - xx

Total number of downloads (2009-06-22 to 2009-09-03):
       - xxxxx

Total number of upgrades (2009-07-18 to 2009-09-03):
       - xxxxx

Upgrade rate (over base of xxxxx):
       - xx.xx%

Approximate total income revenue (AUD):
       - 0.0

Rankings (as of 2009-09-04 16:59:27.615497 UTC):

       Country                  Category                 Ranking
       -------                  --------                 -------
       New Zealand              Lifestyle                67
       Australia                Lifestyle                6
&lt;/pre&gt;
&lt;p&gt;I&amp;#8217;ve been using App Sales Machine for the past week and it&amp;#8217;s been working beautifully. It lets me and the other stakeholders in the app know about its progress and how it&amp;#8217;s tracking.&lt;/p&gt;

&lt;p&gt;And because everything is stored in GAE&amp;#8217;s datastore under your own administrator account, you can write new &lt;code&gt;webapp&lt;/code&gt; handlers and templates to query the data and generate graphs, etc. if you wish.&lt;/p&gt;

&lt;p&gt;The usual disclaimers apply here. Although I&amp;#8217;ve been using it happily for a while now, I take no responsibility for incorrect reporting or loss of data that App Sales Machine causes. With that being said, I hope you find a use for it.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Using the LLVM/Clang Static Analyzer for iPhone apps</title>
   <link href="http://neat.io/posts//2009/01/06/using-the-llvm-clang-static-analyzer-for-iphone-apps.html"/>
   <updated>2009-01-06T00:00:00+11:00</updated>
   <id>/2009/01/06/using-the-llvm-clang-static-analyzer-for-iphone-apps</id>
   <content type="html">&lt;p&gt;This set of instructions will help you get started with finding potential bugs in your app. They are provided for developers who do not have their provisioning certificate yet.&lt;/p&gt;

&lt;p&gt;Why would you want to use this static code analysis tool? Why wouldn&amp;#8217;t you? It&amp;#8217;s another tool in your belt to detect bugs early and is probably a good idea to do before submission to the App Store.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure the project active build configuration is the &lt;code&gt;Debug&lt;/code&gt; profile that Xcode sets up for you when you create a new iPhone project. &lt;pre&gt;
Project &amp;gt; Set Active Build Configuration &amp;gt; Debug
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;Navigate to your project directory in your shell and check that you can run &lt;code&gt;xcodebuild&lt;/code&gt; from the root directory of your project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you haven&amp;#8217;t run this tool before, you may run into this output:&lt;/p&gt;
&lt;pre&gt;
$ xcodebuild
=== BUILDING NATIVE TARGET Property Machine OF PROJECT Test Project WITH THE DEFAULT CONFIGURATION (Debug) ===

Checking Dependencies...
CodeSign error: Code Signing Identity 'iPhone Developer' does not match any code-signing certificate in your keychain.  Once added to the keychain, touch a file or clean the project to continue.
** BUILD FAILED **
&lt;/pre&gt;
&lt;p&gt;In this particular case, the project was set up to build against the iPhone device and not the iPhone simulator. Building for the device requires you to use an iPhone provisioning certificate which can be had for USD 99 from the &lt;a href='http://developer.apple.com/iPhone/program'&gt;Apple iPhone Developer Program&lt;/a&gt;. If you wish to write and compile software without a provisioning certificate - you may still test your app in the simulator provided with the SDK however you will not be able to test your app on the device itself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You must change your build settings for the project. &lt;pre&gt;
Project &amp;gt; Edit Project Settings
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;Ensure the Base SDK is set to &lt;code&gt;Simulator - iPhone OS 2.2&lt;/code&gt; (or whichever version of the iPhone OS you wish to build for).&lt;/li&gt;

&lt;li&gt;Ensure the &lt;code&gt;Code Signing Identity&lt;/code&gt; is set to &lt;code&gt;Don&amp;#39;t Code Sign&lt;/code&gt; (if you don&amp;#8217;t have a provisioning certificate yet).&lt;/li&gt;

&lt;li&gt;Check the code signing SDK (expand the &lt;code&gt;Code Signing Identity&lt;/code&gt; disclosure) and ensure it is also set to a simulator SDK. Also ensure the value for this option is &lt;code&gt;Don&amp;#39;t Code Sign&lt;/code&gt;.&lt;/li&gt;

&lt;li&gt;You should end up with something like this:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img alt='Xcode Project Properties' src='/posts/post_resources/20090106_01.png' /&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Back in your shell, you should be able to run &lt;code&gt;xcodebuild&lt;/code&gt; inside your project&amp;#8217;s directory and your project should now build.&lt;/li&gt;

&lt;li&gt;Download the analyzer tool from &lt;a href='http://clang.llvm.org/StaticAnalysisUsage.html'&gt;here&lt;/a&gt;, extract it and optionally add it to your path for easy accessibility.&lt;/li&gt;

&lt;li&gt;The analyzer must be run after a &lt;code&gt;xcodebuild clean&lt;/code&gt; command.&lt;/li&gt;

&lt;li&gt;Do so like this: &lt;pre&gt;
xcodebuild clean
scan-build -k -V xcodebuild
&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;After the tool has run, it launches its own web server and opens your default browser allowing you to view the results of the analysis.&lt;/li&gt;

&lt;li&gt;You will be pleasantly surprised at the quality of the results:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img alt='Clang/LLVM Output' src='/posts/post_resources/20090106_02.png' /&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Overview of Jekyll - a static site generator written in Ruby</title>
   <link href="http://neat.io/posts//2008/12/27/overview-of-jekyll--a-static-site-generator-written-in-ruby.html"/>
   <updated>2008-12-27T00:00:00+11:00</updated>
   <id>/2008/12/27/overview-of-jekyll--a-static-site-generator-written-in-ruby</id>
   <content type="html">&lt;p&gt;GitHub Pages was &lt;a href='http://github.com/blog/272-github-pages'&gt;announced&lt;/a&gt; a couple of weeks ago and seemed to be received &lt;a href='http://www.reddit.com/r/programming/comments/7kexh/github_pages_a_home_for_you_and_your_projects'&gt;quite&lt;/a&gt; &lt;a href='http://news.ycombinator.com/item?id=402648'&gt;well&lt;/a&gt;. Although I find this service extremely awesome, especially now that they&amp;#8217;ve gone even &lt;a href='http://github.com/blog/277-pages-generator'&gt;further&lt;/a&gt; with it than their initial announcement, the bit of news that excited me more was released much earlier: &lt;a href='http://github.com/blog/277-pages-generator'&gt;Jekyll&lt;/a&gt;. In fact, I used Jekyll to generate this site for me.&lt;/p&gt;

&lt;p&gt;The connection between GitHub Pages and Jekyll is that each Pages-bound repo is piped through Jekyll automatically, allowing you to create a site and host it at GitHub. The beauty of this system is that all your posts and site changes are stored in your Git repo allowing your site the benefits of a distributed VCS such as the ability to sync your site on any machine, pull or push changes to the GitHub repo and publishing posts remotely by pushing new posts in raw markdown form to GitHub.&lt;/p&gt;

&lt;p&gt;Of course you can choose not to use Jekyll with GitHub and opt for another VCS or eschew VCS altogether. So far you may be thinking that these benefits don&amp;#8217;t seem like much compared to a typical Wordpress install and you&amp;#8217;d be right! After all Wordpress offers version controlled posts, the ability to submit new posts from any web browser and import/export tools for your posts. People who choose to use Jekyll will probably have these requirements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Limited hosting facilities such as lack of a DBMS.&lt;/li&gt;

&lt;li&gt;Command-line junkies.&lt;/li&gt;

&lt;li&gt;Need to merge changes and track revisions VCS style.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In fact, the latter point seems ideal for software projects with large groups of people contributing to the site documentation and is what looks to be addressed by the latest GitHub Pages generation &lt;a href='http://github.com/blog/277-pages-generator'&gt;feature&lt;/a&gt; for existing hosted projects.&lt;/p&gt;

&lt;p&gt;As one redditor commented, the barrier to entry for Jekyll with a VCS is high. You must have knowledge of VCS&amp;#8217;s as well as being very comfortable in the command line. If you are happy with that, the end gain and primary advantage of Jekyll + a VCS seems to be an efficient and transparent way of storing your version controlled posts, plus it lets you &lt;a href='http://tom.preston-werner.com/2008/11/17/blogging-like-a-hacker.html'&gt;blog like a hacker&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id='templating_troubles'&gt;Templating Troubles&lt;/h2&gt;

&lt;p&gt;The worst aspect in setting up this site was dealing with the templating engine &lt;a href='http://www.liquidmarkup.org'&gt;Liquid&lt;/a&gt;. For example I could not find a way to loop over the site topics like so:&lt;/p&gt;
&lt;pre class='prettyprint'&gt;
{&amp;#37; for topics in site.topic_list &amp;#37;}
	{&amp;#37; for post in site.topics.topic &amp;#37;}
		{&amp;#123; post.date | date_to_long_string &amp;#125;} &amp;raquo; {&amp;#123; post.url &amp;#125;} {&amp;#123; post.title &amp;#125;}
	{&amp;#37; endfor &amp;#37;}
{&amp;#37; endfor &amp;#37;}
&lt;/pre&gt;
&lt;p&gt;(Just a note: there is no &lt;code&gt;site.topic_list&lt;/code&gt; attribute. I forked the &lt;a href='http://github.com/baz/jekyll/tree/master'&gt;project&lt;/a&gt; and added it in &lt;code&gt;/lib/site.rb&lt;/code&gt;. Also, there is no &lt;code&gt;site.topics&lt;/code&gt; attribute in v0.3.0. If you wish to use it we&amp;#8217;ll have to see if &lt;a href='http://github.com/mojombo'&gt;Tom&lt;/a&gt; accepts my pull request. Or you can apply my &lt;a href='http://github.com/baz/jekyll/commit/60b81d8a8d967f5e8afb0c323ffeca71897b61dd'&gt;patch&lt;/a&gt;, or you can clone the forked &lt;a href='http://github.com/baz/jekyll/tree/master'&gt;repo&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.topic_list&lt;/code&gt; was just a list of all topics belonging to a site. In this case, I was using Jekyll&amp;#8217;s topics as tags and foregoing categories. The difference seems to me to be semantical and as I don&amp;#8217;t require 2 levels of categorisation for posts, I chose the latter as it appears to me to be a cleaner way of organising posts in terms of directory structure, i.e.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/_posts/tag1/tag2/yyyy-mm-dd-post-title.markdown&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;as opposed to&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/cat1/cat2/_posts/yyyy-mm-dd-post-title.markdown&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So I wanted a method of tagging posts and the ability to display all tags with corresponding posts in a site. For this, I used the pre-existing topics functionality and added the &lt;code&gt;.topics&lt;/code&gt; attribute to the Site Liquid object. This now allows me to display my posts (use the &amp;#8216;topics&amp;#8217; link in this page&amp;#8217;s header) organised by tag/topic.&lt;/p&gt;

&lt;p&gt;The disadvantage of this comes back to Liquid. I could not figure out a way to use the enumerator inside the Liquid for loop tags as an attribute name (see above). So currently this means I must specify the topic name manually like so:&lt;/p&gt;
&lt;pre class='prettyprint'&gt;
{&amp;#37; for post in site.topics.TOPICNAME &amp;#37;}
	{&amp;#123; post.date | date_to_long_string &amp;#125;} &amp;raquo; {&amp;#123; post.url &amp;#125;} {&amp;#123; post.title &amp;#125;}
{&amp;#37; endfor &amp;#37;}
&lt;/pre&gt;
&lt;p&gt;Where &lt;code&gt;TOPICNAME&lt;/code&gt; is &lt;code&gt;ruby&lt;/code&gt; or &lt;code&gt;github&lt;/code&gt; (i.e. the topics for this post, and all the topics currently in use for this site).&lt;/p&gt;

&lt;p&gt;This was the only issue that came up and was not a dealbreaker. That is as complicated as the Liquid markup got.&lt;/p&gt;

&lt;h2 id='how_do_i_get_started_with_jekyll'&gt;How do I get started with Jekyll?&lt;/h2&gt;

&lt;p&gt;So from all this, you can see that Jekyll is still a young project but showing promise and has the ability right now to publish fully blown blogs. It will appeal to people who like to get their hands dirty. However once you have set up the infrastructure of your site, the process of creating and pushing your posts should be very simple.&lt;/p&gt;

&lt;p&gt;Dr Nic has created a &lt;a href='http://drnicwilliams.com/2008/12/21/migrating-project-websites-to-github-pages-with-sake-tasks-new-websites-with-jekyll_generator'&gt;generator&lt;/a&gt; that creates a simple Jekyll site structure for you with a choice of 2 themes. It even includes the &lt;a href='http://disqus.com'&gt;Disqus&lt;/a&gt; and &lt;a href='http://www.lighthouseapp.com'&gt;Lighthouse&lt;/a&gt; code you need. Unfortunately he didn&amp;#8217;t count on the agile skills of the GitHub team who released something even more polished a couple days later in the shape of their very own &lt;a href='http://github.com/blog/277-pages-generator'&gt;Pages generator&lt;/a&gt; which allows existing hosted repo owners to generate a project page from the Admin tab of their account.&lt;/p&gt;

&lt;p&gt;The way in which you get started depends on the initial level of control you wish to have over the site.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You can install the tool on your own server &lt;code&gt;sudo gem install mojombo-jekyll -s http://gems.github.com/&lt;/code&gt; and generate a Jekyll site structure with Dr Nic&amp;#8217;s generator and then tweak it to your liking.&lt;/li&gt;

&lt;li&gt;If you already have a hosted project on GitHub, you can generate a project page from the Admin tab of your repo. (Note: this feature is currently unavailable. In place of the generate link is this text: &lt;em&gt;&amp;#8216;Page generation is disabled while we sort out a bug.&amp;#8217;&lt;/em&gt;.)&lt;/li&gt;

&lt;li&gt;Or you can create a GitHub account if you don&amp;#8217;t have one already, set up a new repo called &lt;code&gt;your_username.github.com&lt;/code&gt; and push your Jekyll structure to it in the master branch.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id='staticsite_generators'&gt;Static-site generators&lt;/h2&gt;

&lt;p&gt;Having only used Jekyll, I found the whole process very satisfying. There is a minimalist simplicity in the ability to serve pre-generated static pages instead of relying on a DBMS to store content for you. As well, all your posts are in simple text files stored in a logical directory structure which is (hopefully) backed up to a VCS in the cloud, minimising the chance that you could ever lose your posts.&lt;/p&gt;

&lt;p&gt;The Unix-like approach of storing everything in text seems to suit this particular application because in essence, there is little that needs to be done to produce content, able to be rendered by web browsers. As well, I am using Vim to author this post - it almost doesn&amp;#8217;t feel like I&amp;#8217;m writing text. It feels like I&amp;#8217;m doing some sort of sysadmin task and that is probably part of the appeal and why I like it so much.&lt;/p&gt;</content>
 </entry>
 
 
</feed>

