Merge "Revert "Generate care map after merging target_files""
diff --git a/Changes.md b/Changes.md
index 0a6adc4..1ab005f 100644
--- a/Changes.md
+++ b/Changes.md
@@ -1,5 +1,49 @@
# Build System Changes for Android.mk Writers
+## Dexpreopt starts enforcing `<uses-library>` checks (for Java modules)
+
+In order to construct correct class loader context for dexpreopt, build system
+needs to know about the shared library dependencies of Java modules listed in
+the `<uses-library>` tags in the manifest. Since the build system does not have
+access to the manifest contents, that information must be present in the build
+files. In simple cases Soong is able to infer it from its knowledge of Java SDK
+libraries and the `libs` property in Android.bp, but in more complex cases it is
+necessary to add the missing information in Android.bp/Android.mk manually.
+
+To specify a list of libraries for a given modules, use:
+
+* Android.bp properties: `uses_libs`, `optional_uses_libs`
+* Android.mk variables: `LOCAL_USES_LIBRARIES`, `LOCAL_OPTIONAL_USES_LIBRARIES`
+
+If a library is in `libs`, it usually should *not* be added to the above
+properties, and Soong should be able to infer the `<uses-library>` tag. But
+sometimes a library also needs additional information in its
+Android.bp/Android.mk file (e.g. when it is a `java_library` rather than a
+`java_sdk_library`, or when the library name is different from its module name,
+or when the module is defined in Android.mk rather than Android.bp). In such
+cases it is possible to tell the build system that the library provides a
+`<uses-library>` with a given name (however, this is discouraged and will be
+deprecated in the future, and it is recommended to fix the underlying problem):
+
+* Android.bp property: `provides_uses_lib`
+* Android.mk variable: `LOCAL_PROVIDES_USES_LIBRARY`
+
+It is possible to disable the check on a per-module basis. When doing that it is
+also recommended to disable dexpreopt, as disabling a failed check will result
+in incorrect class loader context recorded in the .odex file, which will cause
+class loader context mismatch and dexopt at first boot.
+
+* Android.bp property: `enforce_uses_lib`
+* Android.mk variable: `LOCAL_ENFORCE_USES_LIBRARIES`
+
+Finally, it is possible to globally disable the check:
+
+* For a given product: `PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true`
+* On the command line: `RELAX_USES_LIBRARY_CHECK=true`
+
+The environment variable overrides the product variable, so it is possible to
+disable the check for a product, but quickly re-enable it for a local build.
+
## `LOCAL_REQUIRED_MODULES` requires listed modules to exist {#BUILD_BROKEN_MISSING_REQUIRED_MODULES}
Modules listed in `LOCAL_REQUIRED_MODULES`, `LOCAL_HOST_REQUIRED_MODULES` and
diff --git a/core/binary.mk b/core/binary.mk
index 2c20eed..0d7206f 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -266,10 +266,7 @@
endif
endif
- ifneq (,$(filter armeabi armeabi-v7a,$(my_cpu_variant)))
- my_ndk_stl_static_lib += $(my_libcxx_libdir)/libunwind.a
- endif
-
+ my_ndk_stl_static_lib += $(my_libcxx_libdir)/libunwind.a
my_ldlibs += -ldl
else # LOCAL_NDK_STL_VARIANT must be none
# Do nothing.
diff --git a/core/cxx_stl_setup.mk b/core/cxx_stl_setup.mk
index f71ef72..0d557c7 100644
--- a/core/cxx_stl_setup.mk
+++ b/core/cxx_stl_setup.mk
@@ -82,15 +82,7 @@
endif
endif
else ifeq ($(my_cxx_stl),ndk)
- # Using an NDK STL. Handled in binary.mk, except for the unwinder.
- # TODO: Switch the NDK over to the LLVM unwinder for non-arm32 architectures.
- ifeq (arm,$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH))
- my_static_libraries += libunwind_llvm
- my_ldflags += -Wl,--exclude-libs,libunwind_llvm.a
- else
- my_static_libraries += libgcc_stripped
- my_ldflags += -Wl,--exclude-libs,libgcc_stripped.a
- endif
+ # Using an NDK STL. Handled in binary.mk.
else ifeq ($(my_cxx_stl),libstdc++)
$(error $(LOCAL_PATH): $(LOCAL_MODULE): libstdc++ is not supported)
else ifeq ($(my_cxx_stl),none)
diff --git a/core/envsetup.rbc b/core/envsetup.rbc
index 2924ee1..451623b 100644
--- a/core/envsetup.rbc
+++ b/core/envsetup.rbc
@@ -1,4 +1,3 @@
-
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,14 +12,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load(":build_id.rbc|init", _build_id_init="init")
+load(":build_id.rbc|init", _build_id_init = "init")
def _all_versions():
"""Returns all known versions."""
- versions = ["OPR1", "OPD1", "OPD2","OPM1", "OPM2", "PPR1", "PPD1", "PPD2", "PPM1", "PPM2", "QPR1" ]
+ versions = ["OPR1", "OPD1", "OPD2", "OPM1", "OPM2", "PPR1", "PPD1", "PPD2", "PPM1", "PPM2", "QPR1"]
for v in ("Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"):
- for e in ("P1A", "P1B", "P2A", "P2B", "D1A", "D1B", "D2A", "D2B", "Q1A", "Q1B", "Q2A", "Q2B", "Q3A", "Q3B"):
- versions.append(v+e)
+ for e in ("P1A", "P1B", "P2A", "P2B", "D1A", "D1B", "D2A", "D2B", "Q1A", "Q1B", "Q2A", "Q2B", "Q3A", "Q3B"):
+ versions.append(v + e)
return versions
def _allowed_versions(all_versions, min_version, max_version, default_version):
@@ -36,7 +35,7 @@
fail("%s should come before %s in the version list" % (min_version, max_version))
if def_i < min_i or def_i > max_i:
fail("%s should come between % and %s" % (default_version, min_version, max_version))
- return all_versions[min_i:max_i+1]
+ return all_versions[min_i:max_i + 1]
# This function is a manual conversion of the version_defaults.mk
def _versions_default(g, all_versions):
@@ -70,21 +69,22 @@
g.setdefault("PLATFORM_VERSION_CODENAME", g["TARGET_PLATFORM_VERSION"])
# TODO(asmundak): set PLATFORM_VERSION_ALL_CODENAMES
- g.setdefault("PLATFORM_VERSION",
- g["PLATFORM_VERSION_LAST_STABLE"] if g["PLATFORM_VERSION_CODENAME"] == "REL" else g["PLATFORM_VERSION_CODENAME"])
g.setdefault("PLATFORM_SDK_VERSION", 30)
- if g["PLATFORM_VERSION_CODENAME"] == "REL":
+ version_codename = g["PLATFORM_VERSION_CODENAME"]
+ if version_codename == "REL":
+ g.setdefault("PLATFORM_VERSION", g["PLATFORM_VERSION_LAST_STABLE"])
g["PLATFORM_PREVIEW_SDK_VERSION"] = 0
+ g.setdefault("DEFAULT_APP_TARGET_SDK", g["PLATFORM_SDK_VERSION"])
+ g.setdefault("PLATFORM_VNDK_VERSION", g["PLATFORM_SDK_VERSION"])
else:
+ g.setdefault("PLATFORM_VERSION", version_codename)
g.setdefault("PLATFORM_PREVIEW_SDK_VERSION", 1)
+ g.setdefault("DEFAULT_APP_TARGET_SDK", version_codename)
+ g.setdefault("PLATFORM_VNDK_VERSION", version_codename)
- g.setdefault("DEFAULT_APP_TARGET_SDK",
- g["PLATFORM_SDK_VERSION"] if g["PLATFORM_VERSION_CODENAME"] == "REL" else g["PLATFORM_VERSION_CODENAME"])
- g.setdefault("PLATFORM_VNDK_VERSION",
- g["PLATFORM_SDK_VERSION"] if g["PLATFORM_VERSION_CODENAME"] == "REL" else g["PLATFORM_VERSION_CODENAME"])
g.setdefault("PLATFORM_SYSTEMSDK_MIN_VERSION", 28)
versions = [str(i) for i in range(g["PLATFORM_SYSTEMSDK_MIN_VERSION"], g["PLATFORM_SDK_VERSION"] + 1)]
- versions.append(g["PLATFORM_VERSION_CODENAME"])
+ versions.append(version_codename)
g["PLATFORM_SYSTEMSDK_VERSIONS"] = sorted(versions)
# Used to indicate the security patch that has been applied to the device.
@@ -117,6 +117,13 @@
g.setdefault("PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION", 23)
def init(g):
+ """Initializes globals.
+
+ The code is the Starlark counterpart of the contents of the
+ envsetup.mk file.
+ Args:
+ g: globals dictionary
+ """
all_versions = _all_versions()
_versions_default(g, all_versions)
for v in all_versions:
@@ -168,7 +175,8 @@
g["HOST_CROSS_2ND_ARCH_MODULE_SUFFIX"] = "_64"
g["TARGET_2ND_ARCH_VAR_PREFIX"] = "2ND_"
- # TODO(asmundak): combo-related stuff
+ # TODO(asmundak): envsetup.mk lines 216-226:
+ # convert combo-related stuff from combo/select.mk
# on windows, the tools have .exe at the end, and we depend on the
# host config stuff being done first
@@ -177,23 +185,23 @@
# the host build defaults to release, and it must be release or debug
g.setdefault("HOST_BUILD_TYPE", "release")
- if g["HOST_BUILD_TYPE"] != "release" and g["HOST_BUILD_TYPE"] != "debug":
+ if g["HOST_BUILD_TYPE"] not in ["release", "debug"]:
fail("HOST_BUILD_TYPE must be either release or debug, not '%s'" % g["HOST_BUILD_TYPE"])
- # TODO(asmundak): a lot more, but not needed for the product configuration
+ # TODO(asmundak): there is more stuff in envsetup.mk lines 249-292, but
+ # it does not seem to affect product configuration. Revisit this.
g["ART_APEX_JARS"] = [
"com.android.art:core-oj",
"com.android.art:core-libart",
"com.android.art:okhttp",
"com.android.art:bouncycastle",
- "com.android.art:apache-xml"
+ "com.android.art:apache-xml",
]
if g.get("TARGET_BUILD_TYPE", "") != "debug":
g["TARGET_BUILD_TYPE"] = "release"
-
v_default = "SP1A"
v_min = "SP1A"
v_max = "SP1A"
diff --git a/core/fuzz_test.mk b/core/fuzz_test.mk
index 4a0fcfa..8a4b8c3 100644
--- a/core/fuzz_test.mk
+++ b/core/fuzz_test.mk
@@ -19,35 +19,6 @@
ifeq ($(my_fuzzer),libFuzzer)
LOCAL_STATIC_LIBRARIES += libFuzzer
-else ifeq ($(my_fuzzer),honggfuzz)
-LOCAL_STATIC_LIBRARIES += honggfuzz_libhfuzz
-LOCAL_REQUIRED_MODULES += honggfuzz
-LOCAL_LDFLAGS += \
- "-Wl,--wrap=strcmp" \
- "-Wl,--wrap=strcasecmp" \
- "-Wl,--wrap=strncmp" \
- "-Wl,--wrap=strncasecmp" \
- "-Wl,--wrap=strstr" \
- "-Wl,--wrap=strcasestr" \
- "-Wl,--wrap=memcmp" \
- "-Wl,--wrap=bcmp" \
- "-Wl,--wrap=memmem" \
- "-Wl,--wrap=ap_cstr_casecmp" \
- "-Wl,--wrap=ap_cstr_casecmpn" \
- "-Wl,--wrap=ap_strcasestr" \
- "-Wl,--wrap=apr_cstr_casecmp" \
- "-Wl,--wrap=apr_cstr_casecmpn" \
- "-Wl,--wrap=CRYPTO_memcmp" \
- "-Wl,--wrap=OPENSSL_memcmp" \
- "-Wl,--wrap=OPENSSL_strcasecmp" \
- "-Wl,--wrap=OPENSSL_strncasecmp" \
- "-Wl,--wrap=xmlStrncmp" \
- "-Wl,--wrap=xmlStrcmp" \
- "-Wl,--wrap=xmlStrEqual" \
- "-Wl,--wrap=xmlStrcasecmp" \
- "-Wl,--wrap=xmlStrncasecmp" \
- "-Wl,--wrap=xmlStrstr" \
- "-Wl,--wrap=xmlStrcasestr"
else
$(call pretty-error, Unknown fuzz engine $(my_fuzzer))
endif
diff --git a/core/main.mk b/core/main.mk
index 56950ec..3362681 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -1573,6 +1573,8 @@
$(INSTALLED_SUPERIMAGE_EMPTY_TARGET) \
$(INSTALLED_PRODUCTIMAGE_TARGET) \
$(INSTALLED_SYSTEMOTHERIMAGE_TARGET) \
+ $(INSTALLED_TEST_HARNESS_RAMDISK_TARGET) \
+ $(INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET) \
$(INSTALLED_FILES_FILE) \
$(INSTALLED_FILES_JSON) \
$(INSTALLED_FILES_FILE_VENDOR) \
@@ -1750,14 +1752,12 @@
$(INSTALLED_FILES_JSON_VENDOR_DEBUG_RAMDISK) \
$(INSTALLED_DEBUG_RAMDISK_TARGET) \
$(INSTALLED_DEBUG_BOOTIMAGE_TARGET) \
+ $(INSTALLED_TEST_HARNESS_RAMDISK_TARGET) \
+ $(INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET) \
$(INSTALLED_VENDOR_DEBUG_BOOTIMAGE_TARGET) \
$(INSTALLED_VENDOR_RAMDISK_TARGET) \
$(INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET) \
)
- $(call dist-for-goals, bootimage_test_harness, \
- $(INSTALLED_TEST_HARNESS_RAMDISK_TARGET) \
- $(INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET) \
- )
endif
ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
diff --git a/core/product_config.rbc b/core/product_config.rbc
index 6e96822..111e759 100644
--- a/core/product_config.rbc
+++ b/core/product_config.rbc
@@ -1,4 +1,3 @@
-
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,7 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-load("//build/make/core:envsetup.rbc", _envsetup_init="init")
+load("//build/make/core:envsetup.rbc", _envsetup_init = "init")
+
"""Runtime functions."""
def _global_init():
@@ -33,10 +33,13 @@
# Variables that should be defined.
mandatory_vars = [
- "PLATFORM_VERSION_CODENAME", "PLATFORM_VERSION",
+ "PLATFORM_VERSION_CODENAME",
+ "PLATFORM_VERSION",
"PRODUCT_SOONG_NAMESPACES",
# TODO(asmundak): do we need TARGET_ARCH? AOSP does not reference it
- "TARGET_BUILD_TYPE", "TARGET_BUILD_VARIANT", "TARGET_PRODUCT",
+ "TARGET_BUILD_TYPE",
+ "TARGET_BUILD_VARIANT",
+ "TARGET_PRODUCT",
]
for bv in mandatory_vars:
if not bv in globals:
@@ -56,29 +59,26 @@
print(attr, "=", repr(value))
elif _options.format == "make":
print(attr, ":=", " ".join(value))
+ elif _options.format == "pretty":
+ print(attr, "=", repr(value))
+ elif _options.format == "make":
+ print(attr, ":=", value)
else:
- if _options.format == "pretty":
- print(attr, "=", repr(value))
- elif _options.format == "make":
- print(attr, ":=", value)
- else:
- fail("bad output format", _options.format)
-
+ fail("bad output format", _options.format)
def _printvars(globals, cfg):
"""Prints known configuration variables."""
for attr, val in sorted(cfg.items()):
__print_attr(attr, val)
if _options.print_globals:
+ print()
for attr, val in sorted(globals.items()):
- print()
if attr not in _globals_base:
__print_attr(attr, val)
-
-def __printvars_rearrange_list(l):
+def __printvars_rearrange_list(value_list):
"""Rearrange value list: return only distinct elements, maybe sorted."""
- seen = { item: 0 for item in l}
+ seen = {item: 0 for item in value_list}
return sorted(seen.keys()) if _options.rearrange == "sort" else seen.keys()
def _product_configuration(top_pcm_name, top_pcm):
@@ -97,44 +97,49 @@
globals = dict(**_globals_base)
- config_postfix = [] # Configs in postfix order
+ config_postfix = [] # Configs in postfix order
+
# Each PCM is represented by a quadruple of function, config, children names
# and readyness (that is, the configurations from inherited PCMs have been
# substituted).
- configs = { top_pcm_name: (top_pcm, None, [], False)} # All known PCMs
+ configs = {top_pcm_name: (top_pcm, None, [], False)} # All known PCMs
- stash = [] # Configs to push once their descendants are done
+ stash = [] # Configs to push once their descendants are done
- # Stack maintaining PCMs to be processed. An item in the stack
+ # Stack containing PCMs to be processed. An item in the stack
# is a pair of PCMs name and its height in the product inheritance tree.
- pcm_stack = []
- pcm_stack.append((top_pcm_name, 0))
+ pcm_stack = [(top_pcm_name, 0)]
pcm_count = 0
+
# Run it until pcm_stack is exhausted, but no more than N times
for n in range(1000):
if not pcm_stack:
break
(name, height) = pcm_stack.pop()
pcm, cfg, c, _ = configs[name]
- # each PCM is executed once
+
+ # cfg is set only after PCM has been called, leverage this
+ # to prevent calling the same PCM twice
if cfg != None:
continue
+
# Push ancestors until we reach this node's height
config_postfix.extend([stash.pop() for i in range(len(stash) - height)])
# Run this one, obtaining its configuration and child PCMs.
if _options.trace_modules:
- print("%s:" % n[0])
+ print("%d:" % n)
- # The handle passed to the PCM consists of config and inheritance state.dict of inherited modules
- # and a list containing the current default value of a list variable.
+ # Run PCM.
handle = __h_new()
pcm(globals, handle)
+
+ # Now we know everything about this PCM, record it in 'configs'.
children = __h_inherited_modules(handle)
if _options.trace_modules:
print(" ", " ".join(children.keys()))
configs[name] = (pcm, __h_cfg(handle), children.keys(), False)
- pcm_count = pcm_count+1
+ pcm_count = pcm_count + 1
if len(children) == 0:
# Leaf PCM goes straight to the config_postfix
@@ -143,17 +148,18 @@
# Stash this PCM, process children in the sorted order
stash.append(name)
- for child_name in sorted(children, reverse=True):
+ for child_name in sorted(children, reverse = True):
if child_name not in configs:
configs[child_name] = (children[child_name], None, [], False)
pcm_stack.append((child_name, len(stash)))
+ if pcm_stack:
+ fail("Inheritance processing took too many iterations")
# Flush the stash
config_postfix.extend([stash.pop() for i in range(len(stash))])
if len(config_postfix) != pcm_count:
fail("Ran %d modules but postfix tree has only %d entries" % (pcm_count, len(config_postfix)))
-
if _options.trace_modules:
print("\n---Postfix---")
for x in config_postfix:
@@ -162,55 +168,56 @@
# Traverse the tree from the bottom, evaluating inherited values
for pcm_name in config_postfix:
pcm, cfg, children_names, ready = configs[pcm_name]
+
# Should run
if cfg == None:
fail("%s: has not been run" % pcm_name)
+
# Ready once
if ready:
continue
+
# Children should be ready
for child_name in children_names:
if not configs[child_name][3]:
fail("%s: child is not ready" % child_name)
- # if _options.trace_modules:
- # print(">%s: %s" % (pcm_name, cfg))
-
_substitute_inherited(configs, pcm_name, cfg)
_percolate_inherited(configs, pcm_name, cfg, children_names)
configs[pcm_name] = pcm, cfg, children_names, True
- # if _options.trace_modules:
- # print("<%s: %s" % (pcm_name, cfg))
return globals, configs[top_pcm_name][1]
-
def _substitute_inherited(configs, pcm_name, cfg):
- """Substitutes inherited values in all the configuration settings."""
- for attr, val in cfg.items():
- trace_it = attr in _options.trace_variables
- if trace_it:
- old_val = val
+ """Substitutes inherited values in all the attributes.
+ When a value of an attribute is a list, some of its items may be
+ references to a value of a same attribute in an inherited product,
+ e.g., for a given module PRODUCT_PACKAGES can be
+ ["foo", (submodule), "bar"]
+ and for 'submodule' PRODUCT_PACKAGES may be ["baz"]
+ (we use a tuple to distinguish submodule references).
+ After the substitution the value of PRODUCT_PACKAGES for the module
+ will become ["foo", "baz", "bar"]
+ """
+ for attr, val in cfg.items():
# TODO(asmundak): should we handle single vars?
if type(val) != "list":
continue
- if trace_it:
+ if attr not in _options.trace_variables:
+ cfg[attr] = _value_expand(configs, attr, val)
+ else:
+ old_val = val
new_val = _value_expand(configs, attr, val)
if new_val != old_val:
print("%s(i): %s=%s (was %s)" % (pcm_name, attr, new_val, old_val))
cfg[attr] = new_val
- continue
-
- cfg[attr] = _value_expand(configs, attr, val)
-
-
def _value_expand(configs, attr, values_list):
"""Expands references to inherited values in a given list."""
result = []
- expanded={}
+ expanded = {}
for item in values_list:
# Inherited values are 1-tuples
if type(item) != "tuple":
@@ -227,7 +234,6 @@
return result
-
def _percolate_inherited(configs, cfg_name, cfg, children_names):
"""Percolates the settings that are present only in children."""
percolated_attrs = {}
@@ -251,19 +257,16 @@
if attr in percolated_attrs:
print("%s: %s^=%s" % (cfg_name, attr, cfg[attr]))
-
def __move_items(to_list, from_cfg, attr):
- l = from_cfg.get(attr, [])
- if l:
- to_list.extend(l)
+ value = from_cfg.get(attr, [])
+ if value:
+ to_list.extend(value)
from_cfg[attr] = []
-
def _indirect(pcm_name):
"""Returns configuration item for the inherited module."""
return (pcm_name,)
-
def _addprefix(prefix, string_or_list):
"""Adds prefix and returns a list.
@@ -276,8 +279,7 @@
string_or_list
"""
- return [ prefix + x for x in __words(string_or_list)]
-
+ return [prefix + x for x in __words(string_or_list)]
def _addsuffix(suffix, string_or_list):
"""Adds suffix and returns a list.
@@ -290,67 +292,82 @@
suffix
string_or_list
"""
- return [ x + suffix for x in __words(string_or_list)]
-
+ return [x + suffix for x in __words(string_or_list)]
def __words(string_or_list):
if type(string_or_list) == "list":
return string_or_list
return string_or_list.split()
-
+# Handle manipulation functions.
+# A handle passed to a PCM consists of:
+# product attributes dict ("cfg")
+# inherited modules dict (maps module name to PCM)
+# default value list (initially empty, modified by inheriting)
def __h_new():
"""Constructs a handle which is passed to PCM."""
return (dict(), dict(), list())
def __h_inherited_modules(handle):
+ """Returns PCM's inherited modules dict."""
return handle[1]
-
def __h_cfg(handle):
+ """Returns PCM's product configuration attributes dict.
+
+ This function is also exported as rblf.cfg, and every PCM
+ calls it at the beginning.
+ """
return handle[0]
-
def _setdefault(handle, attr):
- """Sets given attribute's value if it has not been set."""
+ """If attribute has not been set, assigns default value to it.
+
+ This function is exported as rblf.setdefault().
+ Only list attributes are initialized this way. The default
+ value is kept in the PCM's handle. Calling inherit() updates it.
+ """
cfg = handle[0]
if cfg.get(attr) == None:
cfg[attr] = list(handle[2])
return cfg[attr]
def _inherit(handle, pcm_name, pcm):
- """Records inheritance."""
+ """Records inheritance.
+
+ This function is exported as rblf.inherit, PCM calls it when
+ a module is inherited.
+ """
cfg, inherited, default_lv = handle
- inherited[pcm_name]=pcm
+ inherited[pcm_name] = pcm
default_lv.append(_indirect(pcm_name))
+
# Add inherited module reference to all configuration values
for attr, val in cfg.items():
if type(val) == "list":
val.append(_indirect(pcm_name))
-
def _copy_if_exists(path_pair):
"""If from file exists, returns [from:to] pair."""
- l = path_pair.split(":", 2)
+ value = path_pair.split(":", 2)
+
# Check that l[0] exists
- return [":".join(l)] if rblf_file_exists(l[0]) else []
+ return [":".join(value)] if rblf_file_exists(value[0]) else []
def _enforce_product_packages_exist(pkg_string_or_list):
"""Makes including non-existent modules in PRODUCT_PACKAGES an error."""
+
#TODO(asmundak)
pass
-
def _file_wildcard_exists(file_pattern):
"""Return True if there are files matching given bash pattern."""
return len(rblf_wildcard(file_pattern)) > 0
-
def _find_and_copy(pattern, from_dir, to_dir):
"""Return a copy list for the files matching the pattern."""
return ["%s/%s:%s/%s" % (from_dir, f, to_dir, f) for f in rblf_wildcard(pattern, from_dir)]
-
def _filter_out(pattern, text):
"""Return all the words from `text' that do not match any word in `pattern'.
@@ -367,7 +384,6 @@
res.append(w)
return res
-
def _filter(pattern, text):
"""Return all the words in `text` that match `pattern`.
@@ -383,49 +399,39 @@
res.append(w)
return res
-
def __mk2regex(words):
"""Returns regular expression equivalent to Make pattern."""
# TODO(asmundak): this will mishandle '\%'
return "^(" + "|".join([w.replace("%", ".*", 1) for w in words]) + ")"
-
def _regex_match(regex, w):
return rblf_regex(regex, w)
-
def _require_artifacts_in_path(paths, allowed_paths):
"""TODO."""
- #print("require_artifacts_in_path(", __words(paths), ",", __words(allowed_paths), ")")
pass
-
def _require_artifacts_in_path_relaxed(paths, allowed_paths):
"""TODO."""
pass
-
def _expand_wildcard(pattern):
"""Expands shell wildcard pattern."""
return rblf_wildcard(pattern)
-
-def _mkerror(file, message=""):
+def _mkerror(file, message = ""):
"""Prints error and stops."""
fail("%s: %s. Stop" % (file, message))
-
-def _mkwarning(file, message=""):
+def _mkwarning(file, message = ""):
"""Prints warning."""
print("%s: warning: %s" % (file, message))
-
-def _mkinfo(file, message=""):
+def _mkinfo(file, message = ""):
"""Prints info."""
print(message)
-
def __get_options():
"""Returns struct containing runtime global settings."""
settings = dict(
@@ -455,29 +461,29 @@
# Settings used during debugging.
_options = __get_options()
-rblf = struct(addprefix=_addprefix,
- addsuffix=_addsuffix,
- copy_if_exists=_copy_if_exists,
- cfg=__h_cfg,
- enforce_product_packages_exist=_enforce_product_packages_exist,
- expand_wildcard=_expand_wildcard,
- file_exists=rblf_file_exists,
- file_wildcard_exists=_file_wildcard_exists,
- filter=_filter,
- filter_out=_filter_out,
- find_and_copy=_find_and_copy,
- global_init=_global_init,
- inherit=_inherit,
- indirect=_indirect,
- mkinfo=_mkinfo,
- mkerror=_mkerror,
- mkwarning=_mkwarning,
- printvars=_printvars,
- product_configuration=_product_configuration,
- require_artifacts_in_path=_require_artifacts_in_path,
- require_artifacts_in_path_relaxed=_require_artifacts_in_path_relaxed,
- setdefault=_setdefault,
- shell=rblf_shell,
- warning=_mkwarning,
- )
-
+rblf = struct(
+ addprefix = _addprefix,
+ addsuffix = _addsuffix,
+ copy_if_exists = _copy_if_exists,
+ cfg = __h_cfg,
+ enforce_product_packages_exist = _enforce_product_packages_exist,
+ expand_wildcard = _expand_wildcard,
+ file_exists = rblf_file_exists,
+ file_wildcard_exists = _file_wildcard_exists,
+ filter = _filter,
+ filter_out = _filter_out,
+ find_and_copy = _find_and_copy,
+ global_init = _global_init,
+ inherit = _inherit,
+ indirect = _indirect,
+ mkinfo = _mkinfo,
+ mkerror = _mkerror,
+ mkwarning = _mkwarning,
+ printvars = _printvars,
+ product_configuration = _product_configuration,
+ require_artifacts_in_path = _require_artifacts_in_path,
+ require_artifacts_in_path_relaxed = _require_artifacts_in_path_relaxed,
+ setdefault = _setdefault,
+ shell = rblf_shell,
+ warning = _mkwarning,
+)
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index c87fb73..4fdfc88 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -385,11 +385,6 @@
SettingsProvider \
WallpaperBackup
-# Packages included only for eng/userdebug builds, when building with SANITIZE_TARGET=address
-PRODUCT_PACKAGES_DEBUG_ASAN := \
- fuzz \
- honggfuzz
-
PRODUCT_PACKAGES_DEBUG_JAVA_COVERAGE := \
libdumpcoverage
diff --git a/tools/rbcrun/Android.bp b/tools/rbcrun/Android.bp
index b5f7155..90173ac 100644
--- a/tools/rbcrun/Android.bp
+++ b/tools/rbcrun/Android.bp
@@ -13,6 +13,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
blueprint_go_binary {
name: "rbcrun",
srcs: ["cmd/rbcrun.go"],
diff --git a/tools/rbcrun/host.go b/tools/rbcrun/host.go
index f1697f1..1e43334 100644
--- a/tools/rbcrun/host.go
+++ b/tools/rbcrun/host.go
@@ -182,7 +182,7 @@
}
if shellPath == "" {
return starlark.None,
- fmt.Errorf("cannot run shell, SHELL environment variable is not set (running on Windows?)")
+ fmt.Errorf("cannot run shell, /bin/sh is missing (running on Windows?)")
}
cmd := exec.Command(shellPath, "-c", command)
// We ignore command's status
@@ -234,8 +234,12 @@
"rblf_wildcard": starlark.NewBuiltin("rblf_wildcard", wildcard),
}
- // NOTE(asmundak): OS-specific.
- shellPath, _ = os.LookupEnv("SHELL")
+ // NOTE(asmundak): OS-specific. Behave similar to Linux `system` call,
+ // which always uses /bin/sh to run the command
+ shellPath = "/bin/sh"
+ if _, err := os.Stat(shellPath); err != nil {
+ shellPath = ""
+ }
}
// Parses, resolves, and executes a Starlark file.
diff --git a/tools/releasetools/Android.bp b/tools/releasetools/Android.bp
index 3b0c070..65c035e 100644
--- a/tools/releasetools/Android.bp
+++ b/tools/releasetools/Android.bp
@@ -133,6 +133,7 @@
required: [
"brillo_update_payload",
"checkvintf",
+ "minigzip",
"lz4",
"toybox",
"unpack_bootimg",
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 414ab97..c550490 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -651,6 +651,9 @@
raise KeyError(fn)
return file
+class RamdiskFormat(object):
+ LZ4 = 1
+ GZ = 2
def LoadInfoDict(input_file, repacking=False):
"""Loads the key/value pairs from the given input target_files.
@@ -753,13 +756,17 @@
# Load recovery fstab if applicable.
d["fstab"] = _FindAndLoadRecoveryFstab(d, input_file, read_helper)
+ if d.get('lz4_ramdisks') == 'true':
+ ramdisk_format = RamdiskFormat.LZ4
+ else:
+ ramdisk_format = RamdiskFormat.GZ
# Tries to load the build props for all partitions with care_map, including
# system and vendor.
for partition in PARTITIONS_WITH_BUILD_PROP:
partition_prop = "{}.build.prop".format(partition)
d[partition_prop] = PartitionBuildProps.FromInputFile(
- input_file, partition)
+ input_file, partition, ramdisk_format=ramdisk_format)
d["build.prop"] = d["system.build.prop"]
# Set up the salt (based on fingerprint) that will be used when adding AVB
@@ -818,6 +825,9 @@
placeholder_values: A dict of runtime variables' values to replace the
placeholders in the build.prop file. We expect exactly one value for
each of the variables.
+ ramdisk_format: If name is "boot", the format of ramdisk inside the
+ boot image. Otherwise, its value is ignored.
+ Use lz4 to decompress by default. If its value is gzip, use minigzip.
"""
def __init__(self, input_file, name, placeholder_values=None):
@@ -840,11 +850,11 @@
return props
@staticmethod
- def FromInputFile(input_file, name, placeholder_values=None):
+ def FromInputFile(input_file, name, placeholder_values=None, ramdisk_format=RamdiskFormat.LZ4):
"""Loads the build.prop file and builds the attributes."""
if name == "boot":
- data = PartitionBuildProps._ReadBootPropFile(input_file)
+ data = PartitionBuildProps._ReadBootPropFile(input_file, ramdisk_format=ramdisk_format)
else:
data = PartitionBuildProps._ReadPartitionPropFile(input_file, name)
@@ -853,7 +863,7 @@
return props
@staticmethod
- def _ReadBootPropFile(input_file):
+ def _ReadBootPropFile(input_file, ramdisk_format):
"""
Read build.prop for boot image from input_file.
Return empty string if not found.
@@ -863,7 +873,7 @@
except KeyError:
logger.warning('Failed to read IMAGES/boot.img')
return ''
- prop_file = GetBootImageBuildProp(boot_img)
+ prop_file = GetBootImageBuildProp(boot_img, ramdisk_format=ramdisk_format)
if prop_file is None:
return ''
with open(prop_file, "r") as f:
@@ -3661,12 +3671,12 @@
append('move %s %s' % (p, u.tgt_group))
-def GetBootImageBuildProp(boot_img):
+def GetBootImageBuildProp(boot_img, ramdisk_format=RamdiskFormat.LZ4):
"""
Get build.prop from ramdisk within the boot image
Args:
- boot_img: the boot image file. Ramdisk must be compressed with lz4 format.
+ boot_img: the boot image file. Ramdisk must be compressed with lz4 or minigzip format.
Return:
An extracted file that stores properties in the boot image.
@@ -3679,7 +3689,16 @@
logger.warning('Unable to get boot image timestamp: no ramdisk in boot')
return None
uncompressed_ramdisk = os.path.join(tmp_dir, 'uncompressed_ramdisk')
- RunAndCheckOutput(['lz4', '-d', ramdisk, uncompressed_ramdisk])
+ if ramdisk_format == RamdiskFormat.LZ4:
+ RunAndCheckOutput(['lz4', '-d', ramdisk, uncompressed_ramdisk])
+ elif ramdisk_format == RamdiskFormat.GZ:
+ with open(ramdisk, 'rb') as input_stream:
+ with open(uncompressed_ramdisk, 'wb') as output_stream:
+ p2 = Run(['minigzip', '-d'], stdin=input_stream.fileno(), stdout=output_stream.fileno())
+ p2.wait()
+ else:
+ logger.error('Only support lz4 or minigzip ramdisk format.')
+ return None
abs_uncompressed_ramdisk = os.path.abspath(uncompressed_ramdisk)
extracted_ramdisk = MakeTempDir('extracted_ramdisk')