<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>Geoff is a software developer living in London. He works for Open Hosting Ltd building apps in Ruby on Rails.
In his spare time he likes to play CoD4 and futz about with other languages.</description><title>Geoff Garside</title><generator>Tumblr (3.0; @geoffgarside)</generator><link>http://blog.geoffgarside.co.uk/</link><item><title>Closedown</title><description>&lt;p&gt;Please see &lt;a href="http://geoffgarside.co.uk/"&gt;&lt;a href="http://geoffgarside.co.uk/"&gt;http://geoffgarside.co.uk/&lt;/a&gt;&lt;/a&gt; for future content&lt;/p&gt;</description><link>http://blog.geoffgarside.co.uk/post/153588368</link><guid>http://blog.geoffgarside.co.uk/post/153588368</guid><pubDate>Sat, 01 Aug 2009 12:43:42 +0100</pubDate></item><item><title>RSpec with MacRuby, part 2</title><description>&lt;a href="http://www.comprovisation.com/news/show/69"&gt;RSpec with MacRuby, part 2&lt;/a&gt;</description><link>http://blog.geoffgarside.co.uk/post/148296033</link><guid>http://blog.geoffgarside.co.uk/post/148296033</guid><pubDate>Fri, 24 Jul 2009 16:35:33 +0100</pubDate></item><item><title>RSpec with MacRuby, part 1</title><description>&lt;a href="http://www.comprovisation.com/news/show/68"&gt;RSpec with MacRuby, part 1&lt;/a&gt;</description><link>http://blog.geoffgarside.co.uk/post/148295925</link><guid>http://blog.geoffgarside.co.uk/post/148295925</guid><pubDate>Fri, 24 Jul 2009 16:35:18 +0100</pubDate></item><item><title>"I swear, sometimes it’s as if Hollywood sets out with “failure” plugged right into..."</title><description>“I swear, sometimes it’s as if Hollywood sets out with “failure” plugged right into the GPS.”&lt;br/&gt;&lt;br/&gt; - &lt;em&gt;&lt;a href="http://popwatch.ew.com/popwatch/2009/05/new-buffy-movie.html"&gt;A Joss Whedon-less ‘Buffy’ movie: Worst idea ever of the year&lt;/a&gt;&lt;/em&gt;</description><link>http://blog.geoffgarside.co.uk/post/113239824</link><guid>http://blog.geoffgarside.co.uk/post/113239824</guid><pubDate>Tue, 26 May 2009 14:36:19 +0100</pubDate></item><item><title>Harsh highlighting</title><description>&lt;p&gt;Just read about the &lt;a href="http://carboni.ca/projects/harsh/"&gt;Harsh&lt;/a&gt; ERb/HAML highlighter, it looks quite cool. Also because it uses UltraViolet it can be powered by my version of the &lt;a href="http://github.com/geoffgarside/oniguruma/tree/master"&gt;Oniguruma&lt;/a&gt; gem.&lt;/p&gt;</description><link>http://blog.geoffgarside.co.uk/post/92221246</link><guid>http://blog.geoffgarside.co.uk/post/92221246</guid><pubDate>Thu, 02 Apr 2009 13:23:58 +0100</pubDate></item><item><title>Initialising Cocoa NSValueTransformers</title><description>&lt;p&gt;Just a quicky, I created my first custom Value Transformer this evening. Normally to register your transformer you have to do something like the following&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;+ (void)initialize
{
    [super initialize];
    [self initialiseValueTransformers];
}
+ (void)initialiseValueTransformers
{
    LoginStatusTransformer *loginStatusTransformer =
        [[[LoginStatusTransformer alloc] init] autorelease];
    [LoginStatusTransformer setValueTransformer:loginStatusTransformer
        forName:@"LoginStatusTransformer"];
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;which hurt that part of my brain which likes clean code because of all the repetition.&lt;/p&gt;

&lt;p&gt;So I cooked up a nice little pre-processor macro to tidy it up&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#define init_transformer(klass) \
    klass *vt##klass = [[[klass alloc] init] autorelease]; \
    [klass setValueTransformer:vt##klass forName:@""#klass]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;so now I have&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;+ (void)initialiseValueTransformers
{
    init_transformer(LoginStatusTransformer);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;which will be expanded out to&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;+ (void)initialiseValueTransformers
{
    LoginStatusTransformer *vtLoginStatusTransformer =
        [[[LoginStatusTransformer alloc] init] autorelease];
    [LoginStatusTransformer setValueTransformer:vtLoginStatusTransformer 
        forName:@"LoginStatusTransformer"];
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;it seems to be working for me at the moment, any bugs in the macro please let me know.&lt;/p&gt;</description><link>http://blog.geoffgarside.co.uk/post/89889056</link><guid>http://blog.geoffgarside.co.uk/post/89889056</guid><pubDate>Thu, 26 Mar 2009 02:09:30 +0000</pubDate></item><item><title>Tweaking RDiscount</title><description>&lt;p&gt;As I mentioned in my previous post I&amp;#8217;d had some issues with &lt;a href="http://pygments.org/"&gt;Pygments&lt;/a&gt; and &lt;a href="http://github.com/rtomayko/rdiscount/tree/master"&gt;RDiscount&lt;/a&gt;. I have been using &lt;a href="http://pygments.org/"&gt;Pygments&lt;/a&gt; to highlight my code blocks in my blog. Unfortunately right after using a code block with &lt;code&gt;linenos&lt;/code&gt; none of the markdown was being parsed anymore.&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://www.pell.portland.or.us/~orc/Code/markdown/"&gt;Discount&lt;/a&gt; library upon which &lt;a href="http://github.com/rtomayko/rdiscount/tree/master"&gt;RDiscount&lt;/a&gt; is based has the ability to output a debug tree which shows the different blocks within the document. Things like paragraphs, quotes, code blocks and so on. Using this I was able to determine that the HTML block which contained the highlighted code was the last block being detected.&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://pygments.org/"&gt;Pygments&lt;/a&gt; highlighted source with line numbers is actually rendered in a table. This table closes with&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and herein lay the problem. The &lt;a href="http://www.pell.portland.or.us/~orc/Code/markdown/"&gt;Discount&lt;/a&gt; library detects the closing HTML tag with the following function&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;static Line *
htmlblock(Paragraph *p, char *tag)
{
    Line *t = p-&amp;gt;text, *ret;
    int closesize;
    char close[MAXTAG+4];

    if ( selfclose(t, tag) || (strlen(tag) &amp;gt;= MAXTAG) ) {
        ret = t-&amp;gt;next;
        t-&amp;gt;next = 0;
        return ret;
    }

    closesize = sprintf(close, "&amp;lt;/%s&amp;gt;", tag);

    for ( ; t ; t = t-&amp;gt;next) {
        if ( strncasecmp(T(t-&amp;gt;text), close, closesize) == 0 ) {
            ret = t-&amp;gt;next;
            t-&amp;gt;next = 0;
            return ret;
        }
    }
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;which as you might be able to tell, on line 17, checks the line for the presence of the HTML closing element. In the case of the &lt;a href="http://pygments.org/"&gt;Pygments&lt;/a&gt; closing element, this was not on its own line. While looking for &lt;code&gt;&amp;lt;/table&amp;gt;&lt;/code&gt; it would only read up to &lt;code&gt;&amp;lt;/td&amp;gt;&amp;lt;/t&lt;/code&gt; from the line before giving up.&lt;/p&gt;

&lt;p&gt;Testing with a pre-pygmentised file and pushing the &lt;code&gt;&amp;lt;/table&amp;gt;&lt;/code&gt; onto its own new line confirmed that this was the problem.&lt;/p&gt;

&lt;h3&gt;But how do we fix it?&lt;/h3&gt;

&lt;p&gt;Well I started out looking for C string searching functions, of course &lt;code&gt;strstr&lt;/code&gt; was the first candidate. Replacing line 17 of the aforementioned &lt;code&gt;htmlblock()&lt;/code&gt; function with&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if ( strstr(T(t-&amp;gt;text), close) != NULL ) {
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;seemed like a good idea, but running the &lt;a href="http://github.com/rtomayko/rdiscount/tree/master"&gt;RDiscount&lt;/a&gt; test suite revealed my naivety of the solution. With my change text such as &lt;code&gt;&amp;lt;/table&amp;gt;&lt;/code&gt; was matched breaking HTML code examples, this wasn&amp;#8217;t good enough.&lt;/p&gt;

&lt;p&gt;I spent much longer than I really should have trying other solutions before having the critical &lt;strong&gt;Eureka&lt;/strong&gt; moment. I should add that prior to this moment I&amp;#8217;d learnt of the more suitable &lt;code&gt;strcasestr()&lt;/code&gt; function to better match the &lt;code&gt;strncasecmp()&lt;/code&gt; function originally used.&lt;/p&gt;

&lt;p&gt;At any rate my &lt;strong&gt;Eureka&lt;/strong&gt; was realising that I was only ever going to need to search a string of closing tags, and that these closing tags would never be preceded by white space. Initially was thinking of using the CTYPE &lt;code&gt;isspace&lt;/code&gt; macro, but a far simpler solution also struck me.&lt;/p&gt;

&lt;p&gt;A closing tag, or string of closing tags will always start with a &lt;code&gt;&amp;lt;&lt;/code&gt;, so provided the line started with &lt;code&gt;&amp;lt;&lt;/code&gt; and then contained the respective closing tag I could reasonably safely assume the HTML block was being closed.&lt;/p&gt;

&lt;p&gt;So I next transformed line 17 of &lt;code&gt;htmlblock()&lt;/code&gt; to&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if ( T(t-&amp;gt;text)[0] == '&amp;lt;' &amp;amp;&amp;amp; strcasestr(T(t-&amp;gt;text), close) != NULL ) {
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and re-ran the &lt;a href="http://github.com/rtomayko/rdiscount/tree/master"&gt;RDiscount&lt;/a&gt; test suite to see if the tests passed, they did. Next I added a snippet of the &lt;a href="http://pygments.org/"&gt;Pygments&lt;/a&gt; table to one of the test files with some extra markdown after it, updated the expected output file as well and re-ran the test suite. Again it all passed perfectly.&lt;/p&gt;

&lt;p&gt;Once this was all done, I committed my changes to a &lt;a href="http://github.com/geoffgarside/rdiscount/tree/pygments-html"&gt;branch&lt;/a&gt; of the &lt;a href="http://github.com/geoffgarside/rdiscount/tree/master"&gt;fork&lt;/a&gt; I&amp;#8217;d made of &lt;a href="http://github.com/rtomayko/rdiscount/tree/master"&gt;RDiscount&lt;/a&gt; and pushed them up to my &lt;a href="http://github.com/geoffgarside/rdiscount/tree/master"&gt;fork&lt;/a&gt; on &lt;a href="http://github.com/"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As I final test I updated the &lt;a href="http://www.pell.portland.or.us/~orc/Code/markdown/"&gt;Discount&lt;/a&gt; source as well and re-ran it over the file to output the debug tree again. I was pleased to see all the right blocks of the file being shown, lovely.&lt;/p&gt;

&lt;h3&gt;Update&lt;/h3&gt;

&lt;p&gt;My fork has been merged with the &lt;a href="http://github.com/rtomayko/rdiscount/commit/6bc35d19747f0ecc71223507663910ccf412b1af"&gt;master&lt;/a&gt; and been &lt;a href="http://github.com/rtomayko/rdiscount/commit/5d452caeff8373a1983e60d790a3dc406275ba18"&gt;refined&lt;/a&gt; as well.&lt;/p&gt;</description><link>http://blog.geoffgarside.co.uk/post/86833349</link><guid>http://blog.geoffgarside.co.uk/post/86833349</guid><pubDate>Mon, 16 Mar 2009 03:12:00 +0000</pubDate></item><item><title>Changing the blogging gear</title><description>&lt;p&gt;I&amp;#8217;ve recently been working on merging my two blogs together into one. One of them I host myself, the other is with &lt;a href="http://tumblr.com/"&gt;Tumblr&lt;/a&gt;. One has stagnated quite severely with the last update April 1st, 2008, the other only seems to get periodic and occasionally small updates.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://twitter.com/"&gt;Twitter&lt;/a&gt; has played a large part in the lack of updates to both of these sites. Through &lt;a href="http://twitter.com/"&gt;Twitter&lt;/a&gt; I can post short thoughts, URLs to items of potential interest and frequently have a more live dialogue with a group of people. I also don&amp;#8217;t plug either of my blogs to any degree really, I provide links to them, but I don&amp;#8217;t go telling people to read them.&lt;/p&gt;

&lt;p&gt;So what, you may ask, is the point in merging them at all? Well I still want to blog, but the point of blogging has changed. I now see blogging as a platform from which I can propose my thoughts or detail my current exploits when they merit it. My recent head injury was one such item mainly because I was asked for further details on it and it wouldn&amp;#8217;t fit the &lt;a href="http://twitter.com/"&gt;Twitter&lt;/a&gt; 140 character limit. The post on MySQL Replication was asked for by a friend of mine, while it was simplistic it helped me iron the process down in my head as well.&lt;/p&gt;

&lt;p&gt;So as the game is changing a bit I&amp;#8217;ve been through all of my old blog posts, correcting spelling mistakes as well as changing some grammar here and there. Its a bit vain I know, but some of it read really poorly, I also went and wrapped nearly all of the code blogs so they&amp;#8217;d be parsed by &lt;a href="http://pygments.org/"&gt;Pygments&lt;/a&gt;. I had some fun with that, especially with &lt;a href="http://github.com/rtomayko/rdiscount/tree/master"&gt;RDiscount&lt;/a&gt; which I am using to parse the Markdown post files. I managed to sort out those problems though and now I&amp;#8217;m just down to sorting out some niggly little bits before I close down the other two and redirect them to one location.&lt;/p&gt;</description><link>http://blog.geoffgarside.co.uk/post/86833175</link><guid>http://blog.geoffgarside.co.uk/post/86833175</guid><pubDate>Mon, 16 Mar 2009 02:44:00 +0000</pubDate></item><item><title>Setting up MySQL Replication</title><description>&lt;p&gt;Today I was asked to set up a MySQL Replication server to allow for &lt;em&gt;failover&lt;/em&gt; on one of the services we operate.&lt;/p&gt;

&lt;p&gt;A friend of mine also asked me to document the procedure as its been a while since he&amp;#8217;d done it and couldn&amp;#8217;t remember. So here goes&amp;#8230;.&lt;/p&gt;

&lt;h3&gt;The Setup&lt;/h3&gt;

&lt;p&gt;I&amp;#8217;ll be doing all of this on &lt;a href="http://freebsd.org/" title="FreeBSD: The Power to Serve"&gt;FreeBSD 7.1&lt;/a&gt; servers and I&amp;#8217;ll be installing things from ports and then setting up the replication part.&lt;/p&gt;

&lt;p&gt;Installing MySQL is pretty much a breeze, I do tend to do this first though&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# cat &amp;lt;&amp;lt;EOF &amp;gt; /etc/make.conf
.if ${.CURDIR:M*/databases/mysql5*}
BUILD_OPTIMIZED=YES
.endif
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;to ensure that MySQL is built to run as quickly as possible. Then you have the simple commands to install the server, assuming you use &lt;code&gt;ports-mgmt/portupgrade&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# portinstall databases/mysql50-server
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;once that has been done on each server then we can begin setting up the replication service.&lt;/p&gt;

&lt;h3&gt;Instruct the Master&lt;/h3&gt;

&lt;p&gt;First we need to tell the master that it is a master, we also need to make sure that it&amp;#8217;ll listen for slaves. So we need to add some things to the configuration file. You can use &lt;code&gt;/etc/my.cnf&lt;/code&gt; which is pretty global but I&amp;#8217;ve opted for &lt;code&gt;/var/db/mysql/my.cnf&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[mysqld]
bind-address      = 192.168.0.10
server-id         = 1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;now, it will listen and it knows its the master.&lt;/p&gt;

&lt;p&gt;Next we need to instruct it where to keep the binary log file for replaying to the slaves so in the same file&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;log-bin           = mysql-bin
expire-logs-days  = 20
max_binlog_size   = 104857600
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;so the binary log file will be written to &lt;code&gt;/var/db/mysql/mysql-bin&lt;/code&gt;, entries older than 20 days should be dropped and it shouldn&amp;#8217;t grow bigger than 100 megabytes.&lt;/p&gt;

&lt;p&gt;Finally we tell it exactly which databases we want to replicate, can you ignore this if you don&amp;#8217;t want to be specific. Again in the same file&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;binlog-do-db      = testdb
binlog-ignore-db  = mysql,test
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;so only our &lt;code&gt;testdb&lt;/code&gt; table will be binary logged, additionally &lt;code&gt;mysql&lt;/code&gt; and &lt;code&gt;test&lt;/code&gt; databases will be ignored.&lt;/p&gt;

&lt;p&gt;Now you can restart your MySQL master server, to check that things are working you can connect to the server and run&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mysql&amp;gt; SHOW MASTER STATUS;
+------------------+----------+---------------+-----------------------+
| File             | Position | Binlog_Do_DB  | Binlog_Ignore_DB      |
+------------------+----------+---------------+-----------------------+
| mysql-bin.000001 |       98 | testdb,testdb | mysql,test,mysql,test | 
+------------------+----------+---------------+-----------------------+
1 row in set (0.01 sec)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and you should get something like above. You can also check to make sure the server is listening for connections with&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# sockstat | grep mysql | grep tcp4
mysql    mysqld     90119 13 tcp4   192.168.0.10:3306   *:*
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Creating a replication user&lt;/h3&gt;

&lt;p&gt;So we need to setup an account on the master server for the slave to use to authenticate itself. To do this we create a &lt;code&gt;REPLICATION SLAVE&lt;/code&gt; using the following MySQL statement&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;GRANT REPLICATION SLAVE ON *.* TO 'slave'@'slavehost' IDENTIFIED BY 'slavepass';
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;we&amp;#8217;ll set these values on the slave as well so that it can authenticate to the master.&lt;/p&gt;

&lt;h3&gt;Instructing the Slave&lt;/h3&gt;

&lt;p&gt;Again I&amp;#8217;ll be keeping my configuration in &lt;code&gt;/var/db/mysql/my.cnf&lt;/code&gt;, so for the slave we need to tell it that it isn&amp;#8217;t top of the food chain and also who is. To do this we add&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[mysqld]
bind-address          = 192.168.0.11
server-id             = 2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;to tell the Slave to listen for connections, this is so that external services which perhaps only need read access to the database can use the slave and save the master for writes.&lt;/p&gt;

&lt;p&gt;Next we must inform the Slave of its masters address and its authentication credentials for use when addressing the Master&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;master-host           = 192.168.0.10
master-user           = slave
master-password       = slavepass
master-connect-retry  = 60
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally as we only want one database to be replicated, in my case at least, add the following line to the configuration file&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;replicate-do-db       = testdb
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;so that only the &lt;code&gt;testdb&lt;/code&gt; database will be replicated.&lt;/p&gt;

&lt;h3&gt;Copying the database to the Slave&lt;/h3&gt;

&lt;p&gt;Firstly we need to know where in the binlog we are at the moment, so on the master server run the following command&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mysql&amp;gt; SHOW MASTER STATUS;
+------------------+----------+---------------+-----------------------+
| File             | Position | Binlog_Do_DB  | Binlog_Ignore_DB      |
+------------------+----------+---------------+-----------------------+
| mysql-bin.000001 |   327128 | testdb,testdb | mysql,test,mysql,test | 
+------------------+----------+---------------+-----------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;remember the &lt;code&gt;File&lt;/code&gt; and &lt;code&gt;Position&lt;/code&gt; values as we&amp;#8217;ll need these to resynchronised the databases once the slave has a copy of the data.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;mysqldump&lt;/code&gt; create a copy of the master database to put onto the slave&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# mysqldump --opt --databases testdb &amp;gt; /root/master-databases.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now copy the &lt;code&gt;/root/master-databases.sql&lt;/code&gt; file to the slave and then import it, assuming you copied it to &lt;code&gt;/root/master-databases.sql&lt;/code&gt; on the slave as well&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# mysql &amp;lt; /root/master-databases.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we need to synchronise the two copies. On the slave load up the &lt;code&gt;mysql&lt;/code&gt; client&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mysql&amp;gt; STOP SLAVE;
mysql&amp;gt; CHANGE MASTER TO MASTER_HOST = '192.168.0.10',
    -&amp;gt; MASTER_USER = 'slave_user', MASTER_PASSWORD = 'slave_pass',
    -&amp;gt; MASTER_LOG_FILE = 'mysql-bin.000001', MASTER_LOG_POS = 327128;
mysql&amp;gt; START SLAVE;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and the changes will be synchronised between the two servers.&lt;/p&gt;

&lt;h3&gt;A quick test&lt;/h3&gt;

&lt;p&gt;Now its a good idea to make some test insertions into the master database and then check to see if they exist on the slave as well. I&amp;#8217;ll leave this part up to you&amp;#8230;&lt;/p&gt;</description><link>http://blog.geoffgarside.co.uk/post/85204504</link><guid>http://blog.geoffgarside.co.uk/post/85204504</guid><pubDate>Tue, 10 Mar 2009 14:03:07 +0000</pubDate></item><item><title>So what happened to me on Friday the 6th of March?</title><description>&lt;p&gt;As so many of these tales unravel it all started with alcohol. I&amp;#8217;d been invited out by Claire for her brother Neils fiancé Alices birthday drinks do. This is only the second time I&amp;#8217;ve met Alice, the first time at their engagement party. I&amp;#8217;ve known Neil for a while as he used to work at the same company I&amp;#8217;m at now.&lt;/p&gt;

&lt;p&gt;At any rate over the course of the night quite a few drinks where consumed.&lt;/p&gt;

&lt;p&gt;Towards the end of the evening, one or two people had started to go home, I felt a bit dizzy quite rapidly. Normally I get a slowly increasing buzz which I know well and use as a good indicator of when to stop drinking. I made my way to the toilets to get some water on my face, unfortunately there was a queue of people coming out of the toilets, so I decided to go back up the spiral staircase to get some air instead. The next couple of events are bit more patchy. I recall standing under the staircase, possibly letting some people past, something also makes me think I might have sat down under the stairs, maybe I was waiting to get into the toilets to splash my face. Things just sort of get a bit black and hazy from there.&lt;/p&gt;

&lt;p&gt;The next thing I remember is seeing Claire and the woman from the coat desk standing over me. Claire was pressing some blue paper towels to my forehead.
I don&amp;#8217;t specifically recall the first couple of questions but they were along the lines of &amp;#8220;are you alright&amp;#8221; and &amp;#8220;how many fingers am I holding up&amp;#8221;. Then we came to the slightly more tricky questions of did I remember what happened. As you can probably guess at this point, I wasn&amp;#8217;t completely sure. I&amp;#8217;d apparently been unconscious for a minute or so as well.&lt;/p&gt;

&lt;p&gt;After a few minutes the ambulance &amp;#8220;drunk bus&amp;#8221; arrived, and the paramedics had a look over me, took my blood pressure, checked my blood sugar and took my details. They said the wound seemed superficial but that someone should keep an eye on me and asked if I&amp;#8217;d come with anyone else, I said no and that I&amp;#8217;d met up with every body at the bar. Once they&amp;#8217;d finished collecting my details the paramedic and I wandered back over to my friends and told them that I should be alright but that someone should keep an eye on me over night as it could be worse than it looked. If I started having blurred vision or started vomiting I should be taken to hospital to be checked out fully.&lt;/p&gt;

&lt;p&gt;Everyone came back out of the bar a few minutes later to decide what to do next, I think the party was winding down so most opted to return home. So we said farewell to each other amidst various Harry Potter comments. Claire offered to take me back to her house and keep an eye on me so we headed off in the direction of the tube. On the way back, before we caught the tube, she checked with one of her house mates that was away for the weekend to see if I could sleep in their bed for the night. Fortunately the tube is quite direct though the whole time I was wishing I had a hat to cover up my stupid forehead. When we got off the tube we had a rather pleasant walk to her house, it was good to chat without the noise of the bar.&lt;/p&gt;

&lt;p&gt;When we got to her house Claire stuck some bandages to my forehead and chin so that I wouldn&amp;#8217;t bleed all over her house mates pillow. We each then went to bed, as I couldn&amp;#8217;t quite sleep yet I posted a &lt;a href="http://twitpic.com/1w2lb"&gt;picture&lt;/a&gt; on twitter and then answered a few questions about it before finally putting head down to sleep.&lt;/p&gt;

&lt;p&gt;Around eight in the morning I woke up and checked my bandages, it was good having them there as my chin had bled a bit during the night. I left them in place and then lay back down in the bed for a bit to rest and run through the evening. After a little while I checked the internet to find some tips on speeding up the healing process. Vitamin C, Zinc and protein all seemed like best things to get, so I decided that I&amp;#8217;d have a fry up with Orange Juice when I got home. The best hangover cure if ever there was one. A tasty multivitamin can follow that up for the Zinc. I also did some &amp;#8220;Brain Training&amp;#8221; as I figured it might help.&lt;/p&gt;

&lt;p&gt;Some time later I got up again and carefully remove the bandages from my face, I managed to loosen the scab on my chin from the bandage with water so I didn&amp;#8217;t tear it all off. At the same time I noticed some abrasions on the side of my face, quite shallow though and they&amp;#8217;d scabbed up pretty quickly by the looks of things, a bit swollen though.&lt;/p&gt;

&lt;p&gt;Around 9.30 Claire came down to check on me, by this time I was feeling reasonably well, as she needed to pack up to go to a ball in the evening I decided I would make my way back home. She gave me some directions back to the tube station and I remembered most of it from the walk the opposite direction the night before.&lt;/p&gt;

&lt;p&gt;I got a couple of strange looks from people on the tube but mainly I kept my head down to avoid everyone. When I got back to Mile End I went into the new Tesco got my fry up supplies and some plasters. Then I had a nice big fry up when I got back to my flat.&lt;/p&gt;

&lt;p&gt;Later that day I discovered a couple other &lt;em&gt;party injuries&lt;/em&gt;, a decent sized but shallow cut on my shoulder and a skinned and bruised knee. None of it, bar the knee, is giving me any real pain and I&amp;#8217;ve not had any dizziness or vomiting since the event.&lt;/p&gt;

&lt;h3&gt;So what &lt;em&gt;actually&lt;/em&gt; happened?&lt;/h3&gt;

&lt;p&gt;Well the best I can piece together is that my head collided with the spiral staircase by the toilets, though its difficult to work out exactly how I got the gash I did from that. The cut on my chin did swell up a little but, but as I&amp;#8217;ve no pain in my jaw I don&amp;#8217;t think I hit it very hard at all. I&amp;#8217;ve also no neck pains so I don&amp;#8217;t think I fell down the stairs at all. I suppose its possible that I just stood up into the edge of a stair, that would probably explain the vertical nature of the &lt;a href="http://files.geoffgarside.co.uk/headwound.jpg"&gt;gash&lt;/a&gt; though its not a straight wound.&lt;/p&gt;

&lt;h3&gt;But I wanna see a picture!!!&lt;/h3&gt;

&lt;p&gt;Ok fine, Jason took a pretty good one of it the other night. Fortunately its healing up reasonably well, so with any luck it should be faded in a week or two.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://files.geoffgarside.co.uk/headwound.jpg" alt="headwound"/&gt;&lt;/p&gt;</description><link>http://blog.geoffgarside.co.uk/post/84953240</link><guid>http://blog.geoffgarside.co.uk/post/84953240</guid><pubDate>Mon, 09 Mar 2009 18:47:00 +0000</pubDate></item><item><title>Proxying through complex situations</title><description>&lt;p&gt;I was recently in need of access to my Windows XP desktop machine which is has
been left at my parents house due to lack of space anywhere I&amp;#8217;ve lived in
London. I had previously set up a port forwarding rule on their home router to
push any RDP connections through to my desktop. Annoyingly as I found these
didn&amp;#8217;t want to work. I don&amp;#8217;t know what is wrong with my parents router but it
won&amp;#8217;t forward any ports, this might have something to do with the DMZ which is
also turned on. I&amp;#8217;ve never been a big fan of remote router access so I got on
to their file server via SSH, installed elinks with SpiderMonkey javascript
support and attempted to connect to the router to see if I&amp;#8217;d set up the port
forwarding. This didn&amp;#8217;t work as the javascript &lt;code&gt;location.replace&lt;/code&gt; is apparently
not a function. This left me a bit stumped as to how I might be able to pull
this off.&lt;/p&gt;

&lt;p&gt;After a bit of searching through the SSH manpage I gave the following a try&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ssh -D 8080 -f -C -q -N parents-fileserver
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;this created a SOCKS proxy through which I could tunnel into their local
network and view the routers management interface. It was after a bit of
unsuccessful playing here that I found out their router doesn&amp;#8217;t always forward
ports properly. This left me in a bit of conundrum.&lt;/p&gt;

&lt;h4&gt;Netcat&lt;/h4&gt;

&lt;p&gt;I would say that the majority of Unix people would have heard of Netcat, aka
&lt;code&gt;nc&lt;/code&gt;. Netcat is a networking tool which lets you do just about anything you
could possibly want to with TCP or UDP. So I wondered if I could create an
instance of &lt;code&gt;nc&lt;/code&gt; to listen on the RDP port and then somehow pass that through
to my desktop machine. A very quick google turned up this command&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ nc -l -p 3389 | nc 10.0.0.10 3389 | nc -b -l -p 3389
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;though many of the command switches had disappeared or their combinations were
now invalid I turned it into this&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ nc -l 3389 | nc 10.0.0.10 3389 | nc -l 3389
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and tried to connect up to my desktop. This command should create an instance
of &lt;code&gt;nc&lt;/code&gt; that listens on the RDP port and pipes whatever it gets through to
another instance of &lt;code&gt;nc&lt;/code&gt; which is connected to my desktop machine, this again
pipes whatever it gets back through the listening port.&lt;/p&gt;

&lt;p&gt;This didn&amp;#8217;t work&amp;#8230; at all.&lt;/p&gt;

&lt;p&gt;So a bit more googling turned up this on the freebsd mailing lists&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ mkfifo /tmp/fifo
$ nc -l 3389 &amp;lt; /tmp/fifo | nc 10.0.0.10 3389 &amp;gt; /tmp/fifo
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;this should again pipe anything hitting the server RDP port to the desktop RDP
port, the desktop RDP traffic gets written into &lt;code&gt;/tmp/fifo&lt;/code&gt; which is then sent
back to the originating client.&lt;/p&gt;

&lt;p&gt;This also didn&amp;#8217;t work&amp;#8230; at all.&lt;/p&gt;

&lt;p&gt;So now I was at a bit of a loss, but the freebsd mailing list entry mentioned
a website from which they were basing their experiment on, so I went to check
that out. The bottom of the page mentioned an alternative solution using a
program called &lt;code&gt;socat&lt;/code&gt;. Ok, I thought, lets give that a try and installed that.&lt;/p&gt;

&lt;p&gt;So I ran the following command to create the &lt;code&gt;socat&lt;/code&gt; proxy&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ socat tcp4-listen:3389,reuseaddr,fork TCP:10.0.0.10:3389
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This worked&amp;#8230; very, very well.&lt;/p&gt;

&lt;p&gt;So now when I need to get into my desktop machine I can SSH to the file server
and setup the proxy, do what I need to and then shut it down when I&amp;#8217;m done.&lt;/p&gt;</description><link>http://blog.geoffgarside.co.uk/post/76180586</link><guid>http://blog.geoffgarside.co.uk/post/76180586</guid><pubDate>Fri, 06 Feb 2009 16:54:59 +0000</pubDate></item><item><title>Ruby on Rails on Vimeo (via Vimeo)

This is brilliant to watch,...</title><description>&lt;iframe src="http://player.vimeo.com/video/2979844" width="400" height="300" frameborder="0"&gt;&lt;/iframe&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Ruby on Rails on Vimeo (via &lt;a href="http://vimeo.com/2979844"&gt;Vimeo&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;This is brilliant to watch, it starts off in SVN and around 5:10 I think its been moved into git. At around 6:05 you might also spot a recognisable avatar ;-)&lt;/p&gt;</description><link>http://blog.geoffgarside.co.uk/post/73718886</link><guid>http://blog.geoffgarside.co.uk/post/73718886</guid><pubDate>Wed, 28 Jan 2009 09:21:57 +0000</pubDate></item><item><title>My first Nu script</title><description>&lt;p&gt;I get bored, quite easily and my desktop picture is no exception to this. Thankfully
in Mac OS X, I believe Windows too, you can have a rotating desktop picture. By
rotating, I don&amp;#8217;t mean spinning, rather I mean you provide a directory of images
and the OS displays them in a random order. So every 5 minutes I get another
image.&lt;/p&gt;

&lt;p&gt;Occasionally it will display and image which I am very bored of, or just don&amp;#8217;t
like. In this case I then have to flip through the images in my &lt;em&gt;Desktop Pictures&lt;/em&gt;
directory to find the offending image and remove it. Every time I had to do
this I was sure there was an easier way. A couple months ago I found that the
&lt;code&gt;~/Library/Preferences/com.apple.desktop.plist&lt;/code&gt; file contained the information
which I required to get the image file name, and more portably the path used
for the &lt;em&gt;Desktop Pictures&lt;/em&gt;. Originally I wrote up a small bash script to &lt;code&gt;grep&lt;/code&gt;
the information I needed from the &lt;code&gt;defaults read&lt;/code&gt; output, but I never liked this.
The reason I never liked this was that the &lt;code&gt;ChangePath&lt;/code&gt; and &lt;code&gt;LastName&lt;/code&gt; property
list keys appeared something like three times in the file. So I was having to
&lt;code&gt;tail&lt;/code&gt; the &lt;code&gt;grep&lt;/code&gt; output to only select the last one, as this is the one I cared
about.&lt;/p&gt;

&lt;p&gt;What I really wanted was a way to use the &lt;code&gt;defaults&lt;/code&gt; program to access a slightly
more complicated key structure than it would allow.&lt;/p&gt;

&lt;h3&gt;Along came Nu&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://programming.nu/" title="Programming Nu"&gt;Nu&lt;/a&gt; is a &lt;a href="http://en.wikipedia.org/wiki/Lisp_programming_language" title="Lisp on Wikipedia"&gt;lisp&lt;/a&gt; like language written by &lt;a href="http://blog.neontology.com/" title="Tim Burks weblog"&gt;Tim Burks&lt;/a&gt; which
allows access to the &lt;a href="http://en.wikipedia.org/wiki/Cocoa_API" title="Cocoa API on Wikipedia"&gt;Cocoa&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Foundation_Kit" title="Foundation Kit on Wikipedia"&gt;Foundation&lt;/a&gt; API&amp;#8217;s in a
scripting like shell (through &lt;code&gt;nush&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The most I&amp;#8217;d really used &lt;a href="http://programming.nu/" title="Programming Nu"&gt;Nu&lt;/a&gt; for at this point was just playing around
with the &lt;a href="http://en.wikipedia.org/wiki/Cocoa_API" title="Cocoa API on Wikipedia"&gt;Cocoa&lt;/a&gt; API&amp;#8217;s, messing with functions and seeing how things worked.
This is one of the most frequent uses I have of &lt;a href="http://programming.nu/" title="Programming Nu"&gt;Nu&lt;/a&gt; because it lets me
essentially debug interactively in a sensible way.&lt;/p&gt;

&lt;p&gt;Given my rather amateur usage of &lt;a href="http://programming.nu/" title="Programming Nu"&gt;Nu&lt;/a&gt; so far I wanted to try and use it in
its own right. Given my issues with the &lt;code&gt;defaults&lt;/code&gt; program for accessing
complex key paths, and knowing an &lt;code&gt;NSDictionary&lt;/code&gt; would do this easily I thought
this would be a good little dip in the sparkling &lt;a href="http://programming.nu/" title="Programming Nu"&gt;Nu&lt;/a&gt; waters.&lt;/p&gt;

&lt;p&gt;The script below is what I came up with, it is pretty simple, and pretty self
explanatory if you already know the &lt;a href="http://en.wikipedia.org/wiki/Cocoa_API" title="Cocoa API on Wikipedia"&gt;Cocoa&lt;/a&gt; API&amp;#8217;s. As a simple walkthrough
though&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Check to see if the script was called with the &amp;#8220;-rm&amp;#8221; argument

&lt;ol&gt;&lt;li&gt;Set &lt;code&gt;shouldOfferToRemove&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; if it did, &lt;code&gt;nil&lt;/code&gt; if not&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;li&gt;Read in the &lt;code&gt;com.apple.desktop.plist&lt;/code&gt; file contents&lt;/li&gt;
&lt;li&gt;Get the dictionary for the &lt;em&gt;Background/default&lt;/em&gt; key&lt;/li&gt;
&lt;li&gt;Extract the &lt;em&gt;ChangePath&lt;/em&gt; value which is the path to the &lt;em&gt;Desktop Pictures&lt;/em&gt;
directory.&lt;/li&gt;
&lt;li&gt;Extract the &lt;em&gt;LastName&lt;/em&gt; value which is the file name of the image file&lt;/li&gt;
&lt;li&gt;Print the name of the image file&lt;/li&gt;
&lt;li&gt;Prompt the user to delete the file if requested

&lt;ol&gt;&lt;li&gt;Delete the file if instructed&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;The most complicated portion of the script is the part where the response to
either delete or leave the file is read.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(set input (((NSString alloc)
    initWithData:((NSFileHandle fileHandleWithStandardInput) availableData)
    encoding:NSUTF8StringEncoding)
        stringByTrimmingCharactersInSet:
            (NSCharacterSet whitespaceAndNewlineCharacterSet)))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;this section could be broken down a bit to something more like the following&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(set stdin (NSFileHandle fileHandleWithStandardInput))
(set inputData (stdin availableData))
(set inputString ((NSString alloc) initWithData:inputData
  encoding:NSUTF8StringEncoding))
(set trimSet (NSCharacterSet whitespaceAndNewlineCharacterSet))
(set input (inputString stringByTrimmingCharactersInSet:trimSet))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;which does give a better indication of the operations being carried out, firstly
a file handle to the input stream is obtained, then the &lt;code&gt;availableData&lt;/code&gt; is read.
The &lt;code&gt;availableData&lt;/code&gt; returns whatever the user types before hitting &lt;em&gt;Enter&lt;/em&gt;.
The next couple of lines convert the &lt;code&gt;NSData&lt;/code&gt; into an &lt;code&gt;NSString&lt;/code&gt; and then trim
any whitespace or newline characters in the string. This lets the script more
easily compare the input against &amp;#8220;y&amp;#8221; and &amp;#8220;Y&amp;#8221;.&lt;/p&gt;

&lt;p&gt;So without further ado, here is the script (also on &lt;a href="http://gist.github.com/48202" title="Gist: 48202 - Mac OS X Current Background script"&gt;gist&lt;/a&gt;)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/usr/bin/env nush
; Useful script for when you have a rotating background on Mac OS X
; this script will tell you which image is currently being displayed.
; If you add -rm when calling the command then it will provide you with
; prompt to let you delete the background.
;
; Installation:
;  Copy this into something like ~/bin/current_background and then
;  $ chmod 750 ~/bin/current_background
;  then use :D
;
; Usage: (assuming you call it current_background)
; Show the current background image filename
;  $ current_background
;  Current desktop image is background-1.jpg
; Show and optionally delete the current background image file
;  $ current_background -rm
;  Current desktop image is background-1.jpg
;  Are you sure you want to delete background-1.jpg [y/N]: 
;  y
;  Background background-1.jpg has been deleted
;
; Bugs:
;  1. When prompting for user input I can't seem to flush stdout manually
;     so I have to print a new line character in order to show the prompt.
;

(set processInfo (NSProcessInfo processInfo))
(set args (processInfo arguments))

(if (and (eq (args count) 3) (eq (args objectAtIndex:2) "-rm"))
    (set shouldOfferToRemove t)
    (else (set shouldOfferToRemove nil)))

;; Get the dictionary
(set plist ("~/Library/Preferences/com.apple.desktop.plist" stringByExpandingTildeInPath))
(set prefs (NSDictionary dictionaryWithContentsOfFile:plist))

;; Drill down to the dictionary key we care about
(set default ((prefs valueForKey:"Background") valueForKey:"default"))

;; Extract the fields we need
(set changePath (default valueForKey:"ChangePath"))
(set currentImage (default valueForKey:"LastName"))

;; Print the information
(puts "Current desktop image is #{currentImage}")

;; Offer to delete
(if (eq t shouldOfferToRemove)
    (print "Are you sure you want to delete #{currentImage} [y/N]: \n")
    (set input (((NSString alloc)
        initWithData:((NSFileHandle fileHandleWithStandardInput) availableData)
        encoding:NSUTF8StringEncoding)
            stringByTrimmingCharactersInSet:
                (NSCharacterSet whitespaceAndNewlineCharacterSet)))
    (if (or (input isEqualToString:"y") (input isEqualToString:"Y"))
        (set fm (NSFileManager defaultManager))
        (set path (changePath stringByAppendingPathComponent:currentImage))
        (if (fm removeFileAtPath:path handler:nil)
            (puts "Background #{currentImage} has been deleted")
            (else (puts "Background #{currentImage} could not be deleted")))
        (else
            (puts "Background #{currentImage} has not been deleted"))))
&lt;/code&gt;&lt;/pre&gt;</description><link>http://blog.geoffgarside.co.uk/post/71025790</link><guid>http://blog.geoffgarside.co.uk/post/71025790</guid><pubDate>Sat, 17 Jan 2009 00:49:38 +0000</pubDate><category>nu</category><category>script</category><category>desktop picture</category><category>osx</category></item><item><title>"What the Fedora developers failed to realize, however, is that the USS Leonidas was a derelict..."</title><description>“What the Fedora developers failed to realize, however, is that the USS Leonidas was a derelict vessel that the Union army obtained to intentionally sink”&lt;br/&gt;&lt;br/&gt; - &lt;em&gt;&lt;a href="http://arstechnica.com/journals/linux.ars/2009/01/12/fedora-11-codenamed-leonidas-will-kick-bad-guys-into-pit"&gt;Regarding the Fedora 11 codename
&lt;/a&gt;&lt;/em&gt;</description><link>http://blog.geoffgarside.co.uk/post/70166371</link><guid>http://blog.geoffgarside.co.uk/post/70166371</guid><pubDate>Tue, 13 Jan 2009 10:26:17 +0000</pubDate></item><item><title>Apple Wish: Xcode Building Embedded Projects</title><description>&lt;p&gt;I&amp;#8217;ve been spending quite a lot of my time recently using &lt;a href="http://www.apple.com/"&gt;Apple&lt;/a&gt;&amp;#8217;s &lt;a href="http://www.apple.com/xcode/"&gt;Xcode&lt;/a&gt;
just hacking on things which scratch a bit of an itch I get from time to time. Mainly
I&amp;#8217;ve been working on developing Mac OS frameworks for a couple purposes and I recently
wanted to make a GUI demo app which used my framework, so I created a new project and
use a &lt;a href="http://git-scm.com/"&gt;git&lt;/a&gt; submodule to import the framework project. This all worked just fine,
I was able to hook in the framework project to the demo project, set up the framework
as a dependency of the GUI app and slapped the old &lt;em&gt;Build&lt;/em&gt; button and got two errors.&lt;/p&gt;

&lt;p&gt;Seems Xcode first builds the framework into &lt;code&gt;Framework/build/Debug/Framework.framework&lt;/code&gt;
and then the GUI app into &lt;code&gt;build/Debug/Gui.app&lt;/code&gt; which means the GUI app can&amp;#8217;t find the
framework to get the headers from.&lt;/p&gt;

&lt;h2&gt;What are our options?&lt;/h2&gt;

&lt;p&gt;Well what is required is for the build directories of both projects to be the same.
You&amp;#8217;ve got a couple of choices here. You can set an &lt;a href="http://www.apple.com/xcode/"&gt;Xcode&lt;/a&gt; wide preference and
build all projects into a specific directory, or you can set the build directory in
each of the projects (or just one) to make them the same. Lets explore the latter for
the sake of argument as its the least disruptive to other projects.&lt;/p&gt;

&lt;h3&gt;Option 1&lt;/h3&gt;

&lt;p&gt;The first option, which is advocated in &lt;a href="http://www.amazon.co.uk/Xcode-3-Unleashed-Fritz-Anderson/dp/0321552636"&gt;Xcode 3 Unleashed&lt;/a&gt;, is to
place the two projects in the same directory. In this case you have two &lt;code&gt;.xcodeproj&lt;/code&gt;
files in your project directory, which therefore use the same &lt;code&gt;build&lt;/code&gt; directory. The
downside to this method is that it doesn&amp;#8217;t work terribly well with &lt;a href="http://git-scm.com/"&gt;git&lt;/a&gt;
submodules as each submodule has to exist as a separate folder.&lt;/p&gt;

&lt;p&gt;So because of the requirement to use &lt;a href="http://git-scm.com/"&gt;git&lt;/a&gt; submodules this method isn&amp;#8217;t really
that feasible.&lt;/p&gt;

&lt;h3&gt;Option 2&lt;/h3&gt;

&lt;p&gt;A second option might be to change the sub project to build into &lt;code&gt;../build&lt;/code&gt; which is
the build directory of the &lt;em&gt;primary&lt;/em&gt; project. This has the benefit of keeping the
build results in the logical place of the &lt;em&gt;primary&lt;/em&gt; project. The down side is that
you have to modify the submodule in order to make it work. While in most cases if
you &lt;code&gt;git pull&lt;/code&gt; on the submodule to update the source it shouldn&amp;#8217;t break it but it
is a nuisance none the less. So for this reason I also don&amp;#8217;t really like this
option either.&lt;/p&gt;

&lt;h3&gt;Option 3&lt;/h3&gt;

&lt;p&gt;The final option would be to change our GUI project to use the build directory to use
the build directory of the framework project. This keeps us from having to modify the
submodule but I personally don&amp;#8217;t like this solution as it means our &lt;em&gt;primary&lt;/em&gt; project
in this case is building into the space of a &lt;em&gt;sub&lt;/em&gt; project.&lt;/p&gt;

&lt;h2&gt;What would be better?&lt;/h2&gt;

&lt;p&gt;So why is this a wishlist item? Well I&amp;#8217;d personally like to be able to override the
&lt;em&gt;sub&lt;/em&gt; project build directory in the &lt;em&gt;primary&lt;/em&gt; project. So you&amp;#8217;d be able to &lt;em&gt;Get Info&lt;/em&gt;
on the &lt;code&gt;Framework.xcodeproj&lt;/code&gt; in your &lt;em&gt;Groups &amp;amp; Files&lt;/em&gt; pane and change the build
directory. This would then either build the &lt;em&gt;sub&lt;/em&gt; project and then copy those contents
into the &lt;em&gt;primary&lt;/em&gt; projects build directory, or else just have the project when its
being built by the &lt;em&gt;primary&lt;/em&gt; build into the &lt;em&gt;primary&lt;/em&gt; &lt;code&gt;build&lt;/code&gt; directory.&lt;/p&gt;

&lt;h2&gt;Update: A Stop Gap&lt;/h2&gt;

&lt;p&gt;Played around a bit further and I &lt;em&gt;believe&lt;/em&gt; the &lt;em&gt;Frameworks Search Paths&lt;/em&gt; build configuration setting is possibly an appropriate solution. You can set this to say
&lt;code&gt;Framework/build/Debug&lt;/code&gt; for your Debug configuration and then the compiler can find your framework project correctly for compiling. All the changes are happily in your &lt;em&gt;primary&lt;/em&gt; project and it makes sense that it should have to search into the Framework directory for the right files. I&amp;#8217;m a bit happier now :-)&lt;/p&gt;</description><link>http://blog.geoffgarside.co.uk/post/68212213</link><guid>http://blog.geoffgarside.co.uk/post/68212213</guid><pubDate>Sun, 04 Jan 2009 01:43:00 +0000</pubDate></item><item><title>"Next we see a much shorter growing up story – one of a boy with pointy ears. He starts off small and..."</title><description>“Next we see a much shorter growing up story – one of a boy with pointy ears. He starts off small and cute with pointy ears. Then gets bigger (but still with the ears), and turns into someone that modern viewers might recognise as Sylar from Heroes.”&lt;br/&gt;&lt;br/&gt; - &lt;em&gt;&lt;a href="http://www.guardian.co.uk/film/2008/dec/16/star-trek-trailer-review"&gt;Star Trek trailer: all 12-year-olds and whizz-bang action&lt;/a&gt;&lt;/em&gt;</description><link>http://blog.geoffgarside.co.uk/post/65187413</link><guid>http://blog.geoffgarside.co.uk/post/65187413</guid><pubDate>Tue, 16 Dec 2008 17:13:44 +0000</pubDate></item><item><title>"But better to be addicted to smartphones and gismos than cocaine or sex, I suppose. Well, I don’t..."</title><description>“But better to be addicted to smartphones and gismos than cocaine or sex, I suppose. Well, I don’t know, the result is the same after all, very little sleep, great expense and horrific mess everywhere.”&lt;br/&gt;&lt;br/&gt; - &lt;em&gt;&lt;a href="http://www.stephenfry.com/blog/2008/12/11/gee-one-bold-storm-coming-up%E2%80%A6/"&gt;The New Adventures of Mr Stephen Fry&lt;/a&gt;&lt;/em&gt;</description><link>http://blog.geoffgarside.co.uk/post/64133240</link><guid>http://blog.geoffgarside.co.uk/post/64133240</guid><pubDate>Wed, 10 Dec 2008 18:07:39 +0000</pubDate></item><item><title>My iPod is inspired</title><description>&lt;p&gt;The other morning my iPod played the following songs:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Follow the Cops Back Home by Placebo&lt;/li&gt;
&lt;li&gt;Evergreen by Faithless&lt;/li&gt;
&lt;li&gt;Starting Over by The Crystal Method&lt;/li&gt;
&lt;li&gt;Angels by Within Temptation&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;I&amp;#8217;m still not quite sure why these songs flow so well into each other but the sequence really is superb.&lt;/p&gt;</description><link>http://blog.geoffgarside.co.uk/post/59493689</link><guid>http://blog.geoffgarside.co.uk/post/59493689</guid><pubDate>Thu, 13 Nov 2008 13:58:00 +0000</pubDate></item><item><title>Jeff Dunham - Achmed the Dead Terrorist (via KrowBatellio)

Not...</title><description>&lt;iframe width="400" height="225" src="http://www.youtube.com/embed/1uwOL4rB-go?wmode=transparent&amp;autohide=1&amp;egm=0&amp;hd=1&amp;iv_load_policy=3&amp;modestbranding=1&amp;rel=0&amp;showinfo=0&amp;showsearch=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Jeff Dunham - Achmed the Dead Terrorist (via &lt;a href="http://youtube.com/user/KrowBatellio"&gt;KrowBatellio&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Not very &lt;em&gt;PC&lt;/em&gt; but still quite hilarious.&lt;/p&gt;</description><link>http://blog.geoffgarside.co.uk/post/57327487</link><guid>http://blog.geoffgarside.co.uk/post/57327487</guid><pubDate>Fri, 31 Oct 2008 18:27:50 +0000</pubDate></item><item><title>My current iPhone wallpaper, w00t Heroes, via Manicho @...</title><description>&lt;img src="http://25.media.tumblr.com/jVGoLshEnf0n0chm3tBFKZcso1_400.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;My current iPhone wallpaper, w00t Heroes, via &lt;a href="http://manicho.deviantart.com/art/370-iPhone-iPod-Wallpapers-59902072"&gt;Manicho @ DeviantArt&lt;/a&gt;&lt;/p&gt;</description><link>http://blog.geoffgarside.co.uk/post/54332872</link><guid>http://blog.geoffgarside.co.uk/post/54332872</guid><pubDate>Mon, 13 Oct 2008 13:39:42 +0100</pubDate></item></channel></rss>

