From 71004f81351511b4873cdb09d52b7624158a4840 Mon Sep 17 00:00:00 2001 From: Ying Wang Date: Thu, 24 May 2012 21:05:19 -0700 Subject: [PATCH] Clean common intermediate files if overlay changed This change cleans the packages' intermediate files if their overlays changed between incremental builds. If two builds have different overlay, they will have different R classes, and so the jar files in the common intermediate dirs can not be shared. Therefore incremental build can't be applied. This change detects the overlay changes on package's base. If a package's overlay is different from the previous build, its common intermediate dir is nuked. This makes broader incremental builds possible. Change-Id: I368610ebbbbc85a80f9aecd714ab22cd78da7f12 --- core/main.mk | 4 ++ core/package.mk | 17 ++++--- core/post_clean.mk | 53 ++++++++++++++++++++ tools/diff_package_overlays.py | 91 ++++++++++++++++++++++++++++++++++ 4 files changed, 159 insertions(+), 6 deletions(-) create mode 100644 core/post_clean.mk create mode 100755 tools/diff_package_overlays.py diff --git a/core/main.mk b/core/main.mk index 3c64d9555..8a5b407d3 100644 --- a/core/main.mk +++ b/core/main.mk @@ -466,8 +466,12 @@ subdir_makefiles := \ $(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git $(subdirs) Android.mk) include $(subdir_makefiles) + endif # ONE_SHOT_MAKEFILE +# Now with all Android.mks loaded we can do post cleaning steps. +include $(BUILD_SYSTEM)/post_clean.mk + ifeq ($(stash_product_vars),true) $(call assert-product-vars, __STASHED) endif diff --git a/core/package.mk b/core/package.mk index 195b346d3..c68903137 100644 --- a/core/package.mk +++ b/core/package.mk @@ -94,12 +94,14 @@ endif ifeq (,$(LOCAL_RESOURCE_DIR)) LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res endif -LOCAL_RESOURCE_DIR := \ - $(wildcard $(foreach dir, $(PRODUCT_PACKAGE_OVERLAYS), \ - $(addprefix $(dir)/, $(LOCAL_RESOURCE_DIR)))) \ - $(wildcard $(foreach dir, $(DEVICE_PACKAGE_OVERLAYS), \ - $(addprefix $(dir)/, $(LOCAL_RESOURCE_DIR)))) \ - $(LOCAL_RESOURCE_DIR) + +package_resource_overlays := $(strip \ + $(wildcard $(foreach dir, $(PRODUCT_PACKAGE_OVERLAYS), \ + $(addprefix $(dir)/, $(LOCAL_RESOURCE_DIR)))) \ + $(wildcard $(foreach dir, $(DEVICE_PACKAGE_OVERLAYS), \ + $(addprefix $(dir)/, $(LOCAL_RESOURCE_DIR))))) + +LOCAL_RESOURCE_DIR := $(package_resource_overlays) $(LOCAL_RESOURCE_DIR) all_assets := $(call find-subdir-assets,$(LOCAL_ASSET_DIR)) all_assets := $(addprefix $(LOCAL_ASSET_DIR)/,$(patsubst assets/%,%,$(all_assets))) @@ -399,6 +401,9 @@ endif # Save information about this package PACKAGES.$(LOCAL_PACKAGE_NAME).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES)) PACKAGES.$(LOCAL_PACKAGE_NAME).RESOURCE_FILES := $(all_resources) +ifdef package_resource_overlays +PACKAGES.$(LOCAL_PACKAGE_NAME).RESOURCE_OVERLAYS := $(package_resource_overlays) +endif PACKAGES := $(PACKAGES) $(LOCAL_PACKAGE_NAME) diff --git a/core/post_clean.mk b/core/post_clean.mk new file mode 100644 index 000000000..213c43c0e --- /dev/null +++ b/core/post_clean.mk @@ -0,0 +1,53 @@ +# Copyright (C) 2012 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Clean steps that need global knowledge of individual modules. +# This file must be included after all Android.mks have been loaded. + +# Checks the current build configurations against the previous build, +# clean artifacts in TARGET_COMMON_OUT_ROOT if necessary. +# If a package's resource overlay has been changed, its R class needs to be +# regenerated. +previous_package_overlay_config := $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS/previous_overlays.txt +current_package_overlay_config := $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS/current_overlays.txt +current_all_packages_config := $(dir $(current_package_overlay_config))current_packages.txt + +$(shell rm -rf $(current_package_overlay_config) \ + && mkdir -p $(dir $(current_package_overlay_config)) \ + && touch $(current_package_overlay_config)) +$(shell echo '$(PACKAGES)' > $(current_all_packages_config)) +$(foreach p, $(PACKAGES), $(if $(PACKAGES.$(p).RESOURCE_OVERLAYS), \ + $(shell echo '$(p)' '$(PACKAGES.$(p).RESOURCE_OVERLAYS)' >> $(current_package_overlay_config)))) + +ifneq (,$(wildcard $(previous_package_overlay_config))) +packages_overlay_changed := $(shell build/tools/diff_package_overlays.py \ + $(current_all_packages_config) $(current_package_overlay_config) \ + $(previous_package_overlay_config)) +ifneq (,$(packages_overlay_changed)) +overlay_cleanup_cmd := $(strip rm -rf $(foreach p, $(packages_overlay_changed),\ + $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS/$(p)_intermediates)) +$(info *** Overlay change detected, clean shared intermediate files...) +$(info *** $(overlay_cleanup_cmd)) +$(shell $(overlay_cleanup_cmd)) +overlay_cleanup_cmd := +endif +packages_overlay_changed := +endif + +# Now current becomes previous. +$(shell mv -f $(current_package_overlay_config) $(previous_package_overlay_config)) + +previous_package_overlay_config := +current_package_overlay_config := +current_all_packages_config := diff --git a/tools/diff_package_overlays.py b/tools/diff_package_overlays.py new file mode 100755 index 000000000..0e2c773d1 --- /dev/null +++ b/tools/diff_package_overlays.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python +# +# Copyright (C) 2012 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Prints to stdout the package names that have overlay changes between +current_overlays.txt and previous_overlays.txt. + +Usage: diff_package_overlays.py +current_packages.txt contains all package names separated by space in the current build. +This script modfies current_packages.txt if necessary: if there is a package in +previous_overlays.txt but absent from current_packages.txt, we copy that line +from previous_overlays.txt over to current_packages.txt. Usually that means we +just don't care that package in the current build (for example we are switching +from a full build to a partial build with mm/mmm), and we should carry on the +previous overlay config so current_overlays.txt always reflects the current +status of the entire tree. + +Format of current_overlays.txt and previous_overlays.txt: + [resource_overlay ...] + [resource_overlay ...] + ... +""" + +import sys + +def main(argv): + if len(argv) != 4: + print >> sys.stderr, __doc__ + sys.exit(1) + + f = open(argv[1]) + all_packages = set(f.read().split()) + f.close() + + def load_overlay_config(filename): + f = open(filename) + result = {} + for line in f: + line = line.strip() + if not line or line.startswith("#"): + continue + words = line.split() + result[words[0]] = " ".join(words[1:]) + f.close() + return result + + current_overlays = load_overlay_config(argv[2]) + previous_overlays = load_overlay_config(argv[3]) + + result = [] + carryon = [] + for p in current_overlays: + if p not in previous_overlays: + result.append(p) + elif current_overlays[p] != previous_overlays[p]: + result.append(p) + for p in previous_overlays: + if p not in current_overlays: + if p in all_packages: + # overlay changed + result.append(p) + else: + # we don't build p in the current build. + carryon.append(p) + + # Add carryon to the current overlay config file. + if carryon: + f = open(argv[2], "a") + for p in carryon: + f.write(p + " " + previous_overlays[p] + "\n") + f.close() + + # Print out the package names that have overlay change. + for r in result: + print r + +if __name__ == "__main__": + main(sys.argv)