Monday, August 26, 2013

Building/Running Android Goldfish kernel

Among the tasks for build an Android kernel development, building the Android Goldfish kernel is the easiest :-) (I mean, no compiling errors...)

First, you need to have access to the cross-compiling tools. The Android source code provides them in folder /prebuilt/linux-x86/toolchain/. 

Steps


1. Set the path to include the pre-build toolchain
   # export PATH=/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/:$PATH
2. Set the Kernel config file. In this case, we are compiling for the ARM emulator (armv7).
   # make ARCH=arm goldfish_armv7_defconfig
3. Run make
   # CROSS_COMPILE=/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi- ARCH=arm make
4. Change var ANDROID_PRODUCT_OUT
   # export ANDROID_PRODUCT_OUT=/out/target/product/generic/
5. Run the emulator
   # /out/host/linux-x86/bin/emulator-arm -system /out/target/product/generic/system.img -kernel /goldfish/arch/arm/boot/zImage -data /out/target/product/generic/userdata.img -ramdisk /out/target/product/generic/ramdisk.img -skindir /sdk/emulator/skins/ -skin HVGA -verbose -show-kernel

Issues


  • The option CONFIG_MODULES is NOT enabled by default. If you want to insert modules into the kernel, make sure to set CONFIG_MODULES;
  • Android emulator does NOT work with Kernels > 2.6.X So, make sure to use the proper Kernel. For devices, any support Kernel will work.


Building Android ICS


To compile ICS (and probably any new version of Android platform >= 4.0), you
might have some problems with the compilation tools.

  • Follow the instructions described on http://source.android.com/source/building.html
    • It also provides information about Android Kernel building.
  • Check which compiler best fits into the version of Android platform you are using.
    • Usually, due to new features (for example, C++11 support on GCC/++ 4.7), it is a bit more complicated to build it with new compilers... you will see several compiling errors. For example, for the ICS, GCC/++ 4.6 works better than GCC/++ 4.7.
  • You may need some changes in order to compile it properly (mostly on Makefile). Again, depending on your compiler, you may apply more or less changes on your code.
  • For ICS, GCC/++ 4.6 works better.
This link provides a good discussion about it (and solutions!). In my case, for compiling ICS, I made only a few changes (see below) and I also used GCC/++ 4.6.

=================================================================

project build/
diff --git a/core/combo/HOST_linux-x86.mk b/core/combo/HOST_linux-x86.mk
index 5ae4972..7df2893 100644
--- a/core/combo/HOST_linux-x86.mk
+++ b/core/combo/HOST_linux-x86.mk
@@ -53,6 +53,6 @@ HOST_GLOBAL_CFLAGS += \
  -include $(call select-android-config-h,linux-x86)
 # Disable new longjmp in glibc 2.11 and later. See bug 2967937.
-HOST_GLOBAL_CFLAGS += -D_FORTIFY_SOURCE=0
+HOST_GLOBAL_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0
 HOST_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined

project dalvik/
diff --git a/vm/native/dalvik_system_Zygote.cpp b/vm/native/dalvik_system_Zygote.cpp
index 31fecfd..b3b745a 100644
--- a/vm/native/dalvik_system_Zygote.cpp
+++ b/vm/native/dalvik_system_Zygote.cpp
@@ -19,6 +19,7 @@
  */
 #include "Dalvik.h"
 #include "native/InternalNativePriv.h"
+#include "sys/resource.h"
 #include
 #include

project development/
diff --git a/tools/emulator/opengl/host/renderer/Android.mk b/tools/emulator/opengl/host/renderer/Android.mk
index 55fcb80..613179c 100644
--- a/tools/emulator/opengl/host/renderer/Android.mk
+++ b/tools/emulator/opengl/host/renderer/Android.mk
@@ -6,6 +6,8 @@ $(call emugl-import,libOpenglRender)
 LOCAL_SRC_FILES := main.cpp
 LOCAL_CFLAGS    += -O0 -g
+LOCAL_LDLIBS += -lX11
+
 #ifeq ($(HOST_OS),windows)
 #LOCAL_LDLIBS += -lws2_32
 #endif

project external/gtest/
diff --git a/include/gtest/internal/gtest-param-util.h b/include/gtest/internal/gtest-param-util.h
index 5559ab4..0af13b0 100644
--- a/include/gtest/internal/gtest-param-util.h
+++ b/include/gtest/internal/gtest-param-util.h
@@ -39,6 +39,7 @@
 #include
 #include
+#include
 #if GTEST_HAS_PARAM_TEST
diff --git a/src/Android.mk b/src/Android.mk
index 2465e16..1d93ac8 100644
--- a/src/Android.mk
+++ b/src/Android.mk
@@ -49,7 +49,7 @@ LOCAL_SRC_FILES := gtest-all.cc
 LOCAL_C_INCLUDES := $(libgtest_host_includes)
-LOCAL_CFLAGS += -O0
+LOCAL_CFLAGS += -O0 -fpermissive
 LOCAL_MODULE := libgtest_host
 LOCAL_MODULE_TAGS := eng
@@ -67,7 +67,7 @@ LOCAL_SRC_FILES := gtest_main.cc
 LOCAL_C_INCLUDES := $(libgtest_host_includes)
-LOCAL_CFLAGS += -O0
+LOCAL_CFLAGS += -O0 -fpermissive
 LOCAL_STATIC_LIBRARIES := libgtest

project external/llvm/
diff --git a/llvm-host-build.mk b/llvm-host-build.mk
index 5219efd..cc91ee0 100644
--- a/llvm-host-build.mk
+++ b/llvm-host-build.mk
@@ -44,6 +44,8 @@ LOCAL_C_INCLUDES := \
 LOCAL_IS_HOST_MODULE := true
+LOCAL_LDLIBS := -lpthread -ldl
+
 ###########################################################
 ## Commands for running tblgen to compile a td file
 ###########################################################

project external/oprofile/
diff --git a/libpp/format_output.h b/libpp/format_output.h
index b6c4592..8e527d5 100644
--- a/libpp/format_output.h
+++ b/libpp/format_output.h
@@ -91,7 +91,7 @@ protected:
  symbol_entry const & symbol;
  sample_entry const & sample;
  size_t pclass;
- mutable counts_t & counts;
+ counts_t & counts;
  extra_images const & extra;
  double diff;
  };

project frameworks/base/
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index 638f72f..127cad9 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -61,7 +61,7 @@ LOCAL_SRC_FILES:= $(commonSources)
 LOCAL_MODULE:= libutils
-LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS)
+LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS) -fpermissive
 LOCAL_C_INCLUDES += external/zlib
 ifeq ($(HOST_OS),windows)
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index a3e5d9a..4c415d6 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -28,7 +28,7 @@ LOCAL_SRC_FILES := \
     ZipFile.cpp
-LOCAL_CFLAGS += -Wno-format-y2k
+LOCAL_CFLAGS += -Wno-format-y2k -fpermissive
 LOCAL_C_INCLUDES += external/expat/lib
 LOCAL_C_INCLUDES += external/libpng

project frameworks/compile/slang/
diff --git a/Android.mk b/Android.mk
index fce3637..8ffe68f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -19,7 +19,7 @@ ifeq ($(TARGET_BUILD_APPS),)
 LOCAL_PATH := $(call my-dir)
-local_cflags_for_slang := -Wno-sign-promo -Wall -Wno-unused-parameter -Werror
+local_cflags_for_slang := -Wno-sign-promo -Wall -Wno-unused-parameter
 ifneq ($(TARGET_BUILD_VARIANT),eng)
 local_cflags_for_slang += -D__DISABLE_ASSERTS
 endif

Android (Goldfish) kernel development

Finally, back to this :-)

Lately, I have being developing a new project which basically needs some kernel changes on Android Goldfish kernel. Initially, I thought that this would be something like "traditional" kernel development, but NOT. Android kernel is, of course, a Linux kernel but it has some peculiarities that impact on the development phase.

[NOTE] I'd rather provide a link to the source that I used than replicating the same information.

So, I split my experience into the following topics:
  1. Building Android ICS
  2. Building/Running Android Goldfish kernel 
  3. Creating a Goldfish kernel module
  4. Adding new syscalls into the Goldfish kernel

Thursday, January 24, 2013

Moving...

My life has changed upside down recently: I have been accepted to Saarland University Graduate School and I will move to Germany soon. I will try to keep this updated as possible.

Thursday, November 29, 2012

LLVM - ARM cross-compilation using Raspberry!!

Well, a short break on continuous integration posts!

I bought my Raspberry Pi (http://www.raspberrypi.org/) board some weeks ago mainly to use it as a developer board (pretty affordable and efficient). So, I decided to use it to cross-compile LLVM (http://www.llvm.org).

So, here you go.

Building

First of all, download LLVM (from either SVN or GIT repositories). I got the following information from  LLVM documentation. For more details, check this out!

  • Checkout LLVM:
    $ cd where-you-want-llvm-to-live
    $ svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm

  • Checkout Clang:
    $ cd where-you-want-llvm-to-live
    $ cd llvm/tools
    $ svn co http://llvm.org/svn/llvm-project/cfe/trunk clang
  • Checkout Compiler-RT:
    $ cd where-you-want-llvm-to-live
    $ cd llvm/projects
    $ svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk compiler-rt
  • Get the Test Suite Source Code [Optional]
    $ cd where-you-want-llvm-to-live
    $ cd llvm/projects
    $ svn co http://llvm.org/svn/llvm-project/test-suite/trunk test-suite

To cross-compile it to ARM platform, you need a toolchain. I use Sourcery G++ Lite 2011.03-41 (MentorGraphics Sourcery CodeBench Lite Edition) - it is free and contains everything we need. Install it and also remember to set the PATH variable so that you can use your toolchain.
$ export $PATH=$PATH:/home/user/CodeSourcery/Sourcery_G++_Lite/bin
Now, it´s time to build the application (and remember: for further details, check this out!)

$ cd where-you-want-to-build-llvm
$ mkdir build
(for building without polluting the source dir)
$ cd build
$ ../configure --target=arm-none-linux-gnueabi --host=arm-none-linux-gnueabi --enable-optimized (the target/host value may change depending on the toolchain that you have chosen.)
$ make

Now, you just need to wait for a couple of minutes :-) Next step is NFS-mounting the LLVM dir in your Raspberry Pi.

NFS-Mounting

Now, LLVM is cross-compiled and we are able to use it and perform some tests on Raspberry Pi. I prefer NFS as partition mounting solution. An important information is that you have to have the same path on both environments (desktop and remote). It means that if you are building LLVM on /home/user/llvm desktop folder, you have to mount it on /home/user/llvm remote folder (in most of cases, you have to create the user on your Raspberry environment - just use the command).  Firstly, set up your desktop machine:
  • Install NFS packages
    @desktop$ sudo apt-get install portmap nfs-kernel-server nfs-common
  • Edit /etc/exports and add the following line
    /home/user/llvm 192.168.1.0/24(rw,sync,no_subtree_check)
  • Restart NFS system
    @desktop$ sudo service nfs-kernel-server restart
  • Change access permission of your shared folder (in this case, I use the same folder)
    @desktop$ chmod -R 777 /home/user/llvm

Configuration on Raspberry Pi is also straightforward:

  • Install NFS packages (most of Raspberry distributions contain NFS installed, so maybe this step is not necessary)
    @remote$ sudo apt-get install portmap nfs-kernel-server nfs-common
  • Create the host folder
    @remote$ mkdir llvm
    @remote$ chmod 777 llvm
  • Mount the NFS-shared folder
    @remote$ sudo mount 192.168.1.4:/home/user/llvm /home/user/llvm
Now it is done and you can use your cross-compiled LLVM on your Raspberry.

Testing

Let´s now focus on LLVM tests and how we can run them on ARM platforms. In this case, I am running tests under /home/user/llvm/tests folder.

  • CD to test dir
    @remote$ cd llvm/build/test
  • Run tests
    @remote:/home/user/llvm/build/test$ make 

After some minutes, LLVM test suite runs all integration tests and provides a report with results.

@remote:/home/user/llvm/build/test$ make
...
PASS: LLVM :: ExecutionEngine/MCJIT/test-shift.ll (59 of 59)
Testing Time: 11.65s
********************
Unexpected Passing Tests (1):
    LLVM :: ExecutionEngine/MCJIT/test-data-align-remote.ll
********************
Failing Tests (7):
    LLVM :: ExecutionEngine/MCJIT/2003-01-04-ArgumentBug.ll
    LLVM :: ExecutionEngine/MCJIT/2005-12-02-TailCallBug.ll
    LLVM :: ExecutionEngine/MCJIT/fpbitcast.ll
    LLVM :: ExecutionEngine/MCJIT/pr13727.ll
    LLVM :: ExecutionEngine/MCJIT/test-call.ll
    LLVM :: ExecutionEngine/MCJIT/test-common-symbols.ll
    LLVM :: ExecutionEngine/MCJIT/test-ret.ll
  Expected Passes    : 45
  Expected Failures  : 6
  Unexpected Passes  : 1
  Unexpected Failures: 7
UPDATE: Raspberry Pi the ARM target platform for LLVM project at this moment. If you want to contribute to LLVM project by supporting ARM features, check a PandaBoard development kit.

Wednesday, November 28, 2012

Setting up your Continuous Integration environment - Part I

Continuous Integration is such a great idea: it works as a trainee that constantly downloads/builds/tests/deploys you application and notifies you whether something goes wrong or nice. I really do believe that (of course, besides several other advantages) it improves the project overall quality and also helps you to keep the application ready to be reviewed by a stakeholder.

If you are still skeptical about it, please take a look that this marvelous post here [Martin Fowler] .

Let´s discuss how you can set up a environment for a more complex project. So, unfortunately, this is tutorial for beginners (for basic/how-to-install-and-run instructions, check it on internet).

Introduction

The system consists of one server located in a external environment (for example, AWS services) and several mobile clients (iOS, Android and QT clients). Basically, the mobile applications fetch content/data from the server.

We need to constantly build/deploy the server and build all mobile clients. One very interesting point in this scenario is the amount of platforms: iOS (to build iOS client), Linux (to build Android/QT client - I´d rather use Linux for Android projects) and Windows (to build the server).

Besides svn checking-out + building + testing + deployment, we will also use QA solutions, such as Sonar and some static analysis tools for different platforms.

We will use Jenkins as CI server.

Proposed design


As I said, the system consists of several components: mobile clients (iOS, Qt and Android) and also servers. In this case, I´d rather use master-slave approach. You can create one slave for each mobile platform and also another one for for servers. To the given example, the solution is defined as it follows:


You might ask me why this is too complicated! But believe on me. If you have complex systems to build, this approach works a lot better: it´s easier to organize and to maintain, and each component on its own environment. In my next post, I describe how we set up all of this :-)

Friday, October 26, 2012

Back!!!

After a loooong break, I am back to this. I have to confess that I had had several new/cool stuff during this pause: new projects, mind-blowing findings, exciting/stressful experiences, lovely/irritating people. And all of this had consumed a lot of my free time. I am not saying that I hadn´t had time at all: I had done some new/different things with such slots of time than only writing about technical stuff.

Well, but anyway, let´s keep track of new stuff. The main reason to start blogging again was the simply fact that I am not used to describe all solutions for tricky problems in general: how to cross-compile certain applications for ARM devices, how to set up a smart CI environment, and so forth. I swear I have tried it really hard, but my evil side always tells to myself: "if you need it some other day, you will remember it". So, this is also a kind of "Raul´s Recipes Book".

I am really convinced that it will work :-)

As part of my next posts, I will describe a bit more about how lovely is a CI environment for a relative huge project (of course, how you can set up all of this and put the pieces together). Specially, when it has such different clients, such as iOS, Android and QT applications.