This article is to describe summary and some important points to establish gnu system root on android devices based on my experience.

Notation
    [] : version used.

===============
Introduction
===============
    Now a days, performance of Android mobile device is much like PC.
    So, why don't you use Android device just like linux desktop?
    As a first step, here is summary to construct gnu system root on Android device.

==============
Setup Sequence
==============
    Installing cross compiling tools
    ----------------------------------------------------------------------
        *** NOTE ****************************************************************
        *    Followings are not tested because I just used built Sourcery g++.  *
        *    [ Codesourcery 2007q3-53 ]                                         *
        *************************************************************************
        * Reference : http://frank.harvard.edu/~coldwell/toolchain/
        * Build GNU binutils
            - Using '--disable-nls' option is recommended (to reduce compile time and dependency.
        * Install Linux Kernel Headers
            - Latest Sourcery g++(2010.09-50) supports only at-least-2.6.16-target-kernel.
        * Build GLIBC headers
        * Build GCC for headers:
            - Using '--disable-nls --without-headers' is recommended.
            - example : configure option of GCC in Codesourcery 2007q3-53
                /vobs/linuxjava/cs_toolchain/mycstc/cs_build_dir/src/gcc-4.2/configure --build=i686-pc-linux-gnu
                  --host=i686-pc-linux-gnu --target=arm-none-linux-gnueabi --enable-threads --disable-libmudflap
                  --disable-libssp --disable-libgomp --disable-libstdcxx-pch --with-gnu-as --with-gnu-ld
                  --enable-languages=c,c++ --enable-shared --enable-symvers=gnu --enable-__cxa_atexit
                  --with-pkgversion=CodeSourcery Sourcery G++ Lite 2007q3-53
                  --with-bugurl=https://support.codesourcery.com/GNUToolchain/
                  --disable-nls --prefix=/opt/codesourcery --with-sysroot=/opt/codesourcery/arm-none-linux-gnueabi/libc
                  --with-build-sysroot=/vobs/linuxjava/cs_toolchain/mycstc/cs_build_dir/install/arm-none-linux-gnueabi/libc
                  --enable-poison-system-directories
                  --with-build-time-tools=/vobs/linuxjava/cs_toolchain/mycstc/cs_build_dir/install/arm-none-linux-gnueabi/bin
                  --with-build-time-tools=/vobs/linuxjava/cs_toolchain/mycstc/cs_build_dir/install/arm-none-linux-gnueabi/binff
        * Build GLIBC libraries
        * Rebuild GCC using newly-built-GLIBC.

    Construct gnu system root
    -------------------------
        * Environments
            # this directory will be new gnu system root on Android target.
            PREFIX=/data/arm-gnu-sysroot/
            # gnu root directory on target device
            TGNUROOT=/data/gnuroot/
            TARGET=arm-none-linux-gnueabi
            export ARCH=arm
            export CROSS_COMPILE=${TARGET}-
            # set PATH
            PATH=<cross-tools>:$PATH
        * Install headers and GLIBC
            - copy cross-compiled glibc, headers etc to $TROOT except for i686 executables and related files
        * Build GNU binutils [binutils-2.18]
            - ./configure --prefix=${PREFIX} --host=${TARGET} --target=${TARGET} --disable-nls
        * Build GCC [gcc-4.2.1]
            - ./configure --prefix=${PREFIX} --build=i686-pc-linux-gnu --target=${TARGET} --host=${TARGET}
                --disable-nls --enable-languages=c
        * Build bash [bash-4.0]
            - ./configure --prefix=${PREFIX} -host=${TARGET} --without-bash-malloc
            - install to $PREFIX/bin. And link $PREFIX/bin/sh to $PREFIX/bin/bash
        * Build gnu make [make-3.82]
            - ./configure --prefix=${PREFIX} -host={TARGET}
        * Build busybox
            - Set cross compiler prefix to 'arm-none-linux-gnueabi-' and make.
            - install to $PREFIX/bin
              (usually commands in busybox are located at /bin)
            - create link to busybox for each command.
        * copy to target device
            - adb push $PREFIX $TGNUROOT
        * link rootfs to gnu system root.
            - ln -s $TGNUROOT/lib /lib
            - ln -s $TGNUROOT/bin /bin
              ...

===============
Confirm & Check
===============
    Build Emacs-23.2
    ----------------
        * push Emacs-23.2 source code to target.
        * ./configure --without-xpm --without-jpeg --without-tiff --without-gif --without-png --without-rsvg
             --without-xft --without-libotf --without-m17n-flt --without-toolkit-scroll-bars --without-xaw3d
             --without-xim --without-gpm
        * 'make' should be done without error.

    Running Emacs
    -------------
        * copy termcap.src from "http://www.opensource.apple.com/source/emacs/emacs-39/emacs/etc/termcap.src".
          And put this /usr/etc/termcap.src.
        * And set following environment variable
            TERM=linux
            TERMCAP=/usr/etc/termcap.src
        * Emacs should work without error in 'adb shell' terminal.

===============
NOTE
===============
    Points
    ------
        * headers and GLIBC built for cross-compiling should be used as they are at target system root.
          (To use cross-compiled binaries on target device without any potential issues.)
        * Some open source packages check only /lib and /usr/lib (/usr/local/lib isn't considered).
          So, fundamental libraries would be better to be installed at /usr/lib,
         even if it's default location is /usr/local/lib

Setting up gnu system root is the first step to construct gnu software stack on the system.
And, now it's done.
So, next step is installing packages to set up development-friendly environment on the Android device.
Below description is summary of issues that I faced against during installing gnu packages.

* Executing /usr/bin/su doesn't run ~/.bashrc
    ~/.bashrc is not executed if user shell is set up as /bin/sh, even if /bin/sh is just symbolic link of /bin/bash.
    Let's assume that /bin/sh -> /bin/bash.
    In this case, executing /bin/sh means "run bash as just 'shell' - sh".
    So, to make ~/.bashrc be run automatically, default shell of user should be set as /bin/bash not /bin/sh

* default .bashrc of normal(ex. ubuntu) desktop PC can be used as a template in Android device.

* terminal editor programs - vi, nano, emacs etc - don't work or work abnormally.
    Environment related with 'Terminal' should be set correctly.
        - Environment variables
            export TERM=xterm
            export TERMINFO=/etc/terminfo
            export TERMCAP=/etc/termcap
    Related files at /etc
        terminfo
            this has setting values for various terminal types - linux, vt100, xterm and so on.
            /etc/terminfo of desktop linux PC can be used as it is.
        termcap
            this is required by emacs.
            termcap.src(included at termcap source release) can be used as /etc/termcap.

* mode of newly created file becomes 0666 or 0777.
    umask should be set at .bashrc .
        umask 022

* window of editor programs like vi, emacs is default screen size (80x24)
 even if real screen size of terminal emulator is bigger.
    resize command should be executed.
    putting it at .bashrc is recommended.
    this command sets environment variables - COLUMNS and LINES - according to current terminal window size
   and export it.

* various colors are not used at the output of ls command.
    check that dircolors command is installed and this command is set correctly at .bashrc

* sudo command doesn't give any chance to enter password. It only says "Sorry, try again.".
    pam is not correctly binded with sudo.
    install /etc/pam.d/sudo file.
    (sample.pam included at sudo source code release can be a good reference.
     - especially, second option - use pam_unix - is recommended)

* icmp protocol is not recognized by ping - included at inetutils - command.
    check /etc/protocols file is correctly installed.
    this file can be used by copying desktop's one.

* localhost is not recognized even though ip address - 127.0.0.1  - works well.
    check followings at /etc/hosts
        127.0.0.1    localhost
    check below line at /etc/nsswitch.conf (related with nameserver)
        hosts: files dns

Anything to do?

This is due to flow control.
C-s and C-q is reserved key sequence for flow control.
So, by disabling it - just type 'stty -ixon' - you can use C-s and C-q key sequence.

RnR(Role and Responsibility)데 대한 정의는 공동업무를 진행하는 과정에서 꼭 필요한 부분이다.
SW 실무적으로 RnR를 정의하는 방법은 크게 두가지로 나뉠 수 있을 것 같다.

첫번째, 기능별 분류이다. (a)
Multimedia Engine, Multimedia Application, GPS, Call 등등으로 구분하는 것이 대표적인 방법이다.
내가 생각하기에 현재 대부분의 SW연구소가 택하는 방법이 아닌가 한다.

두번째, 물리적인 file/directory 단위의 구분이다. (b)
Linux Kernel을 예로 들면, /mm, /kernel, /sound 등의 단위로 나누는 것이다.
이 방법은 몇몇 특수한 경우에만 사용하는 것으로 일반적이지는 않는 것으로 알고있다.

위 두가지 방법을 간단하게 비교해 보자.
먼저 (a)의 경우다.
장점: 특정 기능별로 구분되어 있으므로 해당 분야의 domain knowledge를 쌓아 전문가를 양성하기 좋다. 따라서 해당 분야에 대한 장기적인 성장에 유리하다.
단점: SW code의 물리적인 위치가 기능별로 명확히 구분되어 있지 않고, common한 부분이 많은 경우 (보통의 효율적이고 well-structured 된 code 일 수록  code 공유/재사용 이 많다.) RnR에 대한 논란의 여지가 많다. 따라서, 이로 이한 팀/개인 간의 갈등, communication overhead, 비협조적인 업무진행 등의 문제를 만날 수 있다.

(b)의 경우 (a)와 정확히 반대 된다.
같은 기능이라도 여러 팀이 관여하게 되므로, 업무 진행시 실무자간 제법 많은 양의 communication을 필요로 한다.
Camera 기능을 예로 들어보자.
Camera의 경우, Sensor Driver, HAL(Hardware Abstraction Layer), Application Framework, Application등에 그 기능이 걸쳐 있을 것이다.
따라서 Sensor에서 지원해 주는 특정 기능을 구현하기 위해서는 각 directory (아마도, driver, HAL, FW, App은 각각 다른 directory에 위치해 있을 것이다.) 별 owner들간 많은 대화가 필요할 것이다.

경우에 따라 다르겠지만, 비교/분석해 봐야할 대상은 명확해 진듯 하다.
"RnR의 불확실성에 따른 문제로 인한 업무 비용" vs. "기능별 SW업무시 발생할 수 있는 file/directory owner들 간 communication에 따른 비용"
(a)의 경우는 이미 많이 겪어 봤다. (b)는 아직 경험해 보지 못했다.
과연 어느 쪽어 더 효율적일까? (산업/업무 문야에 따라 다르겠지만...)

+ Recent posts