The tools adb and fastboot are essential for debugging, managing and customizing Android devices. Both adb and fastboot are available for download within the ADT Bundle, however, those prebuilt binaries are for common host platforms (x86 and x86_64). What if you would like to run adb on a different architecture, such as ARM? There are of course multiple ways to get this done. Here we will show you how to cross compile adb and fastboot outside of the Android source tree using a standalone Makefile.
For this tutorial you will need
- A cross compilation toolchain
We will be using the official yocto project toolchain - Source files for adb and fastboot
These will be in the platform/system/core and platform/system/extras repository from the official Android sources - Source files of three “external” projects
Namely zlib, openssl and libselinux, which are also available from the official Android sources
Installing the cross compilation toolchain
Obviously, you may skip this part if you already have a cross compiler set up. We will install an ARM cross compiler from the yocto project. Have a look at the official yocto project quick start guide if you like and then navigate to the toolchain download section. Depending on your host machine select either x86_64 or i686, and then choose the file appropriate for your target hardware. We will select poky-eglibc-x86_64-core-image-sato-armv7a-vfp-neon-toolchain-1.5.sh, since we want to run adb and fastboot on an ARM architecture later on.
Assuming it was downloaded into Downloads, execute the script
chmod a+x ~/Downloads/poky-eglibc-x86_64-core-image-sato-armv7a-vfp-neon-toolchain-1.5.sh ~/Downloads/poky-eglibc-x86_64-core-image-sato-armv7a-vfp-neon-toolchain-1.5.sh
You will be asked where you want to install the toolchain (default location is /opt/poky).
Downloading the sources
In order for the Makefile to work correctly, the core and extras repository need to be placed in a folder called system, while the three external projects need to reside within a folder called external. We will be using a relatively recent Android Kitkat version, namely android-4.4_r1.2. (You may also download the master branch by not specifying any branch at all. I have tried and compiled successfully with “android-4.4_r1.2” however.)
user@host:~$ mkdir work user@host:~$ cd work user@host:~/work$ mkdir system user@host:~/work$ cd system user@host:~/work/system$ git clone -b android-4.4_r1.2 https://android.googlesource.com/platform/system/core user@host:~/work/system$ git clone -b android-4.4_r1.2 https://android.googlesource.com/platform/system/extras user@host:~/work/system$ cd .. user@host:~/work$ mkdir external user@host:~/work$ cd external user@host:~/work/external$ git clone -b android-4.4_r1.2 https://android.googlesource.com/platform/external/zlib user@host:~/work/external$ git clone -b android-4.4_r1.2 https://android.googlesource.com/platform/external/openssl user@host:~/work/external$ git clone -b android-4.4_r1.2 https://android.googlesource.com/platform/external/libselinux
In your development folder you should now have two folders: system and external. The system folder contains two folders named core and extras; and the external folder contains the three projects zlib, openssl and libselinux.
Building
adb
We are going to use a custom Makefile which we copy into system/core/adb. The contents are based on an standalone Makefile for an earlier Android release from Heiher’s Blog, thanks for sharing!
# standalone Makefile for adb SRCS+= adb.c SRCS+= fdevent.c SRCS+= adb_client.c SRCS+= commandline.c SRCS+= console.c SRCS+= file_sync_client.c SRCS+= get_my_path_linux.c SRCS+= services.c SRCS+= sockets.c SRCS+= transport.c SRCS+= transport_local.c SRCS+= transport_usb.c SRCS+= usb_linux.c SRCS+= usb_vendors.c SRCS+= adb_auth_host.c VPATH+= ../libcutils SRCS+= list.c SRCS+= socket_inaddr_any_server.c SRCS+= socket_local_client.c SRCS+= socket_local_server.c SRCS+= socket_loopback_client.c SRCS+= socket_loopback_server.c SRCS+= socket_network_client.c SRCS+= load_file.c VPATH+= ../libzipfile SRCS+= centraldir.c SRCS+= zipfile.c VPATH+= ../../../external/zlib/src SRCS+= adler32.c SRCS+= compress.c SRCS+= crc32.c SRCS+= deflate.c SRCS+= infback.c SRCS+= inffast.c SRCS+= inflate.c SRCS+= inftrees.c SRCS+= trees.c SRCS+= uncompr.c SRCS+= zutil.c CPPFLAGS+= -DADB_HOST=1 CPPFLAGS+= -DHAVE_FORKEXEC=1 CPPFLAGS+= -DHAVE_SYMLINKS CPPFLAGS+= -DHAVE_TERMIO_H CPPFLAGS+= -DHAVE_SYS_SOCKET_H CPPFLAGS+= -D_GNU_SOURCE CPPFLAGS+= -D_XOPEN_SOURCE CPPFLAGS+= -I. CPPFLAGS+= -I../include CPPFLAGS+= -I../../../external/zlib CPPFLAGS+= -I../../../external/openssl/include CFLAGS+= -O2 -g -Wall -Wno-unused-parameter LIBS= -lcrypto -lpthread -lrt TOOLCHAIN= /opt/poky/1.5/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi- CC= $(TOOLCHAIN)gcc LD= $(TOOLCHAIN)gcc OBJS= $(SRCS:.c=.o) all: adb adb: $(OBJS) $(LD) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) clean: rm -rf $(OBJS)
Change the TOOLCHAIN variable to your own cross compiler in case you are not using the yocto toolchain from the previous step. Now simply type make within the system/core/adb directory and you should end up with an ARM executable named adb. If you get an error similar to “Makefile:69: *** missing separator. Stop.”, then most likely the tab-indentations have been converted into white spaces on said lines. You can also check which shared libraries are needed on your target with the objdump tool.
$ vim Makefile $ make $ file adb adb: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.16, BuildID[sha1]=0x6c31475e9105d3f378a985e6177cafde5f3228ea, not stripped $ objdump -x adb | grep NEEDED NEEDED libcrypto.so.1.0.0 NEEDED libpthread.so.0 NEEDED librt.so.1 NEEDED libc.so.6
fastboot
For compiling fastboot we will use a different Makefile inside system/core/fastboot with the following contents:
# standalone Makefile for fastboot SRCS+= protocol.c SRCS+= engine.c SRCS+= bootimg.c SRCS+= fastboot.c SRCS+= usb_linux.c SRCS+= util_linux.c VPATH+= ../../../external/zlib/src SRCS+= adler32.c SRCS+= compress.c SRCS+= crc32.c SRCS+= deflate.c SRCS+= gzclose.c SRCS+= gzlib.c SRCS+= gzread.c SRCS+= gzwrite.c SRCS+= infback.c SRCS+= inflate.c SRCS+= inftrees.c SRCS+= inffast.c SRCS+= trees.c SRCS+= uncompr.c SRCS+= zutil.c VPATH+= ../../extras/ext4_utils SRCS+= make_ext4fs.c SRCS+= ext4fixup.c SRCS+= ext4_utils.c SRCS+= allocate.c SRCS+= contents.c SRCS+= extent.c SRCS+= indirect.c SRCS+= uuid.c SRCS+= sha1.c SRCS+= wipe.c SRCS+= crc16.c VPATH+= ../../../external/libselinux/src SRCS+= booleans.c SRCS+= canonicalize_context.c SRCS+= disable.c SRCS+= enabled.c SRCS+= fgetfilecon.c SRCS+= fsetfilecon.c SRCS+= getenforce.c SRCS+= getfilecon.c SRCS+= getpeercon.c SRCS+= lgetfilecon.c SRCS+= load_policy.c SRCS+= lsetfilecon.c SRCS+= policyvers.c SRCS+= procattr.c SRCS+= setenforce.c SRCS+= setfilecon.c SRCS+= context.c SRCS+= mapping.c SRCS+= stringrep.c SRCS+= compute_create.c SRCS+= compute_av.c SRCS+= avc.c SRCS+= avc_internal.c SRCS+= avc_sidtab.c SRCS+= get_initial_context.c SRCS+= checkAccess.c SRCS+= sestatus.c SRCS+= deny_unknown.c SRCS+= callbacks.c SRCS+= check_context.c SRCS+= freecon.c SRCS+= init.c SRCS+= label.c SRCS+= label_file.c SRCS+= label_android_property.c VPATH+= ../libsparse SRCS+= backed_block.c SRCS+= output_file.c SRCS+= sparse.c SRCS+= sparse_crc32.c SRCS+= sparse_err.c SRCS+= sparse_read.c VPATH+= ../libcutils SRCS+= list.c SRCS+= socket_inaddr_any_server.c SRCS+= socket_local_client.c SRCS+= socket_local_server.c SRCS+= socket_loopback_client.c SRCS+= socket_loopback_server.c SRCS+= socket_network_client.c SRCS+= load_file.c VPATH+= ../libzipfile SRCS+= centraldir.c SRCS+= zipfile.c CPPFLAGS+= -DHOST CPPFLAGS+= -DADB_HOST=1 CPPFLAGS+= -DHAVE_FORKEXEC=1 CPPFLAGS+= -DHAVE_SYMLINKS CPPFLAGS+= -DHAVE_TERMIO_H CPPFLAGS+= -DHAVE_SYS_SOCKET_H CPPFLAGS+= -D_GNU_SOURCE CPPFLAGS+= -D_XOPEN_SOURCE CPPFLAGS+= -I. CPPFLAGS+= -I../include CPPFLAGS+= -I../mkbootimg CPPFLAGS+= -I../libsparse/include CPPFLAGS+= -I../../extras/ext4_utils CPPFLAGS+= -I../../../external/zlib CPPFLAGS+= -I../../../external/openssl/include CPPFLAGS+= -I../../../external/libselinux/include CFLAGS+= -O2 -g -Wall -Wno-unused-parameter TOOLCHAIN= /home/rudi/dev/fsl-community-bsp/build/tmp/sysroots/x86_64-linux/usr/bin/cortexa9hf-vfp-neon-poky-linux-gnueabi/arm-poky-linux-gnueabi- CC= $(TOOLCHAIN)gcc LD= $(TOOLCHAIN)gcc OBJS= $(SRCS:.c=.o) all: fastboot fastboot: $(OBJS) $(LD) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) clean: rm -rf $(OBJS)
Again, simply type make and you should be all set! You can now use adb and fastboot on a Wandboard or Raspberry Pi for instance 🙂 Have a look at Getting started with Yocto on Wandboard or 12MB Minimal Image for Raspberry Pi using the Yocto Project to get started.
If you are interested in how to create the above Makefiles, have a look at the Android.mk file within the same folder. Each Makefile basically reproduces the section between include $(CLEAR_VARS) and include $(BUILD_HOST_EXECUTABLE).
Update 18.09.2014: here is also a Makefile to build adb without libcrypto dependencies (tested with Yocto on a Wandboard)
Thanks, this was very useful! I’m compiling for Raspberry Pi, btw.
really helpful,
but can we use static link in lib crypto pthread and rt,
like
LDFLAGS= -static
LIBS= -lcrypto -lpthread -lrt
I have tried,and warning not find these libs, hope we can build non-dependent adb bin file.
Hi Henry,
a while back we created a Makefile without libcrypto dependencies. However, this still needs librt and libpthread dynamically. I have put this file at the end of the post, maybe you can try to extend it. Please tell me if you succeed so we can update the above instructions.
Best Regards
andreas
hi Andreas,Thanks for reply.
In fact I want to use adb (high version),in some low android device.I referenced the host-adb and device adbd,they are all static linked. So I modify the Android.mk which generate adb part like below.At last build the device adb staticly successfully.
diff –git a/adb/Android.mk b/adb/Android.mk
index 721b48d..7e77610 100644
— a/adb/Android.mk
+++ b/adb/Android.mk
@@ -139,7 +139,7 @@ include $(BUILD_EXECUTABLE)
ifneq ($(SDK_ONLY),true)
include $(CLEAR_VARS)
-LOCAL_LDLIBS := -lrt -ldl -lpthread
+#LOCAL_LDLIBS := -lrt -ldl -lpthread
LOCAL_SRC_FILES := \
adb.c \
@@ -172,9 +172,11 @@ LOCAL_C_INCLUDES += external/openssl/include
LOCAL_MODULE := adb
-LOCAL_STATIC_LIBRARIES := libzipfile libunz libcutils
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_STATIC_LIBRARIES := libzipfile libunz libcrypto_static libcutils libc
+#LOCAL_STATIC_LIBRARIES := libzipfile libunz libcutils
-LOCAL_SHARED_LIBRARIES := libcrypto
+#LOCAL_SHARED_LIBRARIES := libcrypto
include $(BUILD_EXECUTABLE)
endif
Hi Henry & Andreas :
I have the same need for build adb staticly for arm and i had follow you and Andreas ‘s action .
But it still warning “ld: cannot find -lcrypto -lpthread -lrt -lc ” when i add “LDFLAGS= -static” to the Makefile .
Can you provide more detail ?
Sincerely thanks
Very nice, works well for a raspberry pi!
Very nice , works well for a raspberry pi!
Thanks for the detailed guide, I was thinking whether you had tried compiling adb for armv8 like in Juno development board. I would like to try compiling adb for 64bit ARM arch and so any pointers in that direction could be helpful. Thanks.
Can someone post a RasPi binary of a *recent* adb? Old adb won’t work with newer Android phones
Works like a charm for a custom ARM board running Linux 2.6.
Thanks in tons! 🙂
Thanks a ton! This is really helpful 🙂
thanks. follow your steps, I build RPi fastboot sucsessfullly. but when I get fastboot from master tip. Makefile not work anymore.
BTW, Makefile TOOLCHAIN variable need change, in order to build.
any update on this?