理解 Android 的 ONE_SHOT_MAKEFILE

本文深入解析Android源码中mmm编译命令的工作原理,包括如何通过mmm函数定位Android.mk文件并生成带有ONE_SHOT_MAKEFILE参数的make命令。此外,还介绍了如何通过main.mk文件处理ONE_SHOT_MAKEFILE变量,确保仅编译指定模块。

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

使用 mmm 编译的时候 Android 执行的 ONE_SHOT make, 其如何实现?

mmm 的源代码在 build/envsetup.sh 中

function mmm()
    641 {
    642     T=$(gettop)
    643     if [ "$T" ]; then
    644         local MAKEFILE=
    645         local MODULES=
    646         local ARGS=
    647         local DIR TO_CHOP
    648         local DASH_ARGS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^-.*$/')
    649         local DIRS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^[^-].*$/')
    650         for DIR in $DIRS ; do
    651             MODULES=`echo $DIR | sed -n -e 's/.*:\(.*$\)/\1/p' | sed 's/,/ /'`
    652             if [ "$MODULES" = "" ]; then
    653                 MODULES=all_modules
    654             fi
    655             DIR=`echo $DIR | sed -e 's/:.*//' -e 's:/$::'`
    656             if [ -f $DIR/Android.mk ]; then
    657                 TO_CHOP=`(cd -P -- $T && pwd -P) | wc -c | tr -d ' '`
    658                 TO_CHOP=`expr $TO_CHOP + 1`
    659                 START=`PWD= /bin/pwd`
    660                 MFILE=`echo $START | cut -c${TO_CHOP}-`
    661                 if [ "$MFILE" = "" ] ; then
    662                     MFILE=$DIR/Android.mk
    663                 else
    664                     MFILE=$MFILE/$DIR/Android.mk
    665                 fi
    666                 MAKEFILE="$MAKEFILE $MFILE"
    667             else
    668                 if [ "$DIR" = snod ]; then
    669                     ARGS="$ARGS snod"
    670                 elif [ "$DIR" = showcommands ]; then
    671                     ARGS="$ARGS showcommands"
    672                 elif [ "$DIR" = dist ]; then
    673                     ARGS="$ARGS dist"
    674                 elif [ "$DIR" = incrementaljavac ]; then
    675                     ARGS="$ARGS incrementaljavac"
    676                 else
    677                     echo "No Android.mk in $DIR."
    678                     return 1
    679                 fi
    680             fi
    681         done
    682         ONE_SHOT_MAKEFILE="$MAKEFILE" make -C $T $DASH_ARGS $MODULES $ARGS
    683     else
    684         echo "Couldn't locate the top of the tree.  Try setting TOP."
    685     fi
    686 }
但运行下面的命令

mmm sdk/emulator/opengl/tests/translator_tests/GLES_V2

最终生成命令行

ONE_SHOT_MAKEFILE=sdk/emulator/opengl/tests/translator_tests/GLES_V2/Android.mk make -C /home/payne/njb all_modules

注意

ONE_SHOT_MAKEFILE=sdk/emulator/opengl/tests/translator_tests/GLES_V2/Android.mk   是参数

make -C /home/payne/njb all_modules 才是命令

就是说带着 ONE_SHOT_MAKEFILE 的参数去执行 make 命令, 而make的target 是 all_modules

在 build/core/main.mk#467

ifneq ($(ONE_SHOT_MAKEFILE),)
# We've probably been invoked by the "mm" shell function
# with a subdirectory's makefile.
include $(ONE_SHOT_MAKEFILE)
# Change CUSTOM_MODULES to include only modules that were
# defined by this makefile; this will install all of those
# modules as a side-effect.  Do this after including ONE_SHOT_MAKEFILE
# so that the modules will be installed in the same place they
# would have been with a normal make.
CUSTOM_MODULES := $(sort $(call get-tagged-modules,$(ALL_MODULE_TAGS)))
FULL_BUILD :=
# Stub out the notice targets, which probably aren't defined
# when using ONE_SHOT_MAKEFILE.
NOTICE-HOST-%: ;
NOTICE-TARGET-%: ;

当环境变量 ONE_SHOT_MAKEFILE不是空的时候, 就被 include 进来了,此 mk 的 LOCAL_MODULE 也将会让  all_modules 去依赖(加入到变量ALL_MODULES中),这样 make all_modules 的时候,就会先编译依赖的 LOCAL_MODULE了; 当然不相关的 module不会加入到 ALL_MODULES

build/core/main.mk#813

    813 .PHONY: all_modules
    814 all_modules: $(ALL_MODULES)

<think>好的,我现在需要帮助用户在Android环境中配置init.sh脚本以支持通配域名。首先,我得了解用户的具体需求。他们可能希望在init脚本中处理类似*.example.com这样的通配域名,可能是为了动态设置多个子域名的解析或者网络配置。 接下来,我得回忆一下Android系统的初始化流程。Android使用init进程和.rc文件来管理系统服务和启动脚本。用户提到的是init.sh脚本,可能是指某个在启动时执行的shell脚本,但通常自定义脚本需要通过.rc文件来触发执行。因此,首先需要确认如何正确地将init.sh集成到Android的启动流程中。 然后,关于通配域名的配置,可能需要修改DNS解析或者网络规则。在Android中,这通常涉及resolv.conf或者dnsmasq的配置,但具体实现可能因版本而异。另外,iptables规则也可能用于处理网络流量,支持通配域名可能需要使用域名匹配模块,比如xt_domain。但需要注意Android系统的兼容性,因为某些内核模块可能不可用。 接下来,我需要考虑如何让init.sh脚本在启动时运行。可能需要创建一个新的.rc服务,定义服务的执行命令和触发时机。例如,在device.mk中添加一个服务,指定执行init.sh的位置。同时,确保脚本具有可执行权限,并且放在正确的目录下,如/system/etc/init.sh。 然后,处理通配域名的具体配置。如果使用iptables,可能需要添加规则来允许或拒绝特定域名的流量。例如,使用iptables -A OUTPUT -m domain --domain "*.example.com" -j ACCEPT。但需要确认Android内核是否支持domain模块,否则可能需要重新编译内核或模块。 另外,可能需要修改DNS设置,比如在resolv.conf中添加搜索域,但Android通常使用Netd管理网络,直接修改resolv.conf可能不持久。因此,可能需要通过设置系统属性或者使用ndc命令来配置DNS。 还需要考虑SELinux策略的问题,因为自定义脚本和服务可能会被SELinux阻止。需要添加相应的策略规则,允许init进程执行脚本,以及脚本访问相关资源。这可能涉及修改.te文件,添加allow规则,并重新编译sepolicy。 在安全性方面,用户版本可能需要调整,因为user版本通常不允许adb root,而调试可能需要userdebug版本。用户可能需要在编译时选择userdebug类型,或者解锁bootloader来获取root权限,以便修改系统文件。 最后,验证配置是否生效。可能需要重启设备,检查日志中的错误信息,使用iptables -L查看规则,或者通过ping、nslookup测试域名解析。同时,确保所有修改在系统更新后仍然有效,可能需要将更改集成到设备的makefile中,以便在编译时包含这些修改。 总结步骤:1. 创建或修改init.rc服务以执行init.sh;2. 编写init.sh脚本,使用iptables或DNS配置处理通配域名;3. 处理SELinux策略;4. 编译并刷入系统;5. 测试和调试。需要提醒用户注意系统版本和内核支持情况,以及可能需要的编译环境配置。</think>在Android系统中配置`init.sh`脚本以支持通配域名(如`*.example.com`),需结合系统启动流程和网络配置。以下是分步实现方法: --- ### 1. **集成`init.sh`到启动流程** Android的初始化进程通过`.rc`文件管理服务。需在设备Makefile(如`device.mk`)中添加自定义服务: ```makefile # 添加init.sh到系统 PRODUCT_COPY_FILES += \ device/<厂商>/<设备>/init.sh:$(TARGET_COPY_OUT_SYSTEM)/etc/init.sh # 定义启动服务 PRODUCT_SYSTEM_SERVER_JARS += init_custom_domain ``` 在`.rc`文件(如`init.custom.rc`)中定义服务: ```rc service custom_domain /system/bin/sh /system/etc/init.sh class main user root oneshot ``` --- ### 2. **编写`init.sh`脚本** 脚本需实现通配域名支持,例如通过`iptables`规则: ```bash #!/system/bin/sh # 允许所有.example.com子域名的流量 iptables -A OUTPUT -m domain --domain "*.example.com" -j ACCEPT ``` > **注意**:需确认内核支持`xt_domain`模块(通过`grep CONFIG_NETFILTER_XT_MATCH_DOMAIN /proc/config.gz`验证)[^3]。 --- ### 3. **处理SELinux策略** 若SELinux阻止脚本执行,需在策略文件(如`domain.te`)中添加: ```te # 允许init进程执行shell脚本 allow init shell_exec:file { execute }; ``` 并在设备`sepolicy`目录下更新相关规则[^2]。 --- ### 4. **编译与验证** - **编译**:使用`mm`或全系统编译,确保修改的`.rc`、脚本和策略文件被包含[^3]。 - **验证**:重启设备后检查: ```bash adb shell iptables -L -nv | grep "example.com" adb logcat | grep "init.sh" ``` --- ### 5. **通配域名的替代方案** 若`iptables`不支持通配: - **DNS配置**:修改`resolv.conf`或通过`ndc`命令设置DNS: ```bash ndc resolver setnetdns eth0 "" 8.8.8.8 example.com ``` - **Hosts文件**:动态生成`/etc/hosts`条目(需`root`权限)[^4]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值