| # 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 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. |
| # 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_trees("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 |
| }, |
| ] |
| } |
| } |
| } |
| } |