Android mk 编译学习
实践:
1、adb shell getprop ro.build.type
user
获取版本
Android mk 编译学习
1.引言
在手机/Tv开发的公司,往往会涉及到源码编译.将项目放在系统源码中编译.而我们通常都是通过gradle编译,打包的.并不适用于系统开发的项目.这节就学习下,常用的android mk 命令. so/ jar文件的编译.
2.正题
- LOCAL_PATH := $(call my-dir)
一个Android.mk file首先必须定义好LOCAL_PATH变量。它用于在开发树中查找源文件。在这个例子中,宏函数‘my-dir’, 由编译系统提供,用于返回当前路径(即包含Android.mk file文件的目录)。
- include $(CLEAR_VARS)
CLEAR_VARS 变量由Build System提供。并指向一个指定的GNU Makefile,由它负责清理很多LOCAL_xxx.
- LOCAL_MODULE := WeChat
LOCAL_MODULE 变量存储您要构建的模块的名称。请在应用的每个模块中使用一次此变量
- LOCAL_MODULE_CLASS :=LIB
如果没有指定LOCAL_MODULE_PATH,LOCAL_MODULE_CLASS 取值如下:
ETC:默认将module放置在/system/ect目录下面
EXECUTABLES:默认将module放置在/system/bin目录下面
JAVA_LIBRARIES:默认将module放置在/system/framework
LIB:默认将module放置在/system/lib目录
APPS:默认将module放置在/system/apps目录
- LOCAL_MODULE_TAGS :=optional
1、user:只有在user版本时该模块才被编译进去;
2、eng:只有在eng版本时该模块才被编译进去;
3、test:只有在tests版本时该模块才被编译进去;
4、optional:在所有版本中都编译该模块进去。
- LOCAL_BUILT_MODULE_STEM := package.apk
表示编译链接后的目标文件的文件名,带后缀,如果本地模块指定了LOCAL_MODULE_STEM的话,它的值就 是(LOCAL_MODULE).(LOCAL_MODULE_SUFFIX),这里没有指定,所以是LOCAL_MODULE.apk。
-
LOCAL_MODULE_SUFFIX
目标文件的后缀,有.apk .so .jar 等等
/build/core/config.mk 中已经定义了如下的变量:
COMMON_PACKAGE_SUFFIX := .zip
COMMON_JAVA_PACKAGE_SUFFIX := .jar
COMMON_ANDROID_PACKAGE_SUFFIX := .apk
所以平时是这样引用的:LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
- LOCAL_CERTIFICATE := platform
编译时签名文件的配置.
android的标准签名key有:
testkey
media
platform
shared
可以在源码的/build/target/product/security里面看到对应的密钥
- LOCAL_SRC_FILES
指定编译的源文件可以是 C文件/ apk. 指定源文件的路径
- **LOCAL_C_INCLUDES += $(LOCAL_PATH)/src **
指定c文件的头文件路径
- include $(BUILD_SHARED_LIBRARY)
BUILD_SHARED_LIBRARY:是Build System提供的一个变量,指向一个GNU Makefile Script。
它负责收集自从上次调用 include $(CLEAR_VARS) 后的所有LOCAL_XXX信息。并决定编译为什么。
BUILD_STATIC_LIBRARY :编译为静态库。
BUILD_SHARED_LIBRARY :编译为动态库
BUILD_EXECUTABLE :编译为Native C可执行程序
BUILD_PREBUILT :该模块已经预先编译
NDK还定义了很多其他的BUILD_XXX_XXX变量,它们用来指定模块的生成方式。
- LOCAL_PREBUILT_JNI_LIBS
这个属性只适用编译第三方app,而且app依赖了so库(这里的例子是在编译32位Android基础上列举的,64位待更新),按照目录结构放置so即可。
LOCAL_PREBUILT_JNI_LIBS:= \
@lib/armeabi/libBDRC4_V1_1.so \
@lib/armeabi/libfileobserver_jni.so \
@lib/armeabi/libfreetype-jni.so \
@lib/armeabi/libKSOStatEncryption.so \
@lib/armeabi/libkwopdf.so \
@lib/armeabi/libOoxmlDecrypt.so \
@lib/armeabi/libweibosdkcore.so
- LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES
这个属性只适用编译第三方app,而且 app 依赖了.外部jar.
LOCAL_STATIC_JAVA_LIBRARIES := xsocket jackson-mapper logging jackson-core javatar log4j
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := xsocket:lib/xSocket-2.8.14.jar \
jackson-mapper:lib/jackson-mapper-asl-1.6.2.jar \
logging:lib/commons-logging.jar \
jackson-core:lib/jackson-core-asl-1.6.2.jar \
javatar:lib/javatar-2.5.jar \
log4j:lib/log4j-1.2.15.jar
```
### 2.常用的mk配置
#### 2.1编译第三方apk,不包含so
```JAVA
LOCAL_PATH := $(call my-dir)
##############################
include $(CLEAR_VARS)
LOCAL_MODULE := ModuleName
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_TAGS := optional$
LOCAL_BUILT_MODULE_STEM := package.apk
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := platform
LOCAL_SRC_FILES := ModuleName.apk
LOCAL_PREBUILT_JNI_LIBS := \
@lib/armeabi-v7a/lib37CF018B.so
# LOCAL_MULTILIB :=32
include $(BUILD_PREBUILT)
2.2编译第三方apk,包含so
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ModuleName
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_TAGS := optional$
LOCAL_BUILT_MODULE_STEM := package.apk
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := platform
LOCAL_SRC_FILES := ModuleName.apk
LOCAL_PREBUILT_JNI_LIBS := \
@lib/armeabi-v7a/libTxCodec_neon.so \
@lib/armeabi-v7a/libPlayerCore_neon.so \
@lib/armeabi-v7a/libp2pproxy.so \
@lib/armeabi-v7a/libRSSupport.so \
@lib/armeabi-v7a/libmarsxlog.so \
@lib/armeabi-v7a/libckeygenerator.so \
@lib/armeabi-v7a/librsjni.so \
@lib/armeabi-v7a/libtv-ticket-tool.so \
@lib/armeabi-v7a/libhttpdns.so \
@lib/armeabi-v7a/libQQMMANDKSignature.so \
@lib/armeabi-v7a/libart.so \
#@lib/armeabi-v7a/librsjni_androidx.so
LOCAL_MULTILIB :=32
include $(BUILD_PREBUILT)
注意:引入第三方apk.假如apk中存在so文件.假如在mk中不声明引入的so.则 在启动编译好的apk之后,会崩溃
https://www.jianshu.com/p/9ba78d6f8892
Android编译选项eng、user、userdebug的区别 - Hello-World3 - 博客园 https://www.cnblogs.com/hellokitty2/p/11248975.html
一、简要说明
1. eng user userdebug 定义
eng:debug 版本,又称工程版本;user: release 版本,又称发行版本;userDebug:部分调试版本
2. Android.mk 中的编译选项 LOCAL_MODULE_TAGS
Android源码编译选项eng、user、userdebug是由Android.mk文件中的 LOCAL_MODULE_TAGS 配置项来决定的。其一般形式如下:
LOCAL_MODULE_TAGS := user eng optional test
其设置为不同值是对应不同编译结果的:
user:只有在user版本时该模块才被编译进去; eng:只有在eng版本时该模块才被编译进去; test:只有在tests版本时该模块才被编译进去; optional:在所有版本中都编译该模块进去。
其中的值可设置为1个或多个,分别对应编译选项的同一个或多个。
3. eng、user、userdebug的区别
(1) 当 make eng 时,也即相当于make。此时BuildType为eng,那么其编译进去的内容和设置包括:
· Intended for platform-level debugging · Installs modules tagged with: eng, debug, user, and/or development · Installs non-APK modules that have no tags specified · Installs APKs according to the product definition files, in addition to tagged APKs · Sets ro.secure=1 · Sets ro.debuggable=0 · Sets ro.kernel.android.checkjni=1 · adbd is enabled by default
(2) 当 make user 时,此时 BuildType 为 user,那么其编译进去的内容包括:
· Intended to be the final release · Installs modules tagged as user · Installs non-APK modules that have no tags specified · Installs APKs according to the product definition files (tags are ignored for APK modules) · Sets ro.secure=1 · Sets ro.debuggable=0 · adbd is disabled by default
(3) 当 make userdebug 时,此时 BuildType 为 userdebug,那么其编译进去的内容包括:
the same as user, except: · Intended for limited debugging · Installs modules tagged with debug · Sets ro.debuggable=1 · adbd is enabled by default
二、对编译MTK版本的补充说明
1. debug log 方面
(1) 因user/eng 版本设置 ro.secure 不同,导致 user 版本 adb 只拥有 shell 权限,而 eng 版本具有 root 权限。
(2) MTK System LOG 在ICS 以后,在 user 版本默认关闭全部 LOG, 在 eng 版本中默认打开,以便抓到完整的资讯。
(3) 在 eng 版本上,LOG 量 >= user 版本的 log 量,一些地方会直接 check eng/user 版本来确认是否打印 LOG
(4) user 版本默认关闭 uart, eng 版本默认开启 uart
(5) 在 eng 版本上,开启 ANR 的 predump, 会抓取 ftrace,可以得到更多ANR的资讯。
(6) 在 eng 版本上,可用 rtt 抓取 backtrace,可开启 kdb 进行 kernel debug, 可用 ftrace 抓取 cpu 执行场景
(7) MTK aee 在 ENG 版本抓取更多的异常资讯,比如 native exception 会抓取 core dump 信息
2. 性能方面,原则上进行性能测试使用 user 版本
(1) user 版本为提高第一次开机速度,使用了 DVM 的预优化,将 dex 文件分解成可直接 load 运行的 odex 文件,ENG 版本不会开启这项优化.
(2) 更少的 LOG 打印,uart 关闭.
3. 如何确认 user/eng 版本
Java 层,check android.os.Build 类中的TYPE 值
native 层,property_get("ro.build.type", char* value, "eng"); 然后check value 值
Debug 时,adb shell getprop ro.build.type 返回值如果是 user 即 user 版本,eng 即 eng 版本
Log 确认, mobile log/Aplog_xxxxx/versions 中查看ro.build.type 属性
4. 如何编译 user/eng 版本
默认编译的是 eng 版本,如果需要编译 user 版本,请加入参数 -o=TARGET_BUILD_VARIANT=user 如:
./mk -o=TARGET_BUILD_VARIANT=user mt6577_phone new
default.prop和/system/build.prop