building android for wandboard on os x
As an application developer I want to spend my time on my macbook because it has (in my opinion) a preferable interface to any other development environment. As a hardware enthusiast and operating system hacker I want to remain in that environment, but often the tools required are not pre-configured or just simply not available on OS X. While customizing android on various boards, most recently the Wandboard, I’ve found some nice tricks and workarounds to get builds running in OS X.
Here I’m going to detail the modifications my environment needed to get a standard build completed for the Wandboard Quad (Rev. B1), however most of these steps apply to building android on other Freescale i.MX6 based devices as their android source trees are based on the Freescale release.
Set up a case sensitive file system
By default the filesystem in OS X is case-insensitive and thus poses problems for some case-sensitive portions of the build (the ext family of filesystems is case-sensitive). To get around this you could reformat your hard disk and reinstall OS X, but that would be a pain and theres a better option.
hdiutil
is a utility that allows you to create and mount virtual file systems. Before you clone the android source, create a case sensitive filesystem and mount it.
# create the filesystem image
$ hdiutil create -type SPARSE -fs 'Case-sensitive Journaled HFS+' -size 60g -volname <name-of-volume> <path-to-filesystem-image>
# mount it, by default the mount point is /Volumes/<name-of-volume>
$ hdiutil attach <path-to-filesystem-image>
Install required packages
OS X is a unix-like operating system, however it has its own flavor. Mostly that flavor is BSD, with some proprietary Apple stuff thrown into the mix. This can cause some issues when building the Linux kernel because certain system utilities behave differently than expected, and Linux has no official OS X build support (that I know of at least…). To fix the issue we can use homebrew
to install the coreutils
package, which includes a collection of GNU utilities.
$ brew install coreutils
OS X also ships with a general incompatibility with the ext family of filesystems, as they are FUSE (Filesystem in USErspace) filesystems. To solve this problem, at least to a certain extent, we can install osxfuse
and fuse-ext2
. osxfuse
is a FUSE kernel extension/library for OS X, and fuse-ext2
is a set of tools made to mimic the ext tools available on Linux systems. Refer to each projects documentation for installation and usage instructions.
Install repo, initialize the build directory, and pull down the source tree
The easiest way to install repo is using homebrew.
$ brew install repo
tl;dr
If you’ve built android before and know your way around repo and the build system, you can skip the next few sections and just initialize from a manifest I’ve created to support OS X builds.
$ repo init -u https://github.com/a-ross-cohen/wand_manifest -b jb4.3_1.1.0-ga__wandboard_osx
The steps to build should be the same as any other AOSP build, but the deployment is a bit different. Skip down to Deploying to a microSD card for deployment instructions.
for those who want the whole scoop
Now from your case-sensitive build directory initialize repo against the Wandboard manifest.
$ repo init -u http://git.wandboard.org/git/manifest.git -b jb4.3_1.1.0-ga__wandboard
Here is where we make our first modification to something under source control. Note that changes to the source code will have to be pushed somewhere if you want to share them or store a backup. Any time you customize android you’re bound to end up with at minimum a handful of repositories to keep track of yourself.
We need to edit the manifest file located at .repo/manifests/wandboard-jb4.3.xml
. (Note: All paths referenced will be relative to the root of the build directory) The reason we’re editing the manifest is to get a single manifest for our project. People will often initialize repo with one manifest, sync, and then replace the manifest and sync again to get their own modified source trees. Instead we’ll be very explicit that anything in this manifest that does not have the specified remote as ‘wandboard’ will default to being fetched from Googles public android source trees. The diff of the change is shown below.
diff --git a/wandboard-jb4.3.xml b/wandboard-jb4.3.xml
index 5972d9c..f722137 100644
--- a/wandboard-jb4.3.xml
+++ b/wandboard-jb4.3.xml
@@ -2,7 +2,7 @@
<manifest>
<remote name="aosp"
- fetch=".." />
+ fetch="https://android.googlesource.com" />
<default revision="refs/tags/android-4.3_r2.1"
remote="aosp"
sync-j="4" />
With this change saved you can pull down the sources using repo sync -c -j8
. The -c
option only pulls down the git refs needed for branch you’re building on for each repo, making the sync faster. -jN
is how you specify how many repos you want syncing concurrently.
Remove breaking packages we don’t need
OS X has no build support for the tools around ubifs. It sucks, but for now its the way things are. There is some consolation though… we don’t care about ubifs. We’re going to boot android from the main MMC 0 micro sd slot, and we’re going to use only FAT32 and ext4 filesystems. The first thing to do is remove the ubifs related packages from device/fsl/imx6/imx6_wand.mk
.
diff --git a/imx6/imx6_wand.mk b/imx6/imx6_wand.mk
index 044d019..46e2649 100644
--- a/imx6/imx6_wand.mk
+++ b/imx6/imx6_wand.mk
@@ -286,7 +286,7 @@ omx_excluded_libs := \
PRODUCT_PACKAGES += $(omx_libs) $(omx_excluded_libs)
-PRODUCT_PACKAGES += libubi ubinize ubiformat ubiattach ubidetach ubiupdatevol ubimkvol ubinfo mkfs.ubifs
+# PRODUCT_PACKAGES += libubi ubinize ubiformat ubiattach ubidetach ubiupdatevol ubimkvol ubinfo mkfs.ubifs
# FUSE based emulated sdcard daemon
PRODUCT_PACKAGES += sdcard
The other edit we have to make to fully remove the ubifs stuff from the build is in another makefile. You only have to make this edit if you’re going to be running an engineering build, which if you’re hacking android it’s likely what you intend to do. Heres the diff of the other edit in external/mtd-utils/new-utils/Android.mk
.
diff --git a/new-utils/Android.mk b/new-utils/Android.mk
index 59b8286..88adb6f 100644
--- a/new-utils/Android.mk
+++ b/new-utils/Android.mk
@@ -19,7 +19,7 @@ LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
LOCAL_MODULE := ubinize
-LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE_TAGS := optional
include $(BUILD_HOST_EXECUTABLE)
Edit the build system
The section of the build system that generates u-boot and the linux kernel makes an assumption that you are compiling from a linux platform. We need to add some conditionals to make sure we’re selecting the darwin host toolchain. We also need to account for flags that are passed to the install
command, as the BSD-based implementation native to OS X differs slightly from the GNU implementation that is standard on linux distributions.
The bootloader
target
Checking to see which host we’re building from is easy using the uname
command, which will return ‘Linux’ or ‘Darwin’. We then set the variables BOOTLOADER_CROSS_TOOLCHAIN
and HOST_PROCESSOR
accordingly. In the case of a linux build (if you’re trying not to break it…) you need to add an INSTALL_FLAGS
variable and set it to -D
which tells install
to create directories if needed. The last step is to replace the existing flags being passed to install
with the INSTALL_FLAGS
variable.
The diff below shows the changes needed to complete the build, but it also includes a few changes I made as a preference. When my full build completes I want my bootloader, kernel, and other contents of the boot partition to be in a sub-directory of the PRODUCT_OUT
path, namely out/target/product/wandboard/boot
. Because of this I changed TARGET_BOOTLOADER_IMAGE
to reflect the location I want. In the same vein I added a call to install
to copy the SPL into our boot directory. Lastly I had to add a call to mkdir
as the BSD-flavor install
does not make directories for you.
diff --git a/core/Makefile b/core/Makefile
index 3ac2967..d98c20a 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -739,25 +739,35 @@ endif
.PHONY: bootloader
ifneq ($(strip $(TARGET_BOOTLOADER_CONFIG)),)
+
+ifeq ($(shell uname -s), Linux)
BOOTLOADER_CROSS_TOOLCHAIN := `pwd`/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-
-BOOTLOADER_ENV := ARCH=arm CROSS_COMPILE=$(BOOTLOADER_CROSS_TOOLCHAIN)
HOST_PROCESSOR := $(shell cat /proc/cpuinfo | grep processor | wc -l)
-TARGET_BOOTLOADER_IMAGE := $(PRODUCT_OUT)/u-boot.bin
+INSTALL_FLAGS := -D
+endif
+ifeq ($(shell uname -s), Darwin)
+BOOTLOADER_CROSS_TOOLCHAIN := `pwd`/prebuilts/gcc/darwin-x86/arm/arm-eabi-4.6/bin/arm-eabi-
+HOST_PROCESSOR := $(shell sysctl -n hw.ncpu)
+endif
+
+BOOTLOADER_ENV := ARCH=arm CROSS_COMPILE=$(BOOTLOADER_CROSS_TOOLCHAIN)
+TARGET_BOOTLOADER_IMAGE := $(PRODUCT_OUT)/boot/u-boot.img
BOOTLOADER_PATH := bootable/bootloader/uboot-imx/
BOOTLOADER_CONFIG_FILE := $(BOOTLOADER_PATH)/include/config.h
bootloader: $(TARGET_BOOTLOADER_IMAGE)
$(TARGET_BOOTLOADER_IMAGE):
+ mkdir -p $(PRODUCT_OUT)/boot
@for ubootplat in $(TARGET_BOOTLOADER_CONFIG); do \
UBOOT_PLATFORM=`echo $$ubootplat | cut -d':' -f1`; \
UBOOT_CONFIG=`echo $$ubootplat | cut -d':' -f2`; \
- $(MAKE) -C bootable/bootloader/uboot-imx/ distclean $(BOOTLOADER_ENV); \
- $(MAKE) -C bootable/bootloader/uboot-imx/ $$UBOOT_CONFIG $(BOOTLOADER_ENV); \
- $(MAKE) -C bootable/bootloader/uboot-imx/ $(BOOTLOADER_ENV); \
- install -D bootable/bootloader/uboot-imx/u-boot.bin $(PRODUCT_OUT)/u-boot-$$UBOOT_PLATFORM.bin; \
- install -D bootable/bootloader/uboot-imx/u-boot.bin $@; \
+ $(MAKE) -C $(BOOTLOADER_PATH) distclean $(BOOTLOADER_ENV); \
+ $(MAKE) -C $(BOOTLOADER_PATH) $$UBOOT_CONFIG $(BOOTLOADER_ENV); \
+ $(MAKE) -C $(BOOTLOADER_PATH) $(BOOTLOADER_ENV); \
+ install $(INSTALL_FLAGS) $(BOOTLOADER_PATH)/u-boot.img $(TARGET_BOOTLOADER_IMAGE); \
+ install $(INSTALL_FLAGS) $(BOOTLOADER_PATH)/SPL $(PRODUCT_OUT)/boot/SPL; \
done
else
bootloader:
The kernelimage
target
Here we want to make changes that are either analogous or identical to the ones we made for the bootloader target. The conditional statements that check uname
and their contents are essentially the same, we just replace the variable name BOOTLOADER_CROSS_TOOLCHAIN
with KERNEL_CROSS_TOOLCHAIN
. The change for the install flags is also identical, and in the same way we updated the TARGET_BOOTLOADER_IMAGE
variable we now update the TARGET_PREBUILT_KERNEL
and INSTALLED_KERNEL_TARGET
paths to represent the location in our new boot folder. In addition to those changes I have removed the regular kernel target, because I’m simply not using it. Our bootloader is set up to load and execute a uImage file, so I only want to copy that file into my boot directory.
The last and possibly most important change shown in the diff below prepends a location to our PATH
when executing the command that will actually build our kernel. After some painful debugging it was made apparent that the BSD implementation of stat
and the GNU implementation are not fully compatible, and GNU stat
is needed to compile a working uImage. We don’t want to replace stat
globally on our system for a variety of reasons, so the best solution is to shim in GNU stat
only when generating the kernel. If you’ve installed the coreutils
package with homebrew
then you can prepend PATH
with their location. In my case (as it should be for most cases) the utils are available by their proper names at /usr/local/opt/coreutils/libexec/gnubin
relative to your system root. If you have an issue with this you can check their install location with brew info coreutils
. Obligatory diff.
@@ -765,11 +775,21 @@ endif
.PHONY: kernelimage
ifneq ($(strip $(TARGET_NO_KERNEL)),true)
+
+ifeq ($(shell uname -s), Linux)
KERNEL_CROSS_TOOLCHAIN := `pwd`/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-
-KERNEL_ENV := ARCH=arm CROSS_COMPILE=$(KERNEL_CROSS_TOOLCHAIN)
HOST_PROCESSOR := $(shell cat /proc/cpuinfo | grep processor | wc -l)
-INSTALLED_KERNEL_TARGET := $(PRODUCT_OUT)/kernel
-TARGET_PREBUILT_KERNEL := $(PRODUCT_OUT)/kernel
+INSTALL_FLAGS := -D
+endif
+
+ifeq ($(shell uname -s), Darwin)
+KERNEL_CROSS_TOOLCHAIN := `pwd`/prebuilts/gcc/darwin-x86/arm/arm-eabi-4.6/bin/arm-eabi-
+HOST_PROCESSOR := $(shell sysctl -n hw.ncpu)
+endif
+
+KERNEL_ENV := ARCH=arm CROSS_COMPILE=$(KERNEL_CROSS_TOOLCHAIN)
+INSTALLED_KERNEL_TARGET := $(PRODUCT_OUT)/boot/uImage
+TARGET_PREBUILT_KERNEL := $(PRODUCT_OUT)/boot/uImage
KERNEL_CONFIGURE := kernel_imx/.config
TARGET_KERNEL_CONFIGURE := $(PRODUCT_OUT)/.config
KERNEL_ZIMAGE := kernel_imx/arch/arm/boot/zImage
@@ -784,12 +804,11 @@ $(KERNEL_CONFIGURE): kernel_imx/arch/arm/configs/$(TARGET_KERNEL_DEFCONF)
$(TARGET_KERNEL_CONFIGURE): kernel_imx/arch/arm/configs/$(TARGET_KERNEL_DEFCONF) $(KERNEL_CONFIGURE)
$(MAKE) -C kernel_imx $(TARGET_KERNEL_DEFCONF) $(KERNEL_ENV)
- install -D $(KERNEL_CONFIGURE) $(TARGET_KERNEL_CONFIGURE)
+ install $(INSTALL_FLAGS) $(KERNEL_CONFIGURE) $(TARGET_KERNEL_CONFIGURE)
$(TARGET_PREBUILT_KERNEL): $(TARGET_KERNEL_CONFIGURE)
- $(MAKE) -C kernel_imx -j$(HOST_PROCESSOR) uImage $(KERNEL_ENV)
- install -D $(KERNEL_UIMAGE) $(PRODUCT_OUT)/uImage
- install -D $(KERNEL_ZIMAGE) $(PRODUCT_OUT)/kernel
+ export PATH=/usr/local/opt/coreutils/libexec/gnubin:$$PATH ; $(MAKE) -C kernel_imx -j$(HOST_PROCESSOR) uImage $(KERNEL_ENV)
+ install $(INSTALL_FLAGS) $(KERNEL_UIMAGE) $(INSTALLED_KERNEL_TARGET)
ifneq ($(TARGET_KERNEL_MODULES), )
$(MAKE) -C kernel_imx -j$(HOST_PROCESSOR) modules $(KERNEL_ENV)
endif
There is one last change that needs to be made at this point to complete the build, and its in a different makefile found at build/target/board/Android.mk
. Since we changed our INSTALLED_KERNEL_TARGET
to a different location, we have to update this secondary makefile to know where we’ve put the built kernel. Its a simple one line change, here’s the diff.
diff --git a/target/board/Android.mk b/target/board/Android.mk
index 7d94ee0..805fdae 100644
--- a/target/board/Android.mk
+++ b/target/board/Android.mk
@@ -15,7 +15,7 @@ else
endif # TARGET_NO_BOOTLOADER
ifneq ($(strip $(TARGET_NO_KERNEL)),true)
- INSTALLED_KERNEL_TARGET := $(PRODUCT_OUT)/kernel
+ INSTALLED_KERNEL_TARGET := $(PRODUCT_OUT)/boot/uImage
else
INSTALLED_KERNEL_TARGET :=
endif
Copy files to the right place
The only thing left to deal with now is the placement of the u-boot environment file. The file generated by the u-boot build process is not actually suitable to boot android. To fix this problem I’ve simply added the environment file I want to the tree and inserted a rule into /Volumes/osxbuildtest/device/fsl/imx6/wandboard.mk
to copy the file into its proper location during the build. I put the file at /Volumes/osxbuildtest/device/fsl/wandboard/boot/uEnv.txt
as it is board specific. Below is the diff of the makefile as well as the contents of the environment file.
diff --git a/imx6/wandboard.mk b/imx6/wandboard.mk
index f59f50d..560be28 100644
--- a/imx6/wandboard.mk
+++ b/imx6/wandboard.mk
@@ -66,3 +66,5 @@ PRODUCT_COPY_FILES += \
PRODUCT_COPY_FILES += \
system/bluetooth/data/main.nonsmartphone.conf:system/etc/bluetooth/main.conf
+PRODUCT_COPY_FILES += \
+ device/fsl/wandboard/boot/uEnv.txt:boot/uEnv.txt
# /Volumes/osxbuildtest/device/fsl/wandboard/boot/uEnv.txt
bootargs_base=console=ttymxc0,115200 androidboot.console=ttymxc0 androidboot.hardware=wandboard vmalloc=400M
video_mode=display0=dev=hdmi0,mode=1280x720@60,if=RGB24,bpp=32 fbmem=28M
expansion=
baseboard=wand
Run the build
After the changes noted above the build should complete, however every system is different and you may still run into issues. The build also takes a long time to run, especially if you run it non-concurrently. The system I develop on, and successfully run this build on all the time, is a Macbook Pro Retina running OS X 10.9.2 (Mavericks). It has a quad-core 2.6 GHz i7 processor, 16 Gigabytes of RAM, and a solid state hard disk. Even with all that computing power, running concurrently with 10 jobs, the build will take between 45 and 75 minutes (depending on what else you’re doing on the machine). This may sound like a long time but in fact its extremely fast considering what’s being compiled, linked, copied, etc.
As an attempt at practicing good habits I redirect the output of the build to a log file so I can view it if something goes awry. The best way to do this is to pipe the build to the tee
command. I also like to wrap the call to make with the time
command so I can track how long each build takes me. The following is an example of the command to build the whole distribution, and track how long it takes, all while piping the output to a log file.
# execute this command from the root of the tree
time make -j10 2>&1 | tee descriptive_file_name.log
There are a few things to note about the command above. The first one is the -j10
flag. This tells make to run 10 jobs concurrently when building, which will speed things up considerably. Usually you want the number of jobs to be one more than the number of cores on your system. The i7 processor I have in my machine has some fancy functionality built in that essentially makes the four cores act like they’re 8 cores, so to calculate how many jobs to run on my system for optimal performance I did the regular calculation (4 cores + 1 = 5 jobs) and then doubled it. This obviously varies from system to system, as every processor is different. The key is to not get carried away and make this number too large, because then the system will spend more time switching process contexts than it will compiling code, making for longer compile times, which nobody wants.
The other important thing to note in the above command is the 2>&1
tacked on the end of the call to make. This is critical for the log file to be of any use in a crash. It’s redirecting STDERR
to STDOUT
, so the STDOUT
of make contains both the STDOUT
and STDERR
streams. If you don’t do this, errors from make will be printed to your terminal (because stdout is directed there by default) but not copied into the log file by tee
because its taking the stream piped to it from the STDOUT
of make
and writing it to the log file, nothing else.
Deploying to a microSD card
Now that the build will complete we need to deploy it to a microSD card so we can boot it. The scripts that are provided to do this do not function properly on OS X primarily because they rely on sfdisk
, which is not readily available for the platform. We can do the same work with fdisk
though, its just a little uglier. Because fdisk
is not automatable like sfdisk
, we have to use a trick of echoing commands into fdisk
with a pipe.
Below is a script that I wrote to replace the scripts that are available for linux. It calculates the disk geometry, clears the partition table, rewrites it, generates the filesystems, burns the prebuilt filesystem images to the card, and then arranges the boot partition with our bootloader, bootloader environment, kernel, and ramdisk. This script must be run as root, from the root of your build directory, and you must specify the device node of the disk to be burned and the product to be deployed. Run it with no arguments to get usage information.
As an example, if the product was called wandboard (which it is by default) and the disk you want to burn to is /dev/disk1 (be careful, this is a destructive operation and will overwrite a disk, you’ve been warned!) then the following should burn the card properly.
# WARNING: Check to make sure /dev/disk1 is the one you actually want to burn. Data will be lost!
$ sudo device/fsl/wandboard/tools/mkcard /dev/rdisk1 wandboard
#!/bin/bash
# A. Ross Cohen
# Android Deployment Script
error() {
echo "! $1"
}
unmount() {
diskutil unmountDisk $disk >/dev/null
}
eject() {
unmount
diskutil eject $disk
}
mb_to_sectors() {
expr $1 \* $sectors_per_megabyte
}
calculate_geometry() {
block_size=`diskutil info $disk | grep "Block Size" | grep -oE "\d+"`
sectors_per_megabyte=`expr 1048576 / $block_size`
sectors=`fdisk $disk | grep -oE 'geometry.*\[\d+' | grep -oE '\[\d+' | grep -oE '\d+'`
megabytes=`expr $sectors / $sectors_per_megabyte`
}
calculate_partition_sizes() {
# partition sizes, all but data are static
bootloader_mb=40
boot_mb=40
recovery_mb=40
system_mb=512
cache_mb=512
vendor_mb=20
misc_mb=20
data_mb=`expr $megabytes - $bootloader_mb - $boot_mb - $recovery_mb - $system_mb - $cache_mb - $vendor_mb - $misc_mb`
bootloader_sectors=`mb_to_sectors $bootloader_mb`
boot_sectors=`mb_to_sectors $boot_mb`
recovery_sectors=`mb_to_sectors $recovery_mb`
system_sectors=`mb_to_sectors $system_mb`
cache_sectors=`mb_to_sectors $cache_mb`
vendor_sectors=`mb_to_sectors $vendor_mb`
misc_sectors=`mb_to_sectors $misc_mb`
data_sectors=`mb_to_sectors $data_mb`
mbr_one_sectors=`expr $sectors - $bootloader_sectors - $boot_sectors - $recovery_sectors - $data_sectors`
}
write_partion_scheme() {
unmount
dd if=/dev/zero of=$disk bs=1m count=1
(
echo erase;
echo e 1;
echo 0C;
echo n;
echo $bootloader_sectors;
echo $boot_sectors;
echo e 2;
echo 83;
echo n;
echo;
echo $recovery_sectors;
echo e 3;
echo 05;
echo n;
echo;
echo $mbr_one_sectors;
echo e 4;
echo 83;
echo n;
echo;
echo $data_sectors
echo w;
echo select 3;
echo y;
echo erase;
echo e 1;
echo 83;
echo n;
echo;
echo $system_sectors
echo e 2;
echo 83;
echo n;
echo;
echo $cache_sectors
echo e 3;
echo 83;
echo n;
echo;
echo $vendor_sectors
echo e 4;
echo 83;
echo n;
echo;
echo $misc_sectors
echo w;
echo exit;
echo exit;
) | fdisk -iey $disk
unmount
}
create_filesystems() {
echo y | newfs_msdos -F 32 -v imx6 ${disk}s1
echo y | newfs_msdos -F 32 -v recovery ${disk}s2
echo y | fuse-ext2.mke2fs -T ext4 -L cache ${disk}s6
echo y | fuse-ext2.mke2fs -T ext4 -L vendor ${disk}s7
echo y | fuse-ext2.mke2fs -T ext4 -L misc ${disk}s8
}
create_data_filesystem() {
echo y | fuse-ext2.mke2fs -T ext4 -L data ${disk}s4
}
burn_images() {
dd if=${product_directory}/boot/SPL of=$disk bs=1k seek=1
dd if=${product_directory}/system.img of=${disk}s5 bs=1m
}
arrange_boot() {
diskutil mount -mountPoint /Volumes/imx6 ${disk}s1
if [ $? ] ; then
mkdir -p /Volumes/imx6/boot
cp ${product_directory}/boot/uImage /Volumes/imx6/boot
cp ${product_directory}/boot/u-boot.img /Volumes/imx6/boot
cp ${product_directory}/boot/uEnv.txt /Volumes/imx6/boot
mkimage -A arm -O linux -T ramdisk -C none -a 0x10800800 -n "Android Root Filesystem" -d ${product_directory}/ramdisk.img /Volumes/imx6/boot/uramdisk.img
else
echo "Mount Failed, exiting."
exit
fi
}
# make sure we have the minimum arguments, if not complain...
if [ "$(id -u)" != "0" ]; then
error "You must sudo to run this command."
exit
elif [ $# -lt 2 ] ; then
error "Insufficient Parameters"
error "Usage: $0 /dev/(r)diskN product"
exit
fi
disk=$1
product=$2
product_directory="out/target/product/$product"
# make sure the disk exists
if ! [ -e $disk ] ; then
error "Disk $disk does not exist. Aborting."
fi
# make sure the product exists
if ! [ -f $product_directory/boot/u-boot.img ] ; then
error "$product_directory/boot/u-boot.img does not exist. Aborting."
exit
elif ! [ -f $product_directory/boot/uImage ] ; then
error "$product_directory/boot/uImage does not exist. Aborting."
exit
elif ! [ -f $product_directory/system.img ] ; then
error "$product_directory/system.img does not exist. Aborting."
exit
fi
calculate_geometry
calculate_partition_sizes
echo "--------------------"
echo " disk: $disk"
echo " product: $product"
echo "--------------------"
echo "block size: $block_size bytes"
echo " sectors: $sectors"
echo "total size: $megabytes megabytes"
echo "--------------------"
printf "%-10s -> sectors: %-10d megabytes: %-10d\n" bootloader $bootloader_sectors $bootloader_mb
printf "%-10s -> sectors: %-10d megabytes: %-10d\n" boot $boot_sectors $boot_mb
printf "%-10s -> sectors: %-10d megabytes: %-10d\n" recovery $recovery_sectors $recovery_mb
printf "%-10s -> sectors: %-10d megabytes: %-10d\n" data $data_sectors $data_mb
printf "%-10s -> sectors: %-10d megabytes: %-10d\n" system $system_sectors $system_mb
printf "%-10s -> sectors: %-10d megabytes: %-10d\n" cache $cache_sectors $cache_mb
printf "%-10s -> sectors: %-10d megabytes: %-10d\n" vendor $vendor_sectors $vendor_mb
printf "%-10s -> sectors: %-10d megabytes: %-10d\n" misc $misc_sectors $misc_mb
echo "--------------------"
echo "writing partition scheme"
write_partion_scheme
echo "--------------------"
echo "creating filesystems"
create_filesystems
echo "--------------------"
echo "burning images"
burn_images
echo "--------------------"
echo "arranging boot"
arrange_boot
echo "--------------------"
echo "creating data filesystem"
create_data_filesystem
echo "--------------------"
echo "ejecting the disk"
eject
echo "--------------------"
echo "done. you may now remove the disk."
To sum it all up
Generally speaking android can be built using OS X and AOSP does support it. Freescale, and thus Wandboard, do not explicitly support building on OS X but it was not all that complicated to implement. All of the solutions listed in this post were discovered with a little stubborn tinkering and some general knowledge of Unix build tools and the discrepancies with their BSD counterparts. You don’t need to change your entire environment just to cross-compile and deploy Linux based operating systems, you just need a little know-how and the willingness to adjust to the requirements.

