function findmakefile() { TOPFILE=build/core/envsetup.mk local HERE=$PWD T= while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do T=`PWD= /bin/pwd` if [ -f "$T/Android.mk" ]; then echo $T/Android.mk \cd $HERE return fi \cd .. done \cd $HERE }
function mm() { local T=$(gettop) local DRV=$(getdriver $T) # If we're sitting in the root of the build tree, just do a # normal make. if [ -f build/core/envsetup.mk -a -f Makefile ]; then $DRV make $@ else # Find the closest Android.mk file. local M=$(findmakefile) local MODULES= local GET_INSTALL_PATH= local ARGS= # Remove the path to top as the makefilepath needs to be relative local M=`echo $M|sed 's:'$T'/::'` if [ ! "$T" ]; then echo "Couldn't locate the top of the tree. Try setting TOP." elif [ ! "$M" ]; then echo "Couldn't locate a makefile from the current directory." else for ARG in $@; do case $ARG in GET-INSTALL-PATH) GET_INSTALL_PATH=$ARG;; esac done if [ -n "$GET_INSTALL_PATH" ]; then MODULES= ARGS=GET-INSTALL-PATH else MODULES=all_modules ARGS=$@ fi ONE_SHOT_MAKEFILE=$M $DRV make -C $T -f build/core/main.mk $MODULES $ARGS fi fi }
# 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),) # We've probably been invoked by the "mm" shell function # with a subdirectory's makefile. include $(ONE_SHOT_MAKEFILE) # Change CUSTOM_MODULES to include only modules that were # defined by this makefile; this will install all of those # modules as a side-effect. Do this after including ONE_SHOT_MAKEFILE # so that the modules will be installed in the same place they # would have been with a normal make. CUSTOM_MODULES := $(sort $(call get-tagged-modules,$(ALL_MODULE_TAGS))) FULL_BUILD := # Stub out the notice targets, which probably aren't defined # when using ONE_SHOT_MAKEFILE. NOTICE-HOST-%: ; NOTICE-TARGET-%: ;
# A helper goal printing out install paths .PHONY: GET-INSTALL-PATH GET-INSTALL-PATH: @$(foreach m, $(ALL_MODULES), $(if $(ALL_MODULES.$(m).INSTALLED), \ echo 'INSTALL-PATH: $(m) $(ALL_MODULES.$(m).INSTALLED)';))
else # ONE_SHOT_MAKEFILE
ifneq ($(dont_bother),true) # # 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_DIR) --prune=.repo --prune=.git $(subdirs) Android.mk)
$(foreach mk, $(subdir_makefiles), $(info including $(mk) ...)$(eval include $(mk)))
endif # dont_bother
endif # ONE_SHOT_MAKEFILE
# Now with all Android.mks loaded we can do post cleaning steps. include $(BUILD_SYSTEM)/post_clean.mk
# User tags are not allowed anymore. Fail early because it will not be installed # like it used to be. ifneq ($(filter $(my_module_tags),user),) $(warning *** Module name: $(LOCAL_MODULE)) $(warning *** Makefile location: $(LOCAL_MODULE_MAKEFILE)) $(warning * ) $(warning * Module is attempting to use the 'user' tag. This) $(warning * used to cause the module to be installed automatically.) $(warning * Now, the module must be listed in the PRODUCT_PACKAGES) $(warning * section of a product makefile to have it installed.) $(warning * ) $(error user tag detected on module.) endif
# Only the tags mentioned in this test are expected to be set by module # makefiles. Anything else is either a typo or a source of unexpected # behaviors. ifneq ($(filter-out debug eng tests optional samples,$(my_module_tags)),) $(warning unusual tags $(my_module_tags) on $(LOCAL_MODULE) at $(LOCAL_PATH)) endif
# Keep track of all the tags we've seen. ALL_MODULE_TAGS := $(sort $(ALL_MODULE_TAGS) $(my_module_tags))
# Add this module to the tag list of each specified tag. # Don't use "+=". If the variable hasn't been set with ":=", # it will default to recursive expansion. $(foreach tag,$(my_module_tags),\ $(eval ALL_MODULE_TAGS.$(tag) := \ $(ALL_MODULE_TAGS.$(tag)) \ $(LOCAL_INSTALLED_MODULE)))
# Same as modules-for-tag-list, but operates on # ALL_MODULE_NAME_TAGS. # $(1): tag list define module-names-for-tag-list $(sort $(foreach tag,$(1),$(ALL_MODULE_NAME_TAGS.$(tag)))) endef
# Given an accept and reject list, find the matching # set of targets. If a target has multiple tags and # any of them are rejected, the target is rejected. # Reject overrides accept. # $(1): list of tags to accept # $(2): list of tags to reject #TODO(dbort): do $(if $(strip $(1)),$(1),$(ALL_MODULE_TAGS)) #TODO(jbq): as of 20100106 nobody uses the second parameter define get-tagged-modules $(filter-out \ $(call modules-for-tag-list,$(2)), \ $(call modules-for-tag-list,$(1))) endef
# These goals don't need to collect and include Android.mks/CleanSpec.mks # in the source tree. dont_bother_goals := clean clobber dataclean installclean \ help out \ snod systemimage-nodeps \ stnod systemtarball-nodeps \ userdataimage-nodeps userdatatarball-nodeps \ cacheimage-nodeps \ vendorimage-nodeps \ ramdisk-nodeps \ bootimage-nodeps
def perform_find(mindepth, prune, dirlist, filename): result = [] pruneleaves = set(map(lambda x: os.path.split(x)[1], prune)) for rootdir in dirlist: rootdepth = rootdir.count("/") for root, dirs, files in os.walk(rootdir, followlinks=True): # prune check_prune = False for d in dirs: if d in pruneleaves: check_prune = True break if check_prune: i = 0 while i < len(dirs): if dirs[i] in prune: del dirs[i] else: i += 1 # mindepth if mindepth > 0: depth = 1 + root.count("/") - rootdepth if depth < mindepth: continue # match if filename in files: result.append(os.path.join(root, filename)) del dirs[:] return result
def usage(): sys.stderr.write("""Usage: %(progName)s [<options>] <dirlist> <filename> Options: --mindepth=<mindepth> Both behave in the same way as their find(1) equivalents. --prune=<dirname> Avoids returning results from inside any directory called <dirname> (e.g., "*/out/*"). May be used multiple times. """ % { "progName": os.path.split(sys.argv[0])[1], }) sys.exit(1)
def main(argv): mindepth = -1 prune = [] i=1 while i<len(argv) and len(argv[i])>2 and argv[i][0:2] == "--": arg = argv[i] if arg.startswith("--mindepth="): try: mindepth = int(arg[len("--mindepth="):]) except ValueError: usage() elif arg.startswith("--prune="): p = arg[len("--prune="):] if len(p) == 0: usage() prune.append(p) else: usage() i += 1 if len(argv)-i < 2: # need both <dirlist> and <filename> usage() dirlist = argv[i:-1] filename = argv[-1] results = list(set(perform_find(mindepth, prune, dirlist, filename))) results.sort() for r in results: print r
def perform_find(mindepth, prune, dirlist, filename):
result = []
pruneleaves = set(map(lambda x: os.path.split(x)[1], prune))
for rootdir in dirlist:
rootdepth = rootdir.count("/")
for root, dirs, files in os.walk(rootdir, followlinks=True):
# prune
check_prune = False
for d in dirs:
if d in pruneleaves:
check_prune = True
break
if check_prune:
i = 0
while i < len(dirs):
if dirs[i] in prune:
del dirs[i]
else:
i += 1
# mindepth
if mindepth > 0:
depth = 1 + root.count("/") - rootdepth
if depth < mindepth:
continue
# match
if filename in files:
result.append(os.path.join(root, filename))
del dirs[:]
return result