Android lunch分析以及产品分支构建

article/2025/10/13 4:21:40

转自:http://blog.csdn.net/generalizesoft/article/details/7253901

Android lunch分析以及产品分支构建

一、背景

随着Android应用范围越来越广泛,用户对Android的需求也越来越趋于复杂,在开发Android应用以及底层产品驱动时,往往两套产品所需要的硬件平台就大不相同,而软件功能却相差不大。在这种纷繁的情况下,是否每种产品就需要一套源代码来维护。如果真这么做的话,那工作量就太大了。所以提出了产品分支的概念。在Android源码中提供了这么一种强大的功能。

公司正在Android上针对硬件平台做调整和开发,手上现有多种方案,有的需要无线wifi,有的底层芯片不一致。在这种情况下,公司使用Android lunch的方式使用一套源代码维护多种方案。

二、文档目的

当前网络上没有成体系的对Android lunch调用关系的研究,所以将Android lunch分析以及产品分支构建这份文档共享出来以帮助对此过程不了解的开发者。如有疑问和建议,请留言。

三、Android lunch调用关系

1.      调用流程图:

2.      调用关系分析

在编译Android产品的时候我们首先会导入. build/envsetup.sh ,然后lunch,这时候我们可以看到几个基本的产品版本。

从现象回推,首先查看envsetup.sh文件中的lunch函数:

具体分析见:lunch函数分析

在envsetup.sh中,有几个比较重要的函数。Lunch(),check_product(),print_lunch_menu(),get_build_var(),gettop,add_lunch_combo(),set_stuff_for_environment(),set_java_home(),findmakefile()。

1)  lunch

[plain] view plain copy
  1. functionlunch()  
  2. {  
  3.     local answer  
  4.     if [ "$1" ] ; then  
  5.        # lunch后面直接带参数  
  6.         answer=$1  
  7.     else  
  8.        # lunch后面不带参数,则打印处所有的target product和variant菜单提供用户选择  
  9.         print_lunch_menu    
  10.         echo -n "Which would you like?[generic-eng] "  
  11.         read answer  
  12.     fi  
  13.     local selection=  
  14.     if [ -z "$answer" ]  
  15.     then  
  16.            # 如果用户在菜单中没有选择,直接回车,则为系统缺省的generic-eng  
  17.         selection=generic-eng  
  18.     elif [ "$answer" ="simulator" ]  
  19.     then  
  20.         # 如果是模拟器  
  21.         selection=simulator  
  22.     elif(echo -n $answer | grep -q -e "^[0-9][0-9]*{1}quot;)  
  23.     then  
  24.         # 如果answer是选择菜单的数字,则获取该数字对应的字符串  
  25.         if [ $answer -le${#LUNCH_MENU_CHOICES[@]} ]  
  26.         then  
  27.            selection=${LUNCH_MENU_CHOICES[$(($answer-$_arrayoffset))]}  
  28.         fi  
  29.         # 如果 answer字符串匹配 *-*模式(*的开头不能为-)  
  30.     elif (echo -n $answer | grep -q -e"^[^\-][^\-]*-[^\-][^\-]*{1}quot;)  
  31.   
  32.     then  
  33.         selection=$answer  
  34.     fi  
  35.    
  36.     if [ -z "$selection" ]  
  37.     then  
  38.         echo  
  39.         echo "Invalid lunch combo:$answer"  
  40.         return 1  
  41.     fi  
  42.    
  43.     # special case the simulator  
  44.     if [ "$selection" ="simulator" ]  
  45.     then  
  46.         # 模拟器模式  
  47.         export TARGET_PRODUCT=sim  
  48.         export TARGET_BUILD_VARIANT=eng  
  49.         export TARGET_SIMULATOR=true  
  50.         export TARGET_BUILD_TYPE=debug  
  51.     else  
  52.    
  53.         # 将 product-variant模式种的product分离出来  
  54.         local product=$(echo -n $selection |sed -e "s/-.*$//")  
  55.    
  56.         # 检查product,调用关系 check_product()->get_build_var()->build/core/config.mk  
  57.         check_product $product  
  58.         if [ $? -ne 0 ]  
  59.         then  
  60.             echo  
  61.             echo "** Don't have a productspec for: '$product'"  
  62.             echo "** Do you have the rightrepo manifest?"  
  63.             product=  
  64.         fi  
  65.    
  66.         # 将 product-variant模式种的variant分离出来  
  67.         local variant=$(echo -n $selection | sed-e "s/^[^\-]*-//")  
  68.    
  69.         # 检查之,看看是否在 (user userdebug eng) 范围内  
  70.         check_variant $variant  
  71.         if [ $? -ne 0 ]  
  72.         then  
  73.             echo  
  74.             echo "** Invalid variant:'$variant'"  
  75.             echo "** Must be one of${VARIANT_CHOICES[@]}"  
  76.             variant=  
  77.         fi  
  78.    
  79.         if [ -z "$product" -o -z"$variant" ]  
  80.         then  
  81.             echo  
  82.             return 1  
  83.         fi  
  84.    
  85.         export TARGET_PRODUCT=$product  
  86.         export TARGET_BUILD_VARIANT=$variant  
  87.         export TARGET_SIMULATOR=false  
  88.         export TARGET_BUILD_TYPE=release  
  89.     fi # !simulator  
  90.    


2)  Check_product:

[plain] view plain copy
  1. functioncheck_product()  
  2. {  
  3.     T=$(gettop)  
  4.     if [ ! "$T" ]; then  
  5.         echo "Couldn't locate the top ofthe tree.  Try setting TOP.">&2  
  6.         return  
  7.     fi  
  8.     CALLED_FROM_SETUP=trueBUILD_SYSTEM=build/core \  
  9.         TARGET_PRODUCT=$1 TARGET_BUILD_VARIANT=\  
  10.         TARGET_SIMULATOR= TARGET_BUILD_TYPE= \  
  11.         TARGET_BUILD_APPS= \  
  12.         get_build_varTARGET_DEVICE > /dev/null  
  13.     # hide successful answers, but allow theerrors to show  
  14. }  
检查指定的TARGET_PRODUCT是否允许,默认的有sim和generic。如果不允许,则输出错误信息,允许则不显示

3)  Print_lunch_menu()

[plain] view plain copy
  1. functionprint_lunch_menu()  
  2. {  
  3.     local uname=$(uname)  
  4.     echo  
  5.     echo "You're building on" $uname  
  6.     echo  
  7.     echo "Lunch menu... pick acombo:"  
  8.    
  9.     local i=1  
  10. local choice  
  11. #循环查找LUNCH_MENU_CHOICES中的版本  
  12.     for choice in ${LUNCH_MENU_CHOICES[@]}  
  13.     do  
  14.         echo "     $i. $choice"  
  15.         i=$(($i+1))  
  16.     done  
  17.    
  18.     echo  
  19. }  
该函数负责打印已经定义的版本

4)  Get_build_var()

[plain] view plain copy
  1. functionget_build_var()  
  2. {  
  3.     T=$(gettop)  
  4.     if [ ! "$T" ]; then  
  5.         echo "Couldn't locate the top ofthe tree.  Try setting TOP.">&2  
  6.         return  
  7.     fi  
  8.     CALLED_FROM_SETUP=trueBUILD_SYSTEM=build/core \  
  9.       make --no-print-directory -C"$T" -f build/core/config.mk dumpvar-$1  
  10. }  
列出make脚本中某变量的值,当前为build/core/config.mk

5)  Gettop()

[plain] view plain copy
  1. function gettop  
  2. {  
  3.     local TOPFILE=build/core/envsetup.mk  
  4.     if [ -n "$TOP" -a -f"$TOP/$TOPFILE" ] ; then  
  5.         echo $TOP  
  6. # 如果TOP不为空,并且envsetup.mk存在,函数直接返回TOP对应路径  
  7.     else  
  8.  # 否则(指找不到envsetup.mk)如下处理  
  9.         if [ -f $TOPFILE ] ; then  
  10.             # The following circumlocution(repeated below as well) ensures  
  11.             # that we record the true directoryname and not one that is  
  12.             # faked up with symlink names.  
  13.             PWD= /bin/pwd  
  14.         else  
  15.             # We redirect cd to /dev/null incase it's aliased to  
  16.             # a command that prints somethingas a side-effect  
  17.             # (like pushd)  
  18.             local HERE=$PWD  
  19.             T=  
  20.             while [ \( ! \( -f $TOPFILE \) \)-a \( $PWD != "/" \) ]; do  
  21.                 cd .. > /dev/null  
  22.                 T=`PWD= /bin/pwd`  
  23.             done  
  24.             cd $HERE > /dev/null  
  25.             if [ -f "$T/$TOPFILE" ];then  
  26.                 echo $T  
  27.             fi  
  28.         fi  
  29.     fi  
  30. }  
返回当前android代码树的顶层路径。前提是当前路径位于android代码树中

6)  Add_lunch_combo()

[plain] view plain copy
  1. functionadd_lunch_combo()  
  2. {  
  3.     local new_combo=$1  
  4.     local c  
  5.     for c in ${LUNCH_MENU_CHOICES[@]} ; do  
  6.         if [ "$new_combo" ="$c" ] ; then  
  7.             return  
  8.         fi  
  9.     done  
  10.    LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo)  
  11. }  
向环境变量LUNCH_MENU_CHOICES标识的列表中添加项

7)  Set_stuff_for_environment()

[plain] view plain copy
  1. functionset_stuff_for_environment()  
  2. {  
  3.     settitle  
  4.     set_java_home  
  5.     setpaths  
  6.     set_sequence_number  
  7.   
  8.     export ANDROID_BUILD_TOP=$(gettop)  
  9. }  
设置android编译需要的环境变量

8)  Set_java_home

[plain] view plain copy
  1. functionset_java_home() {  
  2.     if [ ! "$JAVA_HOME" ]; then  
  3.         case `uname -s` in  
  4.             Darwin)  
  5.                 exportJAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home  
  6.                 ;;  
  7.             *)  
  8.                 exportJAVA_HOME=/usr/lib/jvm/java-6-sun  
  9.                 ;;  
  10.         esac  
  11.     fi  
  12. }  
设置java运行环境

9)  findmakefile

[plain] view plain copy
  1. functionfindmakefile()  
  2. {  
  3.     TOPFILE=build/core/envsetup.mk  
  4.     # We redirect cd to /dev/null in case it's aliased to  
  5.     # a command that prints something as a side-effect  
  6.     # (like pushd)  
  7.     local HERE=$PWD  
  8.     T=  
  9.     while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD !="/" \) ]; do  
  10.         T=$PWD  
  11.         if [ -f "$T/Android.mk" ];then  
  12.             echo$T/Android.mk  
  13.             # 如果找到Android.mk,echo出来的全路径将作为函数的返回值赋给某个变量  
  14.             cd $HERE> /dev/null  
  15.             return  
  16.         fi  
  17.         cd .. > /dev/null  
  18.     done  
  19.     cd $HERE > /dev/null  
  20. }  
此外还有一段比较重要的代码
[plain] view plain copy
  1. # Execute thecontents of any vendorsetup.sh files we can find.  
  2. for f in`/bin/ls vendor/*/vendorsetup.sh vendor/*/build/vendorsetup.sh device/*/*/vendorsetup.sh2> /dev/null`  
  3. do  
  4.     echo "including $f"  
  5.     . $f  
  6. done  
  7. unset f  


这段代码寻找vendor,build,device指定目录下的vendorsetup.sh。在vendorsetup.sh中定义了各版本的产品。

 

注:/dev/null 是 Unix/Linux 里的【无底洞】,任何的 output 送去了【无底洞】就再也没了,一般情况下,要是你不想看到 output 或者output 太多太大了,有可能把硬碟给挤爆了的时候,程序的设计就会考虑把 output 送到 /dev/null 了

 

四、Android lunch产品分支构建

背景:南京广义软件有限公司英文名generalizesoft,所以此处使用generalize来命名总的产品目录。其中generalizex和genx则是对公司产品共性的描述。每套产品将差异性的部分定义在自己产品当中。再调用共性的部分,形成一个完整的产品。这样做日后需要维护所有产品的时候只需要维护一套代码,而不是每套产品有一套代码,修改的内容页不方便管理。

1.  目录结构:


2.  搭建步骤

1)  在device目录下创建一个名为generalize的文件夹


2)  对其中的文件分别进行编辑。generalize.mk 对应我们第一套产品的mk文件,这是差异性文件。不同的产品需要不同的mk文件。而generalizex.mk是无差异文件,意为产品的共性。所以在generalize.mk中定义如下,它需要引用generalizex.mk中定义的部分。这样做方便以后的产品差异性对比。同样的,BoardConfigCommon.mk定义了generalize一系列产品板文件的共性。在调用关系中可以看出它们之间的关系


3)  Vendorsetup文件是定义lunch内容的文件。在其中加上我们产品。


4)  上述步骤处理完之后。运行envsetup.sh:

. build/envsetup.sh

之后再使用lunch,就可以看到基础效果图:

 


5)  编译android

             


 



http://chatgpt.dhexx.cn/article/OQDptmjN.shtml

相关文章

Free Lunch is Over (免费午餐已经结束)

原文链接:The Free Lunch Is Over: A Fundamental Turn Toward Concurrency in Software 免费的午餐结束了 软件并行计算的基本转折点 继OO之后软件发展的又一重大变革——并行计算 你的免费午餐即将即将结束。我们能做什么?我们又将做什么&#xff1f…

Free Lunch for Few-Shot Learning: Distribution Calibration(ICLR 2021)

论文笔记 FSL 7】Free Lunch for Few-Shot Learning: Distribution Calibration(ICLR 2021) 下载地址 | 论文源码

2022-11-16 AndroidS 新建产品lunch

一、新建lunch方法 二、实际操作,可以lunch新的菜单。

6-3 There is No Free Lunch (40分)

One day, CYLL found an interesting piece of commercial from newspaper: the Cyber-restaurant was offering a kind of “Lunch Special” which was said that one could “buy one get two for free”. That is, if you buy one of the dishes on their menu, denoted by…

android编译系统分析一:source build/envsetup.sh与lunch

Android编译系统分析系列文章&#xff1a; android编译系统分析一<source build/envsetup.sh与lunch> Android编译系统<二>-mm编译单个模块 android编译系统分析&#xff08;三&#xff09;-make android编译系统&#xff08;四&#xff09;-实战&#xff1a;新增一…

Lesson 2 Breakfast or lunch? 早餐还是午餐?

1.原文 2. 参考译文 3. New words and expressions ★until prep.直到 until用于表示动作、状态等的持续&#xff0c;可译为“一直到……为止”或“在……以前”。在肯定句中&#xff0c;它与表示持续性状态的动词连用&#xff0c;表示持续到某一时刻&#xff1a; I’ll wait…

Android 10 添加 lunch

需求&#xff08;当然这只是其中一个&#xff09;&#xff1a;多个产品用同一个核心板&#xff0c;外设驱动不一样&#xff0c;设备树不一样&#xff0c;开机画面等不一样&#xff0c;如果不添加&#xff0c;就会每次要生成哪个板子就覆盖对应的文件&#xff0c;麻烦不说还容易…

没有免费午餐定理No Free Lunch Theorem

不得不说&#xff0c;网上博客千千万&#xff0c;在技术方面&#xff0c;我承认这些博客的重要性。然而&#xff0c;只要和机器学习理论挂钩&#xff0c;似乎都讲得不清不楚&#xff0c;大家都是各自地抄&#xff0c;抄书籍&#xff0c;抄论文&#xff0c;抄别人的博客或者直接…

没有免费午餐定理(No Free Lunch Theorem)

当我们拿到数据之后&#xff0c;构建机器学习算法的第一步应当是&#xff1a;观察数据&#xff0c;总结规律。 目前由于大数据和深度学习的发展&#xff0c;很多人会认为&#xff0c;只要收集足够多的数据&#xff0c;从网上的开源算法模型中随便找一个&#xff0c;直接将数据丢…

[TIST 2022] No Free Lunch Theorem for Security and Utility in Federated Learning

联邦学习中的安全性和实用性没有免费午餐定理 No Free Lunch Theorem for Security and Utility in Federated Learning 目录 摘要简介2 相关文献2.1 隐私测量2.2 联邦学习2.2.1 FL 中的威胁模型。2.2.2 FL 中的保护机制。 2.3 隐私-实用权衡 3 一般设置和框架3.1 符号3.2 一般…

Andriod中如何新建lunch项

Andriod编译过程一般为&#xff1a; 1.source build/envsetup.sh //加载命令&#xff0c;在项目根目录下&#xff08;~/purple/code/a/A_code20211126/sdm660&#xff09;目录 备注&#xff1a;在envsetup.sh里将执行vendor和device目录及各自子目录下所有的vendorsetup.sh&a…

VS中创建自定义控件

第一步&#xff1a;创建一个ASP.NET WEB应用程序 第二步&#xff1a;在同一个解决方案中创建一个服务控件项目 2.1 再次创建一个asp.net web应用程序。如图&#xff1a; 2.2 然后在这个项目下创建一个Web窗体服务器控件 第三步&#xff1a;编辑为我想要的控件 在这个我这个…

C#自定义控件的设计与调用

在C#下建立自己的控件库&#xff0c;需用到自定义控件的设计与调用。 一、自定义控件的设计 自定义控件&#xff0c;步骤如下&#xff1a; 1.点击文件&#xff0d;&#xff1e;新建项目&#xff0d;&#xff1e;选择Windows控件库2.编辑控件3.点击生成&#xff0d;&#xff1…

树形控件

一&#xff0e;分析过程 1.今天就来说说树形控件&#xff0c;什么是树形控件呢&#xff1f;树形控件在Windows系统中是很常见的&#xff0c;例如资源管理器左侧的窗口中就有用来显示目录的树形视图。 树形视图中以分层结构显示数据&#xff0c;每层的缩进不同&#xff0c;层次越…

WPF基本控件简介

默认可见的基本控件有 1、Border 设置控件画边框&#xff0c;2、Button 按钮 3、Calendar 日历 4、Canvas 画布控件 5、Checkbox 复选框 6、Combobox 下拉列表框 7、ContentControl 内容控件 8、DataGrid 显示表格数据 9、DataPicker 日期选择控件&#xff0c;带日历 10、Dock…

labview自定义控件

创建自定义输入控件、显示控件和自定义类型 目录 LabVIEW 2011帮助 版本日期&#xff1a;June 2011 产品编号&#xff1a;371361H-0118 查看产品信息 下载帮助&#xff08;仅限Windows&#xff09; 自定义输入控件和显示控件是对现有前面板对象集的扩展。用户可创建外观与内置L…

Excel 2010 VBA 入门 124 日期选择控件

目录 码 DTPicker控件 DTPicker控件的时间和日期的切换 DTPicker控件的日期输入方式 DTPicker控件的Value属性与Change事件 使用DTPicker控件实现日期选择并赋值给单元格 注册DTPicker控件 在Excel中&#xff0c;经常需要输入日期。为保证输入正确&#xff0c;可以通过一…

vue日期控件

<el-form-item label"有效期限" ><el-col :span"6"><el-form-item><el-date-pickertype"date"placeholder"选择日期"value-format"yyyy-MM-dd 00:00:00"v-model"effectiveStartTime":picker…

QT 布局,控件自适应大小 自动缩放 自动布局

目录 前言 1. 先来说简单的布局控件自适应 说明我们实现了自动布局&#xff1b; 3.通过代码设置控件自动缩放重写resizeEvent 4. 源码&#xff1a;https://upload.csdn.net/creation/uploadResources/86620882 前言 QT版本&#xff1a;Qt5.12.3(msvc2017_64) 有时&#xf…

WindowsFormsHost控件

WPF和WinForms是两个不同的UI框架&#xff0c;都是由Microsoft创建的。 WPF是WinForms的一个更现代的替代品&#xff0c;WinForms是第一个.NET UI框架。 为了在两者之间轻松过渡&#xff0c;Microsoft确保WinForms控件仍然可以在WPF应用程序中使用。 这是通过WindowsFormsHost完…