blob: 7724d6f9d5082dbf66d7f82dac8a8570b19f055d [file] [log] [blame]
Daniel Normanbfc51ef2019-07-24 14:34:54 -07001#!/usr/bin/env python
2#
3# Copyright (C) 2019 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may not
6# use this file except in compliance with the License. You may obtain a copy of
7# the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations under
15# the License.
16#
17"""Merges two non-dist partial builds together.
18
19Given two partial builds, a framework build and a vendor build, merge the builds
20together so that the images can be flashed using 'fastboot flashall'.
21
22To support both DAP and non-DAP vendor builds with a single framework partial
23build, the framework partial build should always be built with DAP enabled. The
24vendor partial build determines whether the merged result supports DAP.
25
26This script does not require builds to be built with 'make dist'.
27This script assumes that images other than super_empty.img do not require
28regeneration, including vbmeta images.
29TODO(b/137853921): Add support for regenerating vbmeta images.
30
31Usage: merge_builds.py [args]
32
33 --framework_images comma_separated_image_list
34 Comma-separated list of image names that should come from the framework
35 build.
36
37 --product_out_framework product_out_framework_path
38 Path to out/target/product/<framework build>.
39
40 --product_out_vendor product_out_vendor_path
41 Path to out/target/product/<vendor build>.
42"""
43from __future__ import print_function
44
45import logging
46import os
47import sys
48
49import build_super_image
50import common
51
52logger = logging.getLogger(__name__)
53
54OPTIONS = common.OPTIONS
55OPTIONS.framework_images = ("system",)
56OPTIONS.product_out_framework = None
57OPTIONS.product_out_vendor = None
58
59
60def CreateImageSymlinks():
61 for image in OPTIONS.framework_images:
62 image_path = os.path.join(OPTIONS.product_out_framework, "%s.img" % image)
63 symlink_path = os.path.join(OPTIONS.product_out_vendor, "%s.img" % image)
64 if os.path.exists(symlink_path):
65 if os.path.islink(symlink_path):
66 os.remove(symlink_path)
67 else:
68 raise ValueError("Attempting to overwrite built image: %s" %
69 symlink_path)
70 os.symlink(image_path, symlink_path)
71
72
73def BuildSuperEmpty():
74 framework_dict = common.LoadDictionaryFromFile(
75 os.path.join(OPTIONS.product_out_framework, "misc_info.txt"))
76 vendor_dict = common.LoadDictionaryFromFile(
77 os.path.join(OPTIONS.product_out_vendor, "misc_info.txt"))
78 # Regenerate super_empty.img if both partial builds enable DAP. If only the
79 # the vendor build enables DAP, the vendor build's existing super_empty.img
80 # will be reused. If only the framework build should enable DAP, super_empty
81 # should be included in the --framework_images flag to copy the existing
82 # super_empty.img from the framework build.
83 if (framework_dict.get("use_dynamic_partitions") == "true") and (
84 vendor_dict.get("use_dynamic_partitions") == "true"):
85 merged_dict = dict(vendor_dict)
86 merged_dict.update(
87 common.MergeDynamicPartitionInfoDicts(
88 framework_dict=framework_dict,
89 vendor_dict=vendor_dict,
90 size_prefix="super_",
91 size_suffix="_group_size",
92 list_prefix="super_",
93 list_suffix="_partition_list"))
94 output_super_empty_path = os.path.join(OPTIONS.product_out_vendor,
95 "super_empty.img")
96 build_super_image.BuildSuperImage(merged_dict, output_super_empty_path)
97
98
99def MergeBuilds():
100 CreateImageSymlinks()
101 BuildSuperEmpty()
102 # TODO(b/137853921): Add support for regenerating vbmeta images.
103
104
105def main():
106 common.InitLogging()
107
108 def option_handler(o, a):
109 if o == "--framework_images":
110 OPTIONS.framework_images = [i.strip() for i in a.split(",")]
111 elif o == "--product_out_framework":
112 OPTIONS.product_out_framework = a
113 elif o == "--product_out_vendor":
114 OPTIONS.product_out_vendor = a
115 else:
116 return False
117 return True
118
119 args = common.ParseOptions(
120 sys.argv[1:],
121 __doc__,
122 extra_long_opts=[
123 "framework_images=",
124 "product_out_framework=",
125 "product_out_vendor=",
126 ],
127 extra_option_handler=option_handler)
128
129 if (args or OPTIONS.product_out_framework is None or
130 OPTIONS.product_out_vendor is None):
131 common.Usage(__doc__)
132 sys.exit(1)
133
134 MergeBuilds()
135
136
137if __name__ == "__main__":
138 main()