剖析安卓build系统的设计思想以及案例模拟

本文探讨了安卓编译系统的组织方式及其背后的设计理念。通过对比单一模块Makefile与多模块Makefile的不同,揭示了模块间依赖关系处理的重要性,并提供了一种改进方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.引言
安卓系统在根目录中只有一个Makefile文件,每个模块只有一个android.mk文件,这是Makefile文件的一个片段,为什么要这么设计呢?这种设计方式解决了什么问题呢?相信读完本文将会找到这些问题的答案。

2.问题的提出
对于一个小菜鸟来说,最先想到的方案是为每个模块写一个makefile,示例工程如下:

Project
  ----Makefile
  ----ant
       ----Makefile
       ----main.c
  ----bee
       ----Makefile
       ----parse.c
       ----parse.h

顶级目录的makefile内容如下:

MODULES = ant bee
all:
    for dir in $(MODULES); do \
        (cd $$dir; $(MAKE) all); \
    done

ant目录下的makefile内容如下:

all: main.o
main.o: main.c ../bee/parse.h
    $(CC) -I../bee -c main.c

bee目录下的makefile内容如下:

OBJ = ../ant/main.o parse.o
all: prog
prog: $(OBJ)
    $(CC) -o $@ $(OBJ)
parse.o: parser.c parse.h
    $(CC) -c parse.c

我们使用DAG来描述ant模块文件依赖关系:
这里写图片描述

同样的,bee模块的文件依赖关系如下:
这里写图片描述

这样我们就构建好2个模块的编译系统,只要make一下就能够得到我们想要的结果,不知道细心的读者是否发现了一个问题:main.o是依赖parse.h的,但是main.o并不清楚parse.h是如何诞生的,毕竟他们是处于两个模块的,两个makefile就像两个房间一样,他们各自身处于自己的空间当中,所以为了暴露这个问题,我们增加如下情景:

bee目录的parse.h和parse.c文件是通过yacc工具自动生成的,也就是我们在bee/Makefile文件增加以下内容来生成parse.h和parse.c文件。依赖关系现在如下:
这里写图片描述

假如我们修改了parse.y文件,然后在工程的根目录下执行make指令,得到的结果是否是我们想要的呢?答案是否定的,且听我细细道来。

make指定一旦执行,就会分别进入每个模块分别进行编译,即执行里面的makefile,那么这里首先进入ant模块,由于仅仅修改parse.y文件,所以main.o不会更新,完蛋啦,因为实际上parse.y更新,parse.h就要更新,进而main.o也是需要更新的,但这里却没有更新,也就是说,prog使用了陈旧的main.o。

问题出在哪里?还是每个模块一个makefile的方案是不对的。
每个模块一个makefile就需要依次编译每个模块,但是模块间又太过于松散,也就是一个模块中的目标可能无法感知依赖的变化,比如ant模块无法感知其依赖的变化(依赖由bee模块生成),一旦先编译了ant模块,那么就会出现我们不想要的结果。

3.改进实现

找到原因之后,那么如何解决呢?其实就是增加模块之间的耦合度,本质上就是让模块之间能够互相感知变化,下面将改进上面的设计,从而帮助我们理解安卓编译系统的设计思想。

改进以后的工程结构如下:
这里写图片描述
示例代码地址如下:
http://download.youkuaiyun.com/detail/getnextwindow/9063217

根目录下面只有一个Makefile文件,ant和bee模块下只有一个makefile片段,depend.sh自动生成头文件依赖的脚本。

Makefile实现如下:

MODULES :=ant bee
CFLAGS +=$(patsubst %,-I %,$(MODULES))
LIBS :=
SRC :=
include $(patsubst %,%/module.mk,$(MODULES))
OBJ:=$(patsubst %.c,%.o,$(filter %.c,$(SRC)))
prog:$(OBJ)
        $(CC) -o $@ $(OBJ) $(LIBS)
include $(OBJ:.o=.d)
%.d: %.c
        depend.sh `dirname $*.c` $(CFLAGS) $*.c >$@
.PHONY :clean
clean:
        rm -f prog $(OBJ) $(OBJ:.o=.d)

bee模块的module.mk文件如下:

SRC += bee/parse.y
LIBS += -ly
%.c %.h: %.y
$(YACC) -d $*.y
mv y.tab.c $*.c
mv y.tab.h $*.h

现在来分析新设计是如何解决前面的问题的,假如我们现在仅仅修改了parse.y文件。

一旦开始执行make命令,会将所有include指令中的文件加载进来,然后才开始根据所有规则产生目标文件。加载进来bee模块的module.mk以后,就会更新parse.c和parse.h,接着就会更新依赖parse.c和parse.h的目标文件,即parse.o、parse.d和main.o,所以这里main.o感知到了变化。

<think>好的,用户需要做一个基于Android的校园自助点餐取餐系统的毕业设计,需要设计方案、示例代码、文档和参考资料。首先,我需要整理系统的核心功能模块,确保覆盖用户需求。然后考虑技术选型,Android开发通常用Kotlin或Java,后端可能需要Spring Boot或Firebase。接着是数据库设计,用户、商家、订单这些表的结构得明确。系统架构方面,分层设计比较清晰,比如表现层、业务逻辑层和数据访问层。 用户可能还需要界面设计的示例,比如登录、菜单展示和订单管理。代码示例部分可以举一个简单的菜品列表适配器,展示RecyclerView的使用。文档结构方面,要包括需求分析、系统设计、测试等部分,符合毕业设计的要求。 然后要生成相关问题,帮助用户深入思考,比如性能优化、支付接口集成、数据同步机制等。需要确保回答结构清晰,引用相关的参考资料,比如提到的Java大作业的引用,可能涉及数据库操作和工程设计规范。另外,引用中的Android Widget开发示例可能对界面设计有帮助,虽然点餐系统不需要Widget,但布局和配置可以参考。校园智能照明系统的传感器数据采集和自动控制思路也可以借鉴到订单状态更新和通知功能中。最后,处理ZIP文件的错误引用可能不相关,但其他引用中的工程设计规范需要注意。</think>### 基于 Android 的校园自助点餐取餐系统设计方案 #### 一、系统核心模块设计 1. **用户端功能** - 用户注册/登录(支持手机号、学号绑定) - 食堂/档口信息展示(地图定位+列表视图) - 在线菜单浏览与分类筛选(支持价格、口味标签) - 购物车管理(实时计算总价) - 订单支付(集成支付宝/微信支付沙箱环境) - 取餐码生成与状态追踪(结合蓝牙/NFC近场通信)[^3] 2. **商家端功能** - 菜品信息管理(增删改查) - 订单实时接收与处理状态标记 - 销售数据分析(日/周/月报表) - 库存预警与自动补货提醒 3. **后台管理功能** - 用户权限分级管理(学生/商户/管理员)[^1] - 系统日志审计 - 优惠活动配置 - 智能推荐算法(基于历史订单) #### 二、技术选型建议 | 层级 | 技术方案 | |-------------|---------------------------------| | 客户端 | Android(Kotlin + Jetpack Compose)| | 服务端 | Spring Boot + MySQL | | 实时通信 | WebSocket/MQTT | | 地图服务 | 高德地图API | | 数据加密 | AES + HTTPS | #### 三、数据库设计示例 ```sql -- 用户表 CREATE TABLE users ( user_id INT PRIMARY KEY AUTO_INCREMENT, student_id VARCHAR(20) UNIQUE, password_hash CHAR(64), balance DECIMAL(10,2) ); -- 订单表(包含时空信息) CREATE TABLE orders ( order_id CHAR(36) PRIMARY KEY, user_id INT, pickup_time DATETIME, geohash CHAR(7), -- 用于空间索引 total_price DECIMAL(10,2), status ENUM('待支付','制作中','可领取','已完成') ); ``` #### 四、界面设计示例 1. **用户主界面** ```xml <!-- 档口列表项 --> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="120dp"> <ImageView android:id="@+id/store_image"/> <TextView android:id="@+id/store_name" android:textStyle="bold"/> <RatingBar android:id="@+id/store_rating" android:numStars="5"/> </androidx.cardview.widget.CardView> ``` 2. **订单状态流程图** ```mermaid graph TD A[订单创建] --> B{支付成功?} B -->|是| C[后厨接单] C --> D[制作完成] D --> E[取餐码激活] E --> F[用户取餐] ``` #### 五、代码示例(核心功能) ```kotlin // 订单状态观察者 class OrderViewModel : ViewModel() { private val _orderState = MutableLiveData<OrderState>() val orderState: LiveData<OrderState> = _orderState fun updateState(newState: OrderState) { viewModelScope.launch { repository.updateOrderState(newState) _orderState.postValue(newState) } } } // 地理围栏检测 private fun setupGeofencing() { val geofence = Geofence.Builder() .setRequestId("canteen_area") .setCircularRegion(39.9042, 116.4074, 100f) .setExpirationDuration(Geofence.NEVER_EXPIRE) .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER) .build() } ``` #### 六、文档结构建议 1. **需求分析文档** - 用户角色用例图 - 非功能需求(并发量≥500TPS,响应时间<2s) 2. **系统设计文档** - 类图(包含Order、User、MenuItem等核心类) - 时序图(支付流程、订单状态变更) 3. **测试文档** - 压力测试方案(使用JMeter模拟高并发) - 安全性测试(SQL注入/XSS防御验证) #### 七、推荐参考资料 1. [《Android应用开发实战》](https://example.com) - 包含完整电商项目案例 2. [《Spring Boot企业级开发》](https://example.com) - 后端API设计参考 3. GitHub开源项目:`SmartCampusDining`(含NFC取餐实现)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值