Homebrew iOS

From Second Life Wiki
Jump to: navigation, search

Created by Wizardry and Steamworks and brought to you by Kira Komarov, escorting you through iOS land at 0 burritos/hour.

Credit

  • First and foremost Nathan Rajlich for describing how to set up gcc on iDevices and providing some packages that actually work - we did this before and it was a hassle since we needed to mess with Frameworks and ended picking them manually - ouch!
  • Homebrew for doing a great job for Mac users!
  • iphone-dev team for providing the ability to ssh into the device (as well as a few bootstrapping tools which we needed).
  • Apple, of course, for the toys. :-)

Goals

  • Run a webserver with php and a fully-blown mysql on an iOS device (accomplished, earlier, just not as elegant as we will this time).
  • Run a bot on an iPad (yeah it'll work, mono might have to be compiled manually since it is not part of Homebrew).
  • Run OpenSIM on an iOS device (yeah this will work as well, exactly as above).

Coolness Factor

About as cool as the HUMANCENTiPAD.

Seriously though, you fancy running your own grid on your iOS device and hyperjumping to other grids by using the pocket metaverse client? Well, you can... Groovy!

DMCA

Under the Digital Millennium Copyright Act, jailbreaking iPhones is legal in the United States, although Apple has announced that the practice "can violate the warranty". - source, wikipedia (yeah, we're just that lame today).

Introduction

The following documentation and instructions will hopefully progressively grow in order to allow you to run the OpenSIM daemon on iOS devices. As you may have noticed, since Prowler, we have had the opportunity to take an iPad for a spin in order to see what it is capable of.

We were quite impressed to find a Darwin system on it after a jailbreak, or two. The first recommendation is to use Sn0wbreeze instead of Redsn0w or Pwnagetool simply because the former allows you to grow the root partition beyond the insufficient 1GB limit. We have already signaled the bug, it seems that the latter completely ignores the rootfs size and sets it back to 1GB. We have thus chosen Sn0wbreeze and ran it under a VM in order to be able to boot Windows. We set the rootfs size to 7GB which is approximately the dimension of a standard, all-inclusive Slackware distribution (meaning that it is fairly enough). We then transferred the image file back to the Mac and by using Tinyumbrella, and iTunes we managed to flash the iPad with the .ipsw file. We will not cover the process because we believe that the information provided by google and those who spam it, is fairly abundant.

Instead we will jump directly to bootstrapping the environment using Cydia packages, installing an initial development environment and then getting rid of the Cydia packages in order to replace them with fully-automated Homebrew compiled packages.

Motivation

One of major problems with Cydia and the jailbreak is that, well, it is incredibly messy. Most of the tools are built using a cross-compiler which, whilst compiling fast, it also suffers from the side-effect that some paths are build straight into the binaries or scripts. It also has a nasty consequence that it builds dependencies which have to be ported over.

If you really want to know, Kira Komarov was working on the SIM Status and it so happened that pecl_http was needed to do the HTTP part of it and treat the requests nicely, like objects. So, after messing with Cydia, the pecl scripts had paths encoded directly into them. So, well, it was decided that this page should help that problem... xD...

Most Cydia tools are alright, within reason, for the occasional user. However, most of them have a lot of their features ripped out and probably due to the limitations of the build environment they use. The problem is that when you shift hacking to production, a lot of quality gets lost in the translation. In other words, we are aiming to build-up a *NIX-like build environment which will allow for perhaps, more advanced features or packages to be installed. In order to accomplish that, the Cydia applications and *NIX cross-compiled tools are simply insufficient.

What we dislike about Cydia (no worries, we dislike Linux for it too), is that the built-in uninstall feature from the interface, does not scan or remove the dependencies whenever you decide to renounce a package (it can be done with apt-get, it is a dependency issue and not a directly Cydia related issue). This, has the nasty side-effect that the system just keeps expanding... It is not Cydia's fault - there is even a Wikipedia article on it called dependency hell.

Not to mention that a makefile may include:

make install

but not necessarily:

make uninstall

as well; which excludes building any packages my hand (unless something like src2pkg would be used).

We will be using Homebrew. It provides an alternative to MacPorts with a clean interface. We find the following features most interesting:

  • Homebrew uses the /usr/local/ path by default which is standard on an *NIX system for locally installed software as doctrine dictates and makes sense in contrast to /opt where one would conventionally install optional, yet self-contained packages.
  • The system is very clean, every single package has an attached formula, a build-file (similar to LesbianLinux) that gets pulled and the package is compiled and installed on your device. This has the nice consequence of getting all the paths right, linking only to libraries that do exist, complaining when they don't and generally maintaining a fine order of things.
  • Homebrew is generally removable with the following command:
rm -rf /usr/local

and that is really it. Everything you have installed with brew gets wiped and the operating system does not suffer from it. Everything in Homebrew is built with /usr/local as prefix. In that sense, we can mess about with Homebrew by installing packages and thereby not messing up the "real" operating system files.

patchutils Refresher

patchutils are used to create differential patches between files by using diff and then allowing others to apply just the delta by using patch. Here is an example of a patch file which is made using git:

diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh
index 0d2045a..2fdd5ce 100644
--- a/scripts/mysqld_safe.sh
+++ b/scripts/mysqld_safe.sh
@@ -558,7 +558,7 @@ else
 fi
 
 USER_OPTION=""
-if test -w / -o "$USER" = "root"
+if test -w /sbin -o "$USER" = "root"
 then
   if test "$user" != "root" -o $SET_USER = 1
   then

To understand the essential part of it, you can look at the - and + sign which simply indicate, in this example, that:

if test -w / -o "$USER" = "root"

has been removed, and has been replaced by:

if test -w /sbin -o "$USER" = "root"

between the files:

--- a/scripts/mysqld_safe.sh
+++ b/scripts/mysqld_safe.sh

That is, one single line has been replaced.

In this document you will encounter all our changes in diff --Naur notation which is similar:

--- cmd/install.rb.orig	2012-03-08 02:00:41.000000000 +0200
+++ cmd/install.rb	2012-03-08 02:04:31.000000000 +0200
@@ -20,35 +20,35 @@
     install_formulae ARGV.formulae
   end
 
-  def check_ppc
-    case Hardware.cpu_type when :ppc, :dunno
-      abort <<-EOS.undent
-        Sorry, Homebrew does not support your computer's CPU architecture.
-        For PPC support, see: http://github.com/sceaga/homebrew/tree/powerpc
-        EOS
-    end
-  end
+  #def check_ppc
+  # case Hardware.cpu_type when :ppc, :dunno
+  #   abort <<-EOS.undent
+  #     Sorry, Homebrew does not support your computer's CPU architecture.
+  #     For PPC support, see: http://github.com/sceaga/homebrew/tree/powerpc
+  #     EOS
+  # end
+  #end

which essentially means that the whole block with the - sign in front got removed and replaced by the next block with the + sign.

Applying a patch, is easy as well, just takes some getting used to. All you do is navigate to the top-level directory from the header file. In our example it is some directory containing another directory cmd and install.rb.orig in the cmd directory:

cmd/install.rb.orig

Then you create the patch file with an editor, for example:

nano install.rb.patch

and paste the contents of the patch.

After that, you apply the patch:

cat install.rb.patch | patch -p0 --dry-run

The flag:

--dry-run

will not apply the patch and is a good way to test whether the patch will be applied successfully or whether you need to fiddle with it a bit.

The flag:

-p0

represents a relative position between the directory you are in and the directory that the patch will be working from. By increasing the value -p1, -p2, you are really just stripping directories from the patch patch, in our case, at the top of the file:

--- cmd/install.rb.orig	2012-03-08 02:00:41.000000000 +0200

so cmd would be stripped with p1.

If the patch was applied successfully during the dry run, you can apply it definitively by knocking off --dry-run:

cat install.rb.patch | patch -p0

If all else fails, the patches provided here are sufficient to orient yourself in those files and comment out or add what is needed. Just follow the - and +.

Bootstrap: GCC

KBnote.png Note: We previously made some movies for Prowler using veency. The description on Cydia notes that the built-in Apple Screen Sharing is not compatible with iDevices. However, we have found that if you set a password for Veency and then connect through screen-sharing (cmd+k and type vnc://IOS_IP_ADDRESS) you will be asked for the password you set and then get a brief encryption warning. If you continue, then the VNC will connect and you do not need additional software. The steps below might be more convenient if you can connect using Veency.

We make the following assumptions:

  • We name the device running iOS as iDevice which can be any series of machines: iPods, iPhones or iPads...
  • Your iDevice has a rootfs partition is 7GB in size (very, very important - yes, sadly you may need to jailbreak using Sn0wbreeze, yet again...).
  • The iDevice runs at firmware level 4.2.1 (we did say it's coming low-tek). It will work for newer iOSes as well, by following exactly the same "major" guidelines. We just have 4.2.1 right now and we did it with that. The first part, which we took from Nathan Rajlich is the one affected by the iOS version because of the iPhone SDK.
  • The iDevice is jailbroken and has Cydia installed.
  • The iDevice has the IP address IOS_IP_ADDRESS. We will use this constant allover the place when we refer to the IP address of the iDevice.
  • You have Cygwin (for Windows), Linux, BSD a Mac or a VM containing either, which gives you access to *NIX commands.
  • Xcode 3.2.x+ with iOS SDK4.3 which you can download by creating a developer account on Apple.

Most of the bootstrap procedure is due to the excellent instructions provided by Nathan Rajlich. You may want to jump to his page for a while because he provides excellent instructions and we are just summarizing and adding some of our own takes on it.

First thing to do, would be to install:

BigBoss Recommended Tools
aptitude

by using the Cydia interface because it simply is more convenient and then run the following command:

aptitude install file uuid csu odcctools rsync autoconf openssh gawk make python coreutils inetutils git less nano

which should install a minimal environment.

The next step would be to ssh to the iDevice by using:

ssh root@IOS_IP_ADDRESS

which will take a while to generate the ssh keys. Your default password will be alpine. Probably, the next thing you should type after you have logged in is:

passwd

which will allow you to set a new password, try bovine it is equally secure but more cynical (Cydical?).

After that, Nathan Rajlich uploads the rest of the SDK to the iDevice. This is why we needed to extend the rootfs to 7GB because these files will occupy more than 1GB. Some of them may be unnecessary, however we upload them anyway because we have more space now. If you do not have a large rootfs, then please cease with the instructions because this will fill the rootfs and *NIX systems hate it when the filesystem is full.

On a Mac, or if you have unpacked the XCode DMG /PKG file to the root directory, under /Developer..., then the following commands should be issued from your PC to upload via rsync+ssh all the libraries and headers required:

rsync -avz --ignore-existing -e ssh /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/usr/lib/ root@IOS_IP_ADDRESS:/usr/lib
rsync -avz --ignore-existing -e ssh /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/usr/include/ root@IOS_IP_ADDRESS:/usr/include
rsync -avz --ignore-existing -e ssh /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/System/Library/PrivateFrameworks/ root@IOS_IP_ADDRESS:/System/Library/PrivateFrameworks/
rsync -avz --ignore-existing -e ssh /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/System/Library/Frameworks/ root@IOS_IP_ADDRESS:/System/Library/Frameworks/
scp /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/usr/include/crt_externs.h root@IOS_IP_ADDRESS:/usr/include/crt_externs.h

Next, as per the instructions, we ssh into the iDevice:

ssh root@IOS_IP_ADDRESS

and run the following commands:

curl -Ok https://tootallnate.net/how-to-set-up-gcc-on-ios-4/fake-libgcc_1.0_iphoneos-arm.deb
dpkg -i fake-libgcc_1.0_iphoneos-arm.deb

This should install the fake libgcc and we follow-up by installing gcc itself. We run the following commands:

curl -Ok https://tootallnate.net/how-to-set-up-gcc-on-ios-4/iphone-gcc_4.2-20080604-1-8_iphoneos-arm.deb
dpkg -i iphone-gcc_4.2-20080604-1-8_iphoneos-arm.deb

We also additionally create the symlinks, in case we intend to install a different compiler later:

mv /usr/bin/gcc /usr/bin/gcc-4.2
mv /usr/bin/g++-4.2 /usr/bin/g++
ln -sf /usr/bin/gcc-4.2 /usr/bin/gcc
ln -sf /usr/bin/g++-4.2 /usr/bin/g++
ln -sf /bin/gzip /usr/bin/gzip
ln -sf /bin/bzip2 /usr/bin/bzip2

Right now, you can create a file and test whether you are able to compile programs by pasting the following line into the terminal on the iDevice:

echo 'int main(void) { printf("Give me a break, World...\n"); }' > test.c; gcc test.c -o test; ./test; rm test

If you get the message:

Give me a break, World...

then you are ready to move on to the next step.

Bootstrap: Homebrew

Homebrew is a great environment for automatically pulling packages and compiling them on-the fly as well as installing, uninstalling and providing a means to manage packages on a Mac. What we will do, is to graft Homebrew onto iOS so that we benefit from all the features that Homebrew has to offer. We believe that MacPorts is also another, different way to go. Homebrew uses ruby and we find that it is pretty tidy: for example, we like the choice of /usr/local compared to /opt path that MacPorts use.

Homebrew, as well as MacPorts, do not conflict with the rest of the system - which makes them an excellent choice for a good *NIX subsystem on a frail iOS device. From experience, we can say that some formulas will have to be altered in order to accommodate the limitation of the iDevice (yeah, we're not exactly sure that you can run GNOME on it, nor do we need it).

The Homebrew instructions, contain a one-liner with which they recommend installing:

/usr/bin/ruby -e "$(curl -fksSL https://raw.github.com/mxcl/homebrew/master/Library/Contributions/install_homebrew.rb)"

However, that will fail, so for now, we download ruby and compile our own version of it:

curl -Ok http://ftp.ruby-lang.org/pub/ruby/ruby-1.9-stable.tar.gz # might as well upgrade...
tar -zxpvf ruby-1.9-stable.tar.gz
cd ruby-1.9.2-p290/
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var
make
make install

the compile will take some time and will overwrite the Cydia ruby package which apparently fails to work with Homebrew (we suspect it might be the same problem as with pecl, hardcoded paths that do not exist).

The next step is to install Homebrew itself:

curl -fksSL https://raw.github.com/mxcl/homebrew/master/Library/Contributions/install_homebrew.rb -o homebrew
ruby homebrew

Now, Homebrew has a lot of checks, and they are there for a good reason. However, you may disable most of them which are not really needed for the install (perhaps come back later and fix them). We had to reduce the Homebrew file by eliminating most of the checks. The Homebrew delta looks something like this:

--- homebrew.orig	2012-03-11 02:08:45.000000000 +0200
+++ homebrew	2012-03-11 02:08:22.000000000 +0200
@@ -42,38 +42,10 @@
   system *args
 end
 
-def getc  # NOTE only tested on OS X
-  system "/bin/stty raw -echo"
-  if RUBY_VERSION >= '1.8.7'
-    STDIN.getbyte
-  else
-    STDIN.getc
-  end
-ensure
-  system "/bin/stty -raw echo"
-end
-
-def macos_version
-  @macos_version ||= /(10\.\d+)(\.\d+)?/.match(`/usr/bin/sw_vers -productVersion`).captures.first.to_f
-end
-
-
 # The block form of Dir.chdir fails later if Dir.CWD doesn't exist which I
 # guess is fair enough. Also sudo prints a warning message for no good reason
 Dir.chdir "/usr"
 
-####################################################################### script
-abort "MacOS too old, see: https://gist.github.com/1144389" if macos_version < 10.5
-abort "/usr/local/.git already exists!" unless Dir["/usr/local/.git/*"].empty?
-abort "Don't run this as root!" if Process.uid == 0
-abort <<-EOABORT unless `groups`.split.include? "admin"
-This script requires the user #{ENV['USER']} to be an Administrator. If this
-sucks for you then you can install Homebrew in your home directory or however
-you please; please refer to our homepage. If you still want to use this script
-set your user to be an Administrator in System Preferences or `su' to a
-non-root user with Administrator privileges.
-EOABORT
-
 ohai "This script will install:"
 puts "/usr/local/bin/brew"
 puts "/usr/local/Library/Formula/..."
@@ -96,14 +68,6 @@
   puts *chgrps
 end
 
-if STDIN.tty?
-  puts
-  puts "Press enter to continue"
-  c = getc
-  # we test for \r and \n because some stuff does \r instead
-  abort unless c == 13 or c == 10
-end
-
 if File.directory? "/usr/local"
   sudo "/bin/chmod", "g+rwx", *chmods unless chmods.empty?
   sudo "/usr/bin/chgrp", "admin", *chgrps unless chgrps.empty?
@@ -125,11 +89,5 @@
 
 warn "/usr/local/bin is not in your PATH." unless ENV['PATH'].split(':').include? '/usr/local/bin'
 
-if macos_version < 10.7
-  warn "Now install Xcode: https://developer.apple.com/xcode/" unless File.exist? "/usr/bin/cc"
-else
-  warn "Now install the \"Command Line Tools for Xcode\": http://connect.apple.com" unless File.file? "/usr/bin/xcrun"
-end
-
 ohai "Installation successful!"
 puts "Now type: brew help"

Now, after installing Homebrew, we need to navigate to:

/usr/local/Library/Homebrew

and the first file we edit is global.rb, with the following delta:

--- global.rb.orig	2012-03-11 02:11:31.000000000 +0200
+++ global.rb	2012-03-11 02:12:11.000000000 +0200
@@ -55,7 +55,7 @@
 
 
 MACOS_FULL_VERSION = `/usr/bin/sw_vers -productVersion`.chomp
-MACOS_VERSION = /(10\.\d+)(\.\d+)?/.match(MACOS_FULL_VERSION).captures.first.to_f
+MACOS_VERSION = ("10.4").to_f
 
 HOMEBREW_USER_AGENT = "Homebrew #{HOMEBREW_VERSION} (Ruby #{RUBY_VERSION}-#{RUBY_PATCHLEVEL}; Mac OS X #{MACOS_FULL_VERSION})"
 

which will fool Homebrew into thinking that it is on a snow leopard Mac, around 10.6.8.

Then, we need to knock out some architecture checks performed by Homebrew in install.rb:

--- install.rb.orig	2012-03-11 02:13:40.000000000 +0200
+++ install.rb	2012-03-11 02:14:24.000000000 +0200
@@ -68,9 +68,7 @@
   end
 
   def perform_preinstall_checks
-    check_ppc
     check_writable_install_location
-    check_cc
     check_macports
     check_cellar
   end

We knock out the PPC check because we do not need it, most of the software will work correctly - especially the command line tools that we are aiming for. We also knock out the Xcode check since we are using the compiler from the previous section.

And we apply another patch since Homebrew changes some gcc flags which will not be recognized in ENV.rb:

--- ENV.rb.orig	2012-03-11 02:14:53.000000000 +0200
+++ ENV.rb	2012-03-11 02:16:15.000000000 +0200
@@ -148,7 +148,7 @@
     end
 
     replace_in_cflags '-O4', '-O3'
-    set_cpu_cflags 'core2 -msse4', :penryn => 'core2 -msse4.1', :core2 => 'core2', :core => 'prescott', :bottle => 'generic'
+    append_to_cflags '-mcpu=arm7 -mtune=arm7 -mfloat-abi=softfp -fno-math-errno -fno-tree-vectorize'
     @compiler = :gcc
   end
   alias_method :gcc_4_2, :gcc
@@ -291,18 +291,14 @@
 
   def m64
     append_to_cflags '-m64'
-    append 'LDFLAGS', '-arch x86_64'
   end
   def m32
     append_to_cflags '-m32'
-    append 'LDFLAGS', '-arch i386'
   end
 
   # i386 and x86_64 (no PPC)
   def universal_binary
-    append_to_cflags '-arch i386 -arch x86_64'
     replace_in_cflags '-O4', '-O3' # O4 seems to cause the build to fail
-    append 'LDFLAGS', '-arch i386 -arch x86_64'
 
     unless compiler == :clang
       # Can't mix "-march" for a 32-bit CPU  with "-arch x86_64"

You can read more about the cortex processor, cute little bugger.

The brew binary has to be patched as well, so navigate to /usr/local/bin and apply the following patch:

--- brew.orig	2012-03-11 02:19:16.000000000 +0200
+++ brew	2012-03-11 02:19:32.000000000 +0200
@@ -31,12 +31,6 @@
   # it may work, but I only see pain this route and don't want to support it
   abort "Cowardly refusing to continue at this prefix: #{HOMEBREW_PREFIX}"
 end
-if MACOS_VERSION < 10.5
-  abort <<-EOABORT.undent
-    Homebrew requires Leopard or higher. For Tiger support, see:
-    http://github.com/sceaga/homebrew/tree/tiger
-  EOABORT
-end
 
 # Many Pathname operations use getwd when they shouldn't, and then throw
 # odd exceptions. Reduce our support burden by showing a user-friendly error.

Now are are done and we test by installing some packages:

brew install ctorrent

which will pull ctorrent along with all its dependencies and compile them on the iDevice:

Newt:~ root# brew install ctorrent
==> Downloading http://downloads.sourceforge.net/project/dtorrent/dtorrent/3.3.2
######################################################################## 100.0%
==> ./configure --prefix=/usr/local/Cellar/ctorrent/3.3.2 --disable-debug
==> make install
/usr/local/Cellar/ctorrent/3.3.2: 6 files, 296K, built in 97 seconds
Newt:~ root# 

Certificates

In the pervious sections, we called:

curl -Ok

in order to download the necessary software. By default, curl does not have any certificates installed where they should be. Thus, we download them from the curl website in order to get rid of unnecessary errors:

mkdir -p /etc/ssl/certs/
curl -s http://curl.haxx.se/ca/cacert.pem -O /etc/ssl/certs/ca-certificates.crt

Formulas

You can browse and look at the available software:

cd /usr/local/Library/Formula
ls

which is a directory that contains all the build formulas for Homebrew. Not all packages will compile, we picked ctorrent because it certainly will and, most probably, most of the console command line tools will work as well.

We can even see how much software is available (Windows update comes to mind...):

ls -l | wc -l
1944

which means that there are 1944 software packages available for Homebrew. Don't go off straight away to install KDE, GNOME, X.Org and the "fun" parts... They will most likely not work without additional components and alterations to the Homebrew formulas. Most of the command line tools that you would be familiar to on Linux/BSD are there though and usually compile without any modifications.

The advantage is that Homebrew keeps all the build parameters organized nicely in files in /usr/local/Library/Formula. For example, since we were going towards php and mysql, we tried to re-install pcre, and ended up with errors such as these:

Test 1: main functionality (Compatible with Perl >= 5.8)
  OK
  OK with study
Test 2: API, errors, internals, and non-Perl stuff (not UTF-8)
./RunTest: line 226: 27550 Segmentation fault      $sim $valgrind ./pcretest -q $opt $testdata/testinput2 testtry
 
** Test 2 requires a lot of stack. If it has crashed with a
** segmentation fault, it may be that you do not have enough
** stack available by default. Please see the 'pcrestack' man
** page for a discussion of PCRE's stack usage.
 
FAIL: RunTest

Just using common sense, we can see that the package compiled perfectly and the note tells us that it just ran out of memory. So we browse to:

cd /usr/local/Library/Formula

and we just knock out the test, the package does not need the make test to run at all, as indicated by the message above:

require 'formula'

class Pcre < Formula
  homepage 'http://www.pcre.org/'
  url 'ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.21.tar.bz2'
  mirror 'http://downloads.sourceforge.net/project/pcre/pcre/8.21/pcre-8.21.tar.bz2'
  md5 '0a7b592bea64b7aa7f4011fc7171a730'

  fails_with_llvm "Bus error in ld on SL 10.6.4", :build => 2326

  def options
    [["--universal", "Build a universal binary."]]
  end

  def install
    ENV.universal_binary if ARGV.build_universal?

    system "./configure", "--disable-dependency-tracking",
                          "--prefix=#{prefix}",
                          "--enable-utf8",
                          "--enable-unicode-properties",
                          "--enable-pcregrep-libz",
                          "--enable-pcregrep-libbz2"
#    system "make test" 
    system "make install"
  end
end

We do that above, by commenting out system "make test" and now, the package installs as it should.

MySQL

We need a formula change first:

cd /usr/local/Library/Formula
nano mysql.rb

and knock out two options, the tests (yet again) and the universal binary option by knocking them out and we need to add our own patch (it seems that some include file does not mention a arm-architecture for Apple). You will need to open up:

/usr/local/Library/Formula/mysql.rb

In an editor, you can use nano, for example by issuing:

nano /usr/local/Library/Formula/mysql.rb

and then modify it according to the following patch:

--- mysql.rb.orig	2012-03-08 09:48:51.000000000 +0200
+++ mysql.rb	2012-03-09 09:05:34.000000000 +0200
@@ -1,77 +1,32 @@
 require 'formula'
 
 class Mysql < Formula
-  homepage 'http://dev.mysql.com/doc/refman/5.5/en/'
-  url 'http://downloads.mysql.com/archives/mysql-5.5/mysql-5.5.19.tar.gz'
-  md5 'a78cf450974e9202bd43674860349b5a'
-
-  depends_on 'cmake' => :build
+  homepage 'http://dev.mysql.com/doc/refman/5.0/en/'
+  url 'http://downloads.mysql.com/archives/mysql-5.0/mysql-5.0.92.tar.gz'
+  md5 'a72ee3d1d54bff74836de9500858a311'
+  
   depends_on 'readline'
   depends_on 'pidof'
-
-  fails_with_llvm "https://github.com/mxcl/homebrew/issues/issue/144", :build => 2326
-
+  
   skip_clean :all # So "INSTALL PLUGIN" can work.
 
-  def options
-    [
-      ['--with-tests', "Build with unit tests."],
-      ['--with-embedded', "Build the embedded server."],
-      ['--with-libedit', "Compile with EditLine wrapper instead of readline"],
-      ['--with-archive-storage-engine', "Compile with the ARCHIVE storage engine enabled"],
-      ['--with-blackhole-storage-engine', "Compile with the BLACKHOLE storage engine enabled"],
-      ['--universal', "Make mysql a universal binary"],
-      ['--enable-local-infile', "Build with local infile loading support"]
-    ]
-  end
-
   def patches
     DATA
   end
-
+    
   def install
-    # Make sure the var/mysql directory exists
-    (var+"mysql").mkpath
+    # Make sure the /private/var/mysql directory exists
+    Dir.mkdir("/private/var/mysql") unless File.exists?("/private/var/mysql")
 
-    args = [".",
-            "-DCMAKE_INSTALL_PREFIX=#{prefix}",
-            "-DMYSQL_DATADIR=#{var}/mysql",
-            "-DINSTALL_MANDIR=#{man}",
-            "-DINSTALL_DOCDIR=#{doc}",
-            "-DINSTALL_INFODIR=#{info}",
-            # CMake prepends prefix, so use share.basename
-            "-DINSTALL_MYSQLSHAREDIR=#{share.basename}/#{name}",
-            "-DWITH_SSL=yes",
-            "-DDEFAULT_CHARSET=utf8",
-            "-DDEFAULT_COLLATION=utf8_general_ci",
-            "-DSYSCONFDIR=#{etc}"]
-
-    # To enable unit testing at build, we need to download the unit testing suite
-    if ARGV.include? '--with-tests'
-      args << "-DENABLE_DOWNLOADS=ON"
-    else
-      args << "-DWITH_UNIT_TESTS=OFF"
-    end
-
-    # Build the embedded server
-    args << "-DWITH_EMBEDDED_SERVER=ON" if ARGV.include? '--with-embedded'
-
-    # Compile with readline unless libedit is explicitly chosen
-    args << "-DWITH_READLINE=yes" unless ARGV.include? '--with-libedit'
-
-    # Compile with ARCHIVE engine enabled if chosen
-    args << "-DWITH_ARCHIVE_STORAGE_ENGINE=1" if ARGV.include? '--with-archive-storage-engine'
-
-    # Compile with BLACKHOLE engine enabled if chosen
-    args << "-DWITH_BLACKHOLE_STORAGE_ENGINE=1" if ARGV.include? '--with-blackhole-storage-engine'
+    ENV.j1  # if your formula's build system can't parallelize
 
-    # Make universal for binding to universal applications
-    args << "-DCMAKE_OSX_ARCHITECTURES='i386;x86_64'" if ARGV.build_universal?
+    system "./configure", "--without-debug", "--disable-dependency-tracking",
+                          "--prefix=#{prefix}", "--disable-largefile",
+                          "--with-low-memory", "--without-innodb",
+			  "--with-mysqld-user=root", "--without-docs", 
+			  "--without-man", "--without-bench",
+			  "--with-unix-socket-path=/private/var/mysql/mysql.sock"
 
-    # Build with local infile loading support
-    args << "-DENABLED_LOCAL_INFILE=1" if ARGV.include? '--enable-local-infile'
-
-    system "cmake", *args
     system "make"
     system "make install"
 
@@ -81,36 +36,40 @@
     # Don't create databases inside of the prefix!
     # See: https://github.com/mxcl/homebrew/issues/4975
     rm_rf prefix+'data'
-
-    # Link the setup script into bin
-    ln_s prefix+'scripts/mysql_install_db', bin+'mysql_install_db'
-    # Fix up the control script and link into bin
-    inreplace "#{prefix}/support-files/mysql.server" do |s|
-      s.gsub!(/^(PATH=".*)(")/, "\\1:#{HOMEBREW_PREFIX}/bin\\2")
-    end
-    ln_s "#{prefix}/support-files/mysql.server", bin
   end
 
   def caveats; <<-EOS.undent
     Set up databases to run AS YOUR USER ACCOUNT with:
         unset TMPDIR
-        mysql_install_db --verbose --user=`whoami` --basedir="$(brew --prefix mysql)" --datadir=#{var}/mysql --tmpdir=/tmp
+        mysql_secure_install
 
     To set up base tables in another folder, or use a different user to run
     mysqld, view the help for mysqld_install_db:
         mysql_install_db --help
 
     and view the MySQL documentation:
-      * http://dev.mysql.com/doc/refman/5.5/en/mysql-install-db.html
-      * http://dev.mysql.com/doc/refman/5.5/en/default-privileges.html
+      * http://dev.mysql.com/doc/refman/5.0/en/mysql-install-db.html
+      * http://dev.mysql.com/doc/refman/5.0/en/default-privileges.html
 
     To run as, for instance, user "mysql", you may need to `sudo`:
         sudo mysql_install_db ...options...
 
+    * if this is your first install:
+        mkdir -p /Library/LaunchDaemons
+        cp #{plist_path} /Library/LaunchDaemons/
+        launchctl load -w /Library/LaunchDaemons/#{plist_path.basename}
+
+    * if this is an upgrade and you already have the #{plist_path.basename} loaded:
+        launchctl unload -w /Library/LaunchDaemons/#{plist_path.basename}
+        cp #{plist_path} /Library/LaunchDaemons/
+        launchctl load -w /Library/LaunchDaemons/#{plist_path.basename}
+
+    You may also need to edit the plist to use the correct "UserName".
+
     Start mysqld manually with:
-        mysql.server start
+        launchctl start homebrew.mxcl.mysql
 
-        Note: if this fails, you probably forgot to run the first two steps up above
+        Note: if this fails, you probably forgot to run the steps above
 
     A "/etc/my.cnf" from another install may interfere with a Homebrew-built
     server starting up correctly.
@@ -118,19 +77,6 @@
     To connect:
         mysql -uroot
 
-    To launch on startup:
-    * if this is your first install:
-        mkdir -p ~/Library/LaunchAgents
-        cp #{plist_path} ~/Library/LaunchAgents/
-        launchctl load -w ~/Library/LaunchAgents/#{plist_path.basename}
-
-    * if this is an upgrade and you already have the #{plist_path.basename} loaded:
-        launchctl unload -w ~/Library/LaunchAgents/#{plist_path.basename}
-        cp #{plist_path} ~/Library/LaunchAgents/
-        launchctl load -w ~/Library/LaunchAgents/#{plist_path.basename}
-
-    You may also need to edit the plist to use the correct "UserName".
-
     EOS
   end
 
@@ -143,8 +89,14 @@
       <true/>
       <key>Label</key>
       <string>#{plist_name}</string>
-      <key>Program</key>
-      <string>#{HOMEBREW_PREFIX}/bin/mysqld_safe</string>
+      <key>ProgramArguments</key>
+      <array>
+              <string>#{HOMEBREW_PREFIX}/bin/mysqld_safe</string>
+              <string>--socket=/private/var/mysql/mysql.sock</string>
+              <string>--user=root</string>
+              <string>--datadir=/private/var/mysql</string>
+              <string>--pid-file=/private/var/mysql/mysql.pid</string>
+      </array>
       <key>RunAtLoad</key>
       <true/>
       <key>UserName</key>
@@ -155,15 +107,15 @@
     </plist>
     EOPLIST
   end
-end
-
 
+end
+    
 __END__
 diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh
-index 0d2045a..2fdd5ce 100644
+index 4fe325e..71b833c 100644
 --- a/scripts/mysqld_safe.sh
 +++ b/scripts/mysqld_safe.sh
-@@ -558,7 +558,7 @@ else
+@@ -323,7 +323,7 @@ else
  fi
  
  USER_OPTION=""
@@ -172,18 +124,17 @@
  then
    if test "$user" != "root" -o $SET_USER = 1
    then
-diff --git a/scripts/mysql_config.sh b/scripts/mysql_config.sh
-index 9296075..a600de2 100644
---- a/scripts/mysql_config.sh
-+++ b/scripts/mysql_config.sh
-@@ -137,7 +137,8 @@ for remove in DDBUG_OFF DSAFE_MUTEX DUNIV_MUST_NOT_INLINE DFORCE_INIT_OF_VARS \
-               DEXTRA_DEBUG DHAVE_purify O 'O[0-9]' 'xO[0-9]' 'W[-A-Za-z]*' \
-               'mtune=[-A-Za-z0-9]*' 'mcpu=[-A-Za-z0-9]*' 'march=[-A-Za-z0-9]*' \
-               Xa xstrconst "xc99=none" AC99 \
--              unroll2 ip mp restrict
-+              unroll2 ip mp restrict \
-+              mmmx 'msse[0-9.]*' 'mfpmath=sse' w pipe 'fomit-frame-pointer' 'mmacosx-version-min=10.[0-9]'
- do
-   # The first option we might strip will always have a space before it because
-   # we set -I$pkgincludedir as the first option
+diff --git a/include/my_global.h b/include/my_global.h
+index 595c7cd..449cebe 100644
+--- a/include/my_global.h
++++ b/include/my_global.h
+@@ -121,7 +121,7 @@
+ #  define SIZEOF_INT 4
+ #  define SIZEOF_LONG_LONG 8
+ #  define SIZEOF_OFF_T 8
+-#  if defined(__i386__) || defined(__ppc__)
++#  if defined(__i386__) || defined(__ppc__) || defined(__arm__)
+ #    define SIZEOF_CHARP 4
+ #    define SIZEOF_LONG 4
+ #  elif defined(__x86_64__) || defined(__ppc64__)
 

We dropped down to a less recent mysql version and knocked out some options from /usr/local/Library/Formula/mysql.rb at the top of the file and choose the MyISAM engine - it is pointless to compile them all, MyISAM should suffice.

iDevice has a fairly limited amount of RAM and at some point during compilation, the device may crash with the usual spinning rosette. This will vary between iDevices, depending on how much RAM they have to spare. In the worst case, you will just have to add options to disable compiling things that are not needed.

If you really need all the options, or if you still crash after making those changes, you can try to limit the amount of memory that gcc uses. This will get you any package compiled with any options (provided you do not have intermediary errors, of course). It will just take more time. The trick is to pass to the gcc CFLAGS:

CFLAGS='--param ggc-min-heapsize=524288 --param ggc-min-expand=0'

which is an old trick, but provided sufficient time, will get you anything compiled regardless of how little RAM you have available (there is always distcc and ccache that my speed it up, in case you are running an iFarm xD). In any case, if your device restarts during the make phase of mysql, then it is for sure a memory issue. The heap gets exhausted, the system tries to free up RAM, springboard shatters to bits and eventually you get a kernel panic and the whole machine restarts. If that happens, then those options are your ticket out of this problem (this is most probably how we will compile mono).

The 524288KB magic is really just KB=1024*512 so 512MB as a memory allowance for gcc. You may increase it or decrease it depending on how much memory your device has.

In order to add it to a Homebrew formula, you just edit the formula and add:

    ENV.append_to_cflags "--param ggc-min-heapsize=524288"
    ENV.append_to_cflags "--param ggc-min-expand=0"

in the def install section of the formula at the top. This will limit the gcc memory usage and will prevent the iDevice from crashing.

Now, you are ready to run the install (this will really take a while...):

Newt:~ root# brew install mysql
==> Installing mysql dependency: cmake
==> Downloading http://www.cmake.org/files/v2.8/cmake-2.8.7.tar.gz
######################################################################## 100.0%
==> ./bootstrap --prefix=/usr/local/Cellar/cmake/2.8.7 --system-libs --no-system-libarchive --datadir=/share/cmake --docdir=/share/doc/cmake --mandir=/share/man
==> make
==> make install
Warning: m4 macros were installed to "share/aclocal".
Homebrew does not append "/usr/local/share/aclocal"
to "/usr/share/aclocal/dirlist". If an autoconf script you use
requires these m4 macros, you'll need to add this path manually.
==> Summary
/usr/local/Cellar/cmake/2.8.7: 635 files, 28M, built in 53.5 minutes
==> Installing mysql dependency: readline
==> Downloading http://ftpmirror.gnu.org/readline/readline-6.2.tar.gz
######################################################################## 100.0%
==> Downloading patches
######################################################################## 100.0%
######################################################################## 100.0%
==> Patching
patching file vi_mode.c
patching file callback.c
patching file support/shobj-conf
patching file patchlevel
==> ./configure --prefix=/usr/local/Cellar/readline/6.2.2 --mandir=/usr/local/Cellar/readline/6.2.2/share/man --infodir=/usr/local/Cellar/readline/6.2.2/share/info --enable-multibyte
==> make install
==> Caveats
This formula is keg-only, so it was not symlinked into /usr/local.

OS X provides the BSD libedit library, which shadows libreadline.
In order to prevent conflicts when programs look for libreadline we are
defaulting this GNU Readline installation to keg-only.

Generally there are no consequences of this for you.
If you build your own software and it requires this formula, you'll need
to add its lib & include paths to your build variables:

    LDFLAGS  -L/usr/local/Cellar/readline/6.2.2/lib
    CPPFLAGS -I/usr/local/Cellar/readline/6.2.2/include
==> Summary
/usr/local/Cellar/readline/6.2.2: 29 files, 1.1M, built in 2.5 minutes
==> Installing mysql dependency: pidof
==> Downloading http://www.nightproductions.net/downloads/pidof_source.tar.gz
######################################################################## 100.0%
==> make all
==> /usr/bin/gzip pidof.1
/usr/local/Cellar/pidof/0.1.4: 3 files, 32K, built in 2 seconds
==> Installing mysql
==> Downloading http://downloads.mysql.com/archives/mysql-5.0/mysql-5.0.92.tar.gz
File already downloaded in /Library/Caches/Homebrew
==> Patching
patching file scripts/mysqld_safe.sh
patching file include/my_global.h
==> ./configure --without-debug --prefix=/usr/local/Cellar/mysql/5.0.92 --disable-largefile --with-low-memory --wi
==> make
==> make install
==> Caveats
    Set up databases to run AS YOUR USER ACCOUNT with:
        unset TMPDIR
        mysql_secure_install

    To set up base tables in another folder, or use a different user to run
    mysqld, view the help for mysqld_install_db:
        mysql_install_db --help

    and view the MySQL documentation:
      * http://dev.mysql.com/doc/refman/5.0/en/mysql-install-db.html
      * http://dev.mysql.com/doc/refman/5.0/en/default-privileges.html

    To run as, for instance, user "mysql", you may need to `sudo`:
        sudo mysql_install_db ...options...

    * if this is your first install:
        mkdir -p /Library/LaunchDaemons
        cp /usr/local/Cellar/mysql/5.0.92/homebrew.mxcl.mysql.plist /Library/LaunchDaemons/
        launchctl load -w /Library/LaunchDaemons/homebrew.mxcl.mysql.plist

    * if this is an upgrade and you already have the homebrew.mxcl.mysql.plist loaded:
        launchctl unload -w /Library/LaunchDaemons/homebrew.mxcl.mysql.plist
        cp /usr/local/Cellar/mysql/5.0.92/homebrew.mxcl.mysql.plist /Library/LaunchDaemons/
        launchctl load -w /Library/LaunchDaemons/homebrew.mxcl.mysql.plist

    You may also need to edit the plist to use the correct "UserName".

    Start mysqld manually with:
        launchctl start homebrew.mxcl.mysql

        Note: if this fails, you probably forgot to run the steps above

    A "/etc/my.cnf" from another install may interfere with a Homebrew-built
    server starting up correctly.

    To connect:
        mysql -uroot

==> Summary
/usr/local/Cellar/mysql/5.0.92: 2291 files, 53M, built in 38.1 minutes
Newt:~ root# 

So it took about half an hour with our changes to the formula but still without the gcc memory limiting trick. We also got no crashes or memory filling up. We proceed with the usual mysql install. Now you can run the installation with:

mysql_secure_install

which will ask a series of questions.

And you are ready to log-in:

Newt:~ root# mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 5.0.92 Source distribution

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

perl

To compile perl, you need the following formula:

require 'formula'

class Perl < Formula
  homepage 'http://www.cpan.org'
  url 'http://www.cpan.org/src/5.0/perl-5.14.2.tar.gz'
  md5 '3306fbaf976dcebdcd49b2ac0be00eb9'

  def install
    ENV.append_to_cflags "--param ggc-min-heapsize=524288"
    ENV.append_to_cflags "--param ggc-min-expand=0"
    system "./Configure", "-dse"
    system "make"
    system "make install" # if this fails, try separate make/make install steps
  end
end