I run OSX on my laptop. (gasp!) I ssh into my various linux boxes to work on various projects. As I’m doing a little work with Renderscript and my sqlite acceleration project I thought it would be handy to build Android on my OS X laptop. Turns out it’s not entirely difficult and required just one fix to the code.
There are several projects to bring various linux/unix tools onto OSX. I use MacPorts. Brew is probably another good option. Either way this gives us a foundation of tools that the android build system is going to need.
The install instructions offer an extra easy pkg option.
Next we need to install some software.
sudo port install coreutils findutils pngcrush gsed gnupg
Xcode is of course Apple’s development environment for OSX and iOS. You need it, and it can be installed directly out of the App Store.
Make sure you have java installed.
java version "1.6.0_65"
If you don’t, you’ll get a popup dialog that will ask if you want to install it. Do!
Make sure you have python installed. If I recall correctly that’s a default install with OSX Mavericks. There is an option to install via ports.
sudo port install python
Pull down repo.
curl http://commondatastorage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
Make sure you add your ~/bin to your PATH
Android SDK tools
You need to download the android sdk tools built for the Mac. Download these from here. Extract. At this point I created an android directory and put the tools inside of it.
mkdir -p ~/android mv <whereever>/android-sdk ~/android
OSX for all it’s joys doesn’t deal with case differences in it’s file system unless you specifically created the file system to do so. The default doesn’t. It’s not 8.3, but it’s still 1990s lame. So you’ll need to create a file system for the Android source code to live in.
Make sure you have the space in your file system. I created a 100 gig file system. I wouldn’t go below 50. I also put this onto my desktop. Makes it easy to double click later to mount it. Feel free to mount it where it works best for you. However remember this location!
hdiutil create -type SPARSE -fs "Case-sensitive Journaled HFS+" -size 100g -volname "android" -attach ~/Desktop/Android
Android source code
Download as you normally would. (note the cd to the location of where you just attached the new HFS case sensitive file system.
git clone http://android.googlesource.com/platform/manifest.git git branch -r // this will show you all the branch options. I was after the latest. repo init -u git://android.git.kernel.org/platform/manifest.git -b android-4.4_r1.2 repo sync
We need to setup a few environment variables. First add the android sdk tools to your path
export PATH=~/android/android-sdk/sdk/platform-tools:$PATH export BUILD_MAC_SDK_EXPERIMENTAL=1 export LC_CTYPE=C export LANG=C
The One Fix
So in jni_generator.py there is a slight issue where it doesn’t handle that situation where one of the tool parameters isn’t available. So we need to defensively work around it. (yeah yeah I should just post the patch)
At the top of the file (around line 20) add
Then lower down add the following if to check for Darwin so that -fpreprocessed isn’t passed:
531 def _RemoveComments(self, contents): 532 # We need to support both inline and block comments, and we need to handle 533 # strings that contain '//' or '/*'. Rather than trying to do all that with 534 # regexps, we just pipe the contents through the C preprocessor. We tell cpp 535 # the file has already been preprocessed, so it just removes comments and 536 # doesn't try to parse #include, #pragma etc. 537 # 538 # TODO(husky): This is a bit hacky. It would be cleaner to use a real Java 539 # parser. Maybe we could ditch JNIFromJavaSource and just always use 540 # JNIFromJavaP; or maybe we could rewrite this script in Java and use APT. 541 # http://code.google.com/p/chromium/issues/detail?id=138941 542 system = platform.system() 543 if system == 'Darwin': 544 cpp_args = ['cpp'] 545 else: 546 cpp_args = ['cpp', '-fpreprocessed'] 547 p = subprocess.Popen(args=cpp_args, 548 stdin=subprocess.PIPE, 549 stdout=subprocess.PIPE, 550 stderr=subprocess.PIPE) 551 stdout, _ = p.communicate(contents)
Ready To Build
That’s it. Least I hope I captured everything I had to do. Build away.