前言
千呼万唤使出来,答应的事儿一定做到;之前在一篇文章中说到自己会出一篇比较详细介绍Android.mk文件的文章,一言既出,必须得出!本文主要是介绍一些比较常用的mk文件里面的标签使用,同时也给出一些使用实例供大家做模板参考使用,话不多说,上小菜儿!
正文
本文是基于本人测试使用的一个demo来说明android.mk文件属性,我觉得用实例说话会让人更加理解其含义,所以自己写了一个比较全的工程来自写android.mk文件,先把使用的工程demo文件目录列一下吧:
这个demo覆盖了Android工程里面比较常用的,包括jar包/lib库/jni/aidl,先上我自己写好跑过的Android.mk文件:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#编译源文件 声明需要编译的文件类型
LOCAL_SRC_FILES := $(call all-subdir-java-files)
#另外注意,这条语句必须加入到最后面出现LOCAL_SRC_FILES位置后面,否则会无效。
LOCAL_SRC_FILES += src/com/topwise/cloudpos/aidl/AidlDeviceService.aidl
src/com/topwise/cloudpos/aidl/emv/AidlCheckCardListener.aidl
src/com/topwise/cloudpos/aidl/emv/AidlPboc.aidl
src/com/topwise/cloudpos/aidl/emv/AidlPbocStartListener.aidl
#编译的标签 默认为optional
LOCAL_MODULE_TAGS := optional
#签署当前应用的证书名称
LOCAL_CERTIFICATE := platform
#编译生成的apk名称
LOCAL_PACKAGE_NAME := TOPUSDKServiceMk
#指定是否启用混淆
#如果要开混淆 需要同LOCAL_PROGUARD_FLAG_FILES这个属性一起用
LOCAL_PROGUARD_ENABLED := disabled
#编译的静态库
LOCAL_STATIC_JAVA_LIBRARIES := libbcprov_jdk libcore libsc_light_jdk15on
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v4
android-support-v7-appcompat
#依赖的so文件若在lib下没有,则找makefile文件编译 load库的时候去掉lib
LOCAL_REQUIRED_MODULES := libposdevice libemvtopwise
#编译apk结尾
include $(BUILD_PACKAGE)
####预编译模块 --start--
include $(CLEAR_VARS)
#预编译导入的静态库(jar包)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES :=libbcprov_jdk:libs/bcprov-jdk16-145.jar
libcore:libs/core_3.3.0.jar
libsc_light_jdk15on:libs/sc-light-jdk15on-1.47.0.2.jar
#libemv_jni:libs/armeabi/libemvtopwise.so 预编译成libemv_jni.so
#libs/armeabi/libzbar.so 预编译成libzbar.so
LOCAL_PREBUILT_LIBS := libs/armeabi/libzbar.so
libs/armeabi/libDCL.so
LOCAL_MODULE_TAGS := optional
include $(BUILD_MULTI_PREBUILT)
####预编译模块 --end--
include $(call all-makefiles-under,$(LOCAL_PATH))
首先基本的Android.mk文件开始先要定义工程路径,LOCAL_PATH字段定义工程路径,之后清除编译定义变量:
//$(call my-dir)返回当前Android.mk文件所在文件夹
LOCAL_PATH := $(call my-dir)
//清除之前定义的变量值
include $(CLEAR_VARS)
后面的标签一个一个说明:
LOCAL_SRC_FILES :用来定义需要编译的源文件,这里要注意的是aidl文件需放在所有添加源文件之后,也就是要末尾定义;
这里列举几个常用的获取源文件的方法(获取指定目录下的文件,不包含子文件夹下的)
$(call all-java-files-under, src):获取指定目录下的所有 Java 文件。
$(call all-c-files-under, src):获取指定目录下的所有 C 语言文件。
$(call all-Iaidl-files-under, src) :获取指定目录下的所有 AIDL 文件。
$(call all-makefiles-under, folder):获取指定目录下的所有 Make 文件。
LOCAL_MODULE_TAGS:用于说明编译条件;常用的有:debug, eng, user,development 或者 optional。其中,optional 是默认标签。
LOCAL_CERTIFICATE:用于说明签名属性,指需要那种签名文件签名;常用的有:
1、testkey:普通APK,默认情况下使用。 2、platform:该APK完成一些系统的核心功能。经过对系统中存在的文件夹的访问测试,这种方式编译出来的APK所在进程的UID为system。3、shared:该APK需要和home/contacts进程共享数据。4、media:该APK是media/download系统中的一环。
LOCAL_PACKAGE_NAME:编译生成的apk名称;如果你编译的是PACKAGE,那么模块说明就用这个标签。
LOCAL_PROGUARD_ENABLED:是否开启混淆;默认情况下是开混淆的,如果你想自定义混淆规则,可同LOCAL_PROGUARD_FLAG_FILES这个属性一起用。
LOCAL_PROGUARD_FLAG_FILES:定义混淆文件;将混淆文件(+路径)加到此标签后即可。
LOCAL_STATIC_JAVA_LIBRARIES:静态库文件;需要编译到module模块里的库文件需在此标签定义。一般包含AndroidOS库(v4 v7包等)和预编译静态库文件(jar包等);这里跟的是库标签名称,非本库路径。
LOCAL_SHARED_LIBRARIES:动态库文件,一般都具有依赖性;一般为预编译库或者已存在的三方库,无此库的时候先去编译此库;
LOCAL_REQUIRED_MODULES:该模块运行所依赖的模块文件;其中jni代码的编译module就放到这里,libposdevice/libemvtopwise这两个定义是在jni的mk文件定义的module名称,具体见下文;
include $(BUILD_PACKAGE):编译PACKAGE包结尾说明,表示编译成APK包,其他的还有:
include $(BUILD_STATIC_LIBRARY) 表示编译成静态库
include $(BUILD_SHARED_LIBRARY) 表示编译成动态库
include $(BUILD_EXECUTABLE) 表示编译成可执行程序
include $(BUILD_STATIC_JAVA_LIBRARY) 编译成Java静态库
include $(BUILD_MULTI_PREBUILT) 会将prebuild的那些,还有required那些库拷到本地来编译
如果工程中有jar包或者本地库等,需先预编译之后方可编译或者连接,以下就是预编译模块代码:代码块
####预编译模块 --start--
include $(CLEAR_VARS)
#预编译导入的静态库(jar包)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES :=libbcprov_jdk:libs/bcprov-jdk16-145.jar
libcore:libs/core_3.3.0.jar
libsc_light_jdk15on:libs/sc-light-jdk15on-1.47.0.2.jar
#libemv_jni:libs/armeabi/libemvtopwise.so 预编译成libemv_jni.so
#libs/armeabi/libzbar.so 预编译成libzbar.so
LOCAL_PREBUILT_LIBS := libs/armeabi/libzbar.so
libs/armeabi/libDCL.so
LOCAL_MODULE_TAGS := optional
include $(BUILD_MULTI_PREBUILT)
####预编译模块 --end--
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES:预编译静态库;这里是因为jar包需要打包编译到APK中,所以jar包要编译成静态库;编译静态库前面最好加重定义(libbcprov_jdk),这样在模块编译的时候LOCAL_STATIC_JAVA_LIBRARIES下方便进行引用;
LOCAL_PREBUILT_LIBS:预编译动态库;本地库需先预编译为动态库,才可成功连接到APK。
ps:预编译库的时候需注意重定义库名称的使用,防止代码中loadLibrary时引用名称错误;例如如果LOCAL_PREBUILT_LIBS := libemv_jni:libs/armeabi/libemvtopwise.so,编译出的库名称为 libemv_jni.so,但LOCAL_PREBUILT_LIBS := libs/armeabi/libemvtopwise.so,编译出的库名称为libemvtopwise.so;
后面两个属性前面有说明;
include $ (call all-makefiles-under,$(LOCAL_PATH)):此行意思是如果当前mk文件编译完成,递归查找子目录下的mk文件并编译;如果编译jni,此行必出现。
OK,你可以结合上面贴的工程目录树形图和mk文件一一对照,看如何定义各个标签;其中jni的mk文件也贴出如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#编译生成模块名称 编译出来会自带格式:***.so
#跟AS编译出来不一样 AS自带格式:lib***.so
LOCAL_MODULE := libposdevice
LOCAL_SRC_FILES := com_android_topwise_sdk_jni_PosDevice.cpp
LOCAL_SRC_FILES += posdevice.cpp
#理解是链接系统库所用
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libemvtopwise
LOCAL_SRC_FILES += emv/com_android_topwise_sdk_jni_EmvJNI.c
LOCAL_SRC_FILES += emv/jni_util.c
LOCAL_LDLIBS := -llog
#链接共享库 一般为预编译库或者已存在的三方库
#有依赖关系 没有此库时编译此库
LOCAL_SHARED_LIBRARIES += libtop_emv
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_PREBUILT_LIBS := libtop_emv:lib32/libtopemv.so
include $(BUILD_MULTI_PREBUILT)
这里的标签基本在上文都有解释,其中:
LOCAL_LDLIBS := -llog
链接的库不产生依赖关系,一般用于不需要重新编译的库,如库不存在,则会报错找不到。且貌似只能链接那些存在于系统目录下本模块需要连接的库;例如常用的有: -lm –lz –lc -lcutils –lutils –llog;
目前预编译动态库进行局部编译后都会拷贝到系统system/lib目录下的(platform),没有编译到APK内部,所以如果调试过程中想运行编译出的APK,需将编译生成的动态库push到system/lib下调试运行!
OK,到这里基本Android.mk文件就写完了,接下来说说我碰到的钉子以及介绍下其他相关内容吧!
aidl编译过程遇到的障碍:
- aidl使用自定义类(实现序列化接口)作为参数注意,首先构造一个类CardInfo.java:
代码块
package com.topwise.cloudpos.aidl.emv;
import android.os.Parcel;
import android.os.Parcelable;
/**
* 卡数据bean
*
* @author xk
*
*/
public class CardInfo implements Parcelable {
private String cardno = null;
public CardInfo(Parcel source) {
this.cardno = source.readString();
}
public CardInfo(String cardno){
this.cardno = cardno;
}
@Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
public String getCardno() {
return cardno;
}
public void setCardno(String cardno) {
this.cardno = cardno;
}
public static Creator<CardInfo> getCreator() {
return CREATOR;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.cardno);
}
public static final Creator<CardInfo> CREATOR = new Creator<CardInfo>() {
@Override
public CardInfo createFromParcel(Parcel source) {
// TODO Auto-generated method stub
CardInfo cardno = new CardInfo(source);
return cardno;
}
@Override
public CardInfo[] newArray(int size) {
// TODO Auto-generated method stub
return new CardInfo[size];
}
};
}
再定义一个同名的aidl文件CardInfo.aidl,代码块
package com.topwise.cloudpos.aidl.emv;
parcelable CardInfo;
之后才可在aidl接口中使用它作为参数;代码块
package com.topwise.cloudpos.aidl.emv;
import com.topwise.cloudpos.aidl.emv.CardInfo;
interface AidlPbocStartListener{
/ ...
... /
void onConfirmCardInfo(in CardInfo cardInfo);
}
在LOCAL_SRC_FILES中添加编译文件时无需把CardInfo.aidl列入,编译时会自动取文件进行编译!
- 在使用Bundle/Bitmap等作为参数时,如果你是在系统代码中创建的工程,需import声明;如果是AS中创建则不需要;
动态库和静态库的区别
一句话,动态库是运行时加载(.so),静态库是编译时加载(.a),当两者同时存在且同名时,优先使用动态库加载;
具体解释可参考链接:https://blog.csdn.net/zzcchunter/article/details/88995492
编译APK文件到系统时mk文件参考
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := USDKService
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := USDKService.apk
#编译中间暂存目录
LOCAL_MODULE_CLASS := APPS
#后缀名称,使用默认
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := platform
include $(BUILD_PREBUILT)
局编过程遇到的问题汇总
- ninja: error: ‘out/target/product/tpw8735b_t3h/obj/SHARED_LIBRARIES/lib32/libtopemv.so_intermediates/export_includes’,
needed by ‘out/target/product/tpw8735b_t3h/obj/SHARED_LIBRARIES/emvtopwise_intermediates/import_includes’,
missing and no known rule to make it
解决方法:jni预编译库出错 使用BUILD_MULTI_PREBUILT,此类问题一般都是预编译出错,仔细检查预编译的相关代码;
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_PREBUILT_LIBS := libtop_emv:lib32/libtopemv.so
include $(BUILD_MULTI_PREBUILT)
- No resource found that matches the given name 'Theme.AppCompat.Light.DarkActionBar
解决方法:缺少库文件,导入V7包
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-appcompat
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-gridlayout
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v13
后记
稍微写一写就得一晚上时间,又熬夜了~唉~
本文只是介绍了一些android.mk中常用的属性值,后续还会不停补充更新!若有写的不正确的地方,还请大佬们评论指正,谢谢!
最后
以上就是愉快嚓茶最近收集整理的关于Android.mk文件学习,将工程编译到系统中(实践篇)前言后记的全部内容,更多相关Android内容请搜索靠谱客的其他文章。
发表评论 取消回复