Android.mk 杂乱分析

开头参考过:http://www.cnblogs.com/langlang/   

hardware\led\led\Android.mk

LOCAL_PATH := $(call my-dir)
{
    首先需要指定LOCAL_PATH变量,用于查找源文件
    上面的语句的意思是将LOCAL_PATH变量定义成本文件所在目录路径
}

#Android.mk中可以定义多个编译模块,每个编译模块都是以include $(CLEAR_VARS)开始
#以include $(BUILD_XXX)结束。
include $(CLEAR_VARS)  // 开始
{
    问: CLEAR_VARS是什么??
    答: CLEAR_VARS由编译系统提供,指定让GNU MAKEFILE为你清除除LOCAL_PATH以外的所有LOCAL_XXX变量,
    如LOCAL_MODULE,LOCAL_SRC_FILES,LOCAL_SHARED_LIBRARIES,LOCAL_STATIC_LIBRARIES等。    
}
#包含的头文件
LOCAL_C_INCLUDES += \
    hardware/led/include/

LOCAL_PRELINK_MODULE :=  false   //  :=是赋值的意思
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw 
{
     // LOCAL_MODULE_PATH: 最后的目标安装路径
    
    问: TARGET_OUT_SHARED_LIBRARIES是什么?
    答: 在build/core/envsetup.mk中定义。TARGET_OUT_SHARED_LIBRARIES:= $(TARGET_OUT)/lib
    TARGET_ROOT_OUT:表示根文件系统。
    TARGET_OUT:表示system文件系统。
    TARGET_OUT_DATA:表示data文件系统。
    
}
LOCAL_SHARED_LIBRARIES := liblog   // LOCAL_SHARED_LIBRARIES中加入所需要链接的动态库(*.so)的名称
LOCAL_SRC_FILES := led.cpp
LOCAL_MODULE :=led. default    // LOCAL_MODULE表示模块最终的名称
#LOCAL_MODULE的定义规则,led后面跟有default,led.default能够保证我们的模块总能被硬象抽象层加载到
LOCAL_MODULE_TAGS := eng
include $(BUILD_SHARED_LIBRARY)  //  结束
{
    include $(BUILD_STATIC_LIBRARY)表示编译成静态库
    include $(BUILD_SHARED_LIBRARY)表示编译成动态库。
    include $(BUILD_EXECUTABLE)表示编译成可执行程序
}

LOCAL_SRC_FILES中加入源文件路径,LOCAL_C_INCLUDES 中加入所需要包含的头文件路径,
LOCAL_STATIC_LIBRARIES加入所需要链接的静态库(*.a)的名称,
LOCAL_SHARED_LIBRARIES中加入所需要链接的动态库(*.so)的名称,
LOCAL_MODULE表示模块最终的名称,BUILD_EXECUTABLE表示以一个可执行程序的方式进行编译。



hardware\led\Android.mk
include $(call all-subdir-makefiles)


frameworks\ base\services\forlinx_led_jni\LedService.cpp
frameworks\ base\services\forlinx_led_jni\Android.mk
{

    LOCAL_PATH:= $(call my-dir)  // LOCAL_PATH变量定义成本文件所在目录路径
    include $(CLEAR_VARS)
    
    # [optional, user, eng] 
    # eng = required
    # optinal = no install on target
    LOCAL_MODULE_TAGS := eng
    {
        LOCAL_MODULE_TAGS :=optional -->>  out/target/product/OK6410/symbols/system/
        LOCAL_MODULE_TAGS :=eng    -->>  out/target/product/Ok6410/system/
    }
    
    # This  is the target being built.
    LOCAL_MODULE:= libforlinx_runtime
    
    # Target install path.
    LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
    
    # All of the source files that we will compile.
    LOCAL_SRC_FILES:= \
        LedService.cpp
    
    # All of the shared libraries we link against.
    LOCAL_SHARED_LIBRARIES := \
        libandroid_runtime \
        libcutils \
        libhardware \
        libhardware_legacy \
        libnativehelper \
            libsystem_server \
        libutils \
        libui \
            libsurfaceflinger_client
        
    
    # Also need the JNI headers.
    LOCAL_C_INCLUDES += \
        $(JNI_H_INCLUDE) \
            hardware/led/include
    
    
    # No specia compiler flags.
    LOCAL_CFLAGS +=
    {
        LOCAL_CFLAGS += -O3 -fstrict-aliasing -fprefetch-loop-arrays
        通过设定编译器操作,优化级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
        LOCAL_CFLAGS += -W -Wall
        LOCAL_CFLAGS += -fPIC -DPIC
        LOCAL_CFLAGS += -O2 -g -DADB_HOST= 1 -Wall -Wno-unused-parameter
        LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE -DSH_HISTORY
        LOCAL_CFLAGS += -DUSEOVERLAY2
        根据条件选择相应的编译参数
    }
    
    # Don ' t prelink this library.  For more efficient code, you may want
    # to add  this library to the prelink map and  set  this to  true.
    LOCAL_PRELINK_MODULE :=  false
    {
            Prelink利用事先链接代替运行时链接的方法来加速共享库的加载,它不仅可以加快起动速度,还可以减少部分内存开销,
        是各种Linux架构上用于减少程序加载时间、缩短系统启动时间和加快应用程序启动的很受欢迎的一个工具。程序运行时的
        动态链接尤其是重定位(relocation)的开销对于大型系统来说是很大的。
        动态链接和加载的过程开销很大,并且在大多数的系统上, 函数库并不会常常被更动, 每次程序被执行时所进行的链接
        动作都是完全相同的,对于嵌入式系统来说尤其如此。因此,这一过程可以改在运行时之前就可以预先处理好,即花一些时间
        利用Prelink工具对动态共享库和可执行文件进行处理,修改这些二进制文件并加入相应的重定位等信息,节约了本来在程序
        启动时的比较耗时的查询函数地址等工作,这样可以减少程序启动的时间,同时也减少了内存的耗用。 
        Prelink的这种做法当然也有代价:每次更新动态共享库时,相关的可执行文件都需要重新执行一遍Prelink才能保
        证有效,因为新的共享库中的符号信息、地址等很可能与原来的已经不同了,这就是为什么 android framework代码一改动,
        这时候就会导致相关的应用程序重新被编译。
        这种代价对于嵌入式系统的开发者来说可能稍微带来一些复杂度,不过好在对用户来说几乎是可以忽略的。
    }
    
    include $(BUILD_SHARED_LIBRARY)
}

mk中的android:sharedUserIdLOCAL_CERTIFICATE作用

Android中如何修改系统时间(应用程序获得系统权限)
android API中有提供SystemClock.setCurrentTimeMillis()函数来修改系统时间,可惜无论你怎么调用这个函数都是没用的,无论模拟器还是真机,在logcat中总会得到"Unable to open alarm driver: Permissiondenied ".这个函数需要root权限或者运行与系统进程中才可以用。
       
本来以为就没有办法在应用程序这一层改系统时间了,后来在网上搜了好久,知道这个目的还是可以达到的。
       
第一个方法简单点,不过需要在Android系统源码的环境下用make来编译:
       
1. 在应用程序的AndroidManifest.xml中的manifest节点中加入android:sharedUserId="android.uid.system"这个属性。
       
2. 修改Android.mk文件,加入LOCAL_CERTIFICATE :=platform这一行
       
3. 使用mm命令来编译,生成的apk就有修改系统时间的权限了。
       
第二个方法麻烦点,不过不用开虚拟机跑到源码环境下用make来编译:
       
1. 同上,加入android:sharedUserId="android.uid.system"这个属性。
       
2. 使用eclipse编译出apk文件,但是这个apk文件是不能用的。
       
3. 用压缩软件打开apk文件,删掉META-INF目录下的CERT.SFCERT.RSA两个文件。
       
4. 使用目标系统的platform密钥来重新给apk文件签名。这步比较麻烦,首先找到密钥文件,在我的Android源码目录中的位置是"build\target\product\security",下面的platform.pk8platform.x509.pem两个文件。然后用Android提供的Signapk工具来签名,signapk的源代码是在"build\tools\signapk"下,用法为"signapkplatform.x509.pem platform.pk8 input.apk output.apk",文件名最好使用绝对路径防止找不到,也可以修改源代码直接使用。
       
这样最后得到的apk和第一个方法是一样的。
       
最后解释一下原理,首先加入android:sharedUserId="android.uid.system"这个属性。通过Shared User id,拥有同一个User id的多个APK可以配置成运行在同一个进程中。那么把程序的UID配成android.uid.system,也就是要让程序运行在系统进程中,这样就有权限来修改系统时间了。
       
只是加入UID还不够,如果这时候安装APK的话发现无法安装,提示签名不符,原因是程序想要运行在系统进程中还要有目标系统的platform key,就是上面第二个方法提到的platform.pk8platform.x509.pem两个文件。用这两个key签名后apk才真正可以放入系统进程中。第一个方法中加入LOCAL_CERTIFICATE:= platform其实就是用这两个key来签名。
       
这也有一个问题,就是这样生成的程序只有在原始的Android系统或者是自己编译的系统中才可以用,因为这样的系统才可以拿到platform.pk8platform.x509.pem两个文件。要是别家公司做的Android上连安装都安装不了。试试原始的Android中的key来签名,程序在模拟器上运行OK,不过放到G3上安装直接提示"Package ... has nosignatures that match those in shared user android.uid.system",这样也是保护了系统的安全。
       
最最后还说下,这个android:sharedUserId属性不只可以把apk放到系统进程中,也可以配置多个APK运行在一个进程中,这样可以共享数据,应该会很有用的。

 

 

 

 

 

 

 

 

一个android.mk例子分析

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

 

LOCAL_MODULE_TAGS := optional

user:指该模块只在user版本下才编译
 
    eng:指该模块只在eng版本下才编译
 
    tests:指该模块只在tests版本下才编译
 
    optional:指该模块在所有版本下都编译

 

LOCAL_SRC_FILES := $(callall-java-files-under, src)

 

LOCAL_PACKAGE_NAME := Settings    //指定包的名称,这里应该就是最后生成的.apk文件的文件名

LOCAL_CERTIFICATE := platform   //拿到签名权限可以共使用其它JAR还需要

#在应用程序的AndroidManifest.xml中的manifest节点加入android:sharedUserId="android.uid.system"这个属性

 

LOCAL_JAVA_LIBRARIES := com.nvidia.display  //需要的JAR

   #先确定有这个包可以用out/target/common/obj/JAVA_LIBRARIES/这个目录参观了一下,可以发现这里面有许   #多和system/framework下的jar//包对应的文件夹,包里从左到右的文件依次是:emma_out classes.dex        #classes.jar classes-full-debug.jarjavalib.jar

 

LOCAL_JNI_SHARED_LIBRARIES := libnvidia_display_jni //需要的JNI

#前提so文件在源码中编译,并在编译输出中间文件中存在。如libtest.so文件,此文件必须在      #out/target/product/generic/obj/lib/libtest.so

 

include $(BUILD_PACKAGE) //必须有这一行上面才会生效

#MK中文件中include$(BUILD_PACKAGE)是要编译这个工程

# Use the folloing include to make our testapk.

include $(callall-makefiles-under,$(LOCAL_PATH))


Android.mk详解

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := $(call all-java-files-under, src)

# AIDL
# LOCAL_SRC_FILES += core/java/seuic/hardware/ABCD.aidl

#Library
#LOCAL_MODULE_CLASS := JAVA_LIBRARIES
#LOCAL_JAVA_LIBRARIES := android.policy
LOCAL_STATIC_JAVA_LIBRARIES := com.android.libs

LOCAL_PACKAGE_NAME := ABC

LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
include $(BUILD_PACKAGE)

其中几个重要的

LOCAL_SRC_FILES:源文件路径

LOCAL_STATIC_JAVA_LIBRARIES:连接的静态库

LOCAL_MODULE_PATH:模块的目标路径

LOCAL_UNSTRIPPED_PATH:没有经过符号剥离的的目标路径

TARGET_ROOT_OUT:根文件系统,路径为out/target/product/generic/root

TARGET_OUT:system文件系统,路径为out/target/product/generic/system

TARGET_OUT_DATA:data文件系统,路径为out/target/product/generic/data

默认是TARGET_OUT

ALL_PREBUILT

$(callall-java-files-under, src)

$(callwmt-all-files-under, src)

$(addprefixABC, D)

 


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值