xref: /aosp_15_r20/external/pigweed/pw_build/update_bundle.gni (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1# Copyright 2021 The Pigweed Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4# use this file except in compliance with the License. You may obtain a copy of
5# the License at
6#
7#     https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations under
13# the License.
14
15import("//build_overrides/pigweed.gni")
16
17import("$dir_pw_build/python_action.gni")
18
19# GN target that creates update bundles.
20#
21# Args:
22#   out: Filename at which to output the serialized update bundle.
23#   targets: List of targets mapping filenames to target names.
24#   persist: Optional boolean; if true, the raw tuf repo will be persisted to
25#       disk in the target out dir in addition to being serialized as a bundle.
26#   user_manifest: Optional path to an extra user-defined manifest file; if
27#       provided, this file will be included as a target payload, but handled
28#       specially. See the following file for details:
29#         pw_software_update/public/pw_software_update/bundled_update_backend.h
30#   targets_metadata_version: Optional manually-specified int version number for
31#       the targets metadata.
32#   targets_metadata_version_file: Optional manually-specified path/to/file
33#        containing int version number for the targets metadata. Cannot be
34#        specified together with targets_metadata_version
35#   signed_root_metadata: Optional path to a .pb file containing a serialized
36#       SignedRootMetadata (generated and signed via the tools in the
37#       pw_software_update Python module).
38#
39# Each target in targets should be a string formatted as follows:
40#   "/path/to/file > target_name"
41
42template("pw_update_bundle") {
43  assert(defined(invoker.out), "An output path must be provided via 'out'")
44  assert(defined(invoker.targets),
45         "A list of targets must be provided via 'targets'")
46  pw_python_action(target_name) {
47    _delimiter = ">"
48    forward_variables_from(invoker,
49                           [
50                             "deps",
51                             "public_deps",
52                           ])
53    _out_path = invoker.out
54    _persist_path = ""
55    if (defined(invoker.persist) && invoker.persist) {
56      _persist_path = "${target_out_dir}/${target_name}/tuf_repo"
57    }
58    module = "pw_software_update.update_bundle"
59    python_deps = [ "$dir_pw_software_update/py" ]
60    args = [
61      "--out",
62      rebase_path(_out_path),
63      "--targets",
64    ]
65    outputs = [ _out_path ]
66
67    foreach(tuf_target, invoker.targets) {
68      # Remove possible spaces around the delimiter before splitting
69      tuf_target = string_replace(tuf_target, " $_delimiter", _delimiter)
70      tuf_target = string_replace(tuf_target, "$_delimiter ", _delimiter)
71
72      tuf_target_list = []
73      tuf_target_list = string_split(tuf_target, _delimiter)
74      tuf_target_path = rebase_path(tuf_target_list[0], root_build_dir)
75      tuf_target_name = tuf_target_list[1]
76      assert(tuf_target_name != "user_manifest",
77             "The target name 'user_manifest' is reserved for special use.")
78      args += [ "${tuf_target_path} > ${tuf_target_name}" ]
79      if (_persist_path != "") {
80        outputs += [ "${_persist_path}/${tuf_target_name}" ]
81      }
82    }
83
84    if (defined(invoker.user_manifest)) {
85      args += [ rebase_path(invoker.user_manifest, root_build_dir) +
86                " > user_manifest" ]
87    }
88
89    if (_persist_path != "") {
90      args += [
91        "--persist",
92        rebase_path(_persist_path),
93      ]
94    }
95
96    if (defined(invoker.targets_metadata_version)) {
97      args += [
98        "--targets-metadata-version",
99        invoker.targets_metadata_version,
100      ]
101    }
102
103    if (defined(invoker.targets_metadata_version_file)) {
104      args += [
105        "--targets-metadata-version-file",
106        rebase_path(invoker.targets_metadata_version_file),
107      ]
108    }
109
110    assert(
111        !(defined(invoker.targets_metadata_version_file) &&
112              defined(invoker.targets_metadata_version)),
113        "Only one of targets_metadata_version and targets_metadata_version_file can be specified")
114
115    if (defined(invoker.signed_root_metadata)) {
116      args += [
117        "--signed-root-metadata",
118        rebase_path(invoker.signed_root_metadata),
119      ]
120    }
121  }
122}
123