Android开发基础(2.3)--Android交叉工具链的使用

来源:互联网 发布:淘宝哪家多肉植物好 编辑:程序博客网 时间:2024/05/23 01:37

接上篇,Android中提取的工具链搭建好之后:

I.使用工具链移植c/c++程序或库
  这类的程序的标准生成流程都是 :./configure -->make;make install。想往Android上移植该怎么办?
1.(若需)修改代码
  前面说到Android的C库不是POSIX兼容的,很残。若程序/库需要Android没有的内容或者不开放C接口的内容,那就悲剧了,你只有想法子改代码了。比如想移植 alsa-lib,它使用了SYS V SHM(内存共享功能),这个Android没有,有人质疑为何没有,Google官方回答:“Sorry!But NO!”这样的话,只有设法在代码内移除这个需求...
2.(若需)修改工程
  如果原工程没有跨平台支持的话,估计要修改configure,Makefile等文件才行。有两种情况:
1)如zlib,在当前机器上直接./configure --prefix=/data/local,再修改生成的Makefile,将其中的CC=gcc RANLIB=ranlib LD=ld改成 CC=agcc RANLIB=arm-eabi-ranlib LD=arm-eabi-ld ...改完工具就可以直接make了。

2)如libffmpeg,还有另一条路(有时这是最后一条路):如果你够强,直接利用Makefile.am(Makefile的来源文件)写出工程的Android.mk文件,建立标准的NDK工程,利用ndk-build完成一切。(我讨厌这招,因为很费事,难成功)
3.直接上
  若你够幸运,前面两个都不需要的话(所以我非常喜欢freedesktop.org提供的工程,非常规范全面),以下的一条命令就行了:
#CC=agcc CXX=agcc LD=arm-eabi-ld RANLIB=arm-eabi-ranlib /
PKG_CONFIG_LIBDIR=/data/local/lib/pkgconfig:/data/local/share/pkgconfig/ /
    ./configure /
    --prefix=/data/local /
    --host=arm-eabi-linux /
    --enable-malloc0returnsnull /
    --enable-shared

这里有关键几项,
1)CC=agcc 则常见的CFLAGS,CPPFLAGS,LDFLAGS等变量都不用提供了,都在agcc里面。
2)PKG_CONFIG_LIBDIR,当前的工程所需(若需)的库文件的.pc(库的描述文件)在哪个文件夹下面一定要指明,且不要用PKG_CONFIG_PATH,后者会先找主机里面的库(比如主机的/usr/lib/之类的),再找目标环境里的。
3)prefix,目标环境的路径。一般默认的是/usr/local或者/usr, 所以一定要改成目标环境的文件夹前缀,此处是 /data/local
4)host,指的是目标平台,也可以写成 arm-unknown-linux等,不过一定要确认configure脚本能认识这个“型号”,不然会产生问题(拒绝生成动态库等等)
5)--enable-shard,不是所有的configure默认生成动态库(我就碰到过,比如jpeg62),其他的选项类似。
6)还有,有的工程的configure方式很特别(比如openssl和原版X11),但是大体都可以仿照以上解决。(关键是让configure找到所需的工具链,找到所需的环境以及文件,并通过测试,成功生成Makefile)

接下来,除非编译出错(这就是上面两个“若需”的工作),直接
#make;make install
就行了。


II.如何使用/运行编译的成果?
1.基本使用
  收先你要有root权限,可以参考我写的XT800 MOTO的刷机经历。相信大家注意到前面那个奇怪的prefix=/data/local了,Android平台上即使root用户(开发者)也只是对设备的部分文件夹有权限修改,最常用的就是/data/local 和/data/bin了。而JAVA程序都在/data/data下,比如我们的Helloworld.apk安装后

#adb shell ls /data/data/my.helloworld/lib/

-rw-r--r-- system   system      13225 2011-02-28 09:17 libhelloworld.so

可见它“自带的”C库也在里面(如果有多个库,只要确保 ant 最终生成之前将所有的.so放到libs/armeabi/下即可被打包进入.apk,java程序使用时别忘了所有自带库都要load一下)还有android里面库的标准路径是/system/lib/,jni所用的自带库在/data/data/...里面自己能找到,那么C/C++程序呢?要放到允许放的地方去。比如我们上篇的 libahoo.so 和 a
#adb push libahoo.so /data/local/lib
#adb push a /data/local
#adb shell

进入android 设备的shell:
##ls

tmp
pds
cdrom
sqlite_stmt_journals
config
cache
sdcard
d
etc
system
sys
sbin
proc
init_prep_keypad_ttnm.sh
init.rc
init.mapphone_cg.rc
init.goldfish.rc
init
default.prop
data
root
dev
##ps

.....
system    1503  1169  122740 14612 ffffffff afe0d984 S com.motorola.process.system
app_33    1549  1169  121964 14556 ffffffff afe0d984 S com.android.alarmclock
app_51    1557  1169  121632 14024 ffffffff afe0d984 S com.motorola.firewall
app_54    1563  1169  121464 14260 ffffffff afe0d984 S com.motorola.extdisp
app_21    1611  1169  128052 15704 ffffffff afe0d984 S com.android.vending
app_32    1622  1169  123528 14428 ffffffff afe0d984 S com.motorola.apncontrol
app_3     1632  1169  133956 14700 ffffffff afe0d984 S com.hoho.campage
app_48    1648  1169  130216 15652 ffffffff afe0d984 S com.cooliris.media
app_81    1723  1169  123436 15032 ffffffff afe0d984 S com.moto.mobile.appstore
app_1     2507  1169  145004 26464 ffffffff afe0d984 S com.google.android.apps.maps
app_15    2559  1169  122940 16352 ffffffff afe0d984 S android.process.media
dhcp      2691  1     820    428   c00d4b28 afe0d7fc S /system/bin/dhcpcd
app_38    2738  1169  121404 14336 ffffffff afe0d984 S com.svox.pico
app_73    2745  1169  123112 15672 ffffffff afe0d984 S com.eshore.android
root      2770  1148  708    328   c006cb7c afe0d62c S /system/bin/sh
app_92    2776  1169  122612 17108 ffffffff afe0d984 S my.helloworld
root      2781  2770  860    344   00000000 afe0c75c R ps

##cat /proc/2776/maps

.....

80d00000-80d1d000 r-xp 00000000 1f:06 417        /system/lib/libmetainfo.so
80d1d000-80d1e000 rwxp 0001d000 1f:06 417        /system/lib/libmetainfo.so
80e00000-80e03000 r-xp 00000000 1f:08 1925       /data/data/my.helloworld/lib/libhelloworld.so
80e03000-80e04000 rwxp 00002000 1f:08 1925       /data/data/my.helloworld/lib/libhelloworld.so

80f00000-80f03000 r-xp 00000000 1f:06 275        /system/lib/hw/gralloc.omap3.so
80f03000-80f04000 rwxp 00003000 1f:06 275        /system/lib/hw/gralloc.omap3.so
....

##cd /data/local
##ls -l

-rwxrwxrwx shell    shell      458405 2011-02-28 13:04 a
-rwxrwxrwx shell    shell       76232 2009-07-31 19:08 su

drwxrwxrwx root     root       2010-12-08 19:14 mnt

drwxrwxrwx root     shell             2011-02-28 13:05 lib
drwxrwxrwx mot_tcmd shell             2011-03-01 13:04 tmp

##./a

link_image[1721]:  2786 could not load needed library 'libahoo.so' for './a' (load_library[1051]: Library 'libahoo.so' not found)CANNOT LINK EXECUTABLE
所以要把路径加进去。
##LD_LIBRARY_PATH=/system/lib:/data/local/lib ./a

link_image[1721]:  2786 could not load needed library 'libahoo.so'for './a' (load_library[1051]: Library 'libahoo.so' not found)CANNOTLINK EXECUTABLE
??因为要超级权限
##su
##LD_LIBRARY_PATH=/system/lib:/data/local/lib ./a

ahoooooooooo coming!
bagaaaaaaaaa coming!
bagaaaaaaaaa dying!
ahoooooooooo dying!
Horaaaaaaaaaaa
Woraaaaaaaaaaaa
sizeof hana:100
sizeof hana:100
libahoo.so:--exception.runtime_error.string:    --琉球の海風にいる !
libahoo.so:--exception.catch.string:    --You are Foooooooooyoooooooed!
a    :--string:    --づっと、づっと乙女の側に居るように!
这下总行了。


2.给SDK使用

  说实话,在Android设备上运行c程序,有何意义?最常用的还是移植c库给java使用,比如下面这位的工作就很典型:

abitno.me/compile-ffmpeg-android-ndk

Android提供的解码功能有限,他将ffmpeg库移植到Android上成为libffmpeg.so,开放JNI接口供上层JAVA UI使用,其结果就是一个新的Android播放器。而移植一个库的过程如上所述两类:编写Android.mk 利用ndk-build创建libdep.so;或者使用agcc直接生成lib.so;然后再写一个JNI接口层libinterface.so库(除非你直接在原工程内写好接口);放到Android工程的./libs/armeabi里,最后在java内调用接口;要确保最终的.apk内包含所需的自带库。
  以下就是我写的一个底层库-->接口库-->java的示例,可以参考:

#android create project -p ./ -t 4 -n Ahoo -k ore.ahoo -a Ahoo

#cat src/ore/ahoo/Ahoo.java

#cat res/values/styles.xml

(现在不清楚有什么办法让单个Android.mk生成多个动态库,大家可以试试)

#cat jni/dep.h

#cat jni/dep.cpp

#cat jni/ahoo.cpp

分别编译(也可以用ndk-build):

#cd jni

#agcc dep.cpp -shared -o libdep.so -llog
Compile Thumb++    :dep.cpp    ===> dep.o
arm-eabi-g++ dep.cpp -I/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/include -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -DANDROID -DNDEBUG -mthumb-interwork -march=armv5te -mtune=xscale -msoft-float -mthumb -fpic -fPIC -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -Wno-psabi -Wa,--noexecstack -Os -O2 -c -o dep.o
Link ARM shared lib    : dep.o     ====> libdep.so
arm-eabi-gcc dep.o -nostdlib -Wl,-shared,-Bsymbolic -Wl,--whole-archive -Wl,--no-whole-archive -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-rpath-link=/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -L/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -lc -lm /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/lib/gcc/arm-eabi/4.4.0/libgcc.a -o libdep.so -llog

#agcc ahoo.cpp -shared -o libahoo.so -ldep -L./ -llog
Compile Thumb++    :ahoo.cpp    ===> ahoo.o
arm-eabi-g++ ahoo.cpp -I/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/include -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -DANDROID -DNDEBUG -mthumb-interwork -march=armv5te -mtune=xscale -msoft-float -mthumb -fpic -fPIC -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -Wno-psabi -Wa,--noexecstack -Os -O2 -c -o ahoo.o
Link ARM shared lib    : ahoo.o     ====> libahoo.so
arm-eabi-gcc ahoo.o -nostdlib -Wl,-shared,-Bsymbolic -Wl,--whole-archive -Wl,--no-whole-archive -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-rpath-link=/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -L/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -lc -lm /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/lib/gcc/arm-eabi/4.4.0/libgcc.a -o libahoo.so -ldep -L./ -llog

#ls

ahoo.cpp  dep.cpp  dep.h  libahoo.so  libdep.so

#cd ..

#cp jni/lib* libs/armeabi/

#ant debug

........

BUILD SUCCESSFUL
Total time: 3 seconds

#adb install bin/Ahoo-debug.apk
1663 KB/s (188420 bytes in 0.110s)
    pkg: /data/local/tmp/Ahoo-debug.apk
Success
在设备(MOTO XT800)上运行如下:

 

运行日志:

#adb shell logcat

I/ActivityManager( 1278): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=ore.ahoo/.Ahoo }
I/ActivityManager( 1278): Start proc ore.ahoo for activity ore.ahoo/.Ahoo: pid=3024 uid=10091 gids={1015}
I/dalvikvm( 3024): Debugger thread not active, ignoring DDM send (t=0x41504e4d l=38)
I/WindowManager( 1278): Setting rotation to 1, animFlags=0
I/WindowManager( 1278): adjustConfigurationLw fontScale=1.0
I/ActivityManager( 1278): Config changed: { scale=1.0 imsi=0/0 loc=zh_CN touch=3 keys=1/1/2 nav=1/2 orien=2 layout=34}
D/MotoIMEEntry::onConfigurationChanged( 1336): newconfig = { scale=1.0 imsi=0/0 loc=zh_CN touch=3 keys=1/1/2 nav=1/2 orien=2 layout=34}
I/=====suggestion=====( 1336): switch to qwerty mode, enable?true
D/MIMSBase( 1336): onConfigurationChanged()
I/dalvikvm( 3024): Debugger thread not active, ignoring DDM send (t=0x41504e4d l=20)
D/dalvikvm( 3024): Trying to load lib /data/data/ore.ahoo/lib/libdep.so 0x44902140
D/dalvikvm( 3024): Added shared lib /data/data/ore.ahoo/lib/libdep.so 0x44902140
D/dalvikvm( 3024): No JNI_OnLoad found in /data/data/ore.ahoo/lib/libdep.so 0x44902140
D/dalvikvm( 3024): Trying to load lib /data/data/ore.ahoo/lib/libahoo.so 0x44902140
D/dalvikvm( 3024): Added shared lib /data/data/ore.ahoo/lib/libahoo.so 0x44902140
D/dalvikvm( 3024): No JNI_OnLoad found in /data/data/ore.ahoo/lib/libahoo.so 0x44902140
D/dalvikvm( 3024): +++ not scanning '/system/lib/libwebcore.so' for 'weep' (wrong CL)
D/dalvikvm( 3024): +++ not scanning '/system/lib/libexif.so' for 'weep' (wrong CL)
E/fuck GFW!( 3024): ahoooooooooo coming!
D/MIMSBase( 1336): onInitializeInterface()
E/fuck GFW!( 3024): bagaaaaaaaaa coming!
E/fuck GFW!( 3024): bagaaaaaaaaa dying!
E/fuck GFW!( 3024): ahoooooooooo dying!

.................

原创粉丝点击