Merge "Add updatable_apex.mk"
diff --git a/core/Makefile b/core/Makefile
index 78ef81f..5e9fb29 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -662,6 +662,8 @@
# -----------------------------------------------------------------
# package stats
+ifdef BUILDING_SYSTEM_IMAGE
+
PACKAGE_STATS_FILE := $(PRODUCT_OUT)/package-stats.txt
PACKAGES_TO_STAT := \
$(sort $(filter $(TARGET_OUT)/% $(TARGET_OUT_DATA)/%, \
@@ -680,6 +682,8 @@
.PHONY: package-stats
package-stats: $(PACKAGE_STATS_FILE)
+endif # BUILDING_SYSTEM_IMAGE
+
# -----------------------------------------------------------------
# Cert-to-package mapping. Used by the post-build signing tools.
# Use a macro to add newline to each echo command
@@ -2048,6 +2052,8 @@
# on the device because it depends on everything in a given device
# image which defines a vintf_fragment.
+ifdef BUILDING_SYSTEM_IMAGE
+
BUILT_ASSEMBLED_SYSTEM_MANIFEST := $(PRODUCT_OUT)/verified_assembled_system_manifest.xml
$(BUILT_ASSEMBLED_SYSTEM_MANIFEST): $(HOST_OUT_EXECUTABLES)/assemble_vintf
$(BUILT_ASSEMBLED_SYSTEM_MANIFEST): $(BUILT_VENDOR_MATRIX)
@@ -2062,6 +2068,8 @@
find $(TARGET_OUT)/etc/vintf/manifest -type f -name "*.xml" | \
sed "s/^/-i /" | tr '\n' ' ') -o $@
+endif # BUILDING_SYSTEM_IMAGE
+
# -----------------------------------------------------------------
ifdef BUILDING_SYSTEM_IMAGE
@@ -2187,6 +2195,15 @@
# still may create these libraries in /system (b/129006418).
DISABLE_APEX_LIBS_ABSENCE_CHECK ?=
+# Exclude lib/arm and lib/arm64 which contain the native bridge proxy libs.
+# They are compiled for the guest architecture and used with an entirely
+# different linker config. The native libs are then linked to as usual via
+# exported interfaces, so the proxy libs do not violate the interface boundaries
+# on the native architecture.
+# TODO(b/130630776): Introduce a make variable for the appropriate directory
+# when native bridge is active.
+APEX_LIBS_ABSENCE_CHECK_EXCLUDE=lib/arm lib/arm64
+
# If the check below fails, some library has ended up in system/lib or
# system/lib64 that is intended to only go into some APEX package. The likely
# cause is that a library or binary in /system has grown a dependency that
@@ -2211,8 +2228,11 @@
ifndef DISABLE_APEX_LIBS_ABSENCE_CHECK
define check-apex-libs-absence
$(hide) ( \
- cd $(TARGET_OUT); \
- findres=$$(find lib* -type f \( -false $(foreach lib,$(APEX_MODULE_LIBS),-o -name $(lib)) \) -print) || exit 1; \
+ cd $(TARGET_OUT) && \
+ findres=$$(find lib* \
+ $(foreach dir,$(APEX_LIBS_ABSENCE_CHECK_EXCLUDE),-path $(dir) -prune -o) \
+ -type f \( -false $(foreach lib,$(APEX_MODULE_LIBS),-o -name $(lib)) \) \
+ -print) && \
if [ -n "$$findres" ]; then \
echo "APEX libraries found in system image (see comment in build/make/core/Makefile for details):" 1>&2; \
echo "$$findres" | sort 1>&2; \
@@ -3263,6 +3283,7 @@
--output $@
endef
+ifdef BUILDING_SYSTEM_IMAGE
ifdef BOARD_AVB_VBMETA_SYSTEM
INSTALLED_VBMETA_SYSTEMIMAGE_TARGET := $(PRODUCT_OUT)/vbmeta_system.img
$(INSTALLED_VBMETA_SYSTEMIMAGE_TARGET): \
@@ -3271,6 +3292,7 @@
$(BOARD_AVB_VBMETA_SYSTEM_KEY_PATH)
$(call build-chained-vbmeta-image,vbmeta_system)
endif
+endif # BUILDING_SYSTEM_IMAGE
ifdef BOARD_AVB_VBMETA_VENDOR
INSTALLED_VBMETA_VENDORIMAGE_TARGET := $(PRODUCT_OUT)/vbmeta_vendor.img
@@ -3721,6 +3743,13 @@
echo "build_non_sparse_super_partition=true" >> $(1))
endef
+# By conditionally including the dependency of the target files package on the
+# full system image deps, we speed up builds that do not build the system
+# image.
+ifdef BUILDING_SYSTEM_IMAGE
+$(BUILT_TARGET_FILES_PACKAGE): $(FULL_SYSTEMIMAGE_DEPS)
+endif
+
# Depending on the various images guarantees that the underlying
# directories are up-to-date.
$(BUILT_TARGET_FILES_PACKAGE): \
@@ -3728,7 +3757,6 @@
$(INSTALLED_BOOTIMAGE_TARGET) \
$(INSTALLED_RADIOIMAGE_TARGET) \
$(INSTALLED_RECOVERYIMAGE_TARGET) \
- $(FULL_SYSTEMIMAGE_DEPS) \
$(INSTALLED_USERDATAIMAGE_TARGET) \
$(INSTALLED_CACHEIMAGE_TARGET) \
$(INSTALLED_VENDORIMAGE_TARGET) \
@@ -4106,7 +4134,9 @@
endif
@# Metadata for compatibility verification.
$(hide) cp $(BUILT_SYSTEM_MATRIX) $(zip_root)/META/system_matrix.xml
+ifdef BUILT_ASSEMBLED_SYSTEM_MANIFEST
$(hide) cp $(BUILT_ASSEMBLED_SYSTEM_MANIFEST) $(zip_root)/META/system_manifest.xml
+endif
ifdef BUILT_ASSEMBLED_VENDOR_MANIFEST
$(hide) cp $(BUILT_ASSEMBLED_VENDOR_MANIFEST) $(zip_root)/META/vendor_manifest.xml
endif
diff --git a/core/build-system.html b/core/build-system.html
index 3a11a47..cc242d9 100644
--- a/core/build-system.html
+++ b/core/build-system.html
@@ -516,8 +516,8 @@
example the root filesystem instead of in /system, add these lines to your
Android.mk:</p>
<pre>
-LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)
-LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
+LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
+LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
</pre>
<p>For executables and libraries, you need to specify a
<code>LOCAL_UNSTRIPPED_PATH</code> location if you specified a
@@ -527,9 +527,6 @@
<code>LOCAL_MODULE_RELATIVE_PATH</code>.</p>
<p>Look in <code>core/envsetup.mk</code> for all of the variables defining
places to build things.</p>
-<p>FYI: If you're installing an executable to /sbin, you probably also want to
-set <code>LOCAL_FORCE_STATIC_EXCUTABLE := true</code> in your Android.mk, which
-will force the linker to only accept static libraries.</p>
<h3>Android.mk variables</h3>
@@ -685,8 +682,7 @@
<h4>LOCAL_FORCE_STATIC_EXECUTABLE</h4>
<p>If your executable should be linked statically, set
<code>LOCAL_FORCE_STATIC_EXECUTABLE:=true</code>. There is a very short
-list of libraries that we have in static form (currently only libc). This is
-really only used for executables in /sbin on the root filesystem.</p>
+list of libraries that we have in static form (currently only libc).</p>
<h4>LOCAL_GENERATED_SOURCES</h4>
<p>Files that you add to <code>LOCAL_GENERATED_SOURCES</code> will be
@@ -812,7 +808,7 @@
<h4>LOCAL_STATIC_LIBRARIES</h4>
<p>These are the static libraries that you want to include in your module.
Mostly, we use shared libraries, but there are a couple of places, like
-executables in sbin and host executables where we use static libraries instead.
+host executables where we use static libraries instead.
<p><code>LOCAL_STATIC_LIBRARIES := \<br/>
libutils \<br/>
libtinyxml
diff --git a/core/config.mk b/core/config.mk
index 3788721..b5fe866 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -93,6 +93,8 @@
$(KATI_obsolete_var DIST_DIR dist_goal,Use dist-for-goals instead. See $(CHANGES_URL)#dist)
$(KATI_obsolete_var TARGET_ANDROID_FILESYSTEM_CONFIG_H,Use TARGET_FS_CONFIG_GEN instead)
$(KATI_deprecated_var USER,Use BUILD_USERNAME instead. See $(CHANGES_URL)#USER)
+$(KATI_obsolete_var TARGET_ROOT_OUT_SBIN,/sbin has been removed, use /system/bin instead)
+$(KATI_obsolete_var TARGET_ROOT_OUT_SBIN_UNSTRIPPED,/sbin has been removed, use /system/bin instead)
# This is marked as obsolete in envsetup.mk after reading the BoardConfig.mk
$(KATI_deprecate_export It is a global setting. See $(CHANGES_URL)#export_keyword)
diff --git a/core/envsetup.mk b/core/envsetup.mk
index f4be2c7..7b90334 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -825,7 +825,6 @@
TARGET_OUT_SHARED_LIBRARIES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/system/lib
TARGET_OUT_VENDOR_SHARED_LIBRARIES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/$(TARGET_COPY_OUT_VENDOR)/lib
TARGET_ROOT_OUT_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)
-TARGET_ROOT_OUT_SBIN_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/sbin
TARGET_ROOT_OUT_BIN_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/bin
TARGET_OUT_COVERAGE := $(PRODUCT_OUT)/coverage
.KATI_READONLY := \
@@ -834,7 +833,6 @@
TARGET_OUT_SHARED_LIBRARIES_UNSTRIPPED \
TARGET_OUT_VENDOR_SHARED_LIBRARIES_UNSTRIPPED \
TARGET_ROOT_OUT_UNSTRIPPED \
- TARGET_ROOT_OUT_SBIN_UNSTRIPPED \
TARGET_ROOT_OUT_BIN_UNSTRIPPED \
TARGET_OUT_COVERAGE
@@ -843,13 +841,11 @@
TARGET_ROOT_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ROOT)
TARGET_ROOT_OUT_BIN := $(TARGET_ROOT_OUT)/bin
-TARGET_ROOT_OUT_SBIN := $(TARGET_ROOT_OUT)/sbin
TARGET_ROOT_OUT_ETC := $(TARGET_ROOT_OUT)/etc
TARGET_ROOT_OUT_USR := $(TARGET_ROOT_OUT)/usr
.KATI_READONLY := \
TARGET_ROOT_OUT \
TARGET_ROOT_OUT_BIN \
- TARGET_ROOT_OUT_SBIN \
TARGET_ROOT_OUT_ETC \
TARGET_ROOT_OUT_USR
diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py
index 3b72551..e306807 100755
--- a/tools/releasetools/merge_target_files.py
+++ b/tools/releasetools/merge_target_files.py
@@ -13,11 +13,11 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
+"""This script merges two partial target files packages.
-"""
-This script merges two partial target files packages (one of which contains
-system files, and the other contains non-system files) together, producing a
-complete target files package that can be used to generate an OTA package.
+One package contains system files, and the other contains non-system files.
+It produces a complete target files package that can be used to generate an
+OTA package.
Usage: merge_target_files.py [args]
@@ -42,7 +42,25 @@
contents of default_other_item_list if provided.
--output-target-files output-target-files-package
- The output merged target files package. Also a zip archive.
+ If provided, the output merged target files package. Also a zip archive.
+
+ --output-dir output-directory
+ If provided, the destination directory for saving merged files. Requires
+ the --output-item-list flag.
+ Can be provided alongside --output-target-files, or by itself.
+
+ --output-item-list output-item-list-file.
+ The optional path to a newline-separated config file that specifies the
+ file patterns to copy into the --output-dir. Required if providing
+ the --output-dir flag.
+
+ --output-ota output-ota-package
+ The output ota package. This is a zip archive. Use of this flag may
+ require passing the --path common flag; see common.py.
+
+ --output-super-empty output-super-empty-image
+ If provided, creates a super_empty.img file from the merged target
+ files package and saves it at this path.
--rebuild_recovery
Rebuild the recovery patch used by non-A/B devices and write it to the
@@ -57,11 +75,14 @@
import fnmatch
import logging
import os
+import shutil
import sys
import zipfile
-import common
import add_img_to_target_files
+import build_super_image
+import common
+import ota_from_target_files
logger = logging.getLogger(__name__)
OPTIONS = common.OPTIONS
@@ -72,6 +93,10 @@
OPTIONS.other_target_files = None
OPTIONS.other_item_list = None
OPTIONS.output_target_files = None
+OPTIONS.output_dir = None
+OPTIONS.output_item_list = None
+OPTIONS.output_ota = None
+OPTIONS.output_super_empty = None
OPTIONS.rebuild_recovery = False
OPTIONS.keep_tmp = False
@@ -101,8 +126,8 @@
'META/*',
]
-# default_system_misc_info_keys is a list of keys to obtain from the system instance of
-# META/misc_info.txt. The remaining keys from the other instance.
+# default_system_misc_info_keys is a list of keys to obtain from the system
+# instance of META/misc_info.txt. The remaining keys from the other instance.
default_system_misc_info_keys = [
'avb_system_hashtree_enable',
@@ -160,10 +185,8 @@
Args:
target_files: The target files zip archive from which to extract items.
-
target_files_temp_dir: The temporary directory where the extracted items
- will land.
-
+ will land.
extract_item_list: A list of items to extract.
"""
@@ -173,9 +196,7 @@
# zip file. Otherwise, the extraction step will fail.
with zipfile.ZipFile(
- target_files,
- 'r',
- allowZip64=True) as target_files_zipfile:
+ target_files, 'r', allowZip64=True) as target_files_zipfile:
target_files_namelist = target_files_zipfile.namelist()
filtered_extract_item_list = []
@@ -189,10 +210,32 @@
# Extract from target_files into target_files_temp_dir the
# filtered_extract_item_list.
- common.UnzipToDir(
- target_files,
- target_files_temp_dir,
- filtered_extract_item_list)
+ common.UnzipToDir(target_files, target_files_temp_dir,
+ filtered_extract_item_list)
+
+
+def copy_items(from_dir, to_dir, patterns):
+ """Similar to extract_items() except uses an input dir instead of zip."""
+ file_paths = []
+ for dirpath, _, filenames in os.walk(from_dir):
+ file_paths.extend(
+ os.path.relpath(path=os.path.join(dirpath, filename), start=from_dir)
+ for filename in filenames)
+
+ filtered_file_paths = set()
+ for pattern in patterns:
+ filtered_file_paths.update(fnmatch.filter(file_paths, pattern))
+
+ for file_path in filtered_file_paths:
+ original_file_path = os.path.join(from_dir, file_path)
+ copied_file_path = os.path.join(to_dir, file_path)
+ copied_file_dir = os.path.dirname(copied_file_path)
+ if not os.path.exists(copied_file_dir):
+ os.makedirs(copied_file_dir)
+ if os.path.islink(original_file_path):
+ os.symlink(os.readlink(original_file_path), copied_file_path)
+ else:
+ shutil.copyfile(original_file_path, copied_file_path)
def read_config_list(config_file_path):
@@ -202,26 +245,25 @@
Args:
config_file_path: The path to the config file to open and read.
+
+ Returns:
+ The list of strings in the config file.
"""
with open(config_file_path) as config_file:
return config_file.read().splitlines()
-def validate_config_lists(
- system_item_list,
- system_misc_info_keys,
- other_item_list):
+def validate_config_lists(system_item_list, system_misc_info_keys,
+ other_item_list):
"""Performs validations on the merge config lists.
Args:
- system_item_list: The list of items to extract from the partial
- system target files package as is.
-
- system_misc_info_keys: A list of keys to obtain from the system instance
- of META/misc_info.txt. The remaining keys from the other instance.
-
- other_item_list: The list of items to extract from the partial
- other target files package as is.
+ system_item_list: The list of items to extract from the partial system
+ target files package as is.
+ system_misc_info_keys: A list of keys to obtain from the system instance of
+ META/misc_info.txt. The remaining keys from the other instance.
+ other_item_list: The list of items to extract from the partial other target
+ files package as is.
Returns:
False if a validation fails, otherwise true.
@@ -236,7 +278,7 @@
# by the default config lists.
difference = default_combined_item_set.difference(combined_item_set)
if difference:
- logger.error('Missing merge config items: %s' % list(difference))
+ logger.error('Missing merge config items: %s', list(difference))
logger.error('Please ensure missing items are in either the '
'system-item-list or other-item-list files provided to '
'this script.')
@@ -251,11 +293,10 @@
return True
-def process_ab_partitions_txt(
- system_target_files_temp_dir,
- other_target_files_temp_dir,
- output_target_files_temp_dir):
- """Perform special processing for META/ab_partitions.txt
+def process_ab_partitions_txt(system_target_files_temp_dir,
+ other_target_files_temp_dir,
+ output_target_files_temp_dir):
+ """Perform special processing for META/ab_partitions.txt.
This function merges the contents of the META/ab_partitions.txt files from
the system directory and the other directory, placing the merged result in
@@ -266,22 +307,20 @@
names.
Args:
- system_target_files_temp_dir: The name of a directory containing the
- special items extracted from the system target files package.
-
- other_target_files_temp_dir: The name of a directory containing the
- special items extracted from the other target files package.
-
- output_target_files_temp_dir: The name of a directory that will be used
- to create the output target files package after all the special cases
- are processed.
+ system_target_files_temp_dir: The name of a directory containing the special
+ items extracted from the system target files package.
+ other_target_files_temp_dir: The name of a directory containing the special
+ items extracted from the other target files package.
+ output_target_files_temp_dir: The name of a directory that will be used to
+ create the output target files package after all the special cases are
+ processed.
"""
- system_ab_partitions_txt = os.path.join(
- system_target_files_temp_dir, 'META', 'ab_partitions.txt')
+ system_ab_partitions_txt = os.path.join(system_target_files_temp_dir, 'META',
+ 'ab_partitions.txt')
- other_ab_partitions_txt = os.path.join(
- other_target_files_temp_dir, 'META', 'ab_partitions.txt')
+ other_ab_partitions_txt = os.path.join(other_target_files_temp_dir, 'META',
+ 'ab_partitions.txt')
with open(system_ab_partitions_txt) as f:
system_ab_partitions = f.read().splitlines()
@@ -291,8 +330,8 @@
output_ab_partitions = set(system_ab_partitions + other_ab_partitions)
- output_ab_partitions_txt = os.path.join(
- output_target_files_temp_dir, 'META', 'ab_partitions.txt')
+ output_ab_partitions_txt = os.path.join(output_target_files_temp_dir, 'META',
+ 'ab_partitions.txt')
with open(output_ab_partitions_txt, 'w') as output:
for partition in sorted(output_ab_partitions):
@@ -300,42 +339,35 @@
def append_recovery_to_filesystem_config(output_target_files_temp_dir):
- """Perform special processing for META/filesystem_config.txt
+ """Perform special processing for META/filesystem_config.txt.
This function appends recovery information to META/filesystem_config.txt
so that recovery patch regeneration will succeed.
Args:
- output_target_files_temp_dir: The name of a directory that will be used
- to create the output target files package after all the special cases
- are processed. We find filesystem_config.txt here.
+ output_target_files_temp_dir: The name of a directory that will be used to
+ create the output target files package after all the special cases are
+ processed. We find filesystem_config.txt here.
"""
- filesystem_config_txt = os.path.join(
- output_target_files_temp_dir,
- 'META',
- 'filesystem_config.txt')
+ filesystem_config_txt = os.path.join(output_target_files_temp_dir, 'META',
+ 'filesystem_config.txt')
with open(filesystem_config_txt, 'a') as f:
# TODO(bpeckham) this data is hard coded. It should be generated
# programmatically.
- f.write(
- 'system/bin/install-recovery.sh 0 0 750 '
- 'selabel=u:object_r:install_recovery_exec:s0 capabilities=0x0\n')
- f.write(
- 'system/recovery-from-boot.p 0 0 644 '
- 'selabel=u:object_r:system_file:s0 capabilities=0x0\n')
- f.write(
- 'system/etc/recovery.img 0 0 440 '
- 'selabel=u:object_r:install_recovery_exec:s0 capabilities=0x0\n')
+ f.write('system/bin/install-recovery.sh 0 0 750 '
+ 'selabel=u:object_r:install_recovery_exec:s0 capabilities=0x0\n')
+ f.write('system/recovery-from-boot.p 0 0 644 '
+ 'selabel=u:object_r:system_file:s0 capabilities=0x0\n')
+ f.write('system/etc/recovery.img 0 0 440 '
+ 'selabel=u:object_r:install_recovery_exec:s0 capabilities=0x0\n')
-def process_misc_info_txt(
- system_target_files_temp_dir,
- other_target_files_temp_dir,
- output_target_files_temp_dir,
- system_misc_info_keys):
- """Perform special processing for META/misc_info.txt
+def process_misc_info_txt(system_target_files_temp_dir,
+ other_target_files_temp_dir,
+ output_target_files_temp_dir, system_misc_info_keys):
+ """Perform special processing for META/misc_info.txt.
This function merges the contents of the META/misc_info.txt files from the
system directory and the other directory, placing the merged result in the
@@ -344,18 +376,15 @@
content.
Args:
- system_target_files_temp_dir: The name of a directory containing the
- special items extracted from the system target files package.
-
- other_target_files_temp_dir: The name of a directory containing the
- special items extracted from the other target files package.
-
- output_target_files_temp_dir: The name of a directory that will be used
- to create the output target files package after all the special cases
- are processed.
-
- system_misc_info_keys: A list of keys to obtain from the system instance
- of META/misc_info.txt. The remaining keys from the other instance.
+ system_target_files_temp_dir: The name of a directory containing the special
+ items extracted from the system target files package.
+ other_target_files_temp_dir: The name of a directory containing the special
+ items extracted from the other target files package.
+ output_target_files_temp_dir: The name of a directory that will be used to
+ create the output target files package after all the special cases are
+ processed.
+ system_misc_info_keys: A list of keys to obtain from the system instance of
+ META/misc_info.txt. The remaining keys from the other instance.
"""
def read_helper(d):
@@ -386,19 +415,18 @@
# Partition groups and group sizes are defined by the other (non-system)
# misc info file because these values may vary for each board that uses
# a shared system image.
- for partition_group in merged_info_dict['super_partition_groups'].split(' '):
+ for partition_group in merged_info_dict['super_partition_groups'].split(
+ ' '):
if ('super_%s_group_size' % partition_group) not in merged_info_dict:
- raise common.ExternalError(
+ raise ValueError(
'Other META/misc_info.txt does not contain required key '
'super_%s_group_size.' % partition_group)
key = 'super_%s_partition_list' % partition_group
- merged_info_dict[key] = '%s %s' % (
- system_info_dict.get(key, ''),
- merged_info_dict.get(key, ''))
+ merged_info_dict[key] = '%s %s' % (system_info_dict.get(
+ key, ''), merged_info_dict.get(key, ''))
- output_misc_info_txt = os.path.join(
- output_target_files_temp_dir,
- 'META', 'misc_info.txt')
+ output_misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
+ 'misc_info.txt')
sorted_keys = sorted(merged_info_dict.keys())
@@ -416,12 +444,11 @@
Args:
temp_dir: The name of a scratch directory that this function can use for
- intermediate files generated during processing.
-
+ intermediate files generated during processing.
output_target_files_temp_dir: The name of the working directory that must
- already contain plat_file_contexts and vendor_file_contexts (in the
- appropriate sub directories), and to which META/file_contexts.bin will be
- written.
+ already contain plat_file_contexts and vendor_file_contexts (in the
+ appropriate sub directories), and to which META/file_contexts.bin will be
+ written.
"""
# To create a merged file_contexts.bin file, we use the system and vendor
@@ -442,9 +469,8 @@
for partition in ['SYSTEM', 'VENDOR', 'PRODUCT', 'ODM']:
prefix = 'plat' if partition == 'SYSTEM' else partition.lower()
- file_contexts = os.path.join(
- output_target_files_temp_dir,
- partition, 'etc', 'selinux', prefix + '_file_contexts')
+ file_contexts = os.path.join(output_target_files_temp_dir, partition, 'etc',
+ 'selinux', prefix + '_file_contexts')
mandatory = partition in ['SYSTEM', 'VENDOR']
@@ -470,27 +496,23 @@
# Finally, the compile step creates the final META/file_contexts.bin.
- file_contexts_bin = os.path.join(
- output_target_files_temp_dir,
- 'META', 'file_contexts.bin')
+ file_contexts_bin = os.path.join(output_target_files_temp_dir, 'META',
+ 'file_contexts.bin')
command = [
'sefcontext_compile',
- '-o', file_contexts_bin,
+ '-o',
+ file_contexts_bin,
sorted_file_contexts_txt,
]
common.RunAndWait(command, verbose=True)
-def process_special_cases(
- temp_dir,
- system_target_files_temp_dir,
- other_target_files_temp_dir,
- output_target_files_temp_dir,
- system_misc_info_keys,
- rebuild_recovery
-):
+def process_special_cases(temp_dir, system_target_files_temp_dir,
+ other_target_files_temp_dir,
+ output_target_files_temp_dir, system_misc_info_keys,
+ rebuild_recovery):
"""Perform special-case processing for certain target files items.
Certain files in the output target files package require special-case
@@ -498,23 +520,18 @@
Args:
temp_dir: The name of a scratch directory that this function can use for
- intermediate files generated during processing.
-
- system_target_files_temp_dir: The name of a directory containing the
- special items extracted from the system target files package.
-
- other_target_files_temp_dir: The name of a directory containing the
- special items extracted from the other target files package.
-
- output_target_files_temp_dir: The name of a directory that will be used
- to create the output target files package after all the special cases
- are processed.
-
- system_misc_info_keys: A list of keys to obtain from the system instance
- of META/misc_info.txt. The remaining keys from the other instance.
-
+ intermediate files generated during processing.
+ system_target_files_temp_dir: The name of a directory containing the special
+ items extracted from the system target files package.
+ other_target_files_temp_dir: The name of a directory containing the special
+ items extracted from the other target files package.
+ output_target_files_temp_dir: The name of a directory that will be used to
+ create the output target files package after all the special cases are
+ processed.
+ system_misc_info_keys: A list of keys to obtain from the system instance of
+ META/misc_info.txt. The remaining keys from the other instance.
rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
- devices and write it to the system image.
+ devices and write it to the system image.
"""
if 'ab_update' in system_misc_info_keys:
@@ -538,15 +555,11 @@
output_target_files_temp_dir=output_target_files_temp_dir)
-def merge_target_files(
- temp_dir,
- system_target_files,
- system_item_list,
- system_misc_info_keys,
- other_target_files,
- other_item_list,
- output_target_files,
- rebuild_recovery):
+def merge_target_files(temp_dir, system_target_files, system_item_list,
+ system_misc_info_keys, other_target_files,
+ other_item_list, output_target_files, output_dir,
+ output_item_list, output_ota, output_super_empty,
+ rebuild_recovery):
"""Merge two target files packages together.
This function takes system and other target files packages as input, performs
@@ -555,40 +568,35 @@
Args:
temp_dir: The name of a directory we use when we extract items from the
- input target files packages, and also a scratch directory that we use for
- temporary files.
-
+ input target files packages, and also a scratch directory that we use for
+ temporary files.
system_target_files: The name of the zip archive containing the system
- partial target files package.
-
+ partial target files package.
system_item_list: The list of items to extract from the partial system
- target files package as is, meaning these items will land in the output
- target files package exactly as they appear in the input partial system
- target files package.
-
+ target files package as is, meaning these items will land in the output
+ target files package exactly as they appear in the input partial system
+ target files package.
system_misc_info_keys: The list of keys to obtain from the system instance
- of META/misc_info.txt. The remaining keys from the other instance.
-
- other_target_files: The name of the zip archive containing the other
- partial target files package.
-
- other_item_list: The list of items to extract from the partial other
- target files package as is, meaning these items will land in the output
- target files package exactly as they appear in the input partial other
- target files package.
-
- output_target_files: The name of the output zip archive target files
- package created by merging system and other.
-
+ of META/misc_info.txt. The remaining keys from the other instance.
+ other_target_files: The name of the zip archive containing the other partial
+ target files package.
+ other_item_list: The list of items to extract from the partial other target
+ files package as is, meaning these items will land in the output target
+ files package exactly as they appear in the input partial other target
+ files package.
+ output_target_files: The name of the output zip archive target files package
+ created by merging system and other.
+ output_dir: The destination directory for saving merged files.
+ output_item_list: The list of items to copy into the output_dir.
+ output_ota: The name of the output zip archive ota package.
+ output_super_empty: If provided, creates a super_empty.img file from the
+ merged target files package and saves it at this path.
rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
- devices and write it to the system image.
+ devices and write it to the system image.
"""
- logger.info(
- 'starting: merge system %s and other %s into output %s',
- system_target_files,
- other_target_files,
- output_target_files)
+ logger.info('starting: merge system %s and other %s into output %s',
+ system_target_files, other_target_files, output_target_files)
# Create directory names that we'll use when we extract files from system,
# and other, and for zipping the final output.
@@ -646,6 +654,28 @@
system_misc_info_keys=system_misc_info_keys,
rebuild_recovery=rebuild_recovery)
+ # Create super_empty.img using the merged misc_info.txt.
+
+ if output_super_empty:
+ misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
+ 'misc_info.txt')
+
+ def read_helper():
+ with open(misc_info_txt) as f:
+ return list(f.read().splitlines())
+
+ misc_info_dict = common.LoadDictionaryFromLines(read_helper())
+ if misc_info_dict.get('use_dynamic_partitions') != 'true':
+ raise ValueError(
+ 'Building super_empty.img requires use_dynamic_partitions=true.')
+
+ build_super_image_args = [
+ '--verbose',
+ misc_info_txt,
+ output_super_empty,
+ ]
+ build_super_image.main(build_super_image_args)
+
# Regenerate IMAGES in the temporary directory.
add_img_args = ['--verbose']
@@ -655,12 +685,19 @@
add_img_to_target_files.main(add_img_args)
- # Finally, create the output target files zip archive.
+ # Finally, create the output target files zip archive and/or copy the
+ # output items to the output target files directory.
+
+ if output_dir:
+ copy_items(output_target_files_temp_dir, output_dir, output_item_list)
+
+ if not output_target_files:
+ return
output_zip = os.path.abspath(output_target_files)
output_target_files_list = os.path.join(temp_dir, 'output.list')
- output_target_files_meta_dir = os.path.join(
- output_target_files_temp_dir, 'META')
+ output_target_files_meta_dir = os.path.join(output_target_files_temp_dir,
+ 'META')
command = [
'find',
@@ -669,13 +706,8 @@
# TODO(bpeckham): sort this to be more like build.
meta_content = common.RunAndCheckOutput(command, verbose=False)
command = [
- 'find',
- output_target_files_temp_dir,
- '-path',
- output_target_files_meta_dir,
- '-prune',
- '-o',
- '-print'
+ 'find', output_target_files_temp_dir, '-path',
+ output_target_files_meta_dir, '-prune', '-o', '-print'
]
# TODO(bpeckham): sort this to be more like build.
other_content = common.RunAndCheckOutput(command, verbose=False)
@@ -687,13 +719,25 @@
command = [
'soong_zip',
'-d',
- '-o', output_zip,
- '-C', output_target_files_temp_dir,
- '-l', output_target_files_list,
+ '-o',
+ output_zip,
+ '-C',
+ output_target_files_temp_dir,
+ '-l',
+ output_target_files_list,
]
logger.info('creating %s', output_target_files)
common.RunAndWait(command, verbose=True)
+ # Create the OTA package from the merged target files package.
+
+ if output_ota:
+ ota_from_target_files_args = [
+ output_zip,
+ output_ota,
+ ]
+ ota_from_target_files.main(ota_from_target_files_args)
+
def call_func_with_temp_dir(func, keep_tmp):
"""Manage the creation and cleanup of the temporary directory.
@@ -702,9 +746,8 @@
directory. It also cleans up the temporary directory.
Args:
- func: The function to call. Should accept one parameter, the path to
- the temporary directory.
-
+ func: The function to call. Should accept one parameter, the path to the
+ temporary directory.
keep_tmp: Keep the temporary directory after processing is complete.
"""
@@ -747,6 +790,14 @@
OPTIONS.other_item_list = a
elif o == '--output-target-files':
OPTIONS.output_target_files = a
+ elif o == '--output-dir':
+ OPTIONS.output_dir = a
+ elif o == '--output-item-list':
+ OPTIONS.output_item_list = a
+ elif o == '--output-ota':
+ OPTIONS.output_ota = a
+ elif o == '--output-super-empty':
+ OPTIONS.output_super_empty = a
elif o == '--rebuild_recovery':
OPTIONS.rebuild_recovery = True
elif o == '--keep-tmp':
@@ -756,7 +807,8 @@
return True
args = common.ParseOptions(
- sys.argv[1:], __doc__,
+ sys.argv[1:],
+ __doc__,
extra_long_opts=[
'system-target-files=',
'system-item-list=',
@@ -764,15 +816,19 @@
'other-target-files=',
'other-item-list=',
'output-target-files=',
+ 'output-dir=',
+ 'output-item-list=',
+ 'output-ota=',
+ 'output-super-empty=',
'rebuild_recovery',
'keep-tmp',
],
extra_option_handler=option_handler)
- if (len(args) != 0 or
- OPTIONS.system_target_files is None or
+ if (args or OPTIONS.system_target_files is None or
OPTIONS.other_target_files is None or
- OPTIONS.output_target_files is None):
+ (OPTIONS.output_target_files is None and OPTIONS.output_dir is None) or
+ (OPTIONS.output_dir is not None and OPTIONS.output_item_list is None)):
common.Usage(__doc__)
sys.exit(1)
@@ -791,6 +847,11 @@
else:
other_item_list = default_other_item_list
+ if OPTIONS.output_item_list:
+ output_item_list = read_config_list(OPTIONS.output_item_list)
+ else:
+ output_item_list = None
+
if not validate_config_lists(
system_item_list=system_item_list,
system_misc_info_keys=system_misc_info_keys,
@@ -806,8 +867,11 @@
other_target_files=OPTIONS.other_target_files,
other_item_list=other_item_list,
output_target_files=OPTIONS.output_target_files,
- rebuild_recovery=OPTIONS.rebuild_recovery),
- OPTIONS.keep_tmp)
+ output_dir=OPTIONS.output_dir,
+ output_item_list=output_item_list,
+ output_ota=OPTIONS.output_ota,
+ output_super_empty=OPTIONS.output_super_empty,
+ rebuild_recovery=OPTIONS.rebuild_recovery), OPTIONS.keep_tmp)
if __name__ == '__main__':
diff --git a/tools/releasetools/test_merge_target_files.py b/tools/releasetools/test_merge_target_files.py
index ec452a8..7e18a34 100644
--- a/tools/releasetools/test_merge_target_files.py
+++ b/tools/releasetools/test_merge_target_files.py
@@ -16,10 +16,12 @@
import os.path
+import common
import test_utils
-from merge_target_files import (
- read_config_list, validate_config_lists, default_system_item_list,
- default_other_item_list, default_system_misc_info_keys)
+from merge_target_files import (read_config_list, validate_config_lists,
+ default_system_item_list,
+ default_other_item_list,
+ default_system_misc_info_keys, copy_items)
class MergeTargetFilesTest(test_utils.ReleaseToolsTestCase):
@@ -27,6 +29,58 @@
def setUp(self):
self.testdata_dir = test_utils.get_testdata_dir()
+ def test_copy_items_CopiesItemsMatchingPatterns(self):
+
+ def createEmptyFile(path):
+ if not os.path.exists(os.path.dirname(path)):
+ os.makedirs(os.path.dirname(path))
+ open(path, 'a').close()
+ return path
+
+ def createSymLink(source, dest):
+ os.symlink(source, dest)
+ return dest
+
+ def getRelPaths(start, filepaths):
+ return set(
+ os.path.relpath(path=filepath, start=start) for filepath in filepaths)
+
+ input_dir = common.MakeTempDir()
+ output_dir = common.MakeTempDir()
+ expected_copied_items = []
+ actual_copied_items = []
+ patterns = ['*.cpp', 'subdir/*.txt']
+
+ # Create various files that we expect to get copied because they
+ # match one of the patterns.
+ expected_copied_items.extend([
+ createEmptyFile(os.path.join(input_dir, 'a.cpp')),
+ createEmptyFile(os.path.join(input_dir, 'b.cpp')),
+ createEmptyFile(os.path.join(input_dir, 'subdir', 'c.txt')),
+ createEmptyFile(os.path.join(input_dir, 'subdir', 'd.txt')),
+ createEmptyFile(
+ os.path.join(input_dir, 'subdir', 'subsubdir', 'e.txt')),
+ createSymLink('a.cpp', os.path.join(input_dir, 'a_link.cpp')),
+ ])
+ # Create some more files that we expect to not get copied.
+ createEmptyFile(os.path.join(input_dir, 'a.h'))
+ createEmptyFile(os.path.join(input_dir, 'b.h'))
+ createEmptyFile(os.path.join(input_dir, 'subdir', 'subsubdir', 'f.gif'))
+ createSymLink('a.h', os.path.join(input_dir, 'a_link.h'))
+
+ # Copy items.
+ copy_items(input_dir, output_dir, patterns)
+
+ # Assert the actual copied items match the ones we expected.
+ for dirpath, _, filenames in os.walk(output_dir):
+ actual_copied_items.extend(
+ os.path.join(dirpath, filename) for filename in filenames)
+ self.assertEqual(
+ getRelPaths(output_dir, actual_copied_items),
+ getRelPaths(input_dir, expected_copied_items))
+ self.assertEqual(
+ os.readlink(os.path.join(output_dir, 'a_link.cpp')), 'a.cpp')
+
def test_read_config_list(self):
system_item_list_file = os.path.join(self.testdata_dir,
'merge_config_system_item_list')