How to build Android APKs on a FreeBSD server


July 2014.
Edit: this article is out of date. A new one was written two years later here.

Image The FreeBSD logo

Situation


Your team is creating Android apps. Your CI server is running FreeBSD and you'd like Jenkins or something else to be able to build your apps to have nice nightly builds.

You don't care about having adb and you especially don't want to install anything related to X11.

Example


In this example, we'll be building an app using gradle.

Install the build requirements


Install gradle

cd /usr/ports/devel/gradle && make install clean

Install the linux compatibility layer

kldload linux


cd /usr/ports/emulators/linux_base-f10 && make install distclean

Remember, you might need to use brandelf on some parts of the SDK later if they won't execute.

Install bash and link /bin/bash to /usr/local/bin/bash.

cd /usr/ports/shells/bash && make install clean
ln -s /usr/local/bin/bash /bin/bash

Install your favorite flavour of Java.

cd /usr/ports/java/openjdk7 && make install clean

Download and update the Android SDK


Download and extract the Android SDK for Linux.

fetch 'http://dl.google.com/android/android-sdk_r23-linux.tgz'
tar xzf android-sdk_r23-linux.tgz

Go into the tools folder and list the contents of the SDK repositories.

./android list sdk -u
Refresh Sources:
Fetching https://dl-ssl.google.com/android/repository/addons_list-2.xml
Validate XML
Parse XML
Fetched Add-ons List successfully
Refresh Sources
Fetching URL: https://dl-ssl.google.com/android/repository/repository-10.xml
Validate XML: https://dl-ssl.google.com/android/repository/repository-10.xml
Parse XML: https://dl-ssl.google.com/android/repository/repository-10.xml
Fetching URL: https://dl-ssl.google.com/android/repository/addon.xml
Validate XML: https://dl-ssl.google.com/android/repository/addon.xml
Parse XML: https://dl-ssl.google.com/android/repository/addon.xml
Fetching URL: https://dl-ssl.google.com/android/repository/addon-6.xml
Validate XML: https://dl-ssl.google.com/android/repository/addon-6.xml
Parse XML: https://dl-ssl.google.com/android/repository/addon-6.xml
Fetching URL: https://dl-ssl.google.com/glass/gdk/addon.xml
Validate XML: https://dl-ssl.google.com/glass/gdk/addon.xml
Parse XML: https://dl-ssl.google.com/glass/gdk/addon.xml
Fetching URL: https://dl-ssl.google.com/android/repository/extras/intel/addon.xml
Validate XML: https://dl-ssl.google.com/android/repository/extras/intel/addon.xml
Parse XML: https://dl-ssl.google.com/android/repository/extras/intel/addon.xml
Fetching URL: https://dl-ssl.google.com/android/repository/sys-img/android/sys-img.xml
Validate XML: https://dl-ssl.google.com/android/repository/sys-img/android/sys-img.xml
Parse XML: https://dl-ssl.google.com/android/repository/sys-img/android/sys-img.xml
Fetching URL: https://dl-ssl.google.com/android/repository/sys-img/android-wear/sys-img.xml
Validate XML: https://dl-ssl.google.com/android/repository/sys-img/android-wear/sys-img.xml
Parse XML: https://dl-ssl.google.com/android/repository/sys-img/android-wear/sys-img.xml
Fetching URL: https://dl-ssl.google.com/android/repository/sys-img/android-tv/sys-img.xml
Validate XML: https://dl-ssl.google.com/android/repository/sys-img/android-tv/sys-img.xml
Parse XML: https://dl-ssl.google.com/android/repository/sys-img/android-tv/sys-img.xml
Fetching URL: https://dl-ssl.google.com/android/repository/sys-img/x86/addon-x86.xml
Validate XML: https://dl-ssl.google.com/android/repository/sys-img/x86/addon-x86.xml
Parse XML: https://dl-ssl.google.com/android/repository/sys-img/x86/addon-x86.xml
Packages available for installation or update: 63
1- Android SDK Tools, revision 23.0.1
2- Android SDK Platform-tools, revision 20
3- Android SDK Build-tools, revision 20
4- Documentation for Android 'L' Preview SDK, revision 1
5- SDK Platform Android 4.4W, API 20, revision 1
6- SDK Platform Android L Preview, revision 1
7- SDK Platform Android 4.4.2, API 19, revision 3
8- SDK Platform Android 4.3, API 18, revision 2
9- SDK Platform Android 4.2.2, API 17, revision 2
10- SDK Platform Android 4.1.2, API 16, revision 4
11- SDK Platform Android 4.0.3, API 15, revision 3
12- SDK Platform Android 4.0, API 14, revision 3
13- SDK Platform Android 3.2, API 13, revision 1
14- SDK Platform Android 3.1, API 12, revision 3
15- SDK Platform Android 3.0, API 11, revision 2
16- SDK Platform Android 2.3.3, API 10, revision 2
17- SDK Platform Android 2.2, API 8, revision 3
18- SDK Platform Android 2.1, API 7, revision 3
19- SDK Platform Android 1.6, API 4, revision 3
20- SDK Platform Android 1.5, API 3, revision 4
21- Samples for SDK API 20, revision 1
22- Samples for SDK API L Preview, revision 1
23- Samples for SDK API 19, revision 5
24- Samples for SDK API 18, revision 1
25- Samples for SDK API 17, revision 1
26- Samples for SDK API 16, revision 1
27- Samples for SDK API 15, revision 2
28- Samples for SDK API 14, revision 2
29- Samples for SDK API 13, revision 1
30- Samples for SDK API 12, revision 1
31- Samples for SDK API 11, revision 1
32- Samples for SDK API 10, revision 1
33- Samples for SDK API 8, revision 1
34- Samples for SDK API 7, revision 1
35- Google APIs (x86 System Image), Android API 19, revision 5
36- Google APIs (ARM System Image), Android API 19, revision 5
37- Glass Development Kit Preview, Android API 19, revision 8
38- Google APIs, Android API 18, revision 3
39- Google APIs, Android API 17, revision 3
40- Google APIs, Android API 16, revision 3
41- Google APIs, Android API 15, revision 2
42- Google APIs, Android API 14, revision 2
43- Google APIs, Android API 13, revision 1
44- Google TV Addon, Android API 13, revision 1
45- Google APIs, Android API 12, revision 1
46- Google TV Addon, Android API 12, revision 2
47- Google APIs, Android API 11, revision 1
48- Google APIs, Android API 10, revision 2
49- Google APIs, Android API 8, revision 2
50- Google APIs, Android API 7, revision 1
51- Google APIs, Android API 4, revision 2
52- Google APIs, Android API 3, revision 3
53- Android Support Repository, revision 6
54- Android Support Library, revision 20
55- Google Play services for Froyo, revision 12
56- Google Play services, revision 17
57- Google Repository, revision 8
58- Google Play APK Expansion Library, revision 3
59- Google Play Billing Library, revision 5
60- Google Play Licensing Library, revision 2
61- Google USB Driver, revision 10
62- Google Web Driver, revision 2
63- Intel x86 Emulator Accelerator (HAXM installer), revision 4

-u means "no gui".

Install what you need.

./android update sdk --filter 1,2,3,5,6,53,54,56 -u
[license stuff]
Installing Archives:
Preparing to install archives
Downloading Android SDK Platform-tools, revision 20
Installing Android SDK Platform-tools, revision 20
Stopping ADB server failed (code -1).
Installed Android SDK Platform-tools, revision 2099%)
Downloading Android SDK Build-tools, revision 20
Installing Android SDK Build-tools, revision 20
Installed Android SDK Build-tools, revision 2099%)
Downloading SDK Platform Android 4.4W, API 20, revision 1
Installing SDK Platform Android 4.4W, API 20, revision 1
Installed SDK Platform Android 4.4W, API 20, revision 197%)
Downloading SDK Platform Android L Preview, revision 1
Installing SDK Platform Android L Preview, revision 1
Installed SDK Platform Android L Preview, revision 197%)
Downloading Android Support Repository, revision 6
Installing Android Support Repository, revision 6
Installed Android Support Repository, revision 699%)
Downloading Android Support Library, revision 20
Installing Android Support Library, revision 20
Installed Android Support Library, revision 2093%)
Downloading Google Play services, revision 17
Installing Google Play services, revision 17
Installed Google Play services, revision 1796%)
Downloading Android SDK Tools, revision 23.0.1
Installing Android SDK Tools, revision 23.0.1
Installed Android SDK Tools, revision 23.0.199%)
Stopping ADB server failed (code -1).
Unable to run 'adb': Cannot run program "/root/android-sdk-linux/platform-tools/adb": error=2, No such file or directory.
Starting ADB server failed (code -1).
null Done. 8 packages installed.

Build your apps!


Edit local.properties and set your SDK location. Alternatively, you can set the environment variable ANDROID_HOME.

sdk.dir=/some/where/android-sdk-linux

Start gradle and see if it complains.

gradle
[some stuff]
Welcome to Gradle 1.12.

To run a build, run gradle ...

To see a list of available tasks, run gradle tasks

To see a list of command-line options, run gradle --help

BUILD SUCCESSFUL

Total time: 14.139 secs

If not, build!

gradle assembleRelease
[many things]
14:25:54.743 [LIFECYCLE] [org.gradle.BuildResultLogger]
14:25:54.744 [LIFECYCLE] [org.gradle.BuildResultLogger] BUILD SUCCESSFUL
14:25:54.746 [LIFECYCLE] [org.gradle.BuildResultLogger]
14:25:54.748 [LIFECYCLE] [org.gradle.BuildResultLogger] Total time: 1 mins 56.878 secs


ll Truc/build/outputs/apk/
-rw-r--r-- 1 root wheel 1064222 Jul 1 14:25 Truc-release-unaligned.apk
-rw-r--r-- 1 root wheel 1064495 Jul 1 14:25 Truc-release.apk

You can also use the SDK Manager Plugin for gradle, so that your SDK is updated automatically when you build your project.

Problems I met


gradle won't start



gradle

FAILURE: Build failed with an exception.

* What went wrong:
net.rubygrapefruit.platform.internal.jni.PosixFileFunctions.symlink(Ljava/lang/String;Ljava/lang/String;Lnet/rubygrapefruit/platform/internal/FunctionResult;)V

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

libstdc++.so.6 is missing. Install gcc.

cd /usr/ports/lang/gcc && make install clean





Ambiguous method overloading for method java.io.File



> Ambiguous method overloading for method java.io.File#.
Cannot resolve which method to invoke for [null, class java.lang.String] due to overlapping prototypes between:
[class java.lang.String, class java.lang.String]
[class java.io.File, class java.lang.String]

gradle couldn't find the SDK. Did you set sdk.dir in local.properties?




The SDK downloads packages for Windows instead of Linux


The SDK doesn't recognize FreeBSD, so it downloads packages for Windows. It needs to be patched.

Download the sdk source.

git clone https://android.googlesource.com/platform/tools/base

Apply the following patch to the source:

diff -Naur A/common/src/main/java/com/android/SdkConstants.java B/common/src/main/java/com/android/SdkConstants.java
--- A/common/src/main/java/com/android/SdkConstants.java 2014-07-01 16:44:55.000000000 +0200
+++ B/common/src/main/java/com/android/SdkConstants.java 2014-07-01 19:57:58.000000000 +0200
@@ -596,6 +596,8 @@
return PLATFORM_WINDOWS;
} else if (os.startsWith("Linux")) { //$NON-NLS-1$
return PLATFORM_LINUX;
+ } else if (os.startsWith("FreeBSD")) { //$NON-NLS-1$
+ return PLATFORM_LINUX;
}

return PLATFORM_UNKNOWN;
diff -Naur A/sdklib/src/main/java/com/android/sdklib/internal/repository/archives/ArchFilter.java B/sdklib/src/main/java/com/android/sdklib/internal/repository/archives/ArchFilter.java
--- A/sdklib/src/main/java/com/android/sdklib/internal/repository/archives/ArchFilter.java 2014-07-01 19:57:30.000000000 +0200
+++ B/sdklib/src/main/java/com/android/sdklib/internal/repository/archives/ArchFilter.java 2014-07-01 19:55:33.000000000 +0200
@@ -210,6 +210,8 @@
hostOS = HostOs.WINDOWS;
} else if (os.startsWith("Linux")) { //$NON-NLS-1$
hostOS = HostOs.LINUX;
+ } else if (os.startsWith("FreeBSD")) { //$NON-NLS-1$
+ hostOS = HostOs.LINUX;
}

BitSize jvmBits;


Rebuild the patched files.

javac sdklib/src/main/java/com/android/sdklib/internal/repository/archives/ArchFilter.java -cp "sdklib/src/main/java:common/src/main/java"
javac common/src/main/java/com/android/SdkConstants.java

Replace the files inside the jar.

cd sdklib/src/main/java/ && jar uf /some/where/android-sdk-linux/tools/lib/sdklib.jar com/android/sdklib/internal/repository/archives/ArchFilter.class
cd common/src/main/java && jar uf /some/where/android-sdk-linux/tools/lib/common.jar com/android/SdkConstants.class

See this patch on the Android website: https://android-review.googlesource.com/#/c/100271/.

Profit!