众所周知,Android系统是基于Linux系统的构建的,习惯Linux开发的伙伴们都知道,写Linux程序一般有三种情况:
(1)如果你的程序只有一个文件(一般都是一些测试验证程序),那么只需要gcc xxx.c -o xxx就可以了;
(2)如果你的工程包含不止一个源文件,那么就需要一个漂亮的Makefile来指定自己的编译器,头文件目录,依赖库吗,源文件等;
(3)做过实际产品的人应该知道,一个产品往往只有一个交叉编译工具链,但是有众多的工程,kernel,文件系统,各种应用程序。这个时候,我们的工程管理就会复杂一些了,我们一般会用一个总的Makefile加一系列的xxx.mk文件来对整个产品的多个工程进行管理,最后实现只要一个make或者make all命令就可以编译全部工程!而使用不同的参数,则可以分别单独编译任意一个子工程。
好了,AOSP(Android开放源码工程)实际上就是上面的第三种情况,它是一个大工程,其下有非常多的子工程,包括kernel、文件系统、framework、Dalvik等等。Android的做法也是用一个Makefile然后再加一系列xxx.mk的方式构建了自己的一套编译系统!其实跟我们做法是一样的,只不过Android做的更完善罢了。下载好AOSP的源码后,只要在顶层目录一个make all命令即可把Android系统全部编译!
如果是我们自己开发的一个c/c++程序如何编译到Android系统呢?方法有两种:
(1)找到AOSP使用的交叉编译器,直接在你的Makefile里面指定,这当然行的通,但做法并不正规,有走后门的嫌疑;
(2)使用Android规范的Android.mk进行编译,Android.mk跟我们平常写的xxx.mk一样,本身并不是完整的Makefile,只是一些局部变量的设置,这些局部变量即:编译所需的源文件、头文件目录、依赖库以及目标文件名称等。
以上两种方式编译出来的二进制文件,可以直接运行在Android系统上,而且就算Dalvik不启动,这些程序也照样可以运行,因为他们跟Dalvik是同一层次的东西,都是c/c++交叉编译器直接编译出来的。这也打了很多人说c/c++无法开发Android或者必须使用JNI方式来开发的观点;
用自己的Makefile编译Android程序的,可以自己看看AOSP的编译系统,找到其交叉编译器,我试过,是可以的。
下面用一个例子来说明Android.mk的用法:
因为使用了c++ stl模板的程序不太好编译过,所以下面程序变用了stl,并且我们把可执行文件拷贝了一份到/data目录下:
Android.mk代码:
LOCAL_PATH:=$(callmy-dir)
include$(CLEAR_VARS)
C_SRC:=$(wildcard$(LOCAL_PATH)/*.cpp)
C_SRC:=$(C_SRC:$(LOCAL_PATH)/%=%)
$(warning"C_SRCis:"$(C_SRC))
LOCAL_SRC_FILES:=$(C_SRC)
LOCAL_C_INCLUDES :=prebuilts/ndk/9/sources/cxx-stl/stlport/stlport
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog \
prebuilts/ndk/9/sources/cxx-stl/stlport/libs/x86/libstlport_static.a
LOCAL_MODULE:=helloVector
LOCAL_MODULE_OWNER:=zhanghw
LOCAL_MODULE_TAGS:=optional
LOCAL_MODULE_PATH:=$(TARGET_OUT_DATA)/system/bin
$(shellmkdir-p$(TARGET_OUT_DATA)/data)
include$(BUILD_EXECUTABLE)
#include <stdio.h> #include <vector> using namespace std; int main(int argc,char ** argv) { vector<int > tab; tab.push_back(100); tab.push_back(101); tab.push_back(102); for(int i=0;i<3;i++){ printf("%d ",tab[i]); } printf("\n"); return 0; }