Android FrameWork基础之Makefile

Makefile入门教程(结合Android源码编译用例)

一、引言

Makefile是用于自动化构建项目的工具,尤其在Android源码编译中扮演着至关重要的角色。Makefile文件包含了构建过程中所需的各种规则、依赖关系和命令。通过Makefile,我们可以方便地编译、链接和安装项目。

二、Makefile基础

1. 目标和依赖

Makefile的基本单位是规则,每条规则由目标、冒号和依赖列表组成。目标是要生成的文件,依赖是生成目标所需的文件或条件。

例如,一个简单的Makefile规则可能如下:

hello: hello.c
gcc hello.c -o hello

在这个例子中,hello是目标,hello.c是依赖。当执行make hello时,如果hello.c存在且hello不存在或hellohello.c旧,则会执行gcc hello.c -o hello命令来生成hello

2. 变量

Makefile支持变量,可以方便地替换命令中的重复部分。

CC = gcc
CFLAGS = -Wall
hello: hello.c
$(CC) $(CFLAGS) hello.c -o hello

3. 通配符和模式规则

Makefile支持使用通配符和模式规则来匹配多个文件。

%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@

这条规则表示将所有的.c文件编译成对应的.o文件。$<代表依赖列表中的第一个依赖(即.c文件),$@代表目标(即.o文件)。

三、Android源码编译中的Makefile

Android源码编译是一个复杂的构建过程,涉及大量的Makefile文件。下面以Android源码中的某个模块为例,介绍Makefile的用法。

假设我们有一个简单的Android模块,其目录结构如下:

my_module/
Android.mk
src/
main.c

1. Android.mk文件

在Android源码中,每个模块通常包含一个Android.mk文件,用于描述模块的构建规则。

# 定义LOCAL_PATH为当前目录路径
LOCAL_PATH := $(call my-dir)
# 清除之前定义的变量
include $(CLEAR_VARS)
# 定义模块信息
LOCAL_MODULE := my_module
LOCAL_SRC_FILES := src/main.c
# 包含需要的库文件
LOCAL_SHARED_LIBRARIES := \
libutils \
libcutils
# 定义编译类型
include $(BUILD_SHARED_LIBRARY)
  • LOCAL_PATH:指定当前模块的路径。
  • include $(CLEAR_VARS):清除之前定义的变量,确保每个模块都有自己的独立环境。
  • LOCAL_MODULE:定义模块的名称。
  • LOCAL_SRC_FILES:指定模块的源文件列表。
  • LOCAL_SHARED_LIBRARIES:指定模块依赖的共享库。
  • include $(BUILD_SHARED_LIBRARY):指定编译类型,这里是生成共享库。

2. 构建模块

在Android源码根目录下执行以下命令来构建模块:

source build/envsetup.sh
lunch <target_product>-<target_build_variant>
mmm my_module/
  • source build/envsetup.sh:初始化构建环境。
  • lunch <target_product>-<target_build_variant>:选择构建目标和变体。
  • mmm my_module/:只构建my_module模块。

四、常用指令和函数

1. 条件判断

Makefile支持条件判断,可以根据不同的条件执行不同的命令。

ifeq ($(TARGET_OS),android)
# Android平台相关的设置
else
# 其他平台相关的设置
endif

2. 函数

Makefile提供了一些内置函数,用于处理字符串、文件名等。

my_files := $(wildcard src/*.c) # 匹配src目录下的所有.c文件

3.静态库编译

假设我们有一个简单的C语言项目,需要编译成静态库供其他项目使用。

目录结构:

my_lib/
Android.mk
src/
file1.c
file2.c

Android.mk 文件:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := my_static_lib
LOCAL_SRC_FILES := src/file1.c src/file2.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
include $(BUILD_STATIC_LIBRARY)

在这个例子中,BUILD_STATIC_LIBRARY 宏告诉构建系统生成一个静态库。其他项目可以通过 LOCAL_STATIC_LIBRARIES 变量来链接这个静态库。

4.可执行文件编译

假设我们有一个C语言项目,需要编译成一个可执行文件。

目录结构:

my_tool/
Android.mk
src/
main.c

Android.mk 文件:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := my_tool
LOCAL_SRC_FILES := src/main.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
# 如果需要链接其他库
LOCAL_SHARED_LIBRARIES := \
liblog \
libcutils
include $(BUILD_EXECUTABLE)

在这个例子中,BUILD_EXECUTABLE 宏告诉构建系统生成一个可执行文件。LOCAL_SHARED_LIBRARIES 变量列出了这个可执行文件所依赖的共享库。

5.条件编译

有时候,我们可能需要根据不同的条件来编译不同的源文件或设置不同的编译选项。

Android.mk 文件:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := my_module
ifeq ($(TARGET_ARCH),arm)
LOCAL_SRC_FILES := src/arm/main.c
LOCAL_CFLAGS += -DARM_VERSION
else
LOCAL_SRC_FILES := src/x86/main.c
LOCAL_CFLAGS += -DX86_VERSION
endif
include $(BUILD_SHARED_LIBRARY)

在这个例子中,我们根据目标架构(TARGET_ARCH)来决定使用哪个源文件进行编译,并设置相应的编译选项。

6.使用通配符和模式规则

当项目中有大量的源文件时,使用通配符和模式规则可以简化Makefile的编写。

Android.mk 文件:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := my_module
LOCAL_SRC_FILES := $(wildcard src/*.c)
include $(BUILD_SHARED_LIBRARY)

在这个例子中,$(wildcard src/*.c) 会匹配src目录下所有的.c文件,并将其赋值给LOCAL_SRC_FILES。这样,我们就无需手动列出每一个源文件了。

7.使用变量和函数

Makefile中的变量和函数可以帮助我们更加灵活地处理文件名、路径等。

Android.mk 文件:

LOCAL_PATH := $(call my-dir)
MY_SRC_DIR := $(LOCAL_PATH)/src
MY_INCLUDES := $(LOCAL_PATH)/include
include $(CLEAR_VARS)
LOCAL_MODULE := my_module
LOCAL_SRC_FILES := $(wildcard $(MY_SRC_DIR)/*.c)
LOCAL_C_INCLUDES := $(MY_INCLUDES)
include $(BUILD_SHARED_LIBRARY)

当然可以。Android 源码编译是一个复杂的过程,涉及大量的 Makefile 文件和构建规则。下面我会给出更多结合 Android 源码编译的 Makefile 例子,以便你更好地理解其在实际项目中的应用。

8.编译 Android 应用

假设你有一个简单的 Android 应用,它包含一个 Activity 和一些资源文件。

目录结构:

MyApp/
Android.mk
src/
com/example/myapp/MainActivity.java
res/
... (资源文件)

Android.mk 文件:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# 应用的基本信息
LOCAL_PACKAGE_NAME := MyApp
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_CERTIFICATE := platform
# 依赖的库(如果有的话)
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-v4 \
... (其他库)
include $(BUILD_PACKAGE)

在这个例子中,BUILD_PACKAGE 宏告诉构建系统这是一个 Android 应用的构建规则。LOCAL_SRC_FILES 通过 all-subdir-java-files 函数自动包含 src 目录下的所有 Java 文件。LOCAL_RESOURCE_DIR 指定了资源文件的目录。LOCAL_CERTIFICATE := platform 表示这个应用使用平台签名。

9.编译 Android 服务

如果你正在开发一个 Android 服务,它的构建过程与应用的构建类似,但可能包含一些额外的配置。

目录结构:

MyService/
Android.mk
src/
com/example/myservice/MyService.java
res/
... (资源文件,如果有的话)

Android.mk 文件:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# 服务的基本信息
LOCAL_MODULE := MyService
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PRIVILEGED_MODULE := true # 如果服务需要特权
LOCAL_CERTIFICATE := platform # 使用平台签名
# 依赖的库
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-v4 \
... (其他库)
include $(BUILD_JAVA_LIBRARY) # 构建 Java 库,通常用于服务

在这个例子中,我们使用 BUILD_JAVA_LIBRARY 来构建 Java 库,这通常用于 Android 服务。LOCAL_PRIVILEGED_MODULE := true 表示这个服务需要特权才能运行。

10.编译 Android 本地库(C/C++)

对于包含本地代码(C/C++)的 Android 模块,Makefile 的编写会有所不同。

目录结构:

MyNativeLib/
Android.mk
src/
main.cpp
include/
my_native_lib.h

Android.mk 文件:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# 本地库的基本信息
LOCAL_MODULE := my_native_lib
LOCAL_SRC_FILES := src/main.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_SHARED_LIBRARIES := \
liblog \
libcutils \
... (其他共享库)
# 如果需要编译为静态库,使用 BUILD_STATIC_LIBRARY
# include $(BUILD_STATIC_LIBRARY)
# 如果需要编译为动态库(共享库),使用 BUILD_SHARED_LIBRARY
include $(BUILD_SHARED_LIBRARY)

在这个例子中,我们编译一个本地共享库。LOCAL_SRC_FILES 指定了源文件,LOCAL_C_INCLUDES 指定了头文件的搜索路径,LOCAL_SHARED_LIBRARIES 列出了这个库所依赖的其他共享库。根据需要,你可以选择编译为静态库还是动态库。

五、构建规则和属性

在 Android 构建系统中,Makefile 文件用于定义模块的构建规则和属性。这些 Makefile 文件通常包含一系列的变量和宏,用于指定模块的类型、源文件、依赖关系以及其他构建选项。以下是一些 Android 构建系统中常见的固定 Makefile 属性及其详细解释和示例:

1. LOCAL_PATH

LOCAL_PATH 变量用于定义当前 Makefile 文件所在的目录路径。它通常通过 $(call my-dir) 宏来设置,该宏返回当前 Makefile 文件的目录路径。

示例

LOCAL_PATH := $(call my-dir)

2. include $(CLEAR_VARS)

CLEAR_VARS 是一个预定义的宏,用于清除之前定义的局部变量,以确保当前模块的构建环境是干净的。

示例

include $(CLEAR_VARS)

3. LOCAL_MODULE

LOCAL_MODULE 变量用于定义当前模块的名称。这个名称在构建系统中必须是唯一的。

示例

LOCAL_MODULE := my_module

4. LOCAL_SRC_FILES

LOCAL_SRC_FILES 变量用于指定模块的源文件列表。对于 Java 模块,它通常包含 .java 文件;对于本地库(C/C++),它包含 .c.cpp 等源文件。

Java 模块示例

LOCAL_SRC_FILES := $(call all-subdir-java-files)

本地库示例

LOCAL_SRC_FILES := main.cpp util.cpp

5. LOCAL_C_INCLUDES

LOCAL_C_INCLUDES 变量用于指定 C/C++ 源文件搜索头文件的路径列表。

示例

LOCAL_C_INCLUDES := $(LOCAL_PATH)/include

6. LOCAL_STATIC_JAVA_LIBRARIES

LOCAL_STATIC_JAVA_LIBRARIES 变量用于指定模块所依赖的静态 Java 库列表。

示例

LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4

7. LOCAL_SHARED_LIBRARIES

LOCAL_SHARED_LIBRARIES 变量用于指定模块在运行时所依赖的共享库列表。

示例

LOCAL_SHARED_LIBRARIES := liblog libcutils

8. LOCAL_CERTIFICATE

LOCAL_CERTIFICATE 变量用于指定模块的签名证书。通常用于为系统应用或特权服务指定签名。

示例

LOCAL_CERTIFICATE := platform

9. include $(BUILD_XXX)

BUILD_XXX 是一系列预定义的宏,用于指定模块的构建类型。常见的 BUILD_XXX 宏有 BUILD_PACKAGE(用于构建 APK)、BUILD_JAVA_LIBRARY(用于构建 Java 库)、BUILD_SHARED_LIBRARY(用于构建共享库)等。

构建 APK 示例

include $(BUILD_PACKAGE)

构建本地共享库示例

include $(BUILD_SHARED_LIBRARY)

这些只是 Android 构建系统中 Makefile 的一部分属性。实际上,构建系统提供了更多的变量和宏,以支持各种复杂的构建需求。为了编写有效的 Makefile,通常需要查阅 Android 的构建系统文档和相关的源代码,以了解所有可用的选项和宏。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/750560.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单片机第四季-第一课:RTOS

1&#xff0c;RTOS来龙去脉 操作系统是什么&#xff1f; 以人类社会类比&#xff0c;小公司三四个人都是干活的&#xff0c;大公司有几万人其中有几千人从事管理工作&#xff0c;他们的工作是让其他人的干活效率更高。 51单片机为什么没有操作系统&#xff0c;因为51的性能太…

人脸检测的5种实现方法

众所周知&#xff0c;人脸识别是计算机视觉应用的一个重大领域&#xff0c;在学习人脸识别之前&#xff0c;我们先来简单学习下人脸检测的几种用法。 常见的人脸检测方法大致有5种&#xff0c;Haar、Hog、CNN、SSD、MTCNN&#xff1a; 相关构造检测器的文件&#xff1a;opencv…

服务器机器学习环境搭建(包括AanConda的安装和Pytorch的安装)

服务器机器学习环境搭建 1 服务器与用户 在学校中&#xff0c;我们在学校中是以用户的身份进行访问学校的服务器的。整体框架大致如下&#xff1a; 我们与root用户共享服务器的一些资源&#xff0c;比如显卡驱动&#xff0c;Cuda以及一些其他的公共软件。 一般情况下&#…

力扣新思路题:字符串轮转

非常简单的思路&#xff1a;将两个字符串s1接起来&#xff0c;并判断s2字符串是否是加长版s1字符串的子串 bool isFlipedString(char* s1, char* s2){if (strlen(s1) ! strlen(s2)) {return false;}int len strlen(s1);int i 0;char* arr (char*)malloc(sizeof(char) * len…

Netty之@Sharable注解

1.背景 熟悉Netty的人都了解&#xff0c;netty为每个连接的客户端都会创建一个channel用于通信相关。每个channel都绑定到一条channelpipeline上。而channelpipeline里由一个一个的节点channelhandler组成&#xff08;严格来说是channelhandlercontext&#xff09;。如果为所有…

数据库案例学习20240316-mysql数据库异常处理分析优化过程指南2

一、简介 在开始排错Update之前&#xff0c;我们需要知道 Update 在 MySQL 中的生命周期是什么&#xff0c;MySQL 如何执行一个事务的。理解了如何执行&#xff0c;才知道如何去排查故障。 二、Update 生命周期 Server 层阶段 2.1 连接器 客户端发起一个 TCP 请求后&#xf…

(四)PySpark3:Mlib机器学习实战-信用卡交易数据异常检测

目录 一、Spark Mlib 二、案例背景以及数据集 三、代码 四、总结 PySpark系列文章&#xff1a; &#xff08;一&#xff09;PySpark3&#xff1a;安装教程及RDD编程 &#xff08;二&#xff09;PySpark3&#xff1a;SparkSQL编程 &#xff08;三&#xff09;PySpark3&am…

比特币,区块链及相关概念简介(一)

目录 什么是比特币比特币用来交易什么呢应用场景和黄金的关系相似之处&#xff1a;不同之处&#xff1a; 如果是交易才会有比特币奖励 那第一个持有者是怎么获取的呢 又是怎么交易的呢其他加密货币 以下内容结合了chatgpt 3.5以及网络文章。 用于学习记录。 简介&#xff1a; 介…

C++ filesystem库介绍

filesystem 库源自 boost.filesystem 库,在 C++17 中被合并进 C++ 标准库中。filesystem 库它提供了一组用于处理文件系统操作的类和函数。该库为处理文件、目录和路径提供了简单而强大的接口,使得文件系统操作变得更加方便和可移植。 下面是 <filesystem> 库中一些主…

【蓝桥杯选拔赛真题38】C++判断数字 第十四届蓝桥杯青少年创意编程大赛 算法思维 C++编程选拔赛真题解析

目录 C判断数字 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、推荐资料 C判断数字 第十四届蓝桥杯青少年创意编程大赛C选拔赛真题 一、题目要求 1、编程实现 给定一个正整数N(100≤N<100000)…

nginx实时流量拷贝ngx_http_mirror_module

参考&#xff1a; Module ngx_http_mirror_module Nginx流量拷贝ngx_http_mirror_module模块使用方法详解 ngx_http_mirror_module用于实时流量拷贝 请求一个接口&#xff0c;想实时拷贝这个请求转发到自己的服务上&#xff0c;可以使用ngx_http_mirror_module模块。 官网好像…

(done) NLP “bag-of-words“ 方法 (带有二元分类和多元分类两个例子)词袋模型、BoW

一个视频&#xff1a;https://www.bilibili.com/video/BV1mb4y1y7EB/?spm_id_from333.337.search-card.all.click&vd_source7a1a0bc74158c6993c7355c5490fc600 这里有个视频&#xff0c;讲解得更加生动形象一些 总得来说&#xff0c;词袋模型(Bow, bag-of-words) 是最简…

SpringBoot之yml与properties配置文件格式的区别

概念: SpringBoot支持两种格式的配置文件,一种是yml,而另一种就是properties,默认的文件名为application.yml或者.properties 为什么有了properties之后还要有yml呢? 因为properties配置文件存在数据冗余性,在properties配置文件中一切配置都需要从头写到为, 并且Key不能重复,…

PHP+golang开源办公系统CRM管理系统

基于ThinkPHP6 Layui MySQL的企业办公系统。集成系统设置、人事管理、消息管理、审批管理、日常办公、客户管理、合同管理、项目管理、财务管理、电销接口集成、在线签章等模块。系统简约&#xff0c;易于功能扩展&#xff0c;方便二次开发。 服务器运行环境要求 PHP > 7.…

手搭手RocketMQ发送消息

消息中间件的对比 消息中间件 ActiveMQ RabbitMQ RocketMQ kafka 开发语言 java erlang java scala 单击吞吐量 万级 万级 10万级 10万级 时效性 ms us ms ms 可用性 高(主从架构) 高(主从架构) 非常高(主从架构) 非常高(主从架构) 消息中间件: acti…

LabVIEW湍流等离子体束热效率优化

LabVIEW湍流等离子体束热效率优化 利用LabVIEW虚拟仪器技术&#xff0c;对湍流等离子体束的热效率进行了实时监测与优化&#xff0c;提高其在材料处理领域的应用效率和精度。通过双进气湍流等离子体发生器&#xff0c;实现了在不同工作参数下对热效率的实时在线监测&#xff0…

这是二叉搜索树吗?

一棵二叉搜索树可被递归地定义为具有下列性质的二叉树&#xff1a;对于任一结点&#xff0c; 其左子树中所有结点的键值小于该结点的键值&#xff1b;其右子树中所有结点的键值大于等于该结点的键值&#xff1b;其左右子树都是二叉搜索树。 所谓二叉搜索树的“镜像”&#xf…

Linux|centos7|postgresql数据库|yum和编译方式安装总结(全系版本)

一、 yum方式安装postgresql 这个是官方的yum源&#xff0c;包括postgresql的开发包&#xff0c;lib库什么的&#xff0c;很齐全&#xff0c;关键是包括pgbackrest yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-la…

Luckysheet + Exceljs:H5实现Excel在线编辑、导入、导出及上传服务器的示例代码(完整版demo)

创建xeditor.html <!DOCTYPE html> <html><head><meta charset"UTF-8" /><title>Hello World!</title><!-- <link relstylesheet href./luckysheet/plugins/css/pluginsCss.css /><link relstylesheet href./luck…

【 代码随想录算法训练营第二十四天 | LeetCode77. 组合 】

代码随想录算法训练营第二十四天 | LeetCode77. 组合 一、77. 组合 解题代码C&#xff1a; class Solution { private:vector<vector<int>> result; // 存放符合条件结果的集合vector<int> path; // 用来存放符合条件结果void backtracking(int n, int k, …