在android手机上运行C程序 - hello arm!
为了学习arm指令集,当然要先写段 hello arm 试验咯。
写段 hello arm
|
|
编译方式
这里有两种手动编译方式:gcc和ndk-build.
使用gcc
配置交叉编译环境
因为我们要编译出在android手机上运行的程序,必须要为gcc提供android的平台文件和指令集。
而ndk中自带了gcc等一系列工具,所以现在直接调用即可。没有ndk的话需要先行下载。
为~/.bashrc配置如下:
|
|
其中NDKROOT是ndk的主目录;SYSROOT是所选的指令集,这里是arm;NDKTOOL是ndk的工具链目录;ndk-gcc是为后面一串命令起的别名,这样使用时就不用一遍一遍的输参数了;ndk-objdump是可以反汇编arm程序的工具,与ndk-gcc在ndk的同一目录下.
配置完成后可执行source ~./bashrc使立即生效,echo $ndk-gcc查看是否设置成功。
编译
执行ndk-gcc -o hello-arm hello-arm.c直接生成可执行文件。
执行ndk-gcc -S hello-arm.s hello-arm.c生成arm汇编文件。
其他选项执行ndk-gcc --help查看帮助。
使用ndk-build
配置ndk-build环境
如果是单独下的ndk,这时候系统找不到ndk-build命令,需要将其路径加入path中.
ndk-build在ndk根目录下。
新建Android工程
执行android list查看已安装的sdk版本;
执行android create project -t 1 -p ~/Desktop/helloarm -a MainActivity在桌面创建一个新工程.
其中:-t表示新工程目标sdk;-p表示工程的路径;-a表示默认activity的名称.
其他选项可执行android create project -h查看.
配置jni目录
在工程根目录下新建一个jni目录,将hello-arm.c拷贝至此目录.
新建脚本文件名为Android.mk,这是ndk-build需要的工程编译脚本,描述了编译程序的各种选项和依赖.
内容如下:
|
|
其中:LOCAL_PATH表示本工程源码的路径, my-dir表示Android.mk的路径;CLEAR_VARS让编译器清除已经定义过的宏,避免在编译多个模块时发生错误,因为这些宏是全局的,必须重新设置;LOCAL_ARM_MODE指定程序使用的ARM指令模式;LOCAL_MODULE指定生成的模块名,如果生成的是共享库,模块名会变为libhello-arm.so;LOCAL_SRC_FILES指定源文件列表;BUILD_EXECUTABLE表示生成的文件是可执行的,其他选项有BUILD_SHARED_LIBRARY(生成动态库),BUILD_STATIC_LIBRARY(生成静态库).
编译
在工程根目录下执行ndk-build,编译完成后的文件在libs/armeabi目录下.
执行
执行adb push hello-arm /data/localpush到手机上(我用的是genymotion虚拟机),
执行/data/local/hello-arm
出现第一个错误
|
|
这是因为程序指令集和手机指令集不一致造成的。
写一段java代码编译成dex,看看手机是什么架构:
|
|
执行javac GetCPU.java 和 dx --dex --output=GetCPU.dex GetCPU.class 编译成dex文件,
push到手机上的 /data/local/目录, 执行dalvikvm -cp /data/local/GetCPU.dex GetCPU:
果然是intel的..
|
|
换了一个arm架构的手机(真机):
先执行了GetCPU.dex确认指令集:
|
|
现在可以执行 /data/local/hello-arm了.
出现第二个错误!
|
|
这是因为没有执行权限,加上执行权限!777!再次执行!
出现第三个错误!
|
|
这次是因为没有静态编译,重新编译,加上静态选项:
ndk-gcc --static hello-world.c -o hello-arm
颤颤巍巍的再次执行…
终于出现了 ——————— hello arm!