| # Copyright 2020 The Fuchsia Authors. All rights reserved. | 
 | # Use of this source code is governed by a BSD-style license that can be | 
 | # found in the LICENSE file. | 
 |  | 
 | # Declare data files to be accessible at runtime on the target device. | 
 | # | 
 | # A resource() target looks just like a copy() target but $outputs are | 
 | # relative target paths.  Using $data_deps to this resource() target in | 
 | # each target whose code uses $outputs at runtime ensures that the files | 
 | # will be present on the system. | 
 | # | 
 | # If the `sources` list contains more than one file, the `outputs` should use | 
 | # source expansion template placeholders, such as `{{source_file_part}}`. | 
 | # | 
 | # For example: | 
 | # | 
 | #   //some/dir/BUILD.gn: | 
 | #      resource("testdata") { | 
 | #        sources = [ | 
 | #          "testdata/input.json", | 
 | #          "testdata/input_minified.json", | 
 | #        ] | 
 | #        outputs = [ "data/{{source_file_part}}" ] | 
 | #      } | 
 | # | 
 | # The above `resource` target maps files in the subdirectory `testdata` to | 
 | # destination paths in a Fuchsia package as follows: | 
 | # | 
 | #   //some/dir/testdata/input.json           --> data/input.json | 
 | #   //some/dir/testdata/input_minified.json  --> data/input_minified.json | 
 | # | 
 | # For more details on using template placeholders, see the GN documentation: | 
 | # | 
 | #     https://gn.googlesource.com/gn/+/HEAD/docs/reference.md#placeholders | 
 | # | 
 | # If the file is not in the source tree, it should be generated by another | 
 | # target in the build listed in $deps.  If that would be a generated_file() | 
 | # target, then use generated_resource() instead of resource(). | 
 | # | 
 | # Using resource() to install an ELF binary file into bin/ or test/ will | 
 | # break instrumented builds (with an error that only occurs very late in | 
 | # the build, during the packaging step). To solve this, use renamed_binary() | 
 | # to install them instead. | 
 | # | 
 | # Due to this, using resource() with an output directory of bin/ or test/ | 
 | # is an error by default, but can be overridden for data files by setting | 
 | # allow_binary_output_dir to true! | 
 | # | 
 | # Parameters | 
 | # | 
 | #   data_deps | 
 | #     Optional: Additional dependencies for the runtime image.  These are | 
 | #     included in the image if this target is, but are not related to the | 
 | #     $sources list. | 
 | #     Type: list(label) | 
 | # | 
 | #   deps | 
 | #     Optional: Targets that produce $sources.  Any files listed in | 
 | #     $sources that are produced by the build should be produced by a | 
 | #     target listed here.  This is the only thing that guarantees those | 
 | #     files will have been built by the time the image is being packed. | 
 | #     Targets reached only via this $deps list will *not* contribute their | 
 | #     own contents to the image directly.  For that, list them in $data_deps. | 
 | #     Targets listed here are used only to produce the $sources files. | 
 | #     Type: list(label) | 
 | # | 
 | #   outputs | 
 | #     Required: List of one runtime path.  This must be a relative path (no | 
 | #     leading `/`).  It can use placeholders based on $sources; see copy() | 
 | #     and `gn help source_expansion`.  When this resource() target is in | 
 | #     the dependency graph of a zbi() target, then this is the path within | 
 | #     the BOOTFS, which appears at /boot in the namespace of early-boot and | 
 | #     standalone Zircon processes. | 
 | #     Type: list(path) | 
 | # | 
 | #   sources | 
 | #     Required: List of files in the source tree or build that become $outputs. | 
 | #     See copy() for details. | 
 | # | 
 | #     Note: if sources are generated by an action then the resource() target | 
 | #     should be a direct dependency of a fuchsia_package() or of a | 
 | #     fuchsia_component() target. Do not add as an indirect dependency via an | 
 | #     executable() target. | 
 | #     Do this: | 
 | #     fuchsia_package()/fuchsia_component() -> resource() -> action() | 
 | #     Don't do this: | 
 | #     fuchsia_package()/fuchsia_component() -> executable() -> resource() -> action() | 
 | # | 
 | #     Type: list(file) | 
 | # | 
 | #   allow_binary_output_dir | 
 | #     Optional: Set to true to allow copying a resource into either | 
 | #     bin/ or test/. Useful when installing non-ELF files there, while | 
 | #     ELF files should be installed using renamed_binary() instead. | 
 | #     Type: boolean | 
 | # | 
 | # See copy() for other parameters. | 
 | template("resource") { | 
 |   if (invoker.sources != []) { | 
 |     _label = get_label_info(":$target_name", "label_with_toolchain") | 
 |   } | 
 |  | 
 |   # Prevent binaries to be copied to bin/ or test/ with resource() to prevent | 
 |   # build breaks with instrumented builds. See https://fxbug.dev/89436 | 
 |   # | 
 |   _allow_binary_output_dir = defined(invoker.allow_binary_output_dir) && | 
 |                              invoker.allow_binary_output_dir | 
 |   if (!_allow_binary_output_dir) { | 
 |     _outputs = invoker.outputs | 
 |  | 
 |     # invoker.outputs can be a list or a string. If it is a string, turn | 
 |     # it into a list here. | 
 |     if ("${_outputs}" == _outputs) { | 
 |       _outputs = [ _outputs ] | 
 |     } else { | 
 |       assert(_outputs == [ _outputs[0] ], | 
 |              "outputs should be a string or a list of one string!") | 
 |     } | 
 |     _output_dir = get_path_info(_outputs[0], "dir") | 
 |     assert( | 
 |         _output_dir != "bin" && _output_dir != "test", | 
 |         "Installing file to bin/ or test/ requires renamed_binary() or allow_binary_output_dir!") | 
 |   } | 
 |  | 
 |   group(target_name) { | 
 |     forward_variables_from(invoker, | 
 |                            "*", | 
 |                            [ | 
 |                              "metadata", | 
 |                              "outputs", | 
 |                              "sources", | 
 |                            ]) | 
 |     metadata = { | 
 |       # Used by the distribution_manifest() template. | 
 |       distribution_entries_barrier = [] | 
 |       distribution_entries = [] | 
 |  | 
 |       # Used by the zbi() template. | 
 |       zbi_input_barrier = [] | 
 |  | 
 |       if (defined(invoker.metadata)) { | 
 |         forward_variables_from(invoker.metadata, "*") | 
 |       } | 
 |  | 
 |       # Stop *_manifest() and zbi_test() from picking up files or | 
 |       # zbi_input() items from the deps, but let them reach the data_deps. | 
 |       if (defined(data_deps)) { | 
 |         distribution_entries_barrier += data_deps | 
 |         zbi_input_barrier += data_deps | 
 |       } | 
 |  | 
 |       foreach(source, invoker.sources) { | 
 |         foreach(target, process_file_template([ source ], invoker.outputs)) { | 
 |           assert(rebase_path(target, "foo") != target, | 
 |                  "`outputs` in resource() cannot start with /") | 
 |           distribution_entries += [ | 
 |             { | 
 |               source = rebase_path(source, root_build_dir) | 
 |               destination = target | 
 |               label = _label | 
 |             }, | 
 |           ] | 
 |         } | 
 |       } | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | # Declare data files to be accessible at runtime on the target device. | 
 | # | 
 | # Similar to resource() but with a different interface that allows grouping | 
 | # multiple files into a single target when their packaged paths don't follow | 
 | # a common pattern. | 
 | # | 
 | # Parameters | 
 | # | 
 | #   data_deps | 
 | #     Optional: Additional dependencies for the runtime image.  These are | 
 | #     included in the image if this target is, but are not related to the | 
 | #     $sources list. | 
 | #     Type: list(label) | 
 | # | 
 | #   deps | 
 | #     Optional: Targets that produce $sources.  Any files listed in | 
 | #     $sources that are produced by the build should be produced by a | 
 | #     target listed here.  This is the only thing that guarantees those | 
 | #     files will have been built by the time the image is being packed. | 
 | #     Targets reached only via this $deps list will *not* contribute their | 
 | #     own contents to the image directly.  For that, list them in $data_deps. | 
 | #     Targets listed here are used only to produce the $sources files. | 
 | #     Type: list(label) | 
 | # | 
 | #   files | 
 | #     Required: List of scopes containing `source` and `dest` paths. | 
 | #     `source` paths are local file paths. | 
 | #     `dest` paths are packaged paths. | 
 | #     For instance: | 
 | #     files = [ | 
 | #       { | 
 | #         source = "//path/to/file.txt" | 
 | #         dest = "data/first.txt" | 
 | #       }, | 
 | #       { | 
 | #         source = "//path/to/other_file.txt", | 
 | #         dest = "data/second.txt" | 
 | #       }, | 
 | #     ] | 
 | #     Type: list(scope) | 
 | # | 
 | #   allow_binary_output_dir | 
 | #     See resource() | 
 | # | 
 | #   testonly, visibility | 
 | template("resource_group") { | 
 |   if (invoker.files != []) { | 
 |     _label = get_label_info(":$target_name", "label_with_toolchain") | 
 |   } | 
 |  | 
 |   if (!(defined(invoker.allow_binary_output_dir) && | 
 |         invoker.allow_binary_output_dir)) { | 
 |     # Prevent binaries to be copied to bin/ or test/ with resource() to prevent | 
 |     # build breaks with instrumented builds. See https://fxbug.dev/89436 | 
 |     # | 
 |     # NOTE: This check cannot be performed in the metadata definition below | 
 |     # because GN will complain that the _dest_with_prefix temporary variable | 
 |     # is not a list (metadata scope variables can only be lists). | 
 |     foreach(file, invoker.files) { | 
 |       _dest_dir = get_path_info(file.dest, "dir") | 
 |       assert( | 
 |           _dest_dir != "bin" && _dest_dir != "test", | 
 |           "Installing file to bin/ or test/ requires renamed_binary() or allow_binary_output_dir!") | 
 |     } | 
 |   } | 
 |  | 
 |   group(target_name) { | 
 |     forward_variables_from(invoker, | 
 |                            [ | 
 |                              "deps", | 
 |                              "testonly", | 
 |                              "visibility", | 
 |                            ]) | 
 |     metadata = { | 
 |       # Used by the distribution_manifest() template. | 
 |       distribution_entries_barrier = [] | 
 |       distribution_entries = [] | 
 |  | 
 |       # Used by the zbi() template. | 
 |       zbi_input_barrier = [] | 
 |  | 
 |       if (defined(invoker.metadata)) { | 
 |         forward_variables_from(invoker.metadata, "*") | 
 |       } | 
 |  | 
 |       # Stop *_manifest() and zbi_test() from picking up files or | 
 |       # zbi_input() items from the deps, but let them reach the data_deps. | 
 |       if (defined(data_deps)) { | 
 |         distribution_entries_barrier += data_deps | 
 |         zbi_input_barrier += data_deps | 
 |       } | 
 |  | 
 |       foreach(file, invoker.files) { | 
 |         distribution_entries += [ | 
 |           { | 
 |             source = rebase_path(file.source, root_build_dir) | 
 |             destination = file.dest | 
 |             label = _label | 
 |           }, | 
 |         ] | 
 |       } | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | # resource_tree() is similar to resource() but makes it easy to replicate | 
 | # a tree of sources files, relative to a given sources path prefix, to a | 
 | # given destination directory. | 
 | # | 
 | # For example: | 
 | # | 
 | #   //some/dir/BUILD.gn: | 
 | #      resource_tree("my-resources") { | 
 | #        sources_root = "res" | 
 | #        sources = [ | 
 | #          foo.resource", | 
 | #          bar/bar-1.resource", | 
 | #        ] | 
 | #        dest_dir = "data/resources" | 
 | #      } | 
 | # | 
 | # Will declare the following installation requirements: | 
 | # | 
 | #   //some/dir/res/foo.resource      --> data/resources/foo.resource | 
 | #   //some/dir/res/bar/bar.resource  --> data/resources/bar/bar.resource | 
 | # | 
 | # This is difficult to do with resource() because GN source expansion | 
 | # cannot preserve the original sources input paths. | 
 | # | 
 | # This template is useful to avoid calling resource() multiple times | 
 | # in a loop when dealing with resource files laid out into different | 
 | # sub-directories. Note that the files cannot be renamed though! | 
 | # | 
 | # Parameters | 
 | # | 
 | #   source_root | 
 | #     Optional: A path prefix that is prepended to all items in the 'sources' | 
 | #     list. If not specified, the current target's directory is used. | 
 | #     Type: string(path) | 
 | # | 
 | #   sources | 
 | #     Required: List of files in the source tree or build that will be | 
 | #     installed. Each 'file' item in this list is installed to | 
 | #     '$dest_dir/$file', and its content taken from '$sources_root/$file'. | 
 | #     Note that unlike resource(), there is no way to transform or expand | 
 | #     source paths. | 
 | #     Type: list(file) | 
 | # | 
 | #   dest_dir | 
 | #     Required: Destination path where all sources are installed. | 
 | #     Cannot start with a "/". Use an empty string to install files directory | 
 | #     to the package's top-level directory. | 
 | #     Type: string(path) | 
 | # | 
 | #   data_deps | 
 | #     Optional: Additional dependencies for the runtime image.  These are | 
 | #     included in the image if this target is, but are not related to the | 
 | #     $sources list. | 
 | #     Type: list(label) | 
 | # | 
 | #   allow_binary_output_dir | 
 | #     See resource() | 
 | # | 
 | #   deps | 
 | #     Optional: Targets that produce $sources.  Any files listed in | 
 | #     $sources that are produced by the build should be produced by a | 
 | #     target listed here.  This is the only thing that guarantees those | 
 | #     files will have been built by the time the image is being packed. | 
 | #     Targets reached only via this $deps list will *not* contribute their | 
 | #     own contents to the image directly.  For that, list them in $data_deps. | 
 | #     Targets listed here are used only to produce the $sources files. | 
 | #     Type: list(label) | 
 | # | 
 | template("resource_tree") { | 
 |   assert(defined(invoker.sources), "sources is required!") | 
 |   assert(defined(invoker.dest_dir), "dest_dir is required!") | 
 |   dest_dir = invoker.dest_dir | 
 |   if (dest_dir != "") { | 
 |     # Sanitize dest_dir and append a directory separator. | 
 |     assert(rebase_path(dest_dir, "foo") != dest_dir, | 
 |            "dest_dir cannot start with /: $dest_dir") | 
 |     assert(dest_dir != "." && dest_dir != ".." && | 
 |                string_replace(dest_dir, "./", "") == dest_dir, | 
 |            "dest_dir cannot contain . or .. path elements!: $dest_dir") | 
 |     if (!(defined(invoker.allow_binary_output_dir) && | 
 |           invoker.allow_binary_output_dir)) { | 
 |       assert( | 
 |           dest_dir != "bin" && dest_dir != "test", | 
 |           "Installing file to bin/ or test/ requires renamed_binary() or allow_binary_output_dir!") | 
 |     } | 
 |     dest_dir = string_replace(dest_dir + "/", "//", "/") | 
 |   } | 
 |  | 
 |   if (defined(invoker.sources_root)) { | 
 |     assert(invoker.sources_root != "", "sources_root cannot be empty!") | 
 |     sources_prefix = invoker.sources_root | 
 |  | 
 |     # Append trailing separator if needed | 
 |     if (string_replace(sources_prefix + "###", "/###", "") == | 
 |         sources_prefix + "###") { | 
 |       sources_prefix += "/" | 
 |     } | 
 |   } else { | 
 |     sources_prefix = "" | 
 |   } | 
 |  | 
 |   target_label = get_label_info(":$target_name", "label_with_toolchain") | 
 |   if (invoker.sources == []) { | 
 |     # Support resource_tree() targets with empty sources list. | 
 |     not_needed(invoker, | 
 |                [ | 
 |                  "dest_dir", | 
 |                  "sources_root", | 
 |                ]) | 
 |     not_needed([ | 
 |                  "sources_prefix", | 
 |                  "dest_dir", | 
 |                  "target_label", | 
 |                ]) | 
 |   } | 
 |  | 
 |   group(target_name) { | 
 |     forward_variables_from(invoker, | 
 |                            "*", | 
 |                            [ | 
 |                              "dest_dir", | 
 |                              "metadata", | 
 |                              "sources", | 
 |                              "sources_root", | 
 |                            ]) | 
 |     metadata = { | 
 |       # Used by the distribution_manifest() template. | 
 |       distribution_entries_barrier = [] | 
 |       distribution_entries = [] | 
 |  | 
 |       # Used by the zbi() template. | 
 |       zbi_input_barrier = [] | 
 |  | 
 |       if (defined(invoker.metadata)) { | 
 |         forward_variables_from(invoker.metadata, "*") | 
 |       } | 
 |  | 
 |       # Stop *_manifest() and zbi_test() from picking up files or | 
 |       # zbi_input() items from the deps, but let them reach the data_deps. | 
 |       if (defined(data_deps)) { | 
 |         distribution_entries_barrier += data_deps | 
 |         zbi_input_barrier += data_deps | 
 |       } | 
 |  | 
 |       foreach(_source, invoker.sources) { | 
 |         distribution_entries += [ | 
 |           { | 
 |             source = rebase_path(sources_prefix + _source, root_build_dir) | 
 |             destination = dest_dir + _source | 
 |             label = target_label | 
 |           }, | 
 |         ] | 
 |       } | 
 |     } | 
 |   } | 
 | } |