Android 编译脚本
平常写在android 里面的业务代码,java 还是c++ 都需要靠android 编译脚本来进行编译;在android 的高版本,13,14,谷歌其实是比较推荐我们使用bp 文件来进行编译,但是旧版本的业务还是存在的,所以需要两者都掌握。
Android.mk 基本概念和结构
Android.mk 文件是 Android 构建系统中定义编译规则的配置文件,主要用于描述哪些源文件需要编译,以及如何编译它们。
常见的 Android.mk 文件结构:

- LOCAL_PATH:表示当前模块的路径,通常使用 $(call my-dir)。
- include $(CLEAR_VARS):清除之前定义的所有 LOCAL_ 变量,确保不会影响当前模块。
- LOCAL_MODULE:定义模块名称。
- LOCAL_SRC_FILES:定义模块的源文件。
- include $(BUILD_SHARED_LIBRARY):表示编译为动态库(共享库)。
常用变量
- LOCAL_MODULE:定义模块的名称,即生成的目标文件名(例如 .so 文件或可执行文件)。
- LOCAL_SRC_FILES:指定模块的源代码文件列表,支持 .c、.cpp、.java 等文件。
- LOCAL_C_INCLUDES:指定 C/C++ 头文件路径(包括目录)。
- LOCAL_LDLIBS:指定链接时使用的库(例如 -llog 表示链接 liblog.so)。
- LOCAL_STATIC_LIBRARIES:指定静态链接的库。
编译可执行文件
Android.mk 中除了编译库文件外,还可以编译可执行文件。使用 include $(BUILD_EXECUTABLE) 而不是 BUILD_SHARED_LIBRARY。

静态库和动态库
静态库使用 include $(BUILD_STATIC_LIBRARY),动态库使用 include $(BUILD_SHARED_LIBRARY)。
示例编译静态库:

模块间依赖
模块间的依赖关系可以通过 LOCAL_STATIC_LIBRARIES 或 LOCAL_SHARED_LIBRARIES 实现。例如,一个模块可以依赖另一个库:

常见的编译目标
- include $(BUILD_SHARED_LIBRARY):编译为共享库(.so)。
- include $(BUILD_STATIC_LIBRARY):编译为静态库(.a)。
- include $(BUILD_EXECUTABLE):编译为可执行文件。
编译预处理
可以通过 LOCAL_CFLAGS 和 LOCAL_CPPFLAGS 添加编译时的预处理宏、优化选项或警告级别等。例如:
LOCAL_CFLAGS := -Wall -O2
LOCAL_CPPFLAGS := -DDEBUG=1
多文件编译
在 LOCAL_SRC_FILES 中可以指定多个源文件,分行书写或者以空格隔开:
LOCAL_SRC_FILES := file1.c file2.c file3.c
子目录中的 Android.mk
如果你的项目有多个子目录,可以在顶级 Android.mk 文件中使用 $(call all-subdir-makefiles) 来包含子目录中的 Android.mk:
include $(call all-subdir-makefiles)
Android.mk 实战
目录结构:


- 生成 C++ 静态库
static_lib/hello_static.cpp
#include <iostream>
void print_static_hello(){
std::cout << "Hello from static library!" << std::endl;
}
static_lib/Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libhello_static #定义静态库名称
LOCAL_SRC_FILES := hello_static.cpp #指定源文件
include $(BUILD_STATIC_LIBRARY) #编译目标为静态库
- 生成 C++ 动态库
shared_lib/hello_shared.cpp
#include <iostream>
void print_shared_hello(){
std::cout << "Hello from shared library!" << std::endl;
}
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libhello_shared
LOCAL_SRC_FILES := hello_shared.cpp
include $(BUILD_SHARED_LIBRARY)
- 生成可执行文件并依赖静态库和动态库
executable/main.cpp
#include <iostream>
extern void print_static_hello();
extern void print_shared_hello();
int main(){
print_static_hello();
print_shared_hello();
return 0;
}
executable/Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello_executable
LOCAL_SRC_FILES := main.cpp
LOCAL_STATIC_LIBRARIES := libhello_static
LOCAL_SHARED_LIBRARIES := libhello_shared
include $(BUILD_EXECUTABLE)
编译:
mmm external/project/static_lib
mmm external/project/shared_lib
mmm external/project/executable


调试运行
adb push out/target/product/xxx/system/bin/hello_executable /system/bin/
adb push out/target/product/xxx/system/lib64/libhello_shared.so /system/lib64/
adb shell
cd system/bin/
chmod +x hello_executable
./hello_executable
emulator -verbose -writable-system启动虚拟机
writable-system 表示 system 分区可写

adb root
adb remount

3. 把编译出来的可执行程序放到android 虚拟机上验证
adb push hello_executable /system/bin
adb push hello_executable /system/bin
adb shell



ok,程序执行成功
注意点是,不需要把静态库push 到android 设备,因为静态库会在编译的时候合并到源码里面;但是动态库是运行时链接的
静态库 vs 动态库的主要区别
- 静态库(Static Library)
编译时合并:静态库的代码被完整地复制到最终的可执行文件中
独立性:生成的可执行文件独立,运行时不需要外部库文件
体积大:多个程序使用同一库时,每个程序都包含该库的完整副本
更新麻烦:库更新需要重新编译所有依赖它的程序
- 动态库 (Dynamic Library / Shared Library)
运行时链接:程序运行时才从系统中加载所需的库
共享性:多个程序可以共享同一个动态库实例
体积小:可执行文件体积小,只包含引用信息
更新方便:更新库文件,所有程序自动使用新版本
依赖环境:运行时需要确保系统中存在正确的库版本
Android.bp
- 什么是 Android.bp 文件?
Android.bp 文件是 Android 构建系统的一部分,用于定义模块的构建逻辑。它采用 JSON 类似的语法,简单、结构化,可读性更强。构建系统会根据这些规则生成需要的目标文件。
主要功能:
- 定义模块类型(例如应用程序、库、工具等)。
- 描述模块依赖关系。
- 指定源文件、标志和输出路径。
- Android.bp 文件的语法基础
2.1. 基本结构
模块类型 {
属性名1: "值1",
属性名2: ["值2", "值3"],
}
2.2. 常见数据类型
- 字符串: 用于表示路径或模块名称,使用双引号。
name: "MyModule"
- 列表: 用于存储多个值,用方括号括起。
srcs: ["file1.c", "file2.c"]
- 布尔值: true 或 false,用来表示开关。
enabled: true
- 常见模块类型
定义共享库模块(.so 文件)。
cc_library_shared {
name: "mylib",
srcs: ["mylib.cpp"],
shared_libs: ["liblog"], # 依赖其他共享库
include_dirs: ["include"], # 指定头文件目录
}
3.2. cc_library_static
定义静态库模块(.a 文件)。
cc_library_static {
name: "mylib_static",
srcs: ["mylib_static.cpp"],
}
3.3. cc_binary
定义可执行文件模块。
cc_binary {
name: "mytool",
srcs: ["main.cpp"],
shared_libs: ["liblog"], # 依赖共享库
}
3.4. android_app
定义 APK 模块。
android_app {
name: "MyApp",
srcs: ["src/**/*.java"],
manifest: "AndroidManifest.xml",
static_libs: ["mylib"],
}
- 关键属性解析
4.1. name
模块的唯一名称,必须全局唯一。
name: "MyModule"
4.2. srcs
指定源文件列表,可以包含 C/C++ 文件、Java 文件等。
srcs: ["file1.cpp", "file2.c"]
4.3. shared_libs 和 static_libs
- shared_libs: 声明依赖的共享库(.so 文件)。
- static_libs: 声明依赖的静态库(.a 文件)。
shared_libs: ["liblog", "libc"],
static_libs: ["libmylib"],
4.4. include_dirs
指定头文件搜索路径。
include_dirs: ["include"],
4.5. cflags 和 ldflags
- cflags: 传递给编译器的标志(如优化或警告标志)。
- ldflags: 传递给链接器的标志。
cflags: ["-Wall", "-O2"],
ldflags: ["-lm"],
bp 实战
目录结构

编译和调试运行和上面mk 环节一样,这里就不写了。
3450

被折叠的 条评论
为什么被折叠?



