blob: 3b2d28ca080f76951e7c0b42418a927f3719c2bd [file] [log] [blame]
# Copyright 2022 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.
load(":providers.bzl", "FuchsiaComponentManifestShardCollectionInfo", "FuchsiaComponentManifestShardInfo")
def _fuchsia_component_manifest_shard_collection_impl(ctx):
return FuchsiaComponentManifestShardCollectionInfo(
shards = [dep for dep in ctx.attr.deps],
)
fuchsia_component_manifest_shard_collection = rule(
doc = """Encapsulates a collection of component manifests and their include paths.
This rule is not intended to be used directly. Rather, it should be added to the
fuchsia sdk toolchain to be added as implicity dependencies for all manifests.
""",
implementation = _fuchsia_component_manifest_shard_collection_impl,
attrs = {
"deps": attr.label_list(
doc = "A list of component manifest shard targets to collect.",
providers = [[FuchsiaComponentManifestShardInfo]],
),
},
)
def _fuchsia_component_manifest_shard_impl(ctx):
return [
FuchsiaComponentManifestShardInfo(
file = ctx.file.src,
base_path = ctx.attr.include_path,
),
]
fuchsia_component_manifest_shard = rule(
doc = """Encapsulates a component manifest shard from a input file.
""",
implementation = _fuchsia_component_manifest_shard_impl,
attrs = {
"include_path": attr.string(
doc = "Base path of the shard, used in includepath argument of cmc compile",
mandatory = True,
),
"src": attr.label(
doc = "The component manifest shard",
allow_single_file = [".cml"],
),
},
)
def _fuchsia_component_manifest_impl(ctx):
sdk = ctx.toolchains["@rules_fuchsia//fuchsia:toolchain"]
if not ctx.file.src and not ctx.attr.content:
fail("Either 'src' or 'content' needs to be specified.")
if ctx.file.src and ctx.attr.content:
fail("Only one of 'src' and 'content' can be specified.")
if ctx.file.src:
manifest_in = ctx.file.src
else:
# create a manifest file from the given content
if not ctx.attr.component_name:
fail("Attribute 'component_name' has to be specified when using inline content.")
manifest_in = ctx.actions.declare_file("%s.cml" % ctx.attr.component_name)
ctx.actions.write(
output = manifest_in,
content = ctx.attr.content,
is_executable = False,
)
# output should have the .cm extension
manifest_out = ctx.actions.declare_file(manifest_in.basename[:-1])
if ctx.configuration.coverage_enabled:
coverage_shard = ctx.attr._sdk_coverage_shard[FuchsiaComponentManifestShardInfo]
manifest_merged = ctx.actions.declare_file("%s_merged.cml" % manifest_in.basename[:-4])
ctx.actions.run(
executable = sdk.cmc,
arguments = [
"merge",
"--output",
manifest_merged.path,
manifest_in.path,
coverage_shard.file.path,
],
inputs = [
manifest_in,
coverage_shard.file,
],
outputs = [manifest_merged],
)
manifest_in = manifest_merged
# use a dict to eliminate workspace root duplicates
include_path_dict = {}
includes = []
for dep in ctx.attr.includes + sdk.cmc_includes[FuchsiaComponentManifestShardCollectionInfo].shards:
if FuchsiaComponentManifestShardInfo in dep:
shard = dep[FuchsiaComponentManifestShardInfo]
includes.append(shard.file)
include_path_dict[shard.file.owner.workspace_root + "/" + shard.base_path] = 1
include_path = []
for w in include_path_dict.keys():
include_path.extend(["--includepath", w])
ctx.actions.run(
executable = sdk.cmc,
arguments = [
"compile",
"--output",
manifest_out.path,
manifest_in.path,
"--includeroot",
manifest_in.path[:-len(manifest_in.basename)],
] + include_path,
inputs = [manifest_in] + includes,
outputs = [
manifest_out,
],
mnemonic = "CmcCompile",
)
return [
DefaultInfo(files = depset([manifest_out])),
]
fuchsia_component_manifest = rule(
doc = """Compiles a component manifest from a input file.
This rule will compile an input cml file and output a cm file. The file can,
optionally, include additional cml files but they must be relative to the
src file and included in the includes attribute.
```
{
include: ["foo.cml", "some_dir/bar.cml"]
}
```
""",
implementation = _fuchsia_component_manifest_impl,
toolchains = ["@rules_fuchsia//fuchsia:toolchain"],
attrs = {
"src": attr.label(
doc = "The source manifest to compile",
allow_single_file = [".cml"],
),
"content": attr.string(
doc = "Inline content for the manifest",
),
"component_name": attr.string(
doc = "Name of the component for inline manifests",
),
"includes": attr.label_list(
doc = "A list of dependencies which are included in the src cml",
providers = [FuchsiaComponentManifestShardInfo],
),
# This is to get the coverage.shard.cml in the SDK, so it can be merged
# in when coverage is enabled.
"_sdk_coverage_shard": attr.label(
default = "@fuchsia_sdk//pkg/sys/testing:coverage",
),
},
)