blob: 000b756e67d982acd9f460d22ce7cc619c8889eb [file] [log] [blame]
# 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/cml.gni")
import("//tools/cmc/build/cmx.gni")
import("//tools/cmc/build/validate_component_manifest_references.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
#
# 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
if (get_path_info(invoker.manifest, "extension") == "cml") {
manifest_processor = "cm"
manifest_name = "$component_name.cm"
} else if (get_path_info(invoker.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"
validate_target = "${target_name}_validate_component_manifest_references"
# Process the manifest
target(manifest_processor, target_name) {
output_name = manifest_name
forward_variables_from(invoker,
[
"deps",
"manifest",
"testonly",
"visibility",
])
if (!defined(deps)) {
deps = []
}
deps += [
":$manifest_resource_target",
":$validate_target",
]
}
# Add the manifest
resource(manifest_resource_target) {
sources = get_target_outputs(":${invoker.target_name}")
outputs = [ "meta/$manifest_name" ]
visibility = [ ":*" ]
}
# Validate the manifest against packaged files
validate_component_manifest_references(validate_target) {
forward_variables_from(invoker,
[
"deps",
"testonly",
])
visibility = [ ":*" ]
component_manifest = invoker.manifest
label = get_label_info(":$target_name", "label_with_toolchain")
}
}