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} 622lunch命令可以带参数和不带参数,最终导出一些重要的环境变量,从而影响编译系统的编译结果
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:用来清除之前定义的环境变量
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
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_config.mk主要读取vendor目录下不同厂商自己定义的AndrodProducts.mk文件,从该文件里取得所有产品的配置文件,然后再根据lunch选择的编译项TARGET_PRODUCT,找到与之对应的配置文件,然后设置TARGET_DEVICE变量,用于后续编译。: 197# or justin 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 :=
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的函数
总结:
如果用户想个性定制自己的产品,应该有以下流程,包含上一节内容:
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相关环境变量
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 和生成的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的前提