blob: 9d406cdb21e509a6221a0bbf4ca72ec9d2f28539 [file] [log] [blame]
# Copyright 2018 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(":package_info.bzl", "get_aggregate_info", "PackageAggregateInfo", "PackageGeneratedInfo", "PackageLocalInfo")
"""
Defines a Fuchsia package
The package template is used to define a unit of related code and data.
Parameters
name(string, required)
The name of the package
deps(list, required)
The list of targets to be built into this package
"""
# The attributes along which the aspect propagates.
# The value denotes whether the attribute represents a list of target or a
# single target.
_ASPECT_ATTRIBUTES = {
"data": True,
"target": False,
"deps": True,
"srcs": True,
}
def _info_impl(target, context):
mappings = []
if PackageLocalInfo in target:
mappings = target[PackageLocalInfo].mappings
elif PackageGeneratedInfo in target:
mappings = target[PackageGeneratedInfo].mappings
deps = []
for attribute, is_list in _ASPECT_ATTRIBUTES.items():
if hasattr(context.rule.attr, attribute):
value = getattr(context.rule.attr, attribute)
if is_list:
deps += value
else:
deps.append(value)
return [
get_aggregate_info(mappings, deps),
]
# An aspect which turns PackageLocalInfo providers into a PackageAggregateInfo
# provider to identify all elements which need to be included in the package.
_info_aspect = aspect(
implementation = _info_impl,
attr_aspects = _ASPECT_ATTRIBUTES.keys(),
provides = [
PackageAggregateInfo,
],
# If any other aspect is applied to produce package mappings, let the result
# of that process be visible to the present aspect.
required_aspect_providers = [
PackageGeneratedInfo,
],
)
def _fuchsia_package_impl(context):
# List all the files that need to be included in the package.
info = get_aggregate_info([], context.attr.deps)
manifest_file_contents = ""
package_contents = []
for mapping in info.contents.to_list():
manifest_file_contents += "%s=%s\n" % (mapping[0], mapping[1].path)
package_contents.append(mapping[1])
base = context.attr.name + "_pkg/"
meta_package = context.actions.declare_file(base + "meta/package")
manifest_file_contents += "meta/package=%s\n" % meta_package.path
manifest_file = context.actions.declare_file(base + "package_manifest")
package_dir = manifest_file.dirname
# Write the manifest file.
context.actions.write(
output = manifest_file,
content = manifest_file_contents,
)
# Initialize the package's meta directory.
context.actions.run(
executable = context.executable._pm,
arguments = [
"-o",
package_dir,
"-n",
context.attr.name,
"init",
],
outputs = [
meta_package,
],
mnemonic = "PmInit",
)
# TODO(pylaligand): figure out how to specify this key.
# Generate a signing key.
signing_key = context.actions.declare_file(base + "development.key")
context.actions.run(
executable = context.executable._pm,
arguments = [
"-o",
package_dir,
"-k",
signing_key.path,
"genkey",
],
inputs = [
meta_package,
],
outputs = [
signing_key,
],
mnemonic = "PmGenkey",
)
# Build the package metadata.
meta_far = context.actions.declare_file(base + "meta.far")
context.actions.run(
executable = context.executable._pm,
arguments = [
"-o",
package_dir,
"-k",
signing_key.path,
"-m",
manifest_file.path,
"build",
],
inputs = package_contents + [
manifest_file,
meta_package,
signing_key,
],
outputs = [
meta_far,
],
mnemonic = "PmBuild",
)
# Create the package archive.
package_archive = context.actions.declare_file(base + context.attr.name + "-0.far")
context.actions.run(
executable = context.executable._pm,
arguments = [
"-o",
package_dir,
"-k",
signing_key.path,
"-m",
manifest_file.path,
"archive",
],
inputs = [
manifest_file,
signing_key,
meta_far,
] + package_contents,
outputs = [
package_archive,
],
mnemonic = "PmArchive",
)
return [
DefaultInfo(files = depset([package_archive])),
]
fuchsia_package = rule(
implementation = _fuchsia_package_impl,
attrs = {
"deps": attr.label_list(
doc = "The objects to include in the package",
aspects = [
_info_aspect,
],
mandatory = True,
),
"_pm": attr.label(
default = Label("//tools:pm"),
allow_single_file = True,
executable = True,
cfg = "host",
),
},
)