这一期我们继续学习Android.mk的一些语法,主要讲的是如何引入系统库、如何引入第三方库、如何引入静态库、如何进入头文件
首先呢,我们先进入我们的Android目录,配置我们的环境变量 .build/envsetup.sh 配置lunch,我们这里依然选择的是19(这里不再细说)
然后进入我们的代码目录,cd external/test/ 然后用tree命令看一下代码目录,这个目录下有一个Android.mk,两个源文件main.cpp和test1.cpp
我们来看一下我们的main.cpp 使用命令vi src/main.cpp ,
在main.cpp中我们除了引入了stdio.h,我们还使用了utils/Log.h,这个呢,是安卓系统打印log的一个头文件,我们在这里使用的是他的ALOGE来做一个打印,我们在C++层一般都是使用ALOGE/ALOGD来做一些调试打印信息,我们既然引入了ALOGE那么我们就需要在编译的时候引入他所需要的库,那么我们来看一下我们的Android.mk,首先我们编译的是一个libtest动态库,这个暂时我们先不看,我们先来看一下我们的test,在这里test是编译生成一个可执行的二进制文件,文件名称是test,文件源码是src/main.cpp
现在呢,我们还没有导入log的库,我们现在来编译看一下 使用mm命令进行编译
在这里我们看到有一个错误信息,是说在我们的main.cpp中的第七行,没有定义_android_log_print ,我们打开main.cpp来看一下
ALOGE包含在log那个库文件中,我们并没有导入我们的log库,所以会有报错信息,那我们应该怎么解决呢?我们可以在Android.mk中加一个选项,来把我们的库加上,这样我们在编译的时候就能找到我们的库,我们需要加的选项是LOCAL_SHARE LIBRARIES += libxxxx ,这样当我们的Android编译的时候,就会自动的去我们系统下去寻找我们所添加的库,下面我们将Android.mk做一个修改,我们在里面22行加上一个选项
因为ALOGE包含在log里面,所以我们在这里使用的是log这个库,然后我们再来进行编译,我们会看到在这里生成了一个test程序
接下来我们看一下,我们在编译的时候我们的库是放在哪里呢?我们退回到Android的目录,然后查找一下这个库,看看他究竟在哪里。输入命令find out/target/product/ -name liblog.so
可以看到这里有好多相同的库,我们来看一下,他具体的链接的是哪个库,下面我们把第一个库的名字改一下
然后退回到刚才的目录,代码不改变,然后touch src/main.cpp 然后我们重新编译一下 mm
我们可以看到编译是没有问题的,所以不是这个库
我们再把这个库的名字改回来
然后我们再来查找这个库,如此重复,直到编译的时候有错误出现,那么我们就可以肯定,我们所用到的就是这个库文件了,当我们对第二个库进行编译的时候就报了一个错误信息,
那么我们就可以肯定,第二个就是我们要找的链接路径,由此我们可以看出他真正链接的库并不是在我们生成的文件系统那个文件目录下,而是他中间会有一个缓存的库,他的库就会放在这里,这就是如何在安卓下导入系统的库
下面我们来看第二种情况,在当前的Android.mk中,我们自己生成了一个libtest ,如果我想在我的main.cpp里面使用src/test1.cpp里面的函数,那么我们应该怎么做呢?下面我们来修改一下代码 vi main.cpp 我们再来看一下test1.cpp中的函数
我们想要调用这个函数,就需要用extern 声明出来,然后再在主函数中调用call_test();的函数
我想在这里不以源码的形式,而是以库的形式来导入,我们现在来编译一下
现在报错是找不到这个库,那么现在我们来看一下如何加入第三方库,我们可以使用LOCAL_LDFLAGS := -LPath -lxxx来添加,其中-L加的是库的路径,-l加的是库的名字,下面我们来添加一下,打开Android.mk 进行添加
——回复可见内容——
我们是添加到了这里,现在我们的库还需要编译一下,编译的过程呢,首先是生成一个libtest.so ,这个.so会放在我们的LOCAL_PATH/lib目录下,然后会编译生成一个test的二进制程序,下面我们来做一下编译,首先把bin下面的内容清空掉,再把lib下面的内容清空掉,在touch我们的src/main.cpp ,touch src/test1.cpp
然后我们在来进行编译 使用mm命令进行编译,这个编译过程呢是没有问题的,这样就
可以在我们lib下生成libtest.so ,在bin目录下生成test二进制程序
这就是使用Android.mk导入第三方的库
下面我们来看一下我们的main.cpp vi src/main.cpp 在这里我们是以extern的形式来导入我们的函数的,正规方式呢,应该是使用头文件的形式
现在我们来看一下,我们当前目录下有一个inc的文件,他就指定了我们的头文件,头文件就是test1.h,然后我们打开这个头文件
如果没有test1.h我们就定义这个test1.h ,是为了防止重定义,把函数在这里面进行了声明
然后在进入main.cpp ,在上边用include进行声明,因为test1.h是在inc目录下所以应该添加 #include “./inc/test1.h”
现在我们来进行一下编译,看能否找到我们的头文件 mm
可以看到这样是完全没有问题的,那么说如果我们的test1.h他在一个其他目录,或者说inc在往上几个目录,这时候这个办法肯定是不行的,我们就没有办法指定了,此时我们可以添加一个关键字LOCAL_C_INCLUDES := path ,现在我们返回我们的main.cpp文件中进行一下修改,我们将#include “./inc/test1.h”修改成#include
现在我们来进行编译 mm
这样是肯定不行的,有错误,现在我们来改一下我们的Android.mk ,在里边呢加上一个选项 LOCAL_C_INCLUDES := ./inc
现在我们再来进行编译,但是当我们编译的时候他还是会报错,因为是绝对路径,所以呢,我们加的时候要加上我们的LOCAL_PATH
这时我们在进行编译就没问题了
下面我们来看一下我们如何使用我们的静态库,我们先来看一下我们的静态库在哪里,我们首先touch src/test1.cpp 然后 mm 进行编译
这样我们就看到了我们静态库的目录,我们返回我们的Android目录,然后将静态库的目录拷贝到external/test/lib/目录下,这样我们就有了一个静态库
我们来修改一下Android.mk 我们把LOCAL_LDFLAGS修改一下,把它改成我们的静态库
然后我们来做编译 mm
他会报一个错,说编译器找不到我们的./lib/libtest1.a ,这是因为我们需要在刚才修改的地方添加一个绝对路径,也就是我们的LOCAL_PATH
我们修改完之后在进行编译,这时就可以编译过去了