| # 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. |
| |
| import("//build/dist/resource.gni") |
| import("//tools/cmc/build/cmc.gni") |
| import("//tools/cmc/build/cml.gni") |
| import("//tools/cmc/build/cmx.gni") |
| |
| # Defines a Fuchsia component. |
| # See: https://fuchsia.dev/fuchsia-src/development/components/build |
| # |
| # A component is defined by a component manifest. |
| # Component manifests typically reference files in the package that they are |
| # distributed in. Therefore a component can also have dependencies on |
| # `resource()`, such that any package that depends on the component # will |
| # also include that resource. |
| # |
| # A component is launched by a URL. |
| # See: https://fuchsia.dev/fuchsia-src/glossary#component_url |
| # |
| # A component's URL is a function of the name of a package that includes it, |
| # and the path within that package to the component's manifest. For instance if |
| # you defined the following: |
| # ``` |
| # executable("my_program") { |
| # ... |
| # } |
| # |
| # fuchsia_component("my-component") { |
| # manifest = "manifest.cml" |
| # deps = [ ":my_program" ] |
| # } |
| # |
| # fuchsia_package("my-package") { |
| # deps = [ ":my-component" ] |
| # } |
| # ``` |
| # The component above will have the following launch URL: |
| # `fuchsia-pkg://fuchsia.com/my-package#meta/my-component.cm` |
| # |
| # Since the component depends on the executable target, the binary produced by |
| # the executable will be packaged with the manifest. Therefore the manifest |
| # author can reference the path `bin/my_program`. |
| # |
| # Components may depend on any number of `resource()` targets to ensure that |
| # any `fuchsia_package()` that includes them will include the same resources. |
| # |
| # ``` |
| # resource("my_file") { |
| # sources = [ "my_file.txt" ] |
| # outputs = [ "data/{{source_file_part}}" ] |
| # } |
| # |
| # fuchsia_component("my-component") { |
| # deps = [ ":my_file" ] |
| # ... |
| # } |
| # ``` |
| # |
| # The component defined above will be able to read my_file.txt under the path |
| # "/pkg/data/my_file.txt" in its sandbox. |
| # |
| # Parameters |
| # |
| # manifest (required) |
| # The component manifest. |
| # Type: path |
| # |
| # component_name (optional) |
| # The name of the component. |
| # Type: string |
| # Default: target_name |
| # |
| # check_references (optional) |
| # Check component manifest references (e.g. "program.binary") against |
| # package manifest. |
| # Type: boolean |
| # Default: true |
| # |
| # unstable_features (optional) |
| # The set of unstable CML features to allow. Only applicable to v2 components. |
| # The set of features is allowlisted here: //tools/cmc/build/unstable_features/BUILD.gn |
| # where each feature name is represented by a group of the same name. |
| # Type: list of strings |
| # Default: [] |
| # |
| # experimental_force_runner (optional) |
| # Set the --experimental-force-runner flag to the given value. |
| # This flag is experimental and may be removed without warning. |
| # Type: string |
| # |
| # deps |
| # testonly |
| # visibility |
| template("fuchsia_component") { |
| assert( |
| defined(invoker.manifest), |
| "A `manifest` argument was missing when calling fuchsia_component($target_name)") |
| |
| component_name = target_name |
| if (defined(invoker.component_name)) { |
| component_name = invoker.component_name |
| } |
| |
| # Handle different manifest versions |
| manifest_extension = get_path_info(invoker.manifest, "extension") |
| if (manifest_extension == "cml") { |
| manifest_processor = "cm" |
| manifest_name = "$component_name.cm" |
| } else if (manifest_extension == "cmx") { |
| manifest_processor = "cmx" |
| manifest_name = "$component_name.cmx" |
| } else { |
| assert( |
| false, |
| "Unknown manifest format for \"${invoker.manifest}\", must be \".cml\" or \".cmx\"") |
| } |
| |
| manifest_resource_target = "${target_name}_manifest_resource" |
| |
| check_references = true |
| if (defined(invoker.check_references)) { |
| check_references = invoker.check_references |
| } |
| |
| if (check_references) { |
| validate_target = "${target_name}_cmc_validate_references" |
| } |
| |
| # Process the manifest |
| target(manifest_processor, target_name) { |
| output_name = "$manifest_extension/$target_name/$manifest_name" |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "manifest", |
| "unstable_features", |
| "testonly", |
| "visibility", |
| "experimental_force_runner", |
| ]) |
| |
| if (!defined(deps)) { |
| deps = [] |
| } |
| deps += [ ":$manifest_resource_target" ] |
| if (manifest_extension == "cmx") { |
| deps += [ "//build/components/cmx:cmx_allowlist" ] |
| } |
| if (check_references) { |
| deps += [ ":$validate_target" ] |
| } |
| |
| metadata = { |
| if (defined(invoker.metadata)) { |
| forward_variables_from(invoker.metadata, "*") |
| } |
| |
| # Don't collect expected includes via transitive deps of components |
| expect_includes_barrier = [] |
| } |
| } |
| |
| # Add the manifest |
| resource(manifest_resource_target) { |
| sources = get_target_outputs(":${invoker.target_name}") |
| outputs = [ "meta/$manifest_name" ] |
| visibility = [ ":*" ] |
| } |
| |
| if (check_references) { |
| # Validate the manifest against packaged files |
| cmc_validate_references(validate_target) { |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "testonly", |
| ]) |
| visibility = [ ":*" ] |
| component_manifest = invoker.manifest |
| label = get_label_info(":$target_name", "label_with_toolchain") |
| } |
| } |
| } |