在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/local
push到手机上(我用的是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!