首先是可能用得到的基础知识,必须了解基础Makefile的语法,然后下面是Andriod用来编译相应模块使用的核心makefile,当然如果要速成的话也可以不看这些东西,直接按照后面的例子添加就可以了:
     1、prebuilt
      /build/core/base_rules.mk
      /build/core/prebuilt.mk
      /build/core/multi_prebuilt.mk
     2、.so/
      /build/core/base_rules.mk
      /build/core/shared_library.mk
      /build/core/dynamic_library.mk
      /build/core/binary.mk
     3、.a
      /build/core/base_rules.mk
      /build/core/static_library.mk
      /build/core/binary.mk
     编写可执行文件基本上和.so是差不多的,现在分为两类来仔细讲一下,一类是prebuilt files的编译,另外就是.so/.a/elf的编译。
     在所有这许makefile中最重要的是base_rules.mk,它是对module进行处理的核心过程,下面先看看这个文件的内容:

每个模块在编译的时候都会产生一个编译目录和一个安装目录,编译目录就是这个模块编译以后生成的目标文件,安装目录就代表着这个模块是否会编译进文件系统,就是是否编译进IMG啦~~在base_rules.mk提供了两个变量来定义你要输出的目录,仔细弄懂对你了解编译后的生成目录是很有帮助的~~
      built_module_path := $(intermediates)
      LOCAL_BUILT_MODULE := $(built_module_path)/$(LOCAL_BUILT_MODULE_STEM)
      LOCAL_INSTALLED_MODULE := $(LOCAL_MODULE_PATH)/$(LOCAL_MODULE_SUBDIR)$(LOCAL_INSTALLED_MODULE_STEM)
      built_module_path是编译生成的中间文件所在的目录,LOCAL_BUILT_MODULE_STEM就是你要生成的编译目标啦,如果本地模块指定了LOCAL_MODULE_STEM的话,它的值就是$(LOCAL_MODULE_STEM)$(LOCAL_MODULE_SUFFIX),如果没有指定了的话就是$(LOCAL_MODULE)$(LOCAL_MODULE_SUFFIX)。由此可以看到LOCAL_MODULE的定义是很有讲究的,比如什么*.so,一般*就用来作模块名。LOCAL_MODULE_SUFFIX在编译不同的模块时,GOOGLE内置会给你加上相应的值,如果你不了解的话还是尽量自己来指定,不然可能编译出来的东西被篡改了文件名哦噢~~
      将编译目录的文件拷贝到安装目录就是我们的LOCAL_INSTALLED_MODULE了,是否会安装就要看你定义的 LOCAL_MODULE_TAGS了,当然你也可以通过修改LOCAL_MODULE_PATH来自定义安装。LOCAL_MODULE_PATH是有个很有用的变量,首先我们看看当我们在本地模块没有指定这个值的时候,它的值实际上是:LOCAL_MODULE_PATH := $($(my_prefix)OUT$(use_data)_$(LOCAL_MODULE_CLASS)),如果你的模块定义了TAGS := TESTS则user_data的值是DATA,这样的模块会被安装在data/目录下,那么通过替换我们就知道这个LOCAL_MODULE_PATH := TARGET_OUT_$(LOCAL_MODULE_CLASS)。这个LOCAL_MODULE_CLASS在特定的类型编译会被google赋值成固定内容,但是在prebuilt的编译中它是由你自己来赋值的,它的值就会用来定义生成的目录,比如LOCAL_MODULE_CLASS := ETC的时候,则就会被安装在/system/etc目录。那么我们就知道如何来定义prebuilt模块里面的CLASS了,google还提供了一个 LOCAL_MODULE_SUBDIR可以让你来定义子目录,但是要记得的是在每个模块的最后要将这个值清空,因为默认CLEAR_VARS是不会清空这个值的。
      当然前面说的是LOCAL_MODULE_PATH的默认值,我们可以通过给它赋值来强制指定安装的目录,比如说要安装在system/etc /permissions目录,则可以强制指定它的值为$(TARGET_OUT_ETC)/permissions,这样模块就会被强制安装在这个目录了,给LOCAL_MODULE_PATH赋值的情况主要应用在prebuilt模块的编译上,其他的应该尽量采用其默认值。
      下面我们就具体看看我写的一个如何编译自己的.so *.a elf的例子,具体能使用到的变量,和要注意的地方我都写出来了:

这里要说明的是这个prelink,prelinke只有在编译.so的时候才会有的选项,主要是通过预链接的方式来加快程序启动和执行的速度,如果你的本地模块prelink是真的话,那你要在build/core/prelink-linux-arm.map中定义你的库需要使用的空间,空间不够的话会报错(具体使用没仔细研究过)
       下面再看看如何来将我们自己的prebuilt files编译进工程,先让我们和这个相关的最重要的两个makefile:

multi_prebuilt.mk只用来加入需要加入的各种库,仔细注意它里面的那个对加入文件进行处理的函数,尤其是 LOCAL_MODULE,LOCAL_MODULE_SUFFIX ,LOCAL_SRC_FILES这3个变量是如何得到的,使用multi_prebuilt编译进工程的文件都会自动打上USER的tag。而且它最后还是会掉用prebuilt.mk来执行真正的编译操作。
        prebuilt.mk实际上可以编译任何文件到我们的工程中,下面是我写的一个例子,可以自动将目录下相应格式的文件编译进工程:

此外添加prebuilt.mk也有一个粗暴的方式,可以通过下面的规则简单的将所有prebuilt files添加到你工程中去,必须一个一个添加:
        LOCAL_PATH := $(call my-dir)
        include $(CLEAR_VARS)
        # your prebuilt file name
        LOCAL_MODULE := example.so
        LOCAL_MODULE_TAGS := user eng
        # your prebuilt file (must be relative directory )
        LOCAL_SRC_FILES := lib/example.so
        # the path your prebuilt file will be installed   $(TARGET_OUT) is the system directory
        LOCAL_MODULE_PATH := $(TARGET_OUT)/lib  
        include (BUILD_PREBUILT)

在最后说一下Android对模块唯一性检测的规则,在base_rules.mk里面通过module_id里来检测这个模块是否已经存在,我们看看这个值是如何定义的:

module_id := MODULE.$(if /
    $(LOCAL_IS_HOST_MODULE),HOST,TARGET).$(LOCAL_MODULE_CLASS).$(LOCAL_MODULE)

所以它是通过LOCAL_MODULE_CLASS和LOCAL_MODULE这两个变量来检测模块的唯一性,因此当你定义同一样的CLASS和 MODULE的时候,Android就会报错,提示模块必须是唯一的。因此如果你将LOCAL_MODULE_CALSS进行修改,使用 LOCAL_MODULE_PATH来指定安装目录的时候就会逃过Android对模块唯一性的检测,但是这样导致的问题就是同一个目标会有多个规则来实现它,而且每个规则都是相同的命令。这样导致的结果就是MAKE会将所有的依赖放在一起,然后使用命令来将其生成目标,这样是非常危险的,会造成库的覆盖,而且很多时候你不知道它就究竟使用的是哪个依赖来最终生成目标,只能用md5sum来检查。

因此当你使用prebuilt来覆盖系统原有的文件的时候应该特别小心,如果你确认你的文件在覆盖系统原有文件以后系统能正常运行的话,好的方法是还是打开Android对module_id的检测,同时把原来生成这个文件的Makefile进行修改,让其不编译出这个文件~

最后补充一个Android如何来存放模块的编译中间文件:
1、如果你的LOCAL_MODULE_CLASS包含COMMON_MODULE_CLASS := JAVA_LIBRARIES NOTICE_FILES,则你编译出的中间文件会放在:
   $(TARGET__OUT_COMMON_INTERMEDIATES)/$(LOCAL_MODULE_CLASS)/$(LOCAL_MODULE)_intermediates/
TARGET_OUT_COMMON_INTERMEDIATES := out/target/common/obj
2、如果你的LOCAL_MODULE_CLASS不包含COMMON_MODULE_CLASS,则你编译出的中间文件会放在:
     $(TARGET__OUT_INTERMEDIATES)/$(LOCAL_MODULE_CLASS)/$(LOCAL_MODULE)_intermediates/
TARGET_OUT_INTERMEDIATES := out/target/product/msm7627_ffa/ob

Android Makefile分析相关推荐

  1. Android JNI入门第五篇——Android.mk分析

    转载请标明出处: http://blog.csdn.net/michael1112/article/details/56671708 江东橘子的博客 Android.mk文件是在使用NDK编译C代码时 ...

  2. android逆向分析概述_Android存储概述

    android逆向分析概述 Storage is this thing we are all aware of, but always take for granted. Not long ago, ...

  3. Linux内核移植之一:内核源码结构与Makefile分析

    内容来自 韦东山<嵌入式Linux应用开发完全手册> 一.内核介绍 1.版本及其特点 Linux内核的版本号可以从源代码的顶层目录下的Makefile中看到,比如下面几行它们构成了Linu ...

  4. Android多线程分析之二:Thread的实现

    Android多线程分析之二:Thread的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前文<Android多线程分析之一:使 ...

  5. u-boot分析之makefile分析(二)

    目录 u-boot(二)makefile 引入 目录结构(1.1.6) 配置文件 目标 配置具体的单板 编译阶段 过程 链接入口 配置链接地址 附录 附录A:mkconfig解析 附录B 链接脚本 u ...

  6. 操作系统课设--NACHOS试验环境准备、安装与MAKEFILE分析

    山东大学操作系统课设lab1 实验一 NACHOS试验环境准备.安装与MAKEFILE分析(lab1) 实验环境: 分析记录: 1. 准备虚拟机下LINUX宿主操作系统环境 2. NACHOS实验代码 ...

  7. Android内存分析和调优(上)

    Android内存分析和调优(上) Android内存分析和调优(上) Android内存分析工具(四):adb命令 posted on 2017-09-25 19:29 时空观察者9号 阅读(... ...

  8. Android Telephony分析(七) ---- 接口扩展(异步转同步)

    本文是基于上一篇<Android Telephony分析(六) -- 接口扩展(实践篇)>来写的.  上一篇介绍的接口扩展的方法需要实现两部分代码:  1. 从APP至RIL,发送请求:  ...

  9. Android Telephony分析(六) ---- 接口扩展(实践篇)

    本文将结合前面五篇文章所讲解的知识,综合起来,实现一个接口扩展的功能.  如果还没有阅读过前面五篇文章的内容,请先阅读:  <Android Telephony分析(一) - Phone详解 & ...

最新文章

  1. ioremap 与 mmap【转】
  2. VTK:baking烘焙阴影贴图用法实战
  3. (一)U盘安装ubuntu18.04.1
  4. Spring入门(三)之IoC
  5. ​凌云KTV点歌系统功能简介
  6. cts(7)---android 8.1 vts环境和测试
  7. tomcat启动 报tomcat org.apache.catalina.LifecycleException
  8. Region proposal学习笔记
  9. 在python3.5中使用pip
  10. 哥廷根大学计算机博士,德国哥廷根大学 单分子光学 招博士 (75% TV-L E13 工资)...
  11. 最新MATLAB R2020b超详细安装教程---亲自安装成功!!!
  12. 微星主板jsp1接线图_微星主板JSP11接口可制作双BIOS
  13. 2021-7-19 fact函数求阶乘的用法
  14. springmvc中使用forward和redirect
  15. Eclipse初始化
  16. 圣诞节用java画一棵圣诞树给你的女友
  17. 自媒体你不知道的二三事|原来这些好听的声音是这么来的......
  18. 带空格直角三角形图案的输出-c++
  19. 【FFMPEG】H264码流的两种组织方式:AnnexB和AVCC
  20. 大数据在医疗领域应用有哪些挑战?

热门文章

  1. 35-面试:如何找出字符串的字典序全排列的第N种
  2. SQL-92标准 中文翻译——定义、记号和约定 (定义)
  3. Linux - XShell - alt 快捷键的设置
  4. 美素数(HDU 4548)(打表,简化时间复杂度)
  5. bzoj2754: [SCOI2012]喵星球上的点名
  6. 阿里巴巴开源Weex 开发教程
  7. C++模拟实现Objective-C协议和代理模式
  8. MySQL_前缀索引_建立
  9. 2012 Microsoft Intern Hiring Written Test [转]
  10. TCP 端口监听队列原理