Android8.0.0-r4的编译系统

2023-05-16

一、 概述

1.1 编译系统变化

从Android 7.0开始,android的编译系统发生了变化,之前依赖Makefile组织编译系统,从7.0开始逐步引入了kati soong(optional未正式使用,需要USE_SOONG=true开启),将Android.mk文件转化成ninja文件,使用ninja文件对编译系统进行管理。

从8.0开始,android 引入了Android.bp文件来替代之前的Android.mk文件,不同于Android.mk,Android.bp只是纯粹的配置文件,不包括分支、循环等流程控制。在android项目上如何进行选择编译、解析配置、转换成ninja等,Soong就被创造出来,将Android.bp转换为ninja文件进行管理。

同时,Soong还会编译长生一个androidmk命令可以手动将Android.mk转换成Android.bp文件。

1.2 代码位置

Kati的位置是在build/kati/中,平台也自带编译好的ckati

Soong的位置在build/soong,它和build/blueprint同时期作用,他们之间的系统关系如下:

Android.bp --> Blueprint --> Soong --> Ninja

Makefile or Android.mk --> kati --> Ninja

Blueprint是生成、解析Android.bp 的工具,是Soong的一部分。Soong是专门为Android的编译而设计的工具,blueprint只是解析文件的形式,而soong则解释内容的含义。

Blueprint和Soong都是有Go语言写的项目,从7.0开始在prebuilts/go/目录下新增了go语言的运行环境,在编译是使用。

1.3 Android ninja组织

在编译过程中,将所有的android.bp文件搜集成out\soong\build.ninja.d , 并以此为基础生成out\soong\build.ninja规则。

由所有的Android.mk生成build-aosp_arm.ninja文件。通过combined-aosp_arm.ninja将两个文件组织起来。

builddir = out

include out/build-aosp_arm.ninja

include out/soong/build.ninja

build out/combined-aosp_arm.ninja: phony out/soong/build.ninja

通过编译的LOG,首先搜集所有的bp文件生成build.ninja,然后搜集所有的mk文件生成build-aosp-arm.ninja文件。

out/soong/.bootstrap/bin/soong_build out/soong/build.ninja

out/build-aosp_arm-cleanspec.ninja is missing, regenerating...

out/build-aosp_arm.ninja is missing, regenerating...

[1/894] including out/soong/Android-aosp_arm.mk ...

经过试验表明,soong处理后的bp文件生成build.ninja的同时还包含out/soong/Android-aosp_arm.mk,这个文件是编译完成后模块的安装脚本,负责将模块安装到对应位置。比如我们现在处理的vndk相关vendor处理就是在这个目录下进行的。

在out/soong目录下有两个文件.minibootstrap/build.ninja 和.bootstrap/build.ninja两个目录。.minibootstrap/build.ninja 主要是用来编译blueprint和生成.bootstrap/build.ninja。而.bootstrap/build.ninja主要是生成 soong相关工具和out/soong/build.ninja文件。


二 、编译流程

编译步骤如下:

   1、 source build/envsetup.sh:加载命令

   2、 lunch:选择平台编译选项

   3、 make:执行编译

2.1 source build/envsetup.sh

这个命令是用来将envsetup.sh里的所有用到的命令加载到环境变量里去,我们来分析下它。

envsetup.sh里的所有命令如下:

    function hmm() #显示编译命令的帮助信息
    function build_build_var_cache()#获取所需的所有构建变量
    function destroy_build_var_cache()#删除构建变量的缓存
    function get_abs_build_var()#获取构建变量的值昨晚绝对路径
    function check_product()#检查提供的产品是否是我们可以构建的产品
    function check_variant()#检查构建变量的确切值
    function setpaths()#设置文件路径
    function printconfig()#打印配置
    function set_stuff_for_environment()#设置环境变量
    function set_sequence_number()#设置序号
    function settitle()#设置标题
    function addcompletions()#将sdk/bash_completion目录下所有的*.bash文件通过’.’操作导入到当前环境中来
    function choosetype()#根据传入选项或读取用户输入设置编译版本是release还是debug版
    function chooseproduct()#根据预先设置的变量或读取用户输入设置TARGET_PRODUCT
    function choosevariant()#读取用户输入设置TARGET_BUILD_VARIANT为user,userdebug或eng
    function choosecombo()#根据传入的3个参数,分别设置type(release, debug), product和variant(user, userdebug, eng)参数
    function add_lunch_combo()#将提供的编译选项参数添加到LUNCH_MENU_CHOICES列表中
    function print_lunch_menu()#打印编译选项列表LUNCH_MENU_CHOICES的所有项
    function lunch()#操作根据传入参数选项设置TARGET_PRODUCT, TARGET_BUILD_VARIANT和TARGET_BUILD_TYPE
    function _lunch()#提供lunch命令的补全操作
    function tapas()#以交互方式设置单个app编译的build环境变量
    function gettop#函数从指定的$TOP目录或当前目录开始查找build/core/envsetup.mk文件,并将能找到该文件的目录返回给调用函数作为操作的根目录
    function getdriver()#在定义了WITHSTATICANALYZER的情况下,返回用于代码分析工具的一些参数默认编译下WITH_STATIC_ANALYZER没有定义,所以getdriver调用返回空
    function m()#从根目录开始编译
    function findmakefile()#查找当前模块的Android.mk并输出文件的详细路径
    function mm()#编译当前目录下的所有模块,不编译外部依赖
    function mmm()#编译当前目录下的所有模块,编译外部依赖
    function mma()#相当于mm执行相应目录下的all_modules参数
    function mmma()#相当于mmm执行相应目录下的all_modules参数
    function croot()#返回根目录
    function cproj()#用于切换到当前模块的编译目录下(含有Android.mk)
    function qpid()#adb调试类
    function pid()#adb调试类
    function coredump_setup()
    function coredump_enable()
    function core()
    function systemstack()
    function stacks()
    function is64bit()
            function sgrep()#基于(c|h|cc|cpp|S|java|xml|sh|mk|aidl|vts)文件查找
    function gettargetarch#函数返回编译目标系统的CPU架构,如arm
    function ggrep()#基于(.gradle)的文件查找
    function jgrep()#基于(.java)文件查找
    function cgrep()#基于(c|cc|cpp|h|hpp)文件查找
    function resgrep()#基于res目录下(xml)文件查找
    function mangrep()#基于AndroidManifest.xml文件查找
    function sepgrep()#基于sepolicy目录下查找
    function rcgrep()#基于*.rc*文件查找
            function mgrep()#基于(Makefile|Makefile\..*|.*\.make|.*\.mak|.*\.mk)的Makefile文件查找
            function treegrep()#基于代码的文件(c|h|cpp|S|java|xml)进行查找
    function getprebuilt#返回ANDROID_PREBUILTS的路径
    function tracedmdump()
    function runhat()#
    function getbugreports()#得到bug报告
    function getsdcardpath()#得到sd卡路径
    function getscreenshotpath()#得到屏幕路径
    function getlastscreenshot()#得到屏幕焦点
    function startviewserver()#开启view服务
    function stopviewserver()#停止view服务
    function isviewserverstarted()#判断view服务是否开启
    function key_home()#输入键值
    function key_back()#输入键值
    function key_menu()#输入键值
    function smoketest()#冒烟测试
    function runtest()#自动化测试
    function godir ()#函数的用法为”Usage: godir ”,在编译路径下搜索匹配模式的目录,然后跳转到此目录
    function set_java_home()#设置$ANDROID_SET_JAVA_HOME变量
    function pez#函数的参数”$@”是一条可执行命令,通过执行结果来决定打印FAILUE和SUCCESS的颜色,失败打印红色的FAILURE,成功打印绿色的SUCCESS
    function get_make_command()#将make命令转换为command make调用
    function make()
    function provision()

   # add_lunch_combo函数被多次调用,就是它来添加Android编译选项


515unset LUNCH_MENU_CHOICES # 清空LUNCH_MENU_CHOICES变量,用来存在编译选项
516function add_lunch_combo()
517{
518    local new_combo=$1 # 获得add_lunch_combo被调用时的参数
519    local c
520    for c in ${LUNCH_MENU_CHOICES[@]} ; do # 依次遍历LUNCH_MENU_CHOICES里的值,其实该函数第一次调用时,该值为空
521        if [ "$new_combo" = "$c" ] ; then # 如果参数里的值已经存在于LUNCH_MENU_CHOICES变量里,则返回
522            return
523        fi
524    done
525    LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo) # 如果参数的值不存在,则添加到LUNCH_MENU_CHOICES变量里
526}  

  

# 这是系统自动增加的默认编译项
  

528# add the default one here
529add_lunch_combo aosp_arm-eng # 调用上面的add_lunch_combo函数,将aosp_arm-eng作为参数传递过去
530add_lunch_combo aosp_arm64-eng
531add_lunch_combo aosp_mips-eng
532add_lunch_combo aosp_mips64-eng
533add_lunch_combo aosp_x86-eng
534add_lunch_combo aosp_x86_64-eng
535  

  

  

# 从device,vendor,product目录下查找vendorsetup.sh文件,如果查到了,就加载它  

1663
1664# Execute the contents of any vendorsetup.sh files we can find.
1665for f in `test -d device && find -L device -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort` \
1666         `test -d vendor && find -L vendor -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort` \
1667         `test -d product && find -L product -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort`
1668do
1669    echo "including $f" 
1670    . $f  # 执行找到的脚本,其实里面就是厂商自己定义的编译选项
1671done  

envsetup.sh其主要作用如下:

  1. 加载了编译时使用到的函数命令,如:lunch,m,mm,mmm等
  2. 添加编译选项
  3. 查找厂商目录下的vendorsetup.sh,如果存在的话,加载执行它,添加厂商自己定义产品的编译选项
 其实,上述第3条是向编译系统添加了厂商自己定义产品的编译选项,里面的代码就是:add_lunch_combo xxx-xxx。

根据上面的内容,可以推测出,如果要想定义自己的产品编译项,简单的办法是直接在envsetup.sh最后,添加上add_lunch_combo myProduct-eng,当然这么做,不太符合上面代码最后的本意,我们还是老实的在vendor目录下创建自己公司名字,然后在公司目录下创建一个新的vendorsetup.sh,在里面添加上自己的产品编译项

 #mkdir vendor/farsight/
#touch vendor/farsight/vendorsetup.sh
#echo "add_lunch_combo fs100-eng" > vendor/farsight/vendorsetup.sh

这样,当我们在执行source build/envsetup.sh命令的时候,可以在shell上看到下面的信息:

 including vendor/farsight/vendorsetup.sh

2.2 lunch

当然如果你按上述命令执行,它编译的还是通用的eng版本系统,不是我们个性系统,我们可以执行lunch命令,它会打印出一个选择菜单,列出可用的编译选项
如果你按照第一步中添加了vendorsetup.sh那么,你的选项中会出现:
 You're building on Linux
Lunch menu... pick a combo:
     
1. aosp_arm-eng
     2. aosp_arm64-eng
     3. aosp_mips-eng
lunch命令是envsetup.sh里定义的一个命令,用来让用户选择编译项,来定义Product和编译过程中用到的全局变量。
eng是产品的编译类型,除了eng外,还有user, userdebug,分别表示:
eng: 工程机,
user:最终用户机
userdebug:调试测试机
tests:测试机 

eng:  默认的特征. 一个简单的”make”等同于”make eng”. droid 是eng的别名.
安装标记为: eng, debug, user, 以及/或者 development的模块。
安装没有特殊标签的非apk模块。
通过产品定义的文件安装未标记的apk.
ro.secure=0
ro.debuggable=1
ro.kernel.android.checkjni=1
adb默认开启。
user:为release版本的代码特征
安装标签为user的模块.
安装没有特殊标签的非apk模块。
通过产品定义文件安装apk; 对于apk模块来说标签是被忽略的。
ro.secure=1
ro.debuggable=0
adb默认关闭。
userdebug:其他与user相同, 除了:
也安装标签为 debug的模块。
ro.debuggable=1
adb默认开启。

由此可见,除了eng和user外,另外两个一般不能交给最终用户的
那么这四个类型是干什么用的呢?其实,在main.mk里有说明,在Android的源码里,每一个目标(也可以看成工程)目录都有一个Android.mk的makefile,每个目标的Android.mk中有一个类型声明:LOCAL_MODULE_TAGS,这个TAGS就是用来指定,当前的目标编译完了属于哪个分类里。
 PS:Android.mk和Linux里的makefile不太一样,它是Android编译系统自己定义的一个makefile来方便编译成:c,c++的动态、静态库或可执行程序,或java库或android的程序,

lunch命令:


555function lunch()
556{
557    local answer
558
559    if [ "$1" ] ; then
560        answer=$1 # lunch后面直接带参数
561    else
562        print_lunch_menu # lunch后面不带参数,则打印处所有的target product和variant菜单提供用户选择
563        echo -n "Which would you like? [aosp_arm-eng] "
564        read answer
565    fi
566
567    local selection=
568
569    if [ -z "$answer" ]
570    then
571        selection=aosp_arm-eng # 如果用户在菜单中没有选择,直接回车,则为系统缺省的aosp_arm-eng
572    elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
573    then  # 如果answer是选择菜单的数字,则获取该数字对应的字符串
574        if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]
575        then
576            selection=${LUNCH_MENU_CHOICES[$(($answer-1))]}
577        fi
578    else
579        selection=$answer
580    fi
581
582    export TARGET_BUILD_APPS=
583
584    local product variant_and_version variant version
585
586    product=${selection%%-*} # Trim everything up to first dash
587    variant_and_version=${selection#*-} # Trim everything up to first dash
588    if [ "$variant_and_version" != "$selection" ]; then
589        variant=${variant_and_version%%-*}
590        if [ "$variant" != "$variant_and_version" ]; then
591            version=${variant_and_version#*-}
592        fi
593    fi
594
595    if [ -z "$product" ]
596    then
597        echo
598        echo "Invalid lunch combo: $selection"
599        return 1
600    fi
601
602    TARGET_PRODUCT=$product \
603    TARGET_BUILD_VARIANT=$variant \
604    TARGET_PLATFORM_VERSION=$version \
605    build_build_var_cache
606    if [ $? -ne 0 ]
607    then
608        return 1
609    fi
610    #  导出环境变量,这里很重要,因为后面的编译系统都是依赖于这里定义的几个变量的
611    export TARGET_PRODUCT=$(get_build_var TARGET_PRODUCT)
612    export TARGET_BUILD_VARIANT=$(get_build_var TARGET_BUILD_VARIANT)
613    export TARGET_PLATFORM_VERSION=$(get_build_var TARGET_PLATFORM_VERSION)
614    export TARGET_BUILD_TYPE=release
615
616    echo
617    # 设置到环境变量
618    set_stuff_for_environment
619    printconfig  # 打印一些主要的变量, 调用关系 printconfig()->get_build_var()->build/core/config.mk->build/core/envsetup.mk
620    destroy_build_var_cache
621}
622  
lunch命令可以带参数和不带参数,最终导出一些重要的环境变量,从而影响编译系统的编译结果

2.3 make 流程

2.3.1 Makefile文件

执行make命令的结果就是去执行当前目录下的Makefile文件


1### DO NOT EDIT THIS FILE ###
2include build/core/main.mk
3### DO NOT EDIT THIS FILE ###  

main.mk文件里虽然脚本不多,但是却定义了整个Android的编译关系,它主要引入了下列几个重要的mk文件


49include $(BUILD_SYSTEM)/config.mk  

  

86include $(BUILD_SYSTEM)/cleanbuild.mk  

  

273include $(BUILD_SYSTEM)/definitions.mk  

  

  

  

  


所有的Makefile都通过build/core/main.mk这个文件组织在一起,它定义了一个默认goals:droid,当在根目录下,输入make实际上就等同于我们执行make droid。

当Make include所有的文件,完成对所有make文件的解析以后就会寻找生成droid的规则,依次生成它的依赖,直到所有满足的模块被编译好,然后使用相应的工具打包成相应的img。其中,config.mk,envsetup.mk,product_config.mk文件是编译用户指定平台系统的关键文件。上图中红色部分是用户指定平台产品的编译主线,下面config.mk的主要作用

2.3.2 build/core/config.mk

该文件被main.mk包含
定义了以下环境变量:


74SRC_TARGET_DIR := $(TOPDIR)build/target
75SRC_API_DIR := $(TOPDIR)prebuilts/sdk/api
76SRC_SYSTEM_API_DIR := $(TOPDIR)prebuilts/sdk/system-api
77SRC_TEST_API_DIR := $(TOPDIR)prebuilts/sdk/test-api
78
79# Some specific paths to tools
80SRC_DROIDDOC_DIR := $(TOPDIR)build/tools/droiddoc
81
82# Set up efficient math functions which are used in make.
83# Here since this file is included by envsetup as well as during build.
84include $(BUILD_SYSTEM)/math.mk
85
86# Various mappings to avoid hard-coding paths all over the place
87include $(BUILD_SYSTEM)/pathmap.mk
88
89# ###############################################################
90# Build system internal files
91# ###############################################################
92
93BUILD_COMBOS:= $(BUILD_SYSTEM)/combo
94
95CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk
96BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk
97BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk
98BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk
99BUILD_HEADER_LIBRARY:= $(BUILD_SYSTEM)/header_library.mk
100BUILD_AUX_STATIC_LIBRARY:= $(BUILD_SYSTEM)/aux_static_library.mk
101BUILD_AUX_EXECUTABLE:= $(BUILD_SYSTEM)/aux_executable.mk
102BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk
103BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk
104BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk
105BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk
106BUILD_PHONY_PACKAGE:= $(BUILD_SYSTEM)/phony_package.mk
107BUILD_RRO_PACKAGE:= $(BUILD_SYSTEM)/build_rro_package.mk
108BUILD_HOST_PREBUILT:= $(BUILD_SYSTEM)/host_prebuilt.mk
109BUILD_PREBUILT:= $(BUILD_SYSTEM)/prebuilt.mk
110BUILD_MULTI_PREBUILT:= $(BUILD_SYSTEM)/multi_prebuilt.mk
111BUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mk
112BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk
113BUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mk
114BUILD_DROIDDOC:= $(BUILD_SYSTEM)/droiddoc.mk
115BUILD_COPY_HEADERS := $(BUILD_SYSTEM)/copy_headers.mk
116BUILD_NATIVE_TEST := $(BUILD_SYSTEM)/native_test.mk
117BUILD_NATIVE_BENCHMARK := $(BUILD_SYSTEM)/native_benchmark.mk
118BUILD_HOST_NATIVE_TEST := $(BUILD_SYSTEM)/host_native_test.mk
119BUILD_FUZZ_TEST := $(BUILD_SYSTEM)/fuzz_test.mk
120BUILD_HOST_FUZZ_TEST := $(BUILD_SYSTEM)/host_fuzz_test.mk
121
122BUILD_SHARED_TEST_LIBRARY := $(BUILD_SYSTEM)/shared_test_lib.mk
123BUILD_HOST_SHARED_TEST_LIBRARY := $(BUILD_SYSTEM)/host_shared_test_lib.mk
124BUILD_STATIC_TEST_LIBRARY := $(BUILD_SYSTEM)/static_test_lib.mk
125BUILD_HOST_STATIC_TEST_LIBRARY := $(BUILD_SYSTEM)/host_static_test_lib.mk
126
127BUILD_NOTICE_FILE := $(BUILD_SYSTEM)/notice_files.mk
128BUILD_HOST_DALVIK_JAVA_LIBRARY := $(BUILD_SYSTEM)/host_dalvik_java_library.mk
129BUILD_HOST_DALVIK_STATIC_JAVA_LIBRARY := $(BUILD_SYSTEM)/host_dalvik_static_java_library.mk  

  

上述命令变量其实是对应的mk文件名,所有的Android.mk文件里基本上都包含上述命令变量,如  
         CLEAR_VARS:用来清除之前定义的环境变量
         BUILD_SHARED_LIBRARY:用来指定编译动态库过程


184include $(BUILD_SYSTEM)/envsetup.mk  

2.3.3 build/core/envsetup.mk


84# was invoked with a PRODUCT-xxx-yyy goal.
85ifeq ($(TARGET_PRODUCT),) #判断TARGET_PRODUCT是否为空
86TARGET_PRODUCT := aosp_arm
87endif  

  

91ifeq ($(strip $(TARGET_BUILD_VARIANT)),)
92TARGET_BUILD_VARIANT := eng
93endif  

  

  

189include $(BUILD_SYSTEM)/product_config.mk  

  

  

282# ---------------------------------------------------------------
283# figure out the output directories
284
285ifeq (,$(strip $(OUT_DIR)))
286ifeq (,$(strip $(OUT_DIR_COMMON_BASE)))
287OUT_DIR := $(TOPDIR)out
288else
289OUT_DIR := $(OUT_DIR_COMMON_BASE)/$(notdir $(PWD))
290endif
291endif
292
293SOONG_OUT_DIR := $(OUT_DIR)/soong
294
295DEBUG_OUT_DIR := $(OUT_DIR)/debug
296
297# Move the host or target under the debug/ directory
298# if necessary.
299TARGET_OUT_ROOT_release := $(OUT_DIR)/target
300TARGET_OUT_ROOT_debug := $(DEBUG_OUT_DIR)/target
301TARGET_OUT_ROOT := $(TARGET_OUT_ROOT_$(TARGET_BUILD_TYPE))
302
303HOST_OUT_ROOT_release := $(OUT_DIR)/host
304HOST_OUT_ROOT_debug := $(DEBUG_OUT_DIR)/host
305HOST_OUT_ROOT := $(HOST_OUT_ROOT_$(HOST_BUILD_TYPE))
306
307# We want to avoid two host bin directories in multilib build.
308HOST_OUT_release := $(HOST_OUT_ROOT_release)/$(HOST_OS)-$(HOST_PREBUILT_ARCH)
309HOST_OUT_debug := $(HOST_OUT_ROOT_debug)/$(HOST_OS)-$(HOST_PREBUILT_ARCH)
310HOST_OUT := $(HOST_OUT_$(HOST_BUILD_TYPE))
311SOONG_HOST_OUT := $(SOONG_OUT_DIR)/host/$(HOST_OS)-$(HOST_PREBUILT_ARCH)
312# TODO: remove
313BUILD_OUT := $(HOST_OUT)
314
315HOST_CROSS_OUT_release := $(HOST_OUT_ROOT_release)/windows-$(HOST_PREBUILT_ARCH)
316HOST_CROSS_OUT_debug := $(HOST_OUT_ROOT_debug)/windows-$(HOST_PREBUILT_ARCH)
317HOST_CROSS_OUT := $(HOST_CROSS_OUT_$(HOST_BUILD_TYPE))
318
319TARGET_PRODUCT_OUT_ROOT := $(TARGET_OUT_ROOT)/product
320
321TARGET_COMMON_OUT_ROOT := $(TARGET_OUT_ROOT)/common
322HOST_COMMON_OUT_ROOT := $(HOST_OUT_ROOT)/common
323
324PRODUCT_OUT := $(TARGET_PRODUCT_OUT_ROOT)/$(TARGET_DEVICE)
325
326OUT_DOCS := $(TARGET_COMMON_OUT_ROOT)/docs
327
328BUILD_OUT_EXECUTABLES := $(BUILD_OUT)/bin
329SOONG_HOST_OUT_EXECUTABLES := $(SOONG_HOST_OUT)/bin
330
331HOST_OUT_EXECUTABLES := $(HOST_OUT)/bin
332HOST_OUT_SHARED_LIBRARIES := $(HOST_OUT)/lib64
333HOST_OUT_RENDERSCRIPT_BITCODE := $(HOST_OUT_SHARED_LIBRARIES)
334HOST_OUT_JAVA_LIBRARIES := $(HOST_OUT)/framework
335HOST_OUT_SDK_ADDON := $(HOST_OUT)/sdk_addon
336HOST_OUT_NATIVE_TESTS := $(HOST_OUT)/nativetest64
337HOST_OUT_COVERAGE := $(HOST_OUT)/coverage
338
339HOST_CROSS_OUT_EXECUTABLES := $(HOST_CROSS_OUT)/bin
340HOST_CROSS_OUT_SHARED_LIBRARIES := $(HOST_CROSS_OUT)/lib
341HOST_CROSS_OUT_NATIVE_TESTS := $(HOST_CROSS_OUT)/nativetest
342HOST_CROSS_OUT_COVERAGE := $(HOST_CROSS_OUT)/coverage
343HOST_OUT_TESTCASES := $(HOST_OUT)/testcases
344
345HOST_OUT_INTERMEDIATES := $(HOST_OUT)/obj
346HOST_OUT_INTERMEDIATE_LIBRARIES := $(HOST_OUT_INTERMEDIATES)/lib
347HOST_OUT_NOTICE_FILES := $(HOST_OUT_INTERMEDIATES)/NOTICE_FILES
348HOST_OUT_COMMON_INTERMEDIATES := $(HOST_COMMON_OUT_ROOT)/obj
349HOST_OUT_FAKE := $(HOST_OUT)/fake_packages
350
351# Nano environment config
352include $(BUILD_SYSTEM)/aux_config.mk
353
354HOST_CROSS_OUT_INTERMEDIATES := $(HOST_CROSS_OUT)/obj
355HOST_CROSS_OUT_INTERMEDIATE_LIBRARIES := $(HOST_CROSS_OUT_INTERMEDIATES)/lib
356HOST_CROSS_OUT_NOTICE_FILES := $(HOST_CROSS_OUT_INTERMEDIATES)/NOTICE_FILES
357
358HOST_OUT_GEN := $(HOST_OUT)/gen
359HOST_OUT_COMMON_GEN := $(HOST_COMMON_OUT_ROOT)/gen
360
361HOST_CROSS_OUT_GEN := $(HOST_CROSS_OUT)/gen
362
363# Out for HOST_2ND_ARCH
364HOST_2ND_ARCH_VAR_PREFIX := 2ND_
365HOST_2ND_ARCH_MODULE_SUFFIX := _32
366$(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_INTERMEDIATES := $(HOST_OUT)/obj32
367$(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_INTERMEDIATE_LIBRARIES := $($(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_INTERMEDIATES)/lib
368$(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_SHARED_LIBRARIES := $(HOST_OUT)/lib
369$(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_EXECUTABLES := $(HOST_OUT_EXECUTABLES)
370$(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_JAVA_LIBRARIES := $(HOST_OUT_JAVA_LIBRARIES)
371$(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_NATIVE_TESTS := $(HOST_OUT)/nativetest
372$(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_TESTCASES := $(HOST_OUT_TESTCASES)
373
374# The default host library path.
375# It always points to the path where we build libraries in the default bitness.
376HOST_LIBRARY_PATH := $(HOST_OUT_SHARED_LIBRARIES)
377
378# Out for HOST_CROSS_2ND_ARCH
379HOST_CROSS_2ND_ARCH_VAR_PREFIX := 2ND_
380HOST_CROSS_2ND_ARCH_MODULE_SUFFIX := _64
381$(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_OUT_INTERMEDIATES := $(HOST_CROSS_OUT)/obj64
382$(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_OUT_INTERMEDIATE_LIBRARIES := $($(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_OUT_INTERMEDIATES)/lib
383$(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_OUT_SHARED_LIBRARIES := $(HOST_CROSS_OUT)/lib64
384$(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_OUT_EXECUTABLES := $(HOST_CROSS_OUT_EXECUTABLES)
385$(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_OUT_NATIVE_TESTS := $(HOST_CROSS_OUT)/nativetest64
386
387TARGET_OUT_INTERMEDIATES := $(PRODUCT_OUT)/obj
388TARGET_OUT_HEADERS := $(TARGET_OUT_INTERMEDIATES)/include
389TARGET_OUT_INTERMEDIATE_LIBRARIES := $(TARGET_OUT_INTERMEDIATES)/lib
390TARGET_OUT_COMMON_INTERMEDIATES := $(TARGET_COMMON_OUT_ROOT)/obj
391
392TARGET_OUT_GEN := $(PRODUCT_OUT)/gen
393TARGET_OUT_COMMON_GEN := $(TARGET_COMMON_OUT_ROOT)/gen
394
395TARGET_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_SYSTEM)
396ifneq ($(filter address,$(SANITIZE_TARGET)),)
397target_out_shared_libraries_base := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ASAN)/system
398else
399target_out_shared_libraries_base := $(TARGET_OUT)
400endif
401
402TARGET_OUT_EXECUTABLES := $(TARGET_OUT)/bin
403TARGET_OUT_OPTIONAL_EXECUTABLES := $(TARGET_OUT)/xbin
404ifeq ($(TARGET_IS_64_BIT),true)
405# /system/lib always contains 32-bit libraries,
406# and /system/lib64 (if present) always contains 64-bit libraries.
407TARGET_OUT_SHARED_LIBRARIES := $(target_out_shared_libraries_base)/lib64
408else
409TARGET_OUT_SHARED_LIBRARIES := $(target_out_shared_libraries_base)/lib
410endif
411TARGET_OUT_RENDERSCRIPT_BITCODE := $(TARGET_OUT_SHARED_LIBRARIES)
412TARGET_OUT_JAVA_LIBRARIES := $(TARGET_OUT)/framework
413TARGET_OUT_APPS := $(TARGET_OUT)/app
414TARGET_OUT_APPS_PRIVILEGED := $(TARGET_OUT)/priv-app
415TARGET_OUT_KEYLAYOUT := $(TARGET_OUT)/usr/keylayout
416TARGET_OUT_KEYCHARS := $(TARGET_OUT)/usr/keychars
417TARGET_OUT_ETC := $(TARGET_OUT)/etc
418TARGET_OUT_NOTICE_FILES := $(TARGET_OUT_INTERMEDIATES)/NOTICE_FILES
419TARGET_OUT_FAKE := $(PRODUCT_OUT)/fake_packages
420TARGET_OUT_TESTCASES := $(PRODUCT_OUT)/testcases
421
422TARGET_OUT_SYSTEM_OTHER := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_SYSTEM_OTHER)
423
424# Out for TARGET_2ND_ARCH
425TARGET_2ND_ARCH_VAR_PREFIX := $(HOST_2ND_ARCH_VAR_PREFIX)
426ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
427# With this you can reference the arm binary translation library with libfoo_arm in PRODUCT_PACKAGES.
428TARGET_2ND_ARCH_MODULE_SUFFIX := _$(TARGET_2ND_ARCH)
429else
430TARGET_2ND_ARCH_MODULE_SUFFIX := $(HOST_2ND_ARCH_MODULE_SUFFIX)
431endif
432$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_INTERMEDIATES := $(PRODUCT_OUT)/obj_$(TARGET_2ND_ARCH)
433$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_INTERMEDIATE_LIBRARIES := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_INTERMEDIATES)/lib
434ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
435$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_SHARED_LIBRARIES := $(target_out_shared_libraries_base)/lib/$(TARGET_2ND_ARCH)
436else
437$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_SHARED_LIBRARIES := $(target_out_shared_libraries_base)/lib
438endif
439$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_RENDERSCRIPT_BITCODE := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_SHARED_LIBRARIES)
440$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_EXECUTABLES := $(TARGET_OUT_EXECUTABLES)
441$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_APPS := $(TARGET_OUT_APPS)
442$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_APPS_PRIVILEGED := $(TARGET_OUT_APPS_PRIVILEGED)
443$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_TESTCASES := $(TARGET_OUT_TESTCASES)
444
445TARGET_OUT_DATA := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_DATA)
446TARGET_OUT_DATA_EXECUTABLES := $(TARGET_OUT_EXECUTABLES)
447TARGET_OUT_DATA_SHARED_LIBRARIES := $(TARGET_OUT_SHARED_LIBRARIES)
448TARGET_OUT_DATA_JAVA_LIBRARIES := $(TARGET_OUT_DATA)/framework
449TARGET_OUT_DATA_APPS := $(TARGET_OUT_DATA)/app
450TARGET_OUT_DATA_KEYLAYOUT := $(TARGET_OUT_KEYLAYOUT)
451TARGET_OUT_DATA_KEYCHARS := $(TARGET_OUT_KEYCHARS)
452TARGET_OUT_DATA_ETC := $(TARGET_OUT_ETC)
453ifeq ($(TARGET_IS_64_BIT),true)
454TARGET_OUT_DATA_NATIVE_TESTS := $(TARGET_OUT_DATA)/nativetest64
455TARGET_OUT_DATA_METRIC_TESTS := $(TARGET_OUT_DATA)/benchmarktest64
456else
457TARGET_OUT_DATA_NATIVE_TESTS := $(TARGET_OUT_DATA)/nativetest
458TARGET_OUT_DATA_METRIC_TESTS := $(TARGET_OUT_DATA)/benchmarktest
459endif
460TARGET_OUT_DATA_FAKE := $(TARGET_OUT_DATA)/fake_packages
461
462$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_EXECUTABLES := $(TARGET_OUT_DATA_EXECUTABLES)
463$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_SHARED_LIBRARIES := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_SHARED_LIBRARIES)
464$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_APPS := $(TARGET_OUT_DATA_APPS)
465ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
466$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_NATIVE_TESTS := $(TARGET_OUT_DATA)/nativetest/$(TARGET_2ND_ARCH)
467$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_METRIC_TESTS := $(TARGET_OUT_DATA)/benchmarktest/$(TARGET_2ND_ARCH)
468else
469$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_NATIVE_TESTS := $(TARGET_OUT_DATA)/nativetest
470$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_METRIC_TESTS := $(TARGET_OUT_DATA)/benchmarktest
471endif
472
473TARGET_OUT_CACHE := $(PRODUCT_OUT)/cache
474
475TARGET_OUT_VENDOR := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR)
476ifneq ($(filter address,$(SANITIZE_TARGET)),)
477target_out_vendor_shared_libraries_base := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ASAN)/vendor
478else
479target_out_vendor_shared_libraries_base := $(TARGET_OUT_VENDOR)
480endif
481
482TARGET_OUT_VENDOR_EXECUTABLES := $(TARGET_OUT_VENDOR)/bin
483TARGET_OUT_VENDOR_OPTIONAL_EXECUTABLES := $(TARGET_OUT_VENDOR)/xbin
484ifeq ($(TARGET_IS_64_BIT),true)
485TARGET_OUT_VENDOR_SHARED_LIBRARIES := $(target_out_vendor_shared_libraries_base)/lib64
486else
487TARGET_OUT_VENDOR_SHARED_LIBRARIES := $(target_out_vendor_shared_libraries_base)/lib
488endif
489TARGET_OUT_VENDOR_RENDERSCRIPT_BITCODE := $(TARGET_OUT_VENDOR_SHARED_LIBRARIES)
490TARGET_OUT_VENDOR_JAVA_LIBRARIES := $(TARGET_OUT_VENDOR)/framework
491TARGET_OUT_VENDOR_APPS := $(TARGET_OUT_VENDOR)/app
492TARGET_OUT_VENDOR_APPS_PRIVILEGED := $(TARGET_OUT_VENDOR)/priv-app
493TARGET_OUT_VENDOR_ETC := $(TARGET_OUT_VENDOR)/etc
494
495$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_EXECUTABLES := $(TARGET_OUT_VENDOR_EXECUTABLES)
496ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
497$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_SHARED_LIBRARIES := $(target_out_vendor_shared_libraries_base)/lib/$(TARGET_2ND_ARCH)
498else
499$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_SHARED_LIBRARIES := $(target_out_vendor_shared_libraries_base)/lib
500endif
501$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_RENDERSCRIPT_BITCODE := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_SHARED_LIBRARIES)
502$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_APPS := $(TARGET_OUT_VENDOR_APPS)
503$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_APPS_PRIVILEGED := $(TARGET_OUT_VENDOR_APPS_PRIVILEGED)
504
505TARGET_OUT_OEM := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_OEM)
506TARGET_OUT_OEM_EXECUTABLES := $(TARGET_OUT_OEM)/bin
507ifeq ($(TARGET_IS_64_BIT),true)
508TARGET_OUT_OEM_SHARED_LIBRARIES := $(TARGET_OUT_OEM)/lib64
509else
510TARGET_OUT_OEM_SHARED_LIBRARIES := $(TARGET_OUT_OEM)/lib
511endif
512# We don't expect Java libraries in the oem.img.
513# TARGET_OUT_OEM_JAVA_LIBRARIES:= $(TARGET_OUT_OEM)/framework
514TARGET_OUT_OEM_APPS := $(TARGET_OUT_OEM)/app
515TARGET_OUT_OEM_ETC := $(TARGET_OUT_OEM)/etc
516
517$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_OEM_EXECUTABLES := $(TARGET_OUT_OEM_EXECUTABLES)
518ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
519$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_OEM_SHARED_LIBRARIES := $(TARGET_OUT_OEM)/lib/$(TARGET_2ND_ARCH)
520else
521$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_OEM_SHARED_LIBRARIES := $(TARGET_OUT_OEM)/lib
522endif
523$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_OEM_APPS := $(TARGET_OUT_OEM_APPS)
524
525TARGET_OUT_ODM := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ODM)
526TARGET_OUT_ODM_EXECUTABLES := $(TARGET_OUT_ODM)/bin
527ifeq ($(TARGET_IS_64_BIT),true)
528TARGET_OUT_ODM_SHARED_LIBRARIES := $(TARGET_OUT_ODM)/lib64
529else
530TARGET_OUT_ODM_SHARED_LIBRARIES := $(TARGET_OUT_ODM)/lib
531endif
532TARGET_OUT_ODM_APPS := $(TARGET_OUT_ODM)/app
533TARGET_OUT_ODM_ETC := $(TARGET_OUT_ODM)/etc
534
535$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_EXECUTABLES := $(TARGET_OUT_ODM_EXECUTABLES)
536ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
537$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_SHARED_LIBRARIES := $(TARGET_OUT_ODM)/lib/$(TARGET_2ND_ARCH)
538else
539$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_SHARED_LIBRARIES := $(TARGET_OUT_ODM)/lib
540endif
541$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_APPS := $(TARGET_OUT_ODM_APPS)
542
543TARGET_OUT_BREAKPAD := $(PRODUCT_OUT)/breakpad
544
545TARGET_OUT_UNSTRIPPED := $(PRODUCT_OUT)/symbols
546TARGET_OUT_EXECUTABLES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/system/bin
547TARGET_OUT_SHARED_LIBRARIES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/system/lib
548TARGET_OUT_VENDOR_SHARED_LIBRARIES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/$(TARGET_COPY_OUT_VENDOR)/lib
549TARGET_ROOT_OUT_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)
550TARGET_ROOT_OUT_SBIN_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/sbin
551TARGET_ROOT_OUT_BIN_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/bin
552TARGET_OUT_COVERAGE := $(PRODUCT_OUT)/coverage
553
554TARGET_ROOT_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ROOT)
555TARGET_ROOT_OUT_BIN := $(TARGET_ROOT_OUT)/bin
556TARGET_ROOT_OUT_SBIN := $(TARGET_ROOT_OUT)/sbin
557TARGET_ROOT_OUT_ETC := $(TARGET_ROOT_OUT)/etc
558TARGET_ROOT_OUT_USR := $(TARGET_ROOT_OUT)/usr
559
560TARGET_RECOVERY_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_RECOVERY)
561TARGET_RECOVERY_ROOT_OUT := $(TARGET_RECOVERY_OUT)/root
562
563TARGET_SYSLOADER_OUT := $(PRODUCT_OUT)/sysloader
564TARGET_SYSLOADER_ROOT_OUT := $(TARGET_SYSLOADER_OUT)/root
565TARGET_SYSLOADER_SYSTEM_OUT := $(TARGET_SYSLOADER_OUT)/root/system
566
567TARGET_INSTALLER_OUT := $(PRODUCT_OUT)/installer
568TARGET_INSTALLER_DATA_OUT := $(TARGET_INSTALLER_OUT)/data
569TARGET_INSTALLER_ROOT_OUT := $(TARGET_INSTALLER_OUT)/root
570TARGET_INSTALLER_SYSTEM_OUT := $(TARGET_INSTALLER_OUT)/root/system
  


envsetup.mk文件主要包含了product_config.mk文件,然后指定了编译时要输出的所有文件的OUT目录

2.3.4 build/core/product_config.mk


173# ---------------------------------------------------------------
174# Include the product definitions.
175# We need to do this to translate TARGET_PRODUCT into its
176# underlying TARGET_DEVICE before we start defining any rules.
177#
178include $(BUILD_SYSTEM)/node_fns.mk
179include $(BUILD_SYSTEM)/product.mk
180include $(BUILD_SYSTEM)/device.mk
181
182ifneq ($(strip $(TARGET_BUILD_APPS)),)
183# An unbundled app build needs only the core product makefiles.
184all_product_configs := $(call get-product-makefiles,\
185    $(SRC_TARGET_DIR)/product/AndroidProducts.mk)
186else
187# Read in all of the product definitions specified by the AndroidProducts.mk
188# files in the tree.
189all_product_configs := $(get-all-product-makefiles)
190endif
191
192all_named_products :=
193
194# Find the product config makefile for the current product.
195# all_product_configs consists items like:
196# <product_name>:<path_to_the_product_makefile>
197# or just <path_to_the_product_makefile> in case the product name is the
198# same as the base filename of the product config makefile.
199current_product_makefile :=
200all_product_makefiles :=
201$(foreach f, $(all_product_configs),\
202    $(eval _cpm_words := $(subst :,$(space),$(f)))\
203    $(eval _cpm_word1 := $(word 1,$(_cpm_words)))\
204    $(eval _cpm_word2 := $(word 2,$(_cpm_words)))\
205    $(if $(_cpm_word2),\
206        $(eval all_product_makefiles += $(_cpm_word2))\
207        $(eval all_named_products += $(_cpm_word1))\
208        $(if $(filter $(TARGET_PRODUCT),$(_cpm_word1)),\
209            $(eval current_product_makefile += $(_cpm_word2)),),\
210        $(eval all_product_makefiles += $(f))\
211        $(eval all_named_products += $(basename $(notdir $(f))))\
212        $(if $(filter $(TARGET_PRODUCT),$(basename $(notdir $(f)))),\
213            $(eval current_product_makefile += $(f)),)))
214_cpm_words :=
215_cpm_word1 :=
216_cpm_word2 :=
217current_product_makefile := $(strip $(current_product_makefile))
218all_product_makefiles := $(strip $(all_product_makefiles))
219
220load_all_product_makefiles :=
221ifneq (,$(filter product-graph, $(MAKECMDGOALS)))
222ifeq ($(ANDROID_PRODUCT_GRAPH),--all)
223load_all_product_makefiles := true
224endif
225endif
226ifneq (,$(filter dump-products,$(MAKECMDGOALS)))
227ifeq ($(ANDROID_DUMP_PRODUCTS),all)
228load_all_product_makefiles := true
229endif
230endif
231
232ifeq ($(load_all_product_makefiles),true)
233# Import all product makefiles.
234$(call import-products, $(all_product_makefiles)) #读取指定的目录下所有的AndrodProducts.mk文件中定义的产品信息
235else
236# Import just the current product.
237ifndef current_product_makefile
238$(error Can not locate config makefile for product "$(TARGET_PRODUCT)")
239endif
240ifneq (1,$(words $(current_product_makefile)))
241$(error Product "$(TARGET_PRODUCT)" ambiguous: matches $(current_product_makefile))
242endif
243$(call import-products, $(current_product_makefile))
244endif  # Import all or just the current product makefile
245
246# Sanity check
247$(check-all-products)
248
249ifneq ($(filter dump-products, $(MAKECMDGOALS)),)
250$(dump-products)
251$(error done)
252endif
253
254# Convert a short name like "sooner" into the path to the product
255# file defining that product.
256#
257INTERNAL_PRODUCT := $(call resolve-short-product-name, $(TARGET_PRODUCT)) #调用了resolve-short-product-name函数,它将返回TARGET_PRODUCT产品的配置文件目录,并赋给INTERNAL_PRODUCT
258ifneq ($(current_product_makefile),$(INTERNAL_PRODUCT))
259$(error PRODUCT_NAME inconsistent in $(current_product_makefile) and $(INTERNAL_PRODUCT))
260endif
261current_product_makefile :=
262all_product_makefiles :=
263all_product_configs :=
  
product_config.mk主要读取vendor目录下不同厂商自己定义的AndrodProducts.mk文件,从该文件里取得所有产品的配置文件,然后再根据lunch选择的编译项TARGET_PRODUCT,找到与之对应的配置文件,然后设置TARGET_DEVICE变量,用于后续编译。

2.3.5 build/core/product.mk


26# Search for AndroidProducts.mks in the given dir.
27# $(1): the path to the dir
28define _search-android-products-files-in-dir
29$(sort $(shell test -d $(1) && find -L $(1) \
30  -maxdepth 6 \
31  -name .git -prune \
32  -o -name AndroidProducts.mk -print))
33endef
34
35#
36# Returns the list of all AndroidProducts.mk files.
37# $(call ) isn't necessary.
38#
39define _find-android-products-files
40$(foreach d, device vendor product,$(call _search-android-products-files-in-dir,$(d))) \
41  $(SRC_TARGET_DIR)/product/AndroidProducts.mk
42endef
43
44#
45# Returns the sorted concatenation of PRODUCT_MAKEFILES
46# variables set in the given AndroidProducts.mk files.
47# $(1): the list of AndroidProducts.mk files.
48#
49define get-product-makefiles
50$(sort \
51  $(foreach f,$(1), \
52    $(eval PRODUCT_MAKEFILES :=) \
53    $(eval LOCAL_DIR := $(patsubst %/,%,$(dir $(f)))) \
54    $(eval include $(f)) \
55    $(PRODUCT_MAKEFILES) \
56   ) \
57  $(eval PRODUCT_MAKEFILES :=) \
58  $(eval LOCAL_DIR :=) \
59 )
60endef  
要是一些用来处理AndroidProduct.mk的函数
_find-android-products-files:用来获得vendor目录下,所有名字为AndroidProduct.mk的文件列表。
get-all-product-makefiles:用来获得所有AndroidProduct.mk文件里定义的PRODUCT_MAKEFILES的值(其实是产品文件路径名)。
在vendor目录下,每个公司目录下都会存在一个AndroidProduct.mk文件,这个文件是用来定义这个公司的产品列表,每个产品用<product_name>.mk来表示
如Android给的示例:vendor/sample/products/AndroidProduct.mk

总结:
如果用户想个性定制自己的产品,应该有以下流程,包含上一节内容:
1. 创建公司目录
    #mkdir vendor/farsight
2. 创建一个vendorsetup.sh文件,将当前产品编译项添加到lunch里,让lunch能找到用户个性定制编译项
    #echo "add_lunch_combo fs100-eng" > vendor/farsight/vendorsetup.sh
3. 仿着Android示例代码,在公司目录下创建products目录
    #mkdir -p vendor/farsight/products
4. 仿着Android示例代码,在products目录下创建两个mk文件
    #touch vendor/farsight/products/AndroidProduct.mk vendor/farsight/products/fs100.mk
在AndroidProduct.mk里添加如下内容:
PRODUCT_MAKEFILES := $(LOCAL_DIR)/fs100.mk
表示只有一个产品fs100,它对应的配置文件在当前目录下的fs100.mk。
5. 在产品配置文件里添加最基本信息

PRODUCT_PACKAGES := \
    IM \
    VoiceDialer
$(call inherit-product, build/target/product/generic.mk)  ##从某一默认配置开始派生余下内容参考派生起点
# Overrides
PRODUCT_MANUFACTURER := farsight
PRODUCT_NAME := fs100
PRODUCT_DEVICE := fs100

除了编译和定义产品相关环境变量外,还需要定义Board相关环境变量

总结:
build/core/main.mk   包含了config.mk,它主要定义了编译全部代码的依赖关系
build/core/config.mk 定义了大量的编译脚本命令,编译时用到的环境变量,引入了envsetup.mk 文件,加载board相关配置文件。
build/core/envsetup.mk   定义了编译时用到的大量OUT输出目录,加载product_config.mk文件
build/core/product_config.mk 定义了Vendor目录下Product相关配置文件解析脚本,读取AndrodProducts.mk生成TARGET_DEVICE变量
      build/target/product          product config
      build/target/board            board config
      build/core/combo             build flags config 
这里解释下这里的board和product。borad主要是设计到硬件芯片的配置,比如是否提供硬件的某些功能,比如说GPU等等,或者芯片支持浮 点运算等等。product是指针对当前的芯片配置定义你将要生产产品的个性配置,主要是指APK方面的配置,哪些APK会包含在哪个product中, 哪些APK在当前product中是不提供的。
config.mk是一个总括性的东西,它里面定义了各种module编译所需要使用的HOST工具以及如何来编译各种模块,比如说 BUILT_PREBUILT就定义了如何来编译预编译模块。envsetup.mk主要会读取由envsetup.sh写入环境变量中的一些变量来配置编译过程中的输出目录,combo里面主要定义了各种Host和Target结合的编译器和编译选项。


2.4 mm流程

当我们单独编译某个模块时,在这个模块目录下输入mm命令进行编译,在build/envsetup.sh看一下具体实现过程:

function mm()

{

local T=$(gettop)

local DRV=$(getdriver $T)

# If we're sitting in the root of the build tree, just do a

# normal build.

if [ -f build/soong/soong_ui.bash ]; then

_wrap_build $DRV $T/build/soong/soong_ui.bash --make-mode $@

else

ONE_SHOT_MAKEFILE=$M _wrap_build $DRV $T/build/soong/soong_ui.bash --make-mode $MODULES $ARGS

流程上同make差不多只不过目标,是单独模块组成。

同时在mm一个单独模块是,生成独立的ninja文件

combined--aosp_arm-frameworks_native_libs_gui_Android.mk.ninja 和

build- aosp_arm-frameworks_native_libs_gui_Android.mk.ninja

2.3 Soong流程

在介绍soong编译流程之前,先介绍几个命令以便我们后续编译流程的理解,在out/soong/host/linux-x86/bin目录下,有几个命令是soong用到的,

soong_ui: soong编译的入口

androidmk: 后面的Android.bp用到,Android.mk一键转换为android.bp

在out/soong/.bootstrap/bin目录下有几个

out/soong/.bootstrap/bin$ ls

bpglob gotestmain gotestrunner loadplugins minibp soong_build soong_env

minibp: 在bootstrap是用到

soong_build :这个很重要,主要是将bp文件转换为ninja文件

通过上文的分析,当我们make命令敲下去的时候,主要是执行

prebuilts/build-tools/$(host_prebuilts)/bin/makeparallel --ninja build/soong/soong_ui.bash --make-mode $(MAKECMDGOALS)

soong_ui.bash脚本主要是执行如下:

build_go soong_ui android/soong/cmd/soong_ui //生成soong_ui命令

cd ${TOP}

exec "$(getoutdir)/soong_ui" "$@" //soong_ui入口,执行soong流程

比如我们执行make systemimage,到这边就变成了soong_ui –make-mode systemimage

soong_ui代码在build/soong/cmd/soong_ui/main.go 下,主要流程如下:

func main() {

log := logger.New(os.Stderr)

defer log.Cleanup()

if len(os.Args) < 2 || !inList("--make-mode", os.Args) {

log.Fatalln("The `soong` native UI is not yet available.")

}

build.Build(buildCtx, config, build.BuildAll)

主要执行soong/ui/build/build.go,从build.go就可以看到执行soong的大体流程

看一下各个流程

Step 1: runMakeProductConfig 主要配置编译参数

Step 2: runSoongBootstrap 这个主要是为后面编译工具的使用 ckati soong做环境搭建

runSoong 对工具进行编译

/.minibootstrap/build.ninja

- Run minibp to generate .bootstrap/build.ninja (Primary stage) - Run minibp to generate .minibootstrap/build.ninja.in

/.bootstrap/build.ninja

- Build any bootstrap_go_binary rules and dependencies -- usually the primary builder and any build or runtime dependencies. - Run the primary builder to generate build.ninja

同时还会生成out/soong/build.ninja

Step 3: 运行step2生成的ckati,搜集所有的Android.mk文件生成ninja文件,也就是前面提到的 out/build-aosp_arm.ninja

Step4: 将out/soong/build.ninja 和out/build-aosp_arm.ninja 合成为combined-aosp_arm.ninja

Step5: 运行runNinja 解释combined-aosp_arm.ninja 运行编译过程

三 ninja使用

  我们可以使用ninja 和生成的combined-aosp_arm.ninja 编译工程或者某一个module.

$ ./prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-aosp_arm.ninja

同在工程中make一个效果

编译systemimage或者bootimage

$ ./prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-aosp_arm.ninja  systemimage

上面这样做的目的是,不用重新生成ninja文件,直接进行编译,节省部分时间。这是在没有修改Makefile的前提

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android8.0.0-r4的编译系统 的相关文章

随机推荐

  • C语言中的关键字

    C语言共有32个关键字 关键字不能作为常量名 变量名或其他标识符名称 根据关键字的作用 xff0c 可将关键字分为 xff1a 数据类型关键字 控制语句关键字 存储类型关键字和其它关键字这四类 数据类型关键字 xff08 12个 xff09
  • C语言字符串和字符串结束标志

    1 在C语言中 xff0c 是将字符串作为字符数组来处理的 2 C语言规定了一个 字符串结束标志 xff0c 以字符 0 作为结束标志 如果字符数组中存有若干字符 xff0c 前面九个字符都不是空字符 xff08 0 xff09 xff0c
  • C语言字符数组的输入和输出

    字符数组的输入输出有两种方法 xff1a xff08 1 xff09 逐个字符输入输出 用格式符 c 输入或输出一个字符 例如 span class token keyword int span span class token funct
  • android手机开启IPv6(电信)

    安卓手机开启IPv6 xff08 电信 xff09 系统设置找到移动网络 接入点 接入点选择CTNET 接入设置点进去可以找到APN协议 xff0c 选择IPv4 IPv6即可 实测手机这样设置后开热点笔记本 xff0c 能稳定获得ipv6
  • C语言 怎样定义函数

    1 定义函数 C语言要求 xff0c 在程序中用到的所有函数必须要 先定义 xff0c 后使用 定义函数应包括以下几个内容 xff1a xff08 1 xff09 指定函数的名字 xff0c 以便以后按名调用 xff08 2 xff09 指
  • C语言 函数的返回值

    通过函数调用使主调函数能得到一个确定的值 xff0c 这就是函数值 xff08 函数的返回值 xff09 1 函数的返回值是通过函数中的return语句获得的 return语句将被调用函数中的一个确定值带回到主调函数中去 如果需要从被调函数
  • C语言 函数的嵌套调用

    C语言的函数定义是互相平行 独立的 xff0c 也就是说 xff0c 在定义函数时 xff0c 一个函数内不能再定义另一个函数 xff0c 即不能嵌套定义 xff0c 但可以嵌套调用函数 xff0c 即 xff0c 在调用一个函数的过程中
  • C语言 Hanoi(汉诺)塔问题,用递归解决

    问题 古代有一个梵塔 xff0c 塔内有3个座A xff0c B xff0c C 开始时A座上有64个盘子 xff0c 盘子大小不等 xff0c 大的在下 xff0c 小的在上 有一个老和尚想把64个盘子从A作移到C座 xff0c 但规定每
  • C语言 数组元素的指针

    1 一个变量有地址 xff0c 一个数组包含若干个元素 xff0c 每个数组元素都在内存中占用存储单元 xff0c 它们都有相应的地址 2 指针变量既然可以指向变量 xff0c 当然也可以指向数组元素 xff08 把某一元素的地址放入一个指
  • Python 实验三 控制语句

    1 从键盘接收整数的一百分制成绩 xff08 0到100 xff0c 要求输出其对应的成绩等级A E 其中 xff0c 90分 xff08 包含 xff09 以上为A xff0c 80 89 xff08 均包含 xff09 分为B xff0
  • Python 实验四 常用数据结构(1)

    1 从键盘输入一个正整数列表 xff0c 以一1结束 xff0c 分别计算列表中奇数和偶数的和 n span class token operator 61 span span class token builtin int span sp
  • Python 实验四 常用数据结构(2)

    6 某企业为职工发放奖金 xff1a 如果入职超过5年 xff0c 且销售业绩超过15000元的员工 xff0c 奖金比例为0 2 xff1b 销售业绩超过10000元的员工 xff0c 奖金比例为0 15 xff1b 销售业绩超过5000
  • JavaScript之入门4篇(DOM节点操作)

    学习记录 xff1a 学习视频链接https www bilibili com video BV1Sy4y1C7ha p 61 194 amp spm id from 61 pageDriver 1 节点操作 xff1a 1 利用DOM提供
  • Please wait while Jenkins is getting ready to work (jenkins)

    如果界面提示Jenkins正在启动 请稍后 或者提示 Please wait while Jenkins is getting ready to work 解决方法 1 需要你进入jenkins的工作目录 xff0c 打开 hudson m
  • 异常点检测的应用场景与检测方法(含代码实操案例)

    异常点检测概述 这里常说的异常点 xff0c 目前并没有具体的严格定义 xff0c 大多数来讲 xff0c 检测异常点都是按照数据分布与业务逻辑结合进行主观判断是否属于异常点 关注金科应用研院 xff0c 回复 CSDN xff0c 领取风
  • ApacheDS搭建

    前提 安装jdk sudo apt get install openjdk 8 jdk 安装 先安装apacheds2 配置客户端远程登录 xff0c 这里使用Apache Directory Studio xff0c 配置界面如下 xff
  • Windows 10 内置linux执行带GUI的应用程序

    1 安装MobaXterm xff0c 并运行 2 打开内置的Linux xff0c 命令执行带GUI的运行程序即可
  • Repo介绍

    目录 1 概要2 工作原理 2 1 项目清单库 repo manifests 2 2 repo脚本库 repo repo 2 3 仓库目录和工作目录 3 使用介绍 3 1 init3 2 sync3 3 upload3 4 download
  • Android 8.0.0-r4源码目录结构详解

    android的移植按如下流程 1 android linux 内核的普通驱动移植 让内核可以在目标平台上运行起来 2 正确挂载文件系统 确保内核启动参数和 android 源代码 system core rootdir 目录下的 init
  • Android8.0.0-r4的编译系统

    一 概述 1 1 编译系统变化 从Android 7 0开始 xff0c android的编译系统发生了变化 xff0c 之前依赖Makefile组织编译系统 xff0c 从7 0开始逐步引入了kati soong optional未正式使