Mobile/Fennec/Android: Difference between revisions
Line 217: | Line 217: | ||
=== Using JimDB === | === Using JimDB === | ||
* jchen has been working on a better Android gdb ('jimdb'). [http://www.jnchen.com/_media/projects/mozilla/moz-gdb | * jchen has been working on a better Android gdb ('jimdb'). [http://www.jnchen.com/_media/projects/mozilla/moz-gdb.tar.bz2 Prebuilt binaries], [https://github.com/darchons/android-gdb source], and [[Mobile/Fennec/Android/GDB|build instructions]] | ||
** has most fixes from NDK gdb | ** has most fixes from NDK gdb | ||
** integrates Android libthread_db (fixed dougt's problem debugging threads) | ** integrates Android libthread_db (fixed dougt's problem debugging threads) |
Revision as of 06:41, 9 September 2011
Setup a Build Environment
Below are instructions for setting up a build environment on Ubuntu. See the build docs here for instructions on setting up a build environment on other OSs.
Quick Script
sudo add-apt-repository ppa:ferramroberto/java sudo apt-get update sudo apt-get install sun-java6-jdk mercurial ccache sudo apt-get build-dep firefox wget http://dl.google.com/android/ndk/android-ndk-r6-linux-x86.tar.bz2 tar -xjf android-ndk-r6-linux-x86.tar.bz2 wget http://dl.google.com/android/android-sdk_r12-linux_x86.tgz tar -xzf android-sdk_r12-linux_x86.tgz # go get lunch, this will take a while ./android-sdk-linux_x86/tools/android update sdk -u ./android-sdk-linux_x86/tools/android update adb
If you're using a 64-bit Ubuntu install, you'll need ia32-libs to allow the toolchain binaries to run.
sudo apt-get install ia32-libs
If you're using 64-bit Fedora install
yum install glibc.i686 ncurses-libs.i686 libstdc++.i686
Explained
Install Java
First install the Sun Java jdk6, which the Android SDK depends on If you're on Ubuntu 11.04, you'll need to use an addtional repo (ppa) as its not available in the partners repo yet. Others report success using the Maverick partners repo to get it.
sudo add-apt-repository ppa:ferramroberto/java sudo apt-get update sudo apt-get install sun-java6-jdk
Install Gecko Requirements
Then install the usual stuff needed for a firefox build, you probably already have it
sudo apt-get install mercurial ccache sudo apt-get build-dep firefox
Install Android NDK
Download and extract the NDK. NDK revs 4, 5 and 6 have been tested and confirmed to work.
wget http://dl.google.com/android/ndk/android-ndk-r6-linux-x86.tar.bz2 tar -xjf android-ndk-r6-linux-x86.tar.bz2
Install Android SDK
You should just install the latest sdk, we set the API level in our manifest files. The sdk download will take a while, make sure you have a decent internet connection and go get coffee, or maybe lunch.
wget http://dl.google.com/android/android-sdk_r12-linux_x86.tgz tar -xzf android-sdk_r12-linux_x86.tgz ./android-sdk-linux_x86/tools/android update sdk -u ./android-sdk-linux_x86/tools/android update adb
You will probably want to add the SDK's "tools" and "platform-tools" directory to the PATH environment variable in your shell, so that you can run adb and other tools easily.
Build
You build as you normally would (make -f client.mk), just with a different mozconfig.
Instructions for getting Mozilla source code are here: https://developer.mozilla.org/en/Mozilla_Source_Code_(Mercurial)
Here's an example mozconfig:
# Add the correct paths here: ac_add_options --with-android-ndk="$HOME/android-ndk-r6" ac_add_options --with-android-sdk="$HOME/android-sdk-linux_x86/platforms/android-13" ac_add_options --with-android-version=5 ac_add_options --with-android-tools="$HOME/android-sdk-linux_x86/tools" ac_add_options --with-android-toolchain="$HOME/android-ndk-r6/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86" ac_add_options --with-android-platform="$HOME/android-ndk-r6/platforms/android-5/arch-arm" # android options ac_add_options --enable-application=mobile ac_add_options --target=arm-linux-androideabi ac_add_options --with-endian=little ac_add_options --with-ccache ac_add_options --enable-tests mk_add_options MOZ_OBJDIR=./objdir-droid mk_add_options MOZ_MAKE_FLAGS="-j9 -s"
hg clone http://hg.mozilla.org/mozilla-central/ src cd src vi mozconfig-droid export MOZCONFIG=~/src/mozconfig-droid make -f client.mk
Increase linking speed (AKA using gold)
On some systems, linking libxul can takes several minutes. Using gold instead of ld can slightly reduce this time (from around 7 minutes to a bit more than 1 minute on my machine ; YMMV, on another machine, it gets from 25 seconds to 10, or from 2 minutes to 1 minute with all system caches dropped).
To use gold, you have to recompile toolchain in the ndk with a newer binutils.
Go to your Android NDK directory then update the toolchain sources:
./build/tools/download-toolchain-sources.sh src
Now, you have to download the latest binutils (currently 2.21.53), go there:
ftp://sourceware.org/pub/binutils/snapshots/
Extract it in src/binutils (in the NDK directory). That should create a new directory named binutils-<VERSION>.
Before building the toolchain, we have to make sure gold is used as the default linker, open build/tools/build-gcc.sh and add:
--enable-gold=default \
in the configure script options. This should be after this line # configure the toolchain, near the line 200.
You are all set and ready to rebuild the toolchain, run this:
./build/tools/build-gcc.sh --binutils-version=<BINUTILS_VERSION> $(pwd)/src $(pwd) arm-linux-androideabi-4.4.3
Finally, you can call this command and make sure the first line output is GNU gold (GNU Binutils [...]):
toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/arm-linux-androideabi/bin/ld --version
Install and run
Run `make package` in your objdir to generate an APK file. The package will have a name like "objdir-droid/dist/fennec-9.0a1.en-US.android-arm.apk":
make -C <objdir-droid> package
Connect your Android device and set up USB debugging, then install the fennec package using adb:
adb install -r <objdir-droid>/dist/fennec-*.apk
The installed app will be named "Fennec".
Testing
In general, android testing requires a parallel host build. Below the path to that build is assumed to be "../objdir-x86/dist/bin". Make sure that your desktop machine and Fennec device are both on the same network for this to work. In addition, you will not be able to run tests with both a reftest and mochitest profile on the device at the same time. You will likely need to wipe the profile dir (/mnt/sdcard/tests) and maybe reboot your device between running different types of tests. (Note: If you can't mount the sdcard properly run |mkdir /data/local/tests| (bug 683895))
Reftests
MOZ_HOST_BIN="<objdir-x86>/dist/bin/" make -C <objdir-droid> reftest-remote
Mochitests
MOZ_HOST_BIN="<objdir-x86>/dist/bin/" make -C <objdir-droid> mochitest-remote
xpcshell
To prepare your device for xpcshell tests:
adb shell mkdir /data/local/tests
Also be sure you have successfully built Fennec and generated an APK, as described above.
To run all tests referenced by the master xpcshell manifest:
cd <objdir-droid> make xpcshell-tests-remote
To run a subset of tests in the specified directory:
make -C <test-directory> xpcshell-tests-remote
Once either of the xpcshell-tests-remote commands has completed successfully, all test files have been copied to device, and it is then possible to run a single test quickly, without setup:
make SOLO_FILE=<test-file> -C <test-directory> check-one-remote
browser-chrome
Before you run tests, you will need to make sure you have packaged the tests in your object dir:
make -C <objdir-droid> package-tests
There is currently no special make command to build and run browser-chrome tests, but it should be possible to make them run by calling:
cd <objdir-droid>/_tests/testing/mochitest python runtestsremote.py --dm_trans=adb --test-path=mobile --browser-chrome --deviceIP=1.2.3.4 --app=org.mozilla.fennec_$USER --xre-path=<objdir_x86>/dist/bin/
talos
This is 100% out of band from mozilla-central (same for desktop also). NOTE: this doesn't work with ADB, only SUT at the moment.
hg clone http://hg.mozilla.org/build/talos
setup a local webserver (I use apache) to have http://localhost point to the talos directory.
cd talos/page_load_test wget http://people.mozilla.org/~jmaher/mobile_tp4.zip unzip mobile_tp4.zip cd ../mobile_profile/extensions hg clone http://hg.mozilla.org/build/pageloader pageloader@mozilla.org hg clone http://hg.mozilla.org/users/tglek_mozilla.com/fennecmark bench@taras.glek cd ../../ python remotePerfConfigurator.py -v -e org.mozilla.fennec --activeTests tpan --resultsServer ' ' --resultsLink ' ' --output tpan.yml --remoteDevice <ip of your sutagent> --webServer <ip of your host> python run_tests.py -d -n tpan.yml
Trouble-shooting testing problems
- Does your mozconfig contain "ac_add_options --enable-tests"?
- Is adb in your $PATH?
- Is your device connected? Does it appear in the output from "adb devices"?
- Can you run adb shell?
- If running xpcshell, did you create /data/local/tests?
- If running "make check-one-remote", did you first setup the device with "make xpcshell-tests-remote"?
Debugging
Using logcat
logcat is a tool that is going to show you some logs prompted by the device. It might be a good help if you don't want to or can't run gdb. You can use it by running this command:
adb logcat
You can make things appear in logcat using printf_stderr. With debug builds, NS_WARNING, NS_ERROR and NS_ASSERTIONS will show up in logcat.
Using nVidia GDB
Nvidia's gdb is better: http://developer.download.nvidia.com/tegra/files/tegra-gdb-20100902.zip
Using JimDB
- jchen has been working on a better Android gdb ('jimdb'). Prebuilt binaries, source, and build instructions
- has most fixes from NDK gdb
- integrates Android libthread_db (fixed dougt's problem debugging threads)
- has Python scripting support
- couple of existing Python scripts (or if using prebuilt binaries above, just run 'git pull' under the 'utils' directory)
- feninit is a tool to initialize the GDB environment (support for multiple devices, multiple object directories; launches Fennec, pulls libraries, sets paths, and attaches gdbserver automatically)
- tracebt is a WIP stack unwinder that traces instructions to find stack frames
- idea for another tool to parse and integrate logcat into gdb
- other ideas welcome!
Using Debug Intent
In order to attach before things get running, launch with (replace "unofficial" with your login name):
adb shell am start -a org.mozilla.gecko.DEBUG -n org.mozilla.fennec_unofficial/.App
and just click launch once gdb is attached. If you need to debug a crash that happens before XRE_Main is called, the patch on bug 572247 may be useful.
this script [1] will attach gdbserver for you
Env Vars
If you need to set an env var at run time, use append --es env# VAR=VAL to your activity manager command where # is the ordered number of variables for example:
adb shell am start -a android.activity.MAIN -n org.mozilla.fennec_unofficial/.App --es env0 VAR=val --es env1 FOO=bar
You may need bug 578493 if the env var you're using is tested before XRE_Main is called
PR Logging
You can use the env vars as described above to make logging work (along with bug 578493). With just that you can log to a file
adb shell am start -a android.activity.MAIN -n org.mozilla.fennec/org.mozilla.fennec.App --es env0 NSPR_LOG_MODULES=all:5 --es env1 NSPR_LOG_FILE=/mnt/sdcard/log.txt
With the patch on bug 578496 you can have the logging directed to the android logs and as such only need:
adb shell am start -a android.activity.MAIN -n org.mozilla.fennec/org.mozilla.fennec.App --es env0 NSPR_LOG_MODULES=all:5
debugging without rooting
with Froyo you can debug without rooting your phone. Instructions are below. See also Fennec/Android/GDBNoRoot for another guide on how to do this.
First thing, to make this work with the nvidia gdb (which I found more reliable than the android r3 gdb) you need to modify install.sh and debug.sh.
first, change the location where install.sh copies gdbserver to somewhere writable by a non-root process. I used /data/local. Be sure to update that both in the push command and the chmod command.
second, update debug.sh with the new location of gdbserver.
finally, you'll need to add run-as $2 to the adb shell command that launches gdbserver. In the end you should have: install.sh:
#!/bin/sh mkdir lib adb push prebuilt/gdbserver /data/local adb shell chmod 755 /data/local/gdbserver for file in $(adb shell ls /system/lib | tr "\n" " " | tr "\r" " "); do adb pull /system/lib/$file lib done adb pull /system/bin/app_process lib
debug.sh:
#!/bin/sh if [ $# -ne 2 ] then echo "usage: $0 /path/to/your/library.so packagename.of.your.activity" echo "for example:" echo " $0 /code/mydemo/libs/armeabi/libmydemo.so com.nvidia.devtech.mydemo" exit fi if [ ! -f $1 ] then echo "ERROR: That library file doesn't exist" exit fi cp $1 lib p=`adb shell ps | grep $2 | awk '{print $2}'` if [ "$p" = "" ]; then echo "ERROR: That doesn't seem to be a running process. Please make sure your" echo "application has been started and that you are using the correct" echo "namespace argument." exit fi adb forward tcp:12345 tcp:12345 adb shell run-as $2 /data/local/gdbserver --attach :12345 $p
Attaching GDB
Assuming you have the nvidia gdb at the top of your home directory and the app_process binary in the current working directory.
~/nvidia-gdb/prebuilt/linux-x86/arm-eabi-gdb ./app_process
Other useful tips and tricks
killer script
#!/bin/sh if [ $# -ne 1 ] then echo "usage: $0 packagename.of.your.activity" echo "for example:" echo " $0 org.mozilla.fennec" exit fi p=`adb shell ps | grep $1 | awk '{print $2}'` if [ "$p" = "" ]; then echo "ERROR: That doesn't seem to be a running process. Please make sure your" echo "application has been started and that you are using the correct" echo "namespace argument." exit fi adb shell run-as $1 kill $p
.gdbinit
This is an example .gdbinit that uses the symbols from a locally built rom and automatically attaches to gdbserver. Note that putting a .gdbinit file inside a directory will make gdb load it thus you will not pollute your regular gdb init with those configurations.
set solib-search-path /home/blassey/android/system/out/target/product/passion/symbols/system/bin:/home/blassey/android/system/out/target/product/passion/symbols/system/lib/:/home/blassey/src/ndk5-m-c/objdir-droid-dbg/dist/bin set solib-absolute-prefix /home/blassey/android/system/out/target/product/passion/symbols/system/lib/ target remote localhost:12345