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
分享到:
相关推荐
2. **编译源码**:使用Android的Build System (例如,make或repo) 编译源码,了解Android系统的构建过程,这对于定制ROM或开发自定义系统组件至关重要。 3. **系统调用分析**:通过阅读系统服务和库函数的源码,...
7. **编译与构建系统**:Android 使用名为“Bionic”的轻量级 C++ 标准库,以及基于 Makefile 和 Python 的构建系统(Build System)。这个系统负责编译源代码并生成可执行文件和系统映像。 8. **安全性**:Android...
Android 5.0源码的学习不仅能够帮助开发者深入理解Android系统,还能为定制ROM、系统优化、漏洞分析等提供宝贵的资料。通过深入研究源码,开发者可以提升自己的技能,创造出更加高效和用户体验优秀的应用或系统。
### Android源码编译及ROM制作 #### 一、概览 在《android源码编译及rom制作.pptx》这份文档中,主要讲解了如何进行Android源码的编译以及ROM的制作过程。这一过程对于那些希望深入了解Android操作系统工作原理、...
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 ...
然而,在开发者或高级用户需要对system分区进行修改时(如安装自定义ROM、刷入模块等),verity模式会成为阻碍。这时,就需要使用`adb disable-verity`命令来临时或永久禁用这一安全特性。这个过程通常需要设备处于...
Android源码组织在一个大型的Git仓库中,由多个模块组成,包括kernel(内核)、system(系统)、frameworks(框架)等。其中,`system/core`包含基础库和系统服务,`frameworks/base`包含了大部分Android API,`...
6. **Build System(构建系统)**:如Build.gradle和Makefile,用于编译和打包整个Android系统,开发者可以定制自己的ROM。 接下来,我们重点关注几个关键的模块: **Dalvik和ART**:两者都是Android的运行时环境...
Android 26源码是Android操作系统的一个重要版本,它的源代码揭示了系统内部的工作机制,为开发者提供了深入理解和定制Android...同时,这也为开发者提供了自定义Android系统、开发自定义ROM或构建特定功能模块的基础。
- 查看Android.mk和Android.bp构建文件,了解模块编译配置。 - 阅读官方文档和源码注释,理解代码功能和设计意图。 6. **调试源码**: - 使用`adb logcat`收集日志,`adb shell`进入设备终端。 - Android ...
Android源码是Android操作系统的原始代码,包含了系统运行所需的所有组件和模块,包括核心库、框架服务、HAL(硬件抽象层)、系统应用等。对于开发者来说,深入理解Android源码可以提升开发技能,优化应用程序性能,...
7. **Build System**:Android 使用名为 “build” 的自定义构建系统,用于编译和打包整个系统。`build` 目录包含了构建脚本和配置,开发者可以在此基础上定制自己的 Android 镜像。 8. **Apps**:预装的应用程序,...
6. **工具和构建系统**:例如,Android Asset Packaging Tool (AAPT)用于处理资源,Build System(如Gradle)用于构建应用和系统映像。 使用Eclipse进行连接绑定的步骤大致如下: 1. 安装ADT插件:首先确保Eclipse...
下载完成后,源码会按照模块分布在不同的子目录下,如`platform/frameworks/base`包含了Android的核心框架代码,`platform/system/core`包含了系统核心服务,而`build`目录则包含了构建系统。 要编译源码,你需要...
- **Build System**:使用Makefile和Android.mk文件,通过mm或mmm命令编译特定模块。 - **环境配置**:包括NDK、SDK、JDK的安装,以及必要的编译工具链。 3. **Android应用程序生命周期**: - **Activity**:...
在本文中,我们将深入探讨如何编译Android源代码,这是Android开发过程中不可或缺的一部分。通过编译源码,你可以自定义系统、修复问题或为设备创建特定的ROM。以下是详细的步骤,分为准备构建环境、获取源码和编译...
- **AOSP(Android Open Source Project)**:Android的开源项目,使用名为mm(make modules)的构建命令来编译单个模块,以及mmm(make multiple modules)来编译多个模块。 - **Gradle**:现代Android开发中广泛...
6. **Build System(构建系统)**: Android使用Makefile和Gradle构建系统,源码包展示了如何编译和打包整个系统。 对于开发者而言,特别是对系统级开发和优化有兴趣的工程师,研究Android 4.2.2源码能够帮助他们...
5. **编译与构建系统**:Android使用Build System来管理源码的编译和打包过程。理解AOSP(Android Open Source Project)的构建流程,可以自定义ROM或进行系统级别的调试。 6. **运行时环境**:Dalvik和ART...