Android編譯系統詳解(三)——編譯流程詳解

原文:http://www.cloudchou.com/android/post-276.html


1.概述

編譯Android的第三步是使用mka命令進行編譯,當然我們也可以使用make –j4,但是推薦使用mka命令。因爲mka將自動計算-j選項的數字,讓我們不用糾結這個數字到底是多少(這個數字其實就是所有cpu的核心數)。在編譯時我們可以帶上我們需要編譯的目標,假設你想生成recovery,那麼使用mka recoveryimage,如果想生成ota包,那麼需要使用mka otapackage,後續會介紹所有可以使用的目標。另外注意有一些目標只是起到修飾的作用,也就是說需要和其它目標一起使用,共有4個用於修飾的僞目標:

  • 1) showcommands 顯示編譯過程中使用的命令
  • 2) incrementaljavac用於增量編譯java代碼
  • 3) checkbuild用於檢驗那些需要檢驗的模塊
  • 4) all如果使用all修飾編譯目標,會編譯所有模塊

研究Android編譯系統時最頭疼的可能是變量,成百個變量我們無法記住其含義,也不知道這些變量會是什麼值,爲此我專門做了一個編譯變量的參考網站android.cloudchou.com,你可以在該網站查找變量,它能告訴你變量的含義,也會給出你該變量的示例值,另外也詳細解釋了編譯系統裏每個Makefile的作用,這樣你在看編譯系統的代碼時不至於一頭霧水。

編譯的核心文件是build/core/main.mkbuild/core/makefile,main.mk主要作用是檢查編譯環境是否符合要求,確定產品配置,決定產品需要使用的模塊,並定義了許多目標供開發者使用,比如droid,sdk等目標,但是生成這些目標的規則主要在Makefile裏定義,而內核的編譯規則放在build/core/task/kernel.mk

我們將先整體介紹main.mk的執行流程,然後再針對在Linux上編譯默認目標時使用的關鍵代碼進行分析。Makefile主要定義了各個目標的生成規則,因此不再詳細介紹它的執行流程,若有興趣看每個目標的生成規則,可查看http://android.cloudchou.com/build/core/Makefile.php

2. main.mk執行流程

2.1 檢驗編譯環境並建立產品配置

  • 1) 設置Shell變量爲bash,不能使用其它shell
  • 2) 關閉make的suffix規則,rcs/sccs規則,並設置一個規則: 當某個規則失敗了,就刪除所有目標
  • 3) 檢驗make的版本,cygwin可使用任意版本make,但是linux或者mac只能使用3.81版本或者3.82版本
  • 4) 設置PWD,TOP,TOPDIR,BUILD_SYSTEM等變量,定義了默認目標變量,但是暫時並未定義默認目標的生成規則
  • 5) 包含build/core/help.mk,該makefile定義了兩個目標help和out, help用於顯示幫助,out用於檢驗編譯系統是否正確
  • 6) 包含build/core/config.mk,config.mk作了很多配置,包括產品配置,包含該makefile後,會建立輸出目錄系列的變量,還會建立PRODUCT系列變量,後續介紹產品配置時,對此會有更多詳細介紹
  • 7) 包含build/core/cleanbuild.mk,該makefile會包含所有工程的CleanSpec.mk,寫了CleanSpec.mk的工程會定義每次編譯前的特殊清理步驟,cleanbuild.mk會執行這些清除步驟
  • 8) 檢驗編譯環境,先檢測上次編譯結果,如果上次檢驗的版本和此次檢驗的版本一致,則不再檢測,然後進行檢測並將此次編譯結果寫入

2.2 包含其它makefile及編譯目標檢測

  • 1) 如果目標裏含有incrementaljavac, 那麼編譯目標時將用incremental javac進行增量編譯
  • 2) 設置EMMA_INSTRUMENT變量的值,emma是用於測試代碼覆蓋率的庫
  • 3) 包含build/core/definistions.mk,該makefile定義了許多輔助函數
  • 4) 包含build/core/qcom_utils.mk,該makefile定義了高通板子的一些輔助函數及宏
  • 5) 包含build/core/dex_preopt.mk,該makefile定義了優化dex代碼的一些宏
  • 6) 檢測編譯目標裏是否有user,userdebug,eng,如果有則告訴用戶放置在buildspec.mk或者使用lunch設置,檢測TARGET_BUILD_VARIANT變量,看是否有效
  • 7) 包含build/core/pdk_config.mk, PDK主要是能提高現有設備升級能力,幫助設備製造商能更快的適配新版本的android

2.3 根據TARGET_BUILD_VARIANT建立配置

  • 1) 如果編譯目標裏有sdk,win_sdk或者sdk_addon,那麼設置is_sdk_build爲true
  • 2) 如果定義了HAVE_SELINUX,那麼編譯時爲build prop添加屬性ro.build.selinux=1
  • 3) 如果TARGET_BUILD_VARIANT是user或者userdebug,那麼tags_to_install += debug 如果用戶未定義DISABLE_DEXPREOPT爲true,並且是user模式,那麼將設置WITH_DEXPREOPT := true,該選項將開啓apk的預優化,即將apk分成odex代碼文件和apk資源文件
  • 4) 判斷enable_target_debugging變量,默認是true,當build_variant是user時,則它是false。如果該變量值爲true,則設置Rom的編譯屬性ro.debuggable爲1,否則設置ro.debuggable爲0
  • 5) 如果TARGET_BUILD_VARIANT是eng,那麼tags_to_install爲debug,eng, 並設置Rom的編譯屬性ro.setupwizard.mode爲OPTIONAL,因爲eng模式並不要安裝嚮導
  • 6) 如果TARGET_BUILD_VARIANT是tests,那麼tags_to_install := debug eng tests
  • 7) 設置sdk相關變量
  • 8) 添加一些額外的編譯屬性
  • 9) 定義should-install-to-system宏函數
  • 10) 若除了修飾目標,沒定義任何目標,那麼將使用默認目標編譯

2.4 包含所有要編譯的模塊的Makefile

如果編譯目標是clean clobber installclean dataclean,那麼設置dont_bother爲true,若dont_bother爲false,則將所有要編譯的模塊包含進來

1) 如果主機操作系統及體系結構爲darwin-ppc(Mac電腦),那麼提示不支持編譯Sdk,並將SDK_ONLY設置爲true

2) 如果主機操作系統是windows,那麼設置SDK_ONLY爲true

3) 根據SDK_ONLY是否爲true,編譯主機操作系統類型,BUILD_TINY_ANDROID的值,設置sudbidrs變量

4) 將所有PRODUCT_*相關變量存儲至stash_product_vars變量,稍後將驗證它是否被修改

5) 根據ONE_SHOT_MAKEFILE的值是否爲空,包含不同的makefile

6) 執行post_clean步驟,並確保產品相關變量沒有變化

7) 檢測是否有文件加入ALL_PREBUILT

8) 包含其它必須在所有Android.mk包含之後需要包含的makefile

9) 將known_custom_modules轉化成安裝路徑得到變量CUSTOM_MODULES

10) 定義模塊之間的依賴關係,$(ALL_MODULES.$(m).REQUIRED))變量指明瞭模塊之間的依賴關係

11)計算下述變量的值:product_MODULES,debug_MODULES,eng_MODULES,tests_MODULES,modules_to_install,overridden_packages,target_gnu_MODULES,ALL_DEFAULT_INSTALLED_MODULES

12) 包含build/core/Makefile

13) 定義變量modules_to_check

2.5 定義多個目標

這一節定義了衆多目標,prebuilt,all_copied_headers,files,checkbuild,ramdisk,factory_ramdisk,factory_bundle,systemtarball,boottarball,userdataimage,userdatatarball,cacheimage,bootimage,droidcore,dist_files,apps_only,all_modules,docs,sdk,lintall,samplecode,findbugs,clean,modules,showcommands,nothing。

後續文章將列出所有可用的目標

3 編譯默認目標時的執行流程

在介紹編譯默認目標時的執行流程之前,先介紹一下ALL_系列的變量,否則看代碼時很難搞懂這些變量的出處,這些變量在包含所有模塊後被建立,每個模塊都有對應的用於編譯的makefile,這些makefile會包含一個編譯類型對應的makefile,比如package.mk,而這些makefile最終都會包含base_rules.mk,在base_rules.mk裏會爲ALL系列變量添加值。所有這些變量及其來源均可在android.cloudchou.com查看詳細解釋:

  • 1) ALL_DOCS所有文檔的全路徑,ALL_DOCS的賦值在droiddoc.mk裏, ALL_DOCS += $(full_target)
  • 2)ALL_MODULES系統的所有模塊的簡單名字集合,編譯系統還爲每一個模塊還定義了其它兩個變量,ALL_MODULES.$(LOCAL_MODULE).BUILT 所有模塊的生成路徑ALL_MODULES.$(LOCAL_MODULE).INSTALLED 所有模塊的各自安裝路徑,詳情請見http://android.cloudchou.com/build/core/definitions.php#ALL_MODULES
  • 3) ALL_DEFAULT_INSTALLED_MODULES 所有默認要安裝的模塊,在build/core/main.mk和build/core/makfile裏設置
  • 4) ALL_MODULE_TAGS 使用LOCAL_MODULE_TAGS定義的所有tag集合,每一個tag對應一個ALL_MODULE_TAGS.變量,詳情請見http://android.cloudchou.com/build/core/definitions.php#ALL_MODULE_TAGS
  • 5) ALL_MODULE_NAME_TAGS類似於ALL_MODULE_TAGS,但是它的值是 某個tag的所有模塊的名稱 詳情請見http://android.cloudchou.com/build/core/definitions.php#ALL_MODULE_NAME_TAGS
  • 6) ALL_HOST_INSTALLED_FILES 安裝在pc上的程序集合
  • 7) ALL_PREBUILT 將會被拷貝的預編譯文件的安裝全路徑的集合
  • 8) ALL_GENERATED_SOURCES 某些工具生成的源代碼文件的集合,比如aidl會生成java源代碼文件
  • 9) ALL_C_CPP_ETC_OBJECTS 所有asm,c,c++,以及lex和yacc生成的c代碼文件的全路徑
  • 10) ALL_ORIGINAL_DYNAMIC_BINARIES 沒有被優化,也沒有被壓縮的動態鏈接庫
  • 11) ALL_SDK_FILES 將會放在sdk的文件
  • 12) ALL_FINDBUGS_FILES 所有findbugs程序用的xml文件
  • 13) ALL_GPL_MODULE_LICENSE_FILES GPL 模塊的 許可文件
  • 14) ANDROID_RESOURCE_GENERATED_CLASSES Android 資源文件生成的java代碼編譯後的類的類型

3.1 關鍵代碼

定義默認目標的代碼位於main.mk:

1
2
3
.PHONY: droid
DEFAULT_GOAL := droid
$(DEFAULT_GOAL):

droid目標依賴的目標有:

1
2
3
4
5
6
7
ifneq ($(TARGET_BUILD_APPS),)
……
droid: apps_only #如果編譯app,那麼droid依賴apps_only目標
else
……
droid: droidcore dist_files #默認依賴droidcore目標和dist_files目標
endif

dist_files目標依賴的目標主要是一些用於打包的工具,它們都是用dist-for-goals宏添加依賴關係的:

1
2
3
4
5
6
7
8
9
10
11
$(call dist-for-goals, dist_files, $(EMMA_META_ZIP))
system/core/mkbootimg/Android.mk$(call dist-for-goals, dist_files, $( LOCAL_BUILT_MODULE ))
system/core/cpio/Android.mk:13:$(call dist-for-goals,dist_files,$(LOCAL_BUILT_MODULE))
system/core/adb/Android.mk:88:$(call dist-for-goals,dist_files sdk,$(LOCAL_BUILT_MODULE))
system/core/fastboot/Android.mk:68:$(call dist-for-goals,dist_files sdk,$(LOCAL_BUILT_MODULE))
external/guava/Android.mk:26:$(call dist-for-goals, dist_files, $(LOCAL_BUILT_MODULE):guava.jar)
external/yaffs2/Android.mk:28:$(call dist-for-goals, dist_files, $(LOCAL_BUILT_MODULE))
external/mp4parser/Android.mk:26:$(call dist-for-goals, dist_files, $(LOCAL_BUILT_MODULE):mp4parser.jar)
external/jsr305/Android.mk:25:$(call dist-for-goals, dist_files, $(LOCAL_BUILT_MODULE):jsr305.jar)
frameworks/support/renderscript/v8/Android.mk:29:#$(call dist-for-goals, dist_files, $(LOCAL_BUILT_MODULE):volley.jar)
frameworks/support/volley/Android.mk:29:#$(call dist-for-goals, dist_files, $(LOCAL_BUILT_MODULE):volley.jar)

我們再看droidcore目標依賴的目標有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
droidcore: files \
	systemimage \ #system.img
	$(INSTALLED_BOOTIMAGE_TARGET) \ #boot.img
	$(INSTALLED_RECOVERYIMAGE_TARGET) \#recovery.img
	$(INSTALLED_USERDATAIMAGE_TARGET) \#data.img
	$(INSTALLED_CACHEIMAGE_TARGET) \#cache.img
	$(INSTALLED_FILES_FILE)# installed-files.txt
ifneq ($(TARGET_BUILD_APPS),).
else
$(call dist-for-goals, droidcore, \
    $(INTERNAL_UPDATE_PACKAGE_TARGET) #cm_find5-img-eng.cloud.zip
    $(INTERNAL_OTA_PACKAGE_TARGET) \ # cm_find5-ota-eng.cloud.zip
    $(SYMBOLS_ZIP) \ # cm_find5-symbols-eng.cloud.zip
    $(INSTALLED_FILES_FILE) \# installed-files.txt
    $(INSTALLED_BUILD_PROP_TARGET) \# system/build.prop
    $(BUILT_TARGET_FILES_PACKAGE) \# cm_find5-target_files-eng.cloud.zip
    $(INSTALLED_ANDROID_INFO_TXT_TARGET) \# android-info.txt
    $(INSTALLED_RAMDISK_TARGET) \# ramdisk.img
    $(INSTALLED_FACTORY_RAMDISK_TARGET) \# factory_ramdisk.gz
    $(INSTALLED_FACTORY_BUNDLE_TARGET) \# cm_find5-factory_bundle- eng.cloud.zip
   )
endif

system.img, boot.img, recovery.img, data.img,cache.img,installed_files.txt的生成規則在Makefile裏定義, 在http://android.cloudchou.com/build/core/Makefile.php裏可以看到詳細的生成規則再看一下files目標所依賴的目標:

1
2
3
files: prebuilt \
        $(modules_to_install) \
        $(INSTALLED_ANDROID_INFO_TXT_TARGET)

prebuilt目標依賴$(ALL_PREBUILT),android-info.txt的生成規則在target/board/board.mk裏定義,而$(modules_to_install)目標是所有要安裝的模塊的集合,計算比較複雜,現在以在linux下編譯默認目標爲例,將涉及到的代碼組織如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
……
tags_to_install :=
ifneq (,$(user_variant))..
  ifeq ($(user_variant),userdebug)
  tags_to_install += debug
  elseendif
endif
ifeq ($(TARGET_BUILD_VARIANT),eng)
tags_to_install := debug eng
…
endif
ifeq ($(TARGET_BUILD_VARIANT),tests)
tags_to_install := debug eng tests
endif
ifdef is_sdk_build
tags_to_install := debug eng
else # !sdk
endif
……
# ------------------------------------------------------------
# Define a function that, given a list of module tags, returns
# non-empty if that module should be installed in /system.
 
# For most goals, anything not tagged with the "tests" tag should
# be installed in /system.
define should-install-to-system
$(if $(filter tests,$(1)),,true)
endef
ifdef is_sdk_build
# For the sdk goal, anything with the "samples" tag should be
# installed in /data even if that module also has "eng"/"debug"/"user".
define should-install-to-system
$(if $(filter samples tests,$(1)),,true)
endef
endif#接下來根據配置計算要查找的subdirs目錄
ifneq ($(dont_bother),true)ifeq ($(SDK_ONLY),true)
include $(TOPDIR)sdk/build/sdk_only_whitelist.mk
include $(TOPDIR)development/build/sdk_only_whitelist.mk
# Exclude tools/acp when cross-compiling windows under linux
ifeq ($(findstring Linux,$(UNAME)),)
subdirs += build/tools/acp
endif
 
else	# !SDK_ONLY
ifeq ($(BUILD_TINY_ANDROID), true)
subdirs := \
	bionic \
	system/core \
	system/extras/ext4_utils \
	system/extras/su \
	build/libs \
	build/target \
	build/tools/acp \
	external/gcc-demangle \
	external/mksh \
	external/openssl \
	external/yaffs2 \
	external/zlib
else	# !BUILD_TINY_ANDROID
subdirs := $(TOP) 
FULL_BUILD := true
endif	# !BUILD_TINY_ANDROID
endif
# Before we go and include all of the module makefiles, stash away
# the PRODUCT_* values so that later we can verify they are not modified.
stash_product_vars:=true
ifeq ($(stash_product_vars),true)
  $(call stash-product-vars, __STASHED)
endif.
ifneq ($(ONE_SHOT_MAKEFILE),)
include $(ONE_SHOT_MAKEFILE)
CUSTOM_MODULES := $(sort $(call get-tagged-modules,$(ALL_MODULE_TAGS)))
FULL_BUILD :=else # ONE_SHOT_MAKEFILE
#
# Include all of the makefiles in the system
#
 
# Can't use first-makefiles-under here because
# --mindepth=2 makes the prunes not work.
subdir_makefiles := \
	$(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git $(subdirs) Android.mk)
 
include $(subdir_makefiles)
 
endif # ONE_SHOT_MAKEFILE
……
ifeq ($(stash_product_vars),true)
  $(call assert-product-vars, __STASHED)
endif# -------------------------------------------------------------------
# Fix up CUSTOM_MODULES to refer to installed files rather than
# just bare module names.  Leave unknown modules alone in case
# they're actually full paths to a particular file.
known_custom_modules := $(filter $(ALL_MODULES),$(CUSTOM_MODULES))
unknown_custom_modules := $(filter-out $(ALL_MODULES),$(CUSTOM_MODULES))
CUSTOM_MODULES := \
	$(call module-installed-files,$(known_custom_modules)) \
	$(unknown_custom_modules
# -------------------------------------------------------------------
# Figure out our module sets.
#
# Of the modules defined by the component makefiles,
# determine what we actually want to build.
 
ifdef FULL_BUILD
  # The base list of modules to build for this product is specified
  # by the appropriate product definition file, which was included
  # by product_config.make.
  product_MODULES := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES)
  # Filter out the overridden packages before doing expansion
  product_MODULES := $(filter-out $(foreach p, $(product_MODULES), \
      $(PACKAGES.$(p).OVERRIDES)), $(product_MODULES))
  $(call expand-required-modules,product_MODULES,$(product_MODULES))
  product_FILES := $(call module-installed-files, $(product_MODULES))
  ifeq (0,1)
    $(info product_FILES for $(TARGET_DEVICE) ($(INTERNAL_PRODUCT)):)
    $(foreach p,$(product_FILES),$(info :   $(p)))
    $(error done)
  endif
else
  # We're not doing a full build, and are probably only including
  # a subset of the module makefiles.  Don't try to build any modules
  # requested by the product, because we probably won't have rules
  # to build them.
  product_FILES :=
endif
# When modules are tagged with debug eng or tests, they are installed
# for those variants regardless of what the product spec says.
debug_MODULES := $(sort \
        $(call get-tagged-modules,debug) \
        $(call module-installed-files, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_DEBUG)) \
    )
eng_MODULES := $(sort \
        $(call get-tagged-modules,eng) \
        $(call module-installed-files, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_ENG)) \
    )
tests_MODULES := $(sort \
        $(call get-tagged-modules,tests) \
        $(call module-installed-files, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_TESTS)) \
)
# TODO: Remove the 3 places in the tree that use ALL_DEFAULT_INSTALLED_MODULES
# and get rid of it from this list.
# TODO: The shell is chosen by magic.  Do we still need this?
modules_to_install := $(sort \
    $(ALL_DEFAULT_INSTALLED_MODULES) \
    $(product_FILES) \
    $(foreach tag,$(tags_to_install),$($(tag)_MODULES)) \
    $(call get-tagged-modules, shell_$(TARGET_SHELL)) \
    $(CUSTOM_MODULES) \
  )
# Some packages may override others using LOCAL_OVERRIDES_PACKAGES.
# Filter out (do not install) any overridden packages.
overridden_packages := $(call get-package-overrides,$(modules_to_install))
ifdef overridden_packages
#  old_modules_to_install := $(modules_to_install)
  modules_to_install := \
      $(filter-out $(foreach p,$(overridden_packages),$(p) %/$(p).apk), \
          $(modules_to_install))
endif
#$(error filtered out
#           $(filter-out $(modules_to_install),$(old_modules_to_install)))
 
# Don't include any GNU targets in the SDK.  It's ok (and necessary)
# to build the host tools, but nothing that's going to be installed
# on the target (including static libraries).
ifdef is_sdk_build
  target_gnu_MODULES := \
              $(filter \
                      $(TARGET_OUT_INTERMEDIATES)/% \
                      $(TARGET_OUT)/% \
                      $(TARGET_OUT_DATA)/%, \
                              $(sort $(call get-tagged-modules,gnu)))
  $(info Removing from sdk:)$(foreach d,$(target_gnu_MODULES),$(info : $(d)))
  modules_to_install := \
              $(filter-out $(target_gnu_MODULES),$(modules_to_install))
 
  # Ensure every module listed in PRODUCT_PACKAGES* gets something installed
  # TODO: Should we do this for all builds and not just the sdk?
  $(foreach m, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES), \
    $(if $(strip $(ALL_MODULES.$(m).INSTALLED)),,\
      $(warning $(ALL_MODULES.$(m).MAKEFILE): Module '$(m)' in PRODUCT_PACKAGES has nothing to install!)))
  $(foreach m, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_DEBUG), \
    $(if $(strip $(ALL_MODULES.$(m).INSTALLED)),,\
      $(warning $(ALL_MODULES.$(m).MAKEFILE): Module '$(m)' in PRODUCT_PACKAGES_DEBUG has nothing to install!)))
  $(foreach m, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_ENG), \
    $(if $(strip $(ALL_MODULES.$(m).INSTALLED)),,\
      $(warning $(ALL_MODULES.$(m).MAKEFILE): Module '$(m)' in PRODUCT_PACKAGES_ENG has nothing to install!)))
  $(foreach m, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_TESTS), \
    $(if $(strip $(ALL_MODULES.$(m).INSTALLED)),,\
      $(warning $(ALL_MODULES.$(m).MAKEFILE): Module '$(m)' in PRODUCT_PACKAGES_TESTS has nothing to install!)))
endif
 
# Install all of the host modules
modules_to_install += $(sort $(modules_to_install) $(ALL_HOST_INSTALLED_FILES))
 
# build/core/Makefile contains extra stuff that we don't want to pollute this
# top-level makefile with.  It expects that ALL_DEFAULT_INSTALLED_MODULES
# contains everything that's built during the current make, but it also further
# extends ALL_DEFAULT_INSTALLED_MODULES.
ALL_DEFAULT_INSTALLED_MODULES := $(modules_to_install)
include $(BUILD_SYSTEM)/Makefile
modules_to_install := $(sort $(ALL_DEFAULT_INSTALLED_MODULES))
ALL_DEFAULT_INSTALLED_MODULES :=
 
endif # dont_bother
# These are additional goals that we build, in order to make sure that there
# is as little code as possible in the tree that doesn't build.
modules_to_check := $(foreach m,$(ALL_MODULES),$(ALL_MODULES.$(m).CHECKED))
 
# If you would like to build all goals, and not skip any intermediate
# steps, you can pass the "all" modifier goal on the commandline.
ifneq ($(filter all,$(MAKECMDGOALS)),)
modules_to_check += $(foreach m,$(ALL_MODULES),$(ALL_MODULES.$(m).BUILT))
endif
 
# for easier debugging
modules_to_check := $(sort $(modules_to_check))
#$(error modules_to_check $(modules_to_check))

發佈了0 篇原創文章 · 獲贊 9 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章