`

Android ROM研究---Android build system增加模块

 
阅读更多

Android build system就是编译系统的意思

在我们需要向自己编译的源代码中增加模块的时候,需要一些规则,当然这个规则都是类似的。

 

Android.mk文件解析

 

让我们来看一个 Android.mk 文件的样子

 

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE :=Hello
LOCAL_SRC_FILES := hello.c
include $(BUILD_SHARED_LIBRARY)

 

 

     LOCAL_PATH :=$(call my-dir)

固定写法, LOCAL_PATH 表示此时位于工程目录的根目录中, (call my-dir) 的功能由编译器提供,被用来返回当前目录的地址(包含 Android.mk 本身)

     include $(CLEAR_VARS)

固定写法, CLEAR_VARS 这个变量由编译系统提供,并且要执行一个 GNU makefile 文件,这个功能会清理掉所有以 LOCAL_ 开头的内容(比如 LOCAL_MODULE LOCAL_SRC_FILES 等),除了 LOCAL_PATH 。这句话也是必须的,因为如果所有变量都是全局变量的话,所有的可控的编译文件都需要在一个单独的 GNU 中被解析并执行

     LOCAL_MODULE :=Hello

LOCAL_MODLE 变量必须被定义,用来区分 Android.mk 中的每一个模块。文件名必须是唯一的,不能有空格。注意,编译器会为你自动加上一些前缀和后缀,来保证文件是一致的。比如:这里表明一个动态链接库模块被命名为“ Hello ”,但是最后会生成“ libHello.so ”文件。但是在 java 中装载这个库的时候还要使用“ Hello ”名称。

     LOCAL_SRC_FILES :=hello.c

LOCAL_SRC_FILES 变量必须包含一个 C C++ 源文件的列表,这些会被编译并聚合到一个模块中

注意:这里并不需要列头文件和被包含的文件,因为编译系统会自动为你计算相关的属性,源代码的列表会直接传递给编译器

     include $(BUILD_SHARED_LIBRARY)

BUILD_SHARED_LIBRARY 这个变量由系统提供,并且指定给 GNU makefile 的脚本,它可以收集所有你定义的 ”include $(CLEAR_VARS)” 中以 LOCAL_ 开头的变量,并且决定哪些要编译,哪些应该做的更加准确。我们同样可以使用 BUILD_STATIC_LIBRARY 来生成一个静态库,如果使用 BUILD_STATIC_LIBRARY 编译系统便会生成一个以“ lib$(LOCAL_MODULE).a ”为文件名的文件来提供动态库的调用

     TARGET_ARCH

TARGET_ARCH 是指架构中 CPU 的名字已经被 Android 开源代码明确指出了,这里的 arm 包含了任何 ARM- 独立结构的架构,以及每个独立的 CPU 版本

    TARGET_PLATFORM

Android 平台的名字在 Android.mk 文件中被解析,比如 ”android-2.3”

     TARGET_ROOT_OUT :表示根文件系统

用法: CAL_MODULE_PATH:=$(TARGET_ROOT_OUT)

     TARGET_OUT: 表示 system 文件系统

    TARGET_OUT_DATA: 表示 data 文件系统

         TARGET_ABI

TARGET_ABI 平台目标板和 abi 的链接,这里要定义 $(TARGET_PLATFORM)-$(TARGET_ARCH_ABI) ,它们都非常有用,特变是当你想测试一个具体的系统镜像在几个真实设备的时候

下面是 GNU 编译出来的宏,并且它们都必须使用“ $(call <function>) ”才能返回文字化的信息。

all-subdir-makefiles :返回一个 Android.mk 文件所在位置的列表,以及当前 my-dir 的路径。

比如: include $(call all-subdir-makefiles)

this-makefile :返回当前 makefile 的路径(就是哪个功能被调用了)

parent-makefile :返回 makefile 的包含树,也就是包含 makefile 的当前文件

 

Application.mk

 

要讲 C\C++ 编译为 so 文件,光有 Android.mk 文件是不行的,还需要 Application.mk 文件。

Application.mk 文件存放的位置是 NDK 工程的根目录, Application.mk 文件就是用来描述应用程序中所需要的原生的模块(也就是静态库和动态库),每一个 Application.mk 文件都必须放在应用目录下的子目录,例如 $NDK/apps/HelloNdk/Application.mk ,作为 GNU makefile 的一部分, Application.mk 文件必须要定义以下部分

1、  APP_MODULES

APP_MODULES 变量是强制性的,并且会列出所有你所需要的模块(通过 Android.mk

2、  APP_PROJECT_PATH

APP_PROJECT_PATH 变量也是强制性的,并且会给出应用程序工程的根目录一个绝对路径。这是用来复制或者安装一个没有任何版本限制的 JNI 库,从而给 APK 生成工具一个详细的路径。

例如: \HelloNDK\Application.mk

APP_PROJECT_PATH := $(call my-dir)/project

APP_MODULES := HelloNdk

这里定义了工程路径为 $(call my-dir)/project ,而要编译的模块则是 HelloNdk ,这样编译系统才会找到我们要编译的库和原文件

3、  APP_CFLAGS 则是当要编译模块中有任何 C 文件的时候, C 编译器的信号就会被发出

4、  APP_OPTIM

这个变量是可选的,可以定义为发布版或者测试版

 

------------------------------------------------------------------------------------------------------------------------

在Android.mk中:

include $(BUILD_EXECUTABLE)表示生成二进制可执行文件

include $(BUILD_STATIC_LIBRARY)表示生成静态库.a文件,名字叫做lib<工程名>.a

include $(BUILD_SHARED_LIBRARY)表示生成动态库.so文件,名字叫做lib<工程名>.so

 

另外需要注意的是,生成的文件需要放在手机的data/local目录下,才可以有执行的权限(未root),如果root了,则会有些目录是可以执行,但是某些目录依然不能执行,当然可以用umount命令解决。SD卡是没有执行权限的,所以当你生成的比如二进制可执行文件放到sdcard中时,是无法运行的。

 

可以这样测试一下哪些是有执行权限,哪些是没有的:

*将手机插入电脑,并打开USB调试

*在终端输入adb shell进入

*su(root了的手机)

*mount:可以看到一大堆的列表,如果对应的目录的信息中有noexec,说明这个目录就没有执行权限,剩下的都可以执行二进制等文件。

 

Android.mk文件的具体语法参见我的博客:http://hualang.iteye.com/blog/1140414

 

向Android源代码中增加模块主要有如下几种:

 

1、增加可执行文件

增加可执行文件,这些可执行文件一般都是由C/C++生成,下面简单的介绍一些如何向源代码中生成可执行文件

假设我的源代码在~/mydroid目录下

在external/loulijun/test目录下,创建两个文件,一个C,一个Android.mk

hello.c

#include <stdio.h>
int main(void)
{
	printf("Hello world!\n");
	return 0;
}

 Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES :=hello.c
LOCAL_MODULE_TAGS :=optional
LOCAL_MODULE :=test

include $(BUILD_EXECUTABLE)
 

首先退出到mydroid目录下,执行

. build/envsetup.sh
或者
source build/envsetup.sh

 进行环境变量的配置

然后进入到test目录下,执行“mm”(mm表示编译当前项目),如果想重新执行,可以"mm -B"

 

这样,会在out/target/product/generic/obj/EXECUTABLES/test_intermediates/LINKED/目录下生成可执行文件test

 

然后将test文件用adb push test /data/local 到data/local目录下。

 

下面开始执行,你可以在手机中用terminal emulator来执行,也可以以adb shell后,执行

./test
显示:Hello world!
 

2、增加静态库(.a)

Android.mk文件

LOCAL_PATH :=$(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
hello.c
LOCAL_MODULE :=test

include $(BUILD_STATIC_LIBRARY)

编译:

mydroid#. build/envsetup.sh

test#mm

生成的结果在out/target/product/generic/obj/STATIC_LIBRARY

目标文件夹{XXX}_static_intermediates下,XXX为你定义的模块名称test

 

假如这个静态库是由hello.c生成的,但是生成的静态库是不能直接使用的,而是由动态库调用它

 

3、增加动态库(.so)

编译动态库其实可以用NDK的,那样生成非常方便,但是有时候还是需要掌握其他的方法的

Android.mk

LOCAL_PATH :=$(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
hello.c
LOCAL_MODULE :=test

include $(BUILD_SHARED_LIBRARY)

 编译的放法都差不多,只不过Android.mk不同的是最后一句,如果比较一下就会发现那句话决定了生成的是什么

 

不过要想生成动态库,绝非是这么简单的,有时候只需要Android.mk和源文件即可,但是有时候还需要Application.mk文件。Application.mk文件的具体语法很快会在博客中更新

 

 

 

下面是使用 NDK 来生成 .so 文件的,环境是在 ubuntu11.04 下面

1、 下载 Android-NDK-r6 ,将其解压到 ~/android/android-ndk-r6 目录下

2、  配置 .bash_profile 文件,加入

NDK=~/android/android-ndk-r6

export NDK

3、  cd $NDK 后,进入 ndk 的目录,我以它自带的项目为例,进入 samples/hello-jni

在终端输入 $NDK/ndk-build

系统会自动编译这个文件,并将生成的 libhello-jni.so 文件存放在当前目录的 libs/armeabi 目录下

4、  我们可以将这个生成的 libhello-jni.so 放在 Android 源代码的适当的位置即可使用了

下面是相应的文件

hello-jni.c

 

#include <string.h>
#include <jni.h>
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                  jobject thiz )
{
    return (*env)->NewStringUTF(env, "Hello from JNI !");
}
 

 

Android.mk 文件

 

LOCAL_PATH := $(call my-dir)
 
include $(CLEAR_VARS)
 
LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c
 
include $(BUILD_SHARED_LIBRARY)
 

 

由于这里只是使用了一个简单的 C 文件,所以没用用到 Application.mk 文件

然后将 hello-jni 导入到 eclipse 中,运行模拟器,即可显示


下面再看一个例子 native-activity

1、  进入目录后执行 $NDK/ndk-build

2、  生成 libnative_activity.so 并存于当前目录的 lib/armeabi 目录下,另外由源代码生成的还有静态库,存放于 obj/local/armeabi/ libandroid_native_app_glue.a

这里,由于 main.c 比较大,就不贴上了

Android.mk

 

LOCAL_PATH := $(call my-dir)
 
include $(CLEAR_VARS)
 
LOCAL_MODULE    := native-activity
LOCAL_SRC_FILES := main.c
LOCAL_LDLIBS    := -llog -landroid -lEGL -lGLESv1_CM
LOCAL_STATIC_LIBRARIES := android_native_app_glue
 
include $(BUILD_SHARED_LIBRARY)
 
$(call import-module,android/native_app_glue)

 

Application.mk

 

APP_PLATFORM := android-10 

 

 

运行结果:颜色会逐渐变浅,然后再次从这个颜色变浅



 

 

4、增加apk文件(有源代码)

 

如果将 android 程序的源代码加入到 build system 中呢

(1)       eclipse 开发环境中创建你的 android 工程,比如叫做 Success

(2)       将工程拷贝到源代码的 package/apps 目录下

(3)       进入 Success 目录下,创建一个 Android.mk 文件,内容如下

 

LOCAL_PATH :=$(call my-dir)
include $(CLEAR_VARS)
 
LOCAL_MODULE_TAGS :=optional
LOCAL_SRC_FILES :=$(call all-java-files-under, src)
 
LOCAL_PACKAGE_NAME :=(工程名字)
LOCAL_CERTIFICATE :=platform
include $(BUILD_PACKAGE)

 

 

(4)       退回到 android 源代码目录下,执行

#. build/envsetup.sh

#mmm packages/apps/Success

编译成功之后,会在 out/target/product/generic/system/app/Success.apk

(5)       如果要在真机上测试, system 的目录是在 out/target/product/crespo 目录下,编译的时候需要设置一些参数。为了测试,将 crespo 中的 system 记其他内核等文件放入到一个叫做 samsung 的文件夹中,再将 Success.apk 放到 system/app

(6)       #zip –r update.zip . 命令将其打包为 zip ,也可以用 zip 直接压缩

(7)      #java –jar testsign.jar Samsung/update.zip update.zip zip 包签名

(8)       打开手机的 usb 调试,连接到电脑上,在终端输入 #adb push update.zip /sdcard/update.zip ,将 zip 包上传到设备的 sdcard 目录下

(9)       输入 #adb reboot bootloader 进入 bootloader 界面

(10)   输入 #fastboot flash recovery recovery.img recovery, 我刷的是 Recovery 3.0

(11)   进入 Recovery 选项,刷机,重启后就可以见到 Success.apk 程序了

注意:修改 AndroidManifest.xml ,在 manifest 标签中加入 android:sharedUserId=”media” ,当然这个 media 只是个 id ,它的名字随便一般类似包名。我们知道,在不同的 apk 包中默认是不能相互访问数据的,但是如果在 AndroidManifest.xml 中设置 sharedUserId 并且相同的话,那么这两个包就可以相互访问数据。由于我写的只是个测试程序,所以没有加入这条

 

 

5、增加apk文件(无源代码)

 

(1)      这种方式最简单,就是将 ***.apk 文件拷贝到编译 android 源代码时候生成的 out/target/product/crespo/system/app 中,执行 make snod 后就可以把 apk 添加到 system.img 中了,然后将 system 目录及其他的几个文件打包成 zip 并签名后即可,刷机后可以看到这个内置的系统程序。

(2)       上一种方式在 make clean 之后,再次 make 以后才能执行上述的操作,比较麻烦

     新建一个目录,在 packages/apps 下面,专门用来存放 apk 文件

#mkdir packages/apps/apks

#cd packages/apps/apks

在这个目录中新建一个 Android.mk 文件

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_POST_PROCESS_COMMAND := (shell cp –r $(LOCAL_PATH)/*.apk $(TARGET_OUT)/app/)

保存退出

     把需要编译的 apk 拷贝到 apks 目录中,执行 make ,在 apks 中的 apk 就会被拷贝到 out/target/product/generic/system/app

    执行 make snod 即可

这样,在执行 make clean 之后,再次 make ,只需要 make snod 即可了

 

  • 大小: 6 KB
  • 大小: 5.7 KB
分享到:
评论

相关推荐

    android-4.2-src.zip

    2. **编译源码**:使用Android的Build System (例如,make或repo) 编译源码,了解Android系统的构建过程,这对于定制ROM或开发自定义系统组件至关重要。 3. **系统调用分析**:通过阅读系统服务和库函数的源码,...

    Android-4.3-sources源代码

    7. **编译与构建系统**:Android 使用名为“Bionic”的轻量级 C++ 标准库,以及基于 Makefile 和 Python 的构建系统(Build System)。这个系统负责编译源代码并生成可执行文件和系统映像。 8. **安全性**:Android...

    android5.0 android-21 源码

    Android 5.0源码的学习不仅能够帮助开发者深入理解Android系统,还能为定制ROM、系统优化、漏洞分析等提供宝贵的资料。通过深入研究源码,开发者可以提升自己的技能,创造出更加高效和用户体验优秀的应用或系统。

    android源码编译及rom制作.pptx

    ### Android源码编译及ROM制作 #### 一、概览 在《android源码编译及rom制作.pptx》这份文档中,主要讲解了如何进行Android源码的编译以及ROM的制作过程。这一过程对于那些希望深入了解Android操作系统工作原理、...

    新版Android开发教程.rar

    The sections below describe the system and software requirements for developing Android applications using the Android SDK tools included in Android 1.1 SDK, Release 1. Supported Supported Supported ...

    adb,支持adb disable-verity命令,解锁system分区

    然而,在开发者或高级用户需要对system分区进行修改时(如安装自定义ROM、刷入模块等),verity模式会成为阻碍。这时,就需要使用`adb disable-verity`命令来临时或永久禁用这一安全特性。这个过程通常需要设备处于...

    android-18 sources

    Android源码组织在一个大型的Git仓库中,由多个模块组成,包括kernel(内核)、system(系统)、frameworks(框架)等。其中,`system/core`包含基础库和系统服务,`frameworks/base`包含了大部分Android API,`...

    Android Source_source_android_

    6. **Build System(构建系统)**:如Build.gradle和Makefile,用于编译和打包整个Android系统,开发者可以定制自己的ROM。 接下来,我们重点关注几个关键的模块: **Dalvik和ART**:两者都是Android的运行时环境...

    Android 26源码

    Android 26源码是Android操作系统的一个重要版本,它的源代码揭示了系统内部的工作机制,为开发者提供了深入理解和定制Android...同时,这也为开发者提供了自定义Android系统、开发自定义ROM或构建特定功能模块的基础。

    Android源码——快捷查询源码.zip

    - 查看Android.mk和Android.bp构建文件,了解模块编译配置。 - 阅读官方文档和源码注释,理解代码功能和设计意图。 6. **调试源码**: - 使用`adb logcat`收集日志,`adb shell`进入设备终端。 - Android ...

    android源码

    Android源码是Android操作系统的原始代码,包含了系统运行所需的所有组件和模块,包括核心库、框架服务、HAL(硬件抽象层)、系统应用等。对于开发者来说,深入理解Android源码可以提升开发技能,优化应用程序性能,...

    android sources

    7. **Build System**:Android 使用名为 “build” 的自定义构建系统,用于编译和打包整个系统。`build` 目录包含了构建脚本和配置,开发者可以在此基础上定制自己的 Android 镜像。 8. **Apps**:预装的应用程序,...

    Android SDK 4.2源代码

    6. **工具和构建系统**:例如,Android Asset Packaging Tool (AAPT)用于处理资源,Build System(如Gradle)用于构建应用和系统映像。 使用Eclipse进行连接绑定的步骤大致如下: 1. 安装ADT插件:首先确保Eclipse...

    Android源码下载

    下载完成后,源码会按照模块分布在不同的子目录下,如`platform/frameworks/base`包含了Android的核心框架代码,`platform/system/core`包含了系统核心服务,而`build`目录则包含了构建系统。 要编译源码,你需要...

    android源码开发实战6.08.zip

    - **Build System**:使用Makefile和Android.mk文件,通过mm或mmm命令编译特定模块。 - **环境配置**:包括NDK、SDK、JDK的安装,以及必要的编译工具链。 3. **Android应用程序生命周期**: - **Activity**:...

    Android 源码编译过程

    在本文中,我们将深入探讨如何编译Android源代码,这是Android开发过程中不可或缺的一部分。通过编译源码,你可以自定义系统、修复问题或为设备创建特定的ROM。以下是详细的步骤,分为准备构建环境、获取源码和编译...

    Android,.zip

    - **AOSP(Android Open Source Project)**:Android的开源项目,使用名为mm(make modules)的构建命令来编译单个模块,以及mmm(make multiple modules)来编译多个模块。 - **Gradle**:现代Android开发中广泛...

    android sdk 4.2.2源码包

    6. **Build System(构建系统)**: Android使用Makefile和Gradle构建系统,源码包展示了如何编译和打包整个系统。 对于开发者而言,特别是对系统级开发和优化有兴趣的工程师,研究Android 4.2.2源码能够帮助他们...

    Android系统概述——底层开发的资料

    5. **编译与构建系统**:Android使用Build System来管理源码的编译和打包过程。理解AOSP(Android Open Source Project)的构建流程,可以自定义ROM或进行系统级别的调试。 6. **运行时环境**:Dalvik和ART...

Global site tag (gtag.js) - Google Analytics