| # Copyright 2019 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("cmc.gni") |
| |
| declare_args() { |
| # Enable code coverage for Fuchsia components. |
| fuchsia_code_coverage = false |
| } |
| |
| # Defines a Fuchsia component's manifest. |
| # See: https://fuchsia.dev/fuchsia-src/development/components/build |
| # |
| # Parameters |
| # |
| # manifest [required] |
| # The component manifest. |
| # Type: path |
| # |
| # component_name [optional] |
| # The name of the component. |
| # Type: string |
| # Default: target_name |
| # |
| # check_includes [optional] |
| # Check against expect_includes() in deps. |
| # Warning: Do not disable this unless there is a good, documented reason. |
| # Type: boolean |
| # Default: true |
| # |
| # restricted_features [optional] |
| # The set of restricted features to allow. |
| # The set of features is allowlisted here: //tools/cmc/build/restricted_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 |
| # |
| # required_offers (optional) |
| # [list of strings] The set of protocols that should be offered to every child. |
| # |
| # required_uses (optional) |
| # [list of strings] The set of protocols that each child must use. |
| # |
| # include_coverage_shard (optional) |
| # Whether to include the `coverage.shard.cml` in a merged manifest. |
| # Overrides the default based on `fuchsia_code_coverage`. |
| # Should only be used in rare exceptions that do not use CML-based routing. |
| # |
| # data_deps |
| # deps |
| # testonly |
| # visibility |
| template("fuchsia_component_manifest") { |
| assert( |
| defined(invoker.manifest), |
| "A `manifest` argument was missing when calling fuchsia_component_manifest($target_name)") |
| |
| forward_variables_from(invoker, [ "manifest" ]) |
| |
| if (defined(invoker.include_coverage_shard)) { |
| include_coverage_shard = invoker.include_coverage_shard |
| } else { |
| include_coverage_shard = fuchsia_code_coverage |
| } |
| |
| if (include_coverage_shard) { |
| merged_manifest = "${target_name}-coverage" |
| manifest_file = get_path_info(manifest, "file") |
| |
| # Put the coverage merged manifest in a coverage directory to avoid |
| # collision with no base manifest. |
| manifest_rel_path = "coverage/${manifest_file}" |
| cmc_merge(merged_manifest) { |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "testonly", |
| ]) |
| sources = [ |
| "${fuchsia_sdk}/pkg/sys/testing/coverage.shard.cml", |
| manifest, |
| ] |
| output_name = manifest_rel_path |
| } |
| manifest = "${target_out_dir}/${manifest_rel_path}" |
| } |
| |
| _manifest_name = get_path_info(manifest, "name") |
| cmc_compile(target_name) { |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| "required_offers", |
| "required_uses", |
| ]) |
| manifest = rebase_path(manifest) |
| |
| # NOTE: must be kept in sync with path in structured_config.gni |
| config_values_package_path = "$_manifest_name.cvf" |
| deps = [] |
| if (defined(invoker.deps)) { |
| deps += invoker.deps |
| } |
| if (include_coverage_shard) { |
| deps += [ ":${merged_manifest}" ] |
| } |
| } |
| } |
| |
| # Defines a Fuchsia component. |
| # See: https://fuchsia.dev/fuchsia-src/glossary#component |
| # |
| # A component is defined by a component manifest. |
| # A component is a unit of executable software on Fuchsia. When the componet is executed, there are usually many files |
| # needed at runtime, such as the executable itself, shared libraries, and possibly other data resources. These files are |
| # specified by using the GN concept of "data_deps". |
| # |
| # Components are distributed using a fuchsia package which can contain multiple components. The component manifest and |
| # the runtime dependencies of the component are packaged using the fuchsia_package rule. |
| # |
| # By default, the runtime depenencies of the component are included in the package using relative paths calcualted from |
| # the "closest" root of: $root_gen_dir, $root_dir, $out_dir. If a specific path is desired in the package, the "resources" parameter can |
| # be used to explicitly specify the path of a specific file. |
| # |
| # A component is launched by a URL which identifies the package and the component manifest. |
| # See: https://fuchsia.dev/fuchsia-src/glossary#component_url |
| # |
| # Example |
| # |
| # ``` |
| # fuchsia_component("my_component") { |
| # manifest = "meta/component-manifest.cml" |
| # resources = [ |
| # { |
| # path = "testdata/use_case1.json" |
| # dest = "data/testdata/use_case1.json" |
| # }, |
| # ] |
| # data_deps = [ ":hello_world_executable"] |
| # } |
| # ``` |
| # |
| # Parameters |
| # |
| # data_deps |
| # The labels of targets that generate the files needed at runtime by the component. |
| # At minimum, this should include the label of the binary to include in the component. |
| # |
| # Type: list of labels |
| # |
| # manifest [optional] |
| # The source manifest file for this component. |
| # |
| # Type: string (filepath) |
| # |
| # manifest_output_name [optional] |
| # The name of the manifest file contained in the distribution that this |
| # component is included in. The output name should have no extension or |
| # prefixes. The resulting filename will have the ".cm" extension. |
| # For example, if `manifest` is "foo.cml" and `manifest_output_name` is "bar", |
| # the filename will be "bar.cm". |
| # |
| # Type: string |
| # Default: The base file name of `manifest` without an extension. |
| # |
| # resources [optional] |
| # Lists additional files to include for runtime access by the component. |
| # Defines the resources in a package containing this component. A resource |
| # is a data file that may be produced by the build system, checked in to a |
| # source repository, or produced by another system that runs before the |
| # build. Resources are placed in the `data/` directory of the assembled |
| # package. |
| # |
| # Type: list of scopes. Entries in a scope in the resources list: |
| # path (required) |
| # Location of resource in source or build directory. If the |
| # resource is checked in, this will typically be specified |
| # as a path relative to the BUILD.gn file containing the |
| # `package()` target. If the resource is generated, this will |
| # typically be specified relative to `$target_gen_dir`. |
| # |
| # dest (required) string (path) Location the resource will be placed within `data/`. |
| # |
| # cm_label [optional] |
| # Use label of a fuchsia_component_manifest target instead of supplying the manifest source. |
| # Type: string, GN label e.g. `:my-manifest` |
| # |
| # manifest_deps [optional] |
| # Dependencies for the component's manifest, in case it is generated by another target. |
| # Type: list of targets |
| # |
| # required_offers (optional) |
| # [list of strings] The set of protocols that should be offered to every child. |
| # |
| # required_uses (optional) |
| # [list of strings] The set of protocols that each child must use. |
| # |
| # Standard parameters: |
| # data_deps |
| # deps |
| # testonly |
| # visibility |
| # |
| # Metadata |
| # contents - list of scopes describing files for this component. This metadata is consumed by |
| # The fuchsia_package rule, which describes the entries used. |
| # Entries in scope: |
| # type: the usage type of the element, manifest or resource. |
| # Each type can have specific properties included in the scope. |
| # source [type == manifest || resource] The compiled manifest file to include in |
| # the package for this component. |
| # output_name [type == manifest] The basename of the manifest as it should appear in the package. |
| # manifest_version [type == manifest] |
| # dest: [type == resource] The package relative path of the resource. |
| |
| template("fuchsia_component") { |
| forward_variables_from(invoker, [ "manifest_output_name" ]) |
| |
| _manifest_defined = defined(invoker.manifest) |
| _cm_label_defined = defined(invoker.cm_label) |
| assert( |
| (_manifest_defined && !_cm_label_defined) || |
| (!_manifest_defined && _cm_label_defined), |
| "Exactly one of `manifest` or `cm_label` argument must be specified when calling fuchsia_component($target_name)") |
| |
| if (defined(invoker.manifest)) { |
| # Compile the manifest from source |
| cm_target = "${target_name}_manifest_compile" |
| fuchsia_component_manifest(cm_target) { |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "manifest", |
| "testonly", |
| "visibility", |
| "required_offers", |
| "required_uses", |
| "include_coverage_shard", |
| ]) |
| if (defined(invoker.manifest_deps)) { |
| if (!defined(deps)) { |
| deps = [] |
| } |
| deps += invoker.manifest_deps |
| } |
| } |
| cm_label = ":${cm_target}" |
| } else { |
| cm_label = invoker.cm_label |
| } |
| |
| _compiled_manifest_outputs = get_target_outputs(cm_label) |
| _manifest_source = _compiled_manifest_outputs[0] |
| |
| group(target_name) { |
| forward_variables_from(invoker, |
| [ |
| "data", |
| "deps", |
| "data_deps", |
| "resources", |
| "resources_in_json_files", |
| "testonly", |
| "visibility", |
| ]) |
| |
| # Data is used for adding files as runtime dependencies. Files used as |
| # sources in the resources parameter are added as data to make sure |
| # non-generated files listed are captured as dependencies. |
| if (!defined(data)) { |
| data = [] |
| } |
| |
| if (!defined(resources)) { |
| resources = [] |
| } |
| |
| if (!defined(deps)) { |
| deps = [] |
| } |
| deps += [ cm_label ] |
| |
| # Create the component metadata entries. These capture the manifest information and |
| # the resources parameter contents. The metadata is intended for the fuchsia_package rule. |
| component_contents = [ |
| { |
| type = "manifest" |
| source = rebase_path(_manifest_source) |
| if (defined(manifest_output_name)) { |
| output_name = manifest_output_name |
| } |
| }, |
| ] |
| foreach(resource, resources) { |
| data += [ resource.path ] |
| component_contents += [ |
| { |
| type = "resource" |
| source = rebase_path(resource.path) |
| dest = resource.dest |
| }, |
| ] |
| } |
| |
| # TODO(richkadel): Changed from the Fuchsia GN SDK to add |
| # `resources_in_json_files, so additional resources could be computed at |
| # compile time (in this case, compiled Dart libraries). |
| if (!defined(resources_in_json_files)) { |
| resources_in_json_files = [] |
| } |
| foreach(file, resources_in_json_files) { |
| data += [ file ] |
| component_contents += [ |
| { |
| type = "json_of_resources" |
| source = file |
| }, |
| ] |
| } |
| |
| # The contents of the component are enumerated in the |
| # metadata. |
| metadata = { |
| contents = [ component_contents ] |
| } |
| } |
| } |