Remove fuchsia_runnable.
This also removes support for fuchsia[_test]_package:deps and
fuchsia_test_package:components.
Also register debug symbols for :pkg.publish workflow.
Also propagate far files for all package variants
Fixed: 114603, 117942
Change-Id: I4c263835e54f1db5a2e6316bf39c4643a237c732
Reviewed-on: https://fuchsia-review.googlesource.com/c/sdk-integration/+/787162
Commit-Queue: Darren Chan <chandarren@google.com>
Reviewed-by: Jiaming Li <lijiaming@google.com>
Reviewed-by: Chase Latta <chaselatta@google.com>
diff --git a/bazel_rules_fuchsia/fuchsia/defs.bzl b/bazel_rules_fuchsia/fuchsia/defs.bzl
index 7c11ba1..73b2746 100644
--- a/bazel_rules_fuchsia/fuchsia/defs.bzl
+++ b/bazel_rules_fuchsia/fuchsia/defs.bzl
@@ -62,6 +62,7 @@
"//fuchsia/private:fuchsia_package.bzl",
_fuchsia_package = "fuchsia_package",
_fuchsia_test_package = "fuchsia_test_package",
+ _fuchsia_unittest_package = "fuchsia_unittest_package",
)
load(
"//fuchsia/private:fuchsia_rust.bzl",
@@ -134,6 +135,7 @@
fuchsia_fidl_llcpp_library = _fuchsia_fidl_llcpp_library
fuchsia_package = _fuchsia_package
fuchsia_test_package = _fuchsia_test_package
+fuchsia_unittest_package = _fuchsia_unittest_package
fuchsia_package_resource = _fuchsia_package_resource
fuchsia_package_resource_group = _fuchsia_package_resource_group
fuchsia_package_repository = _fuchsia_package_repository
diff --git a/bazel_rules_fuchsia/fuchsia/private/fuchsia_cc.bzl b/bazel_rules_fuchsia/fuchsia/private/fuchsia_cc.bzl
index 59e597e..0a6a8a4 100644
--- a/bazel_rules_fuchsia/fuchsia/private/fuchsia_cc.bzl
+++ b/bazel_rules_fuchsia/fuchsia/private/fuchsia_cc.bzl
@@ -21,8 +21,8 @@
":providers.bzl",
"FuchsiaComponentInfo",
"FuchsiaDebugSymbolInfo",
- "FuchsiaDefaultComponentInfo",
"FuchsiaPackageResourcesInfo",
+ "FuchsiaUnitTestComponentInfo",
)
KNOWN_PROVIDERS = [
@@ -264,23 +264,23 @@
},
)
-def _add_default_component_info_for_test_impl(ctx):
+def _add_component_info_for_unit_test_impl(ctx):
return forward_providers(ctx, ctx.attr.base) + ([
- FuchsiaDefaultComponentInfo(component = ctx.attr.default_component),
- ] if ctx.attr.default_component else [])
+ FuchsiaUnitTestComponentInfo(test_component = ctx.attr.generated_component),
+ ] if ctx.attr.generated_component else [])
-_add_default_component_info_for_test = rule_variant(
+_add_component_info_for_unit_test = rule_variant(
variant = "test",
- implementation = _add_default_component_info_for_test_impl,
- doc = """Provides FuchsiaDefaultComponentInfo on top of _fuchsia_cc providers.""",
+ implementation = _add_component_info_for_unit_test_impl,
+ doc = """Provides FuchsiaUnitTestComponentInfo on top of _fuchsia_cc providers.""",
attrs = {
"base": attr.label(
doc = "The base _fuchsia_cc target.",
mandatory = True,
providers = [[CcInfo, FuchsiaPackageResourcesInfo]],
),
- "default_component": attr.label(
- doc = "The default component target.",
+ "generated_component": attr.label(
+ doc = "The autogenerated test component.",
providers = [FuchsiaComponentInfo],
),
},
@@ -354,10 +354,10 @@
**kwargs
)
- _add_default_component_info_for_test(
+ _add_component_info_for_unit_test(
name = name,
base = ":%s_native_cc" % name,
- default_component = if_fuchsia(":%s_autogen_component" % name, if_not = None),
+ generated_component = if_fuchsia(":%s_autogen_component" % name, if_not = None),
testonly = True,
**kwargs
)
diff --git a/bazel_rules_fuchsia/fuchsia/private/fuchsia_component.bzl b/bazel_rules_fuchsia/fuchsia/private/fuchsia_component.bzl
index bd9b6fa..86e1f7e 100644
--- a/bazel_rules_fuchsia/fuchsia/private/fuchsia_component.bzl
+++ b/bazel_rules_fuchsia/fuchsia/private/fuchsia_component.bzl
@@ -3,8 +3,8 @@
# found in the LICENSE file.
load(":fuchsia_debug_symbols.bzl", "collect_debug_symbols")
-load(":providers.bzl", "FuchsiaComponentInfo", "FuchsiaPackageResourcesInfo")
-load(":utils.bzl", "make_resource_struct", "rule_variants")
+load(":providers.bzl", "FuchsiaComponentInfo", "FuchsiaPackageResourcesInfo", "FuchsiaUnitTestComponentInfo")
+load(":utils.bzl", "make_resource_struct", "rule_variant", "rule_variants")
def fuchsia_component(name, manifest, deps = None, **kwargs):
"""Creates a Fuchsia component that can be added to a package.
@@ -139,3 +139,18 @@
),
},
)
+
+def _fuchsia_component_for_unit_test_impl(ctx):
+ return [ctx.attr.unit_test[FuchsiaUnitTestComponentInfo].test_component[FuchsiaComponentInfo]]
+
+fuchsia_component_for_unit_test = rule_variant(
+ variant = "test",
+ doc = """Transforms a FuchsiaUnitTestComponentInfo into a test component.""",
+ implementation = _fuchsia_component_for_unit_test_impl,
+ attrs = {
+ "unit_test": attr.label(
+ doc = "The unit test to convert into a test component",
+ providers = [FuchsiaUnitTestComponentInfo],
+ ),
+ },
+)
diff --git a/bazel_rules_fuchsia/fuchsia/private/fuchsia_debug_symbols.bzl b/bazel_rules_fuchsia/fuchsia/private/fuchsia_debug_symbols.bzl
index 3a2d953..69270e2 100644
--- a/bazel_rules_fuchsia/fuchsia/private/fuchsia_debug_symbols.bzl
+++ b/bazel_rules_fuchsia/fuchsia/private/fuchsia_debug_symbols.bzl
@@ -89,27 +89,27 @@
},
)
-def collect_debug_symbols(*targets):
- targets = [target for target in flatten(targets) if FuchsiaDebugSymbolInfo in target]
+def collect_debug_symbols(*targets_or_providers):
+ build_id_dirs = [
+ (target_or_provider if (
+ hasattr(target_or_provider, "build_id_dirs")
+ ) else target_or_provider[FuchsiaDebugSymbolInfo]).build_id_dirs
+ for target_or_provider in flatten(targets_or_providers)
+ if hasattr(target_or_provider, "build_id_dirs") or FuchsiaDebugSymbolInfo in target_or_provider
+ ]
return FuchsiaDebugSymbolInfo(build_id_dirs = {
build_dir: depset(transitive = [
- target[FuchsiaDebugSymbolInfo].build_id_dirs[build_dir]
- for target in targets
- if build_dir in target[FuchsiaDebugSymbolInfo].build_id_dirs
+ build_dir_mapping[build_dir]
+ for build_dir_mapping in build_id_dirs
+ if build_dir in build_dir_mapping
])
for build_dir in depset([
file
- for file in flatten([
- target[FuchsiaDebugSymbolInfo].build_id_dirs.keys()
- for target in targets
- ])
+ for file in flatten([build_id_dir.keys() for build_id_dir in build_id_dirs])
if type(file) == "File"
]).to_list() + depset([
string
- for string in flatten([
- target[FuchsiaDebugSymbolInfo].build_id_dirs.keys()
- for target in targets
- ])
+ for string in flatten([build_id_dir.keys() for build_id_dir in build_id_dirs])
if type(string) == "string"
]).to_list()
})
diff --git a/bazel_rules_fuchsia/fuchsia/private/fuchsia_driver_tool.bzl b/bazel_rules_fuchsia/fuchsia/private/fuchsia_driver_tool.bzl
index 7e80e66..c604abe 100644
--- a/bazel_rules_fuchsia/fuchsia/private/fuchsia_driver_tool.bzl
+++ b/bazel_rules_fuchsia/fuchsia/private/fuchsia_driver_tool.bzl
@@ -59,7 +59,7 @@
fuchsia_package(
name = "pkg",
- deps = [ ":my_tool" ]
+ tools = [ ":my_tool" ]
)
$ bazel run //pkg.my_tool -- --arg1 foo --arg2 bar
diff --git a/bazel_rules_fuchsia/fuchsia/private/fuchsia_package.bzl b/bazel_rules_fuchsia/fuchsia/private/fuchsia_package.bzl
index dbc28c4..8b05773 100644
--- a/bazel_rules_fuchsia/fuchsia/private/fuchsia_package.bzl
+++ b/bazel_rules_fuchsia/fuchsia/private/fuchsia_package.bzl
@@ -5,38 +5,25 @@
load(
":providers.bzl",
"FuchsiaComponentInfo",
- "FuchsiaDebugSymbolInfo",
- "FuchsiaDefaultComponentInfo",
"FuchsiaDriverToolInfo",
"FuchsiaPackageInfo",
"FuchsiaPackageResourcesInfo",
)
-load(":fuchsia_debug_symbols.bzl", "get_build_id_dirs", "strip_resources")
-load(":fuchsia_runnable.bzl", "fuchsia_runnable", "fuchsia_runnable_test")
+load(":fuchsia_component.bzl", "fuchsia_component_for_unit_test")
+load(":fuchsia_debug_symbols.bzl", "collect_debug_symbols", "get_build_id_dirs", "strip_resources")
load(":fuchsia_transition.bzl", "fuchsia_transition")
load(":package_publishing.bzl", "package_repo_path_from_label", "publish_package")
-load(":utils.bzl", "forward_providers", "make_resource_struct", "rule_variant", "rule_variants", "stub_executable")
-load("@rules_fuchsia//fuchsia/private/workflows:fuchsia_task_publish.bzl", "fuchsia_task_publish")
-load("@rules_fuchsia//fuchsia/private/workflows:fuchsia_workflow.bzl", "fuchsia_workflow")
-load("@rules_fuchsia//fuchsia/private/workflows:fuchsia_task_register_debug_symbols.bzl", "fuchsia_task_register_debug_symbols")
-load("@rules_fuchsia//fuchsia/private/workflows:fuchsia_shell_task.bzl", "fuchsia_shell_task")
-load("@rules_fuchsia//fuchsia/private/workflows:providers.bzl", "FuchsiaWorkflowInfo")
-
-def _dep_name(dep):
- # convert the dependency to a single word
- # //foo/bar -> bar
- # :bar -> bar
- # //foo:bar -> bar
- return dep.split("/")[-1].split(":")[-1]
+load(":utils.bzl", "label_name", "make_resource_struct", "rule_variants", "stub_executable")
+load("//fuchsia/private/workflows:fuchsia_package_tasks.bzl", "fuchsia_package_tasks")
def fuchsia_package(
+ *,
name,
package_name = None,
archive_name = None,
components = [],
resources = [],
tools = [],
- deps = [],
**kwargs):
"""Builds a fuchsia package.
@@ -57,6 +44,7 @@
tools = [":my_tool"]
)
```
+ - pkg.help: Calling run on this target will show the valid macro-expanded targets
- pkg.publish: Calling run on this target will publish the package
- pkg.my_component: Calling run on this target will call `ffx component run`
with the component url if it is fuchsia_component instance and will
@@ -72,75 +60,109 @@
resources: A list of additional resources to add to this package. These
resources will not have debug symbols stripped.
tools: Additional tools that should be added to this package.
- deps: (Deprecated) use components, resources and tools instead.
package_name: An optional name to use for this package, defaults to name.
archive_name: An option name for the far file.
**kwargs: extra attributes to pass along to the build rule.
"""
- if deps != []:
- print("""
-\nNOTICE: fuchsia_package:deps is deprecated and will be removed soon.
-Use components, resources and tools instead.
- """) # buildifier: disable=print
-
- # We need to soft transition away from deps. For now, just change the public
- # API but keep all the existing functionality.
- deps = deps + components + resources + tools
-
_build_fuchsia_package(
- name = name,
- deps = deps,
- package_name = package_name,
+ name = "%s_fuchsia_package" % name,
+ components = components,
+ resources = resources,
+ tools = tools,
+ package_name = package_name or name,
archive_name = archive_name,
**kwargs
)
- fuchsia_task_publish(
- name = "%s.publish" % name,
- packages = [name],
- apply_fuchsia_transition = True,
+ fuchsia_package_tasks(
+ name = name,
+ package = "%s_fuchsia_package" % name,
+ components = {component: component for component in components},
+ tools = {tool: tool for tool in tools},
**kwargs
)
- if "package_repository_name" in kwargs:
- kwargs.pop("package_repository_name")
+def _fuchsia_test_package(
+ *,
+ name,
+ package_name = None,
+ archive_name = None,
+ resources = [],
+ _test_component_mapping,
+ _components = [],
+ **kwargs):
+ """Defines test variants of fuchsia_package.
- fuchsia_task_register_debug_symbols(
- name = "%s.debug_symbols" % name,
- deps = deps + [name, "@fuchsia_sdk//:debug_symbols"],
- apply_fuchsia_transition = True,
+ See fuchsia_package for argument descriptions."""
+
+ _build_fuchsia_package_test(
+ name = "%s_fuchsia_package" % name,
+ test_components = _test_component_mapping.values(),
+ components = _components,
+ resources = resources,
+ package_name = package_name or name,
+ archive_name = archive_name,
**kwargs
)
- # create targets for each component & tool
- for dep in components + tools or deps:
- child_name = name + "." + _dep_name(dep)
- fuchsia_runnable(
- name = "%s_runnable" % child_name,
- package = name,
- target = dep,
+ fuchsia_package_tasks(
+ name = name,
+ package = "%s_fuchsia_package" % name,
+ components = _test_component_mapping,
+ is_test = True,
+ **kwargs
+ )
+
+def fuchsia_test_package(
+ *,
+ name,
+ test_components = [],
+ components = [],
+ **kwargs):
+ """A test variant of fuchsia_package.
+
+ See _fuchsia_test_package for additional arguments."""
+ _fuchsia_test_package(
+ name = name,
+ _test_component_mapping = {component: component for component in test_components},
+ _components = components,
+ **kwargs
+ )
+
+def fuchsia_unittest_package(
+ *,
+ name,
+ package_name = None,
+ archive_name = None,
+ resources = [],
+ unit_tests,
+ **kwargs):
+ """A variant of fuchsia_test_package containing unit tests.
+
+ See _fuchsia_test_package for additional arguments."""
+
+ test_component_mapping = {}
+ for unit_test in unit_tests:
+ test_component_mapping[unit_test] = "%s_unit_test" % label_name(unit_test)
+ fuchsia_component_for_unit_test(
+ name = test_component_mapping[unit_test],
+ unit_test = unit_test,
**kwargs
)
- fuchsia_shell_task(
- name = "%s.run" % child_name,
- default_argument_scope = "global",
- target = "%s_runnable" % child_name,
- **kwargs
- )
- fuchsia_workflow(
- name = child_name,
- sequence = [
- "%s.debug_symbols" % name,
- "%s.run" % child_name,
- ],
- apply_fuchsia_transition = True,
- **kwargs
- )
+
+ _fuchsia_test_package(
+ name = name,
+ package_name = package_name,
+ archive_name = archive_name,
+ resources = resources,
+ _test_component_mapping = test_component_mapping,
+ **kwargs
+ )
+ pass
def _build_fuchsia_package_impl(ctx):
sdk = ctx.toolchains["@rules_fuchsia//fuchsia:toolchain"]
- package_name = ctx.attr.package_name or ctx.label.name
- archive_name = ctx.attr.archive_name or package_name
+ archive_name = ctx.attr.archive_name or ctx.attr.package_name
if not archive_name.endswith(".far"):
archive_name += ".far"
@@ -174,11 +196,16 @@
components = []
drivers = []
- # Collect all the resources from the deps
- for dep in ctx.attr.deps:
- if FuchsiaDefaultComponentInfo in dep:
- dep = dep[FuchsiaDefaultComponentInfo].component
+ # Verify correctness of test vs non-test components.
+ for test_component in ctx.attr.test_components:
+ if not test_component[FuchsiaComponentInfo].is_test:
+ fail("Please use `components` for non-test components.")
+ for component in ctx.attr.components:
+ if component[FuchsiaComponentInfo].is_test:
+ fail("Please use `test_components` for test components.")
+ # Collect all the resources from the deps
+ for dep in ctx.attr.test_components + ctx.attr.components + ctx.attr.resources + ctx.attr.tools:
if FuchsiaComponentInfo in dep:
component_info = dep[FuchsiaComponentInfo]
component_manifest = component_info.manifest
@@ -196,15 +223,16 @@
),
)
resources_to_strip.extend([r for r in component_info.resources])
- elif FuchsiaPackageResourcesInfo in dep:
- resources_to_strip.extend(dep[FuchsiaPackageResourcesInfo].resources)
elif FuchsiaDriverToolInfo in dep:
resources_to_strip.extend(dep[FuchsiaDriverToolInfo].resources)
+ elif FuchsiaPackageResourcesInfo in dep:
+ # Don't strip debug symbols from resources.
+ package_resources.extend(dep[FuchsiaPackageResourcesInfo].resources)
else:
fail("Unknown dependency type being added to package: %s" % dep.label)
# Grab all of our stripped resources
- stripped_resources, debug_info = strip_resources(ctx, resources_to_strip)
+ stripped_resources, _debug_info = strip_resources(ctx, resources_to_strip)
package_resources.extend(stripped_resources)
# Write our package_manifest file
@@ -221,7 +249,7 @@
"-o", # output directory
output_dir,
"-n", # name of the package
- package_name,
+ ctx.attr.package_name,
"init",
],
outputs = [
@@ -249,7 +277,7 @@
"-m",
manifest.path,
"-n",
- package_name,
+ ctx.attr.package_name,
] + repo_name_args + api_level_input + [
"build",
"--output-package-manifest",
@@ -273,7 +301,7 @@
"-m",
manifest.path,
"-n",
- package_name,
+ ctx.attr.package_name,
"archive",
"-output",
# pm automatically adds .far so we have to remove it here to make
@@ -316,16 +344,23 @@
far_file = far_file,
package_manifest = output_package_manifest,
files = [output_package_manifest, meta_far] + build_inputs,
- package_name = package_name,
+ package_name = ctx.attr.package_name,
components = components,
drivers = drivers,
meta_far = meta_far,
package_resources = package_resources,
# TODO: Remove this field, change usages to FuchsiaDebugSymbolInfo.
- build_id_dir = get_build_id_dirs(debug_info)[0],
+ build_id_dir = get_build_id_dirs(_debug_info)[0],
),
- debug_info,
+ collect_debug_symbols(
+ _debug_info,
+ ctx.attr.test_components,
+ ctx.attr.components,
+ ctx.attr.resources,
+ ctx.attr.tools,
+ ctx.attr._fuchsia_sdk_debug_symbols,
+ ),
]
_build_fuchsia_package, _build_fuchsia_package_test = rule_variants(
@@ -335,20 +370,37 @@
cfg = fuchsia_transition,
toolchains = ["@rules_fuchsia//fuchsia:toolchain", "@bazel_tools//tools/cpp:toolchain_type"],
attrs = {
+ "package_name": attr.string(
+ doc = "The name of the package",
+ mandatory = True,
+ ),
"archive_name": attr.string(
doc = "What to name the archive. The .far file will be appended if not in this name. Defaults to package_name",
),
- "package_name": attr.string(
- doc = "The name of the package, defaults to the rule name",
- ),
# TODO(https://fxbug.dev/114334): Improve doc for this field when we
# have more clarity from the bug.
"package_repository_name": attr.string(
doc = "Repository name of this package, defaults to None",
),
- "deps": attr.label_list(
- doc = "The list of dependencies this package depends on",
- providers = [[FuchsiaComponentInfo], [FuchsiaDefaultComponentInfo], [FuchsiaPackageResourcesInfo], [FuchsiaDriverToolInfo]],
+ "components": attr.label_list(
+ doc = "The list of components included in this package",
+ providers = [FuchsiaComponentInfo],
+ ),
+ "test_components": attr.label_list(
+ doc = "The list of test components included in this package",
+ providers = [FuchsiaComponentInfo],
+ ),
+ "resources": attr.label_list(
+ doc = "The list of resources included in this package",
+ providers = [FuchsiaPackageResourcesInfo],
+ ),
+ "tools": attr.label_list(
+ doc = "The list of tools included in this package",
+ providers = [FuchsiaDriverToolInfo],
+ ),
+ "_fuchsia_sdk_debug_symbols": attr.label(
+ doc = "Include debug symbols from @fuchsia_sdk.",
+ default = "@fuchsia_sdk//:debug_symbols",
),
"_package_repo_path": attr.label(
doc = "The command line flag used to publish packages.",
@@ -372,139 +424,3 @@
),
},
)
-
-def _add_package_providers_impl(ctx):
- return forward_providers(ctx, ctx.attr.workflow) + [
- ctx.attr.package[FuchsiaPackageInfo],
- ctx.attr.package[FuchsiaDebugSymbolInfo],
- ]
-
-_add_package_providers_for_test = rule_variant(
- variant = "test",
- doc = "Adds FuchsiaPackageInfo and FuchsiaDebugSymbolInfo on top of a fuchsia_workflow.",
- implementation = _add_package_providers_impl,
- cfg = fuchsia_transition,
- attrs = {
- "workflow": attr.label(
- doc = "The base fuchsia_workflow to extend.",
- providers = [FuchsiaWorkflowInfo],
- mandatory = True,
- ),
- "package": attr.label(
- doc = "The package to get providers from.",
- providers = [[FuchsiaPackageInfo, FuchsiaDebugSymbolInfo]],
- mandatory = True,
- ),
- "_allowlist_function_transition": attr.label(
- default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
- ),
- },
-)
-
-def fuchsia_test_package(
- name = None,
- package_name = None,
- archive_name = None,
- test_components = [],
- components = [],
- resources = [],
- tools = [],
- deps = [],
- tags = [],
- **kwargs):
- """A test variant of fuchsia_package.
-
- See fuchsia_package for argument descriptions."""
- if deps != []:
- print("""
-\nNOTICE: fuchsia_package:deps is deprecated and will be removed soon.
-Use test_components, components, resources and tools instead.
- """) # buildifier: disable=print
-
- # We need to soft transition away from deps. For now, just change the public
- # API but keep all the existing functionality.
- deps = deps + test_components + components + resources + tools
-
- _build_fuchsia_package_test(
- name = "%s_fuchsia_package" % name,
- deps = deps,
- package_name = package_name or name,
- archive_name = archive_name,
- tags = tags,
- **kwargs
- )
-
- fuchsia_task_register_debug_symbols(
- name = "%s.debug_symbols" % name,
- deps = deps + [
- "%s_fuchsia_package" % name,
- "@fuchsia_sdk//:debug_symbols",
- ],
- testonly = True,
- apply_fuchsia_transition = True,
- tags = tags,
- **kwargs
- )
-
- fuchsia_task_publish(
- name = "%s.publish" % name,
- packages = ["%s_fuchsia_package" % name],
- testonly = True,
- apply_fuchsia_transition = True,
- tags = tags,
- **kwargs
- )
-
- # create targets for each component & tool
- component_test_tasks = []
- for dep in test_components or deps:
- child_name = name + "." + _dep_name(dep)
- fuchsia_runnable_test(
- name = "%s_runnable" % child_name,
- package = name + "_fuchsia_package",
- target = dep,
- testonly = True,
- tags = tags,
- **kwargs
- )
- component_test_tasks.append("%s.run" % child_name)
- fuchsia_shell_task(
- name = "%s.run" % child_name,
- default_argument_scope = "global",
- target = "%s_runnable" % child_name,
- testonly = True,
- tags = tags,
- **kwargs
- )
- fuchsia_workflow(
- name = child_name,
- sequence = [
- "%s.debug_symbols" % name,
- "%s.run" % child_name,
- ],
- testonly = True,
- apply_fuchsia_transition = True,
- # TODO(fxbug.dev/98996): Use ffx isolation. ffx test run currently needs
- # to access ~/.local/share/Fuchsia/ffx/ or else it crashes.
- tags = tags + ["no-sandbox", "no-cache"],
- **kwargs
- )
-
- fuchsia_workflow(
- name = "%s_workflow" % name,
- sequence = [
- "%s.debug_symbols" % name,
- ] + component_test_tasks,
- testonly = True,
- **kwargs
- )
-
- _add_package_providers_for_test(
- name = name,
- workflow = "%s_workflow" % name,
- package = "%s_fuchsia_package" % name,
- # TODO(fxbug.dev/98996): Use ffx isolation. ffx test run currently needs
- # to access ~/.local/share/Fuchsia/ffx/ or else it crashes.
- tags = tags + ["no-sandbox", "no-cache", "manual"],
- **kwargs
- )
diff --git a/bazel_rules_fuchsia/fuchsia/private/fuchsia_runnable.bzl b/bazel_rules_fuchsia/fuchsia/private/fuchsia_runnable.bzl
deleted file mode 100644
index 1759992..0000000
--- a/bazel_rules_fuchsia/fuchsia/private/fuchsia_runnable.bzl
+++ /dev/null
@@ -1,120 +0,0 @@
-# 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(":utils.bzl", "normalized_target_name", "rule_variants")
-load(
- ":providers.bzl",
- "FuchsiaComponentInfo",
- "FuchsiaDefaultComponentInfo",
- "FuchsiaDriverToolInfo",
- "FuchsiaPackageInfo",
- "FuchsiaRunnableInfo",
-)
-
-def _run_as_component(ctx, component):
- sdk = ctx.toolchains["@rules_fuchsia//fuchsia:toolchain"]
- executable_file = ctx.actions.declare_file(ctx.label.name + "_run_component.sh")
-
- package = ctx.attr.package[FuchsiaPackageInfo]
-
- if component.is_driver:
- action = "register_driver"
- else:
- action = "run_component"
-
- ctx.actions.expand_template(
- template = ctx.file._component_run_template,
- output = executable_file,
- substitutions = {
- "{{ffx}}": sdk.ffx.short_path,
- "{{pm}}": sdk.pm.short_path,
- "{{repo_path}}": "pm_repo",
- "{{default_repo_name}}": "bazel." + normalized_target_name(ctx.label),
- "{{far_file}}": package.far_file.short_path,
- "{{package_name}}": package.package_name,
- "{{component_manifest}}": component.manifest.basename,
- "{{run_or_test_component}}": "test_component" if ctx.attr._variant == "test" else action,
- },
- is_executable = True,
- )
-
- runfiles = sdk.runfiles.merge(ctx.runfiles([package.far_file]))
-
- return [
- DefaultInfo(executable = executable_file, runfiles = runfiles),
- FuchsiaRunnableInfo(
- executable = executable_file,
- runfiles = runfiles,
- is_test = ctx.attr._variant == "test",
- ),
- ]
-
-def _run_driver_tool(ctx, tool):
- sdk = ctx.toolchains["@rules_fuchsia//fuchsia:toolchain"]
- executable_file = ctx.actions.declare_file(ctx.label.name + "_run_driver_tool.sh")
-
- archive = ctx.attr.package[FuchsiaPackageInfo]
-
- ctx.actions.expand_template(
- template = ctx.file._driver_tool_run_template,
- output = executable_file,
- substitutions = {
- "{{ffx}}": sdk.ffx.short_path,
- "{{pm}}": sdk.pm.short_path,
- "{{repo_path}}": "pm_repo",
- "{{default_repo_name}}": "bazel." + normalized_target_name(ctx.label),
- "{{far_file}}": archive.far_file.short_path,
- "{{package_name}}": archive.package_name,
- "{{binary}}": tool.dest,
- },
- is_executable = True,
- )
-
- runfiles = sdk.runfiles.merge(ctx.runfiles([archive.far_file]))
-
- return [
- DefaultInfo(executable = executable_file, runfiles = runfiles),
- FuchsiaRunnableInfo(
- executable = executable_file,
- runfiles = runfiles,
- is_test = False,
- ),
- ]
-
-def _fuchsia_runnable_impl(ctx):
- _target = ctx.attr.target
- if FuchsiaDefaultComponentInfo in _target:
- _target = _target[FuchsiaDefaultComponentInfo].component
-
- if FuchsiaComponentInfo in _target and _target[FuchsiaComponentInfo].is_test == (ctx.attr._variant == "test"):
- return _run_as_component(ctx, _target[FuchsiaComponentInfo])
- elif FuchsiaDriverToolInfo in _target:
- return _run_driver_tool(ctx, _target[FuchsiaDriverToolInfo].binary)
- else:
- return []
-
-fuchsia_runnable, fuchsia_runnable_test = rule_variants(
- variants = ("executable", "test"),
- doc = "Creates a rule that can be invoked with bazel run/test",
- implementation = _fuchsia_runnable_impl,
- toolchains = ["@rules_fuchsia//fuchsia:toolchain"],
- attrs = {
- "package": attr.label(
- doc = "The fuchsia_package containing target",
- providers = [FuchsiaPackageInfo],
- ),
- "target": attr.label(
- doc = "The target of the runnable action",
- mandatory = True,
- ),
- "_component_run_template": attr.label(
- default = ":templates/run_component.sh.tmpl",
- allow_single_file = True,
- ),
- "_driver_tool_run_template": attr.label(
- default = ":templates/run_driver_tool.sh.tmpl",
- allow_single_file = True,
- ),
- },
-)
diff --git a/bazel_rules_fuchsia/fuchsia/private/providers.bzl b/bazel_rules_fuchsia/fuchsia/private/providers.bzl
index ea6b92f..104143d 100644
--- a/bazel_rules_fuchsia/fuchsia/private/providers.bzl
+++ b/bazel_rules_fuchsia/fuchsia/private/providers.bzl
@@ -38,10 +38,10 @@
},
)
-FuchsiaDefaultComponentInfo = provider(
- "Information that can be used to construct a FuchsiaComponentInfo.",
+FuchsiaUnitTestComponentInfo = provider(
+ "Allows unit tests to be treated as test components.",
fields = {
- "component": "The label of a target that provides FuchsiaComponentInfo.",
+ "test_component": "The label of the underlying fuchsia_test_component.",
},
)
diff --git a/bazel_rules_fuchsia/fuchsia/private/templates/run_component.sh.tmpl b/bazel_rules_fuchsia/fuchsia/private/templates/run_component.sh.tmpl
deleted file mode 100644
index 4a8c40e..0000000
--- a/bazel_rules_fuchsia/fuchsia/private/templates/run_component.sh.tmpl
+++ /dev/null
@@ -1,177 +0,0 @@
-#!/bin/bash
-# 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.
-
-set -e -o pipefail
-
-help() {
- echo
- echo "runs/tests a component on a the target."
- echo
- echo "Usage:"
- echo " $(basename "$0") [<options>]"
- echo
- echo "Options:"
- echo
- echo " -t, --target <target_name>"
- echo " Specifies the target to run the component on. Defaults to ffx target default get"
- echo " -v, --verbose"
- echo " If set will output more logs"
- echo " -s, --session"
- echo " If set the component will be added to the session (`ffx session add`) instead"
- echo " of running in ffx-laboratory (`ffx component run`)."
- echo " --repository-name <repo_name>"
- echo " Sets the name of the repository to use when publishing the package."
- echo " This command will fail if the repository already exists unless the"
- echo " --use-existing flag is also passed."
- echo " --use-existing"
- echo " Allows for an existing repository to be used. This flag is not yet implemented."
- echo
- echo "All other options will be forwarded to ffx component run (when not using --session),"
- echo "ffx session add (when using --sesssion) or ffx test run."
- echo
-}
-
-function log {
- if [[ "$VERBOSE_LOGS" -eq 1 ]]; then
- echo "$@"
- fi
-}
-
-function repository_name {
- if [[ -n "${REPOSITORY_NAME}" ]]; then
- echo "${REPOSITORY_NAME}"
- else
- echo {{default_repo_name}}
- fi
-}
-
-function component_url {
- local repo_name=$(repository_name)
- echo "fuchsia-pkg://${repo_name}/{{package_name}}#meta/{{component_manifest}}"
-}
-
-function ffx_with_target {
- if [[ -n "${TARGET}" ]]; then
- {{ffx}} --target "${TARGET}" "$@"
- else
- {{ffx}} "$@"
- fi
-}
-
-function cleanup_repo {
- # Do not exit if repo_path doesn't exist
- set +e
- log "Cleaning up repository"
- rm -r {{repo_path}}
- {{ffx}} repository remove "$(repository_name)"
- set -e
-}
-
-function create_and_register_repo {
- local repo_name=$(repository_name)
- log "Creating new repository $(repository_name)"
-
- check_if_repo_exists
-
- {{pm}} newrepo -vt -repo {{repo_path}} || exit 1
-
- {{ffx}} repository add-from-pm -r "${repo_name}" {{repo_path}} || exit 1
- ffx_with_target target repository register -r "${repo_name}" || exit 1
-}
-
-function publish_far_file {
- log "Publishing {{far_file}}"
-
- {{pm}} publish -vt -C -a -f {{far_file}} -repo {{repo_path}} || exit 1
-}
-
-function run_component {
- local url=$(component_url)
- log "running component: ${url} $*"
-
- if [[ "$RUN_IN_SESSION" -eq 1 ]]; then
- ffx_with_target session add "${url}" "${@}"
- else
- # TODO(fxb/113040) - Update moniker to a template variable given to this script by a Bazel rule.
- ffx_with_target component run "/core/ffx-laboratory:{{component_manifest}}" "${url}" --recreate "${@}"
- fi
-
-}
-
-function register_driver {
- local url=$(component_url)
- log "registering driver: ${url} $*"
-
- ffx_with_target driver register "${url}" "${@}"
-}
-
-function test_component {
- local url=$(component_url)
- log "testing component: ${url} $*"
-
- ffx_with_target test run "${url}" "${@}"
-}
-
-function check_if_repo_exists {
- local repo_name=$(repository_name)
- local result=$({{ffx}} --machine JSON repository list | grep "\"name\":\""${repo_name}"\"" >/dev/null)
-
-
- if [[ ! -z "${result}" ]]; then
- echo "ERROR: repository ${repo_name} already exists."
- echo " pass the --use-existing if you would like to use an existing repository."
- exit 1
- fi
-}
-
-function main {
- UNUSED_ARGS=()
- while [[ $# -gt 0 ]]; do
- case $1 in
- -t|--target)
- TARGET="$2"
- shift # past argument
- shift # past value
- ;;
- -v|--verbose)
- VERBOSE_LOGS=1
- shift # past value
- ;;
- -h|--help)
- help
- exit 1
- ;;
- --use-existing)
- shift # past value
- echo "ERROR: the --use-existing flag is not yet supported."
- exit 1
- ;;
- --repository-name)
- REPOSITORY_NAME="$2"
- shift # past argument
- shift # past value
- echo "set repo name"
- ;;
- -s|--session)
- RUN_IN_SESSION=1
- shift # past value
- ;;
- *)
- UNUSED_ARGS+=("$1") # save unused arg
- shift # past argument
- ;;
- esac
- done
- set -- "${UNUSED_ARGS[@]}"
-
- # make sure we cleanup when we are done
- trap cleanup_repo EXIT
-
- create_and_register_repo
- publish_far_file
- {{run_or_test_component}} "$@"
-}
-
-main "$@"
diff --git a/bazel_rules_fuchsia/fuchsia/private/templates/run_driver_tool.sh.tmpl b/bazel_rules_fuchsia/fuchsia/private/templates/run_driver_tool.sh.tmpl
deleted file mode 100644
index 74a865c..0000000
--- a/bazel_rules_fuchsia/fuchsia/private/templates/run_driver_tool.sh.tmpl
+++ /dev/null
@@ -1,131 +0,0 @@
-#!/bin/bash
-# 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.
-
-set -e -o pipefail
-
-help() {
- echo
- echo "runs a driver tool on the target with ffx driver run-tool."
- echo
- echo "Usage:"
- echo " $(basename "$0") [<options>]"
- echo
- echo "Options:"
- echo
- echo " -t, --target <target_name>"
- echo " Specifies the target to run the tool on. Defaults to ffx target default get"
- echo " -v, --verbose"
- echo " If set will output more logs"
- echo
- echo "All other options will be forwarded to ffx driver run-tool."
- echo
-}
-
-function log {
- if [[ "$VERBOSE_LOGS" -eq 1 ]]; then
- echo "$@"
- fi
-}
-
-function repository_name {
- if [[ -n "${REPOSITORY_NAME}" ]]; then
- echo "${REPOSITORY_NAME}"
- else
- echo {{default_repo_name}}
- fi
-}
-
-function driver_tool_url {
- local repo_name=$(repository_name)
- echo "fuchsia-pkg://${repo_name}/{{package_name}}#{{binary}}"
-}
-
-function ffx_with_target {
- if [[ -n "${TARGET}" ]]; then
- {{ffx}} --target "${TARGET}" "$@"
- else
- {{ffx}} "$@"
- fi
-}
-
-function cleanup_repo {
- # Do not exit if repo_path doesn't exist
- set +e
- log "Cleaning up repository"
- rm -r {{repo_path}}
- {{ffx}} repository remove "$(repository_name)"
- set -e
-}
-
-function create_and_register_repo {
- local repo_name=$(repository_name)
- log "Creating new repository $(repository_name)"
-
- check_if_repo_exists
-
- {{pm}} newrepo -vt -repo {{repo_path}} || exit 1
-
- {{ffx}} repository add-from-pm -r "${repo_name}" {{repo_path}} || exit 1
- ffx_with_target target repository register -r "${repo_name}" || exit 1
-}
-
-function publish_far_file {
- log "Publishing {{far_file}}"
-
- {{pm}} publish -vt -C -a -f {{far_file}} -repo {{repo_path}} || exit 1
-}
-
-function run_driver_tool {
- local url=$(driver_tool_url)
- log "running driver tool: ${url} $*"
- ffx_with_target driver run-tool "${url}" -- "$@"
-}
-
-function check_if_repo_exists {
- local repo_name=$(repository_name)
- local result=$({{ffx}} --machine JSON repository list | grep "\"name\":\""${repo_name}"\"" >/dev/null)
-
-
- if [[ ! -z "${result}" ]]; then
- echo "ERROR: repository ${repo_name} already exists."
- echo " pass the --use-existing if you would like to use an existing repository."
- exit 1
- fi
-}
-
-function main {
- UNUSED_ARGS=()
- while [[ $# -gt 0 ]]; do
- case $1 in
- -t|--target)
- TARGET="$2"
- shift
- shift
- ;;
- -v|--verbose)
- VERBOSE_LOGS=1
- shift
- ;;
- -h|--help)
- help
- exit
- ;;
- *)
- UNUSED_ARGS+=("$1") # save unused arg
- shift
- ;;
- esac
- done
- set -- "${UNUSED_ARGS[@]}"
-
- create_and_register_repo
- publish_far_file
- run_driver_tool "$@"
-}
-
-# make sure we cleanup when we are done
-trap cleanup_repo EXIT
-
-main "$@"
diff --git a/bazel_rules_fuchsia/fuchsia/private/utils.bzl b/bazel_rules_fuchsia/fuchsia/private/utils.bzl
index 27e0616..a8aeff3 100644
--- a/bazel_rules_fuchsia/fuchsia/private/utils.bzl
+++ b/bazel_rules_fuchsia/fuchsia/private/utils.bzl
@@ -14,12 +14,19 @@
_INVALID_LABEL_CHARACTERS = "\"!%@^_#$&'()*+,;<=>?[]{|}~/".elems()
-def normalized_target_name(target):
- label = target.name.lower()
+def normalized_target_name(label):
+ label = label.lower()
for c in _INVALID_LABEL_CHARACTERS:
label = label.replace(c, ".")
return label
+def label_name(label):
+ # convert the label to a single word
+ # //foo/bar -> bar
+ # :bar -> bar
+ # //foo:bar -> bar
+ return label.split("/")[-1].split(":")[-1]
+
def get_project_execroot(ctx):
# Gets the project/workspace execroot relative to the output base.
# See https://bazel.build/docs/output_directories.
@@ -273,6 +280,6 @@
if (rparts[1] != ".so"):
return False
for char in rparts[2].elems():
- if not (char.isdigit() or char == '.'):
+ if not (char.isdigit() or char == "."):
return False
return True
diff --git a/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_package_tasks.bzl b/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_package_tasks.bzl
new file mode 100644
index 0000000..7178288
--- /dev/null
+++ b/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_package_tasks.bzl
@@ -0,0 +1,286 @@
+# 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(":fuchsia_shell_task.bzl", "shell_task_rule")
+load(":fuchsia_task_ffx.bzl", "fuchsia_task_ffx")
+load(":fuchsia_task_publish.bzl", "fuchsia_task_publish")
+load(":fuchsia_task_register_debug_symbols.bzl", "fuchsia_task_register_debug_symbols")
+load(":fuchsia_task_run_component.bzl", "fuchsia_task_run_component")
+load(":fuchsia_task_run_driver_tool.bzl", "fuchsia_task_run_driver_tool")
+load(":fuchsia_task_verbs.bzl", "make_help_executable", "verbs")
+load(":fuchsia_workflow.bzl", "fuchsia_workflow", "fuchsia_workflow_rule")
+load(":providers.bzl", "FuchsiaDebugSymbolInfo", "FuchsiaPackageInfo", "FuchsiaWorkflowInfo")
+load(":utils.bzl", "label_name", "normalized_target_name")
+
+def _to_verb(label):
+ return verbs.custom(label_name(label))
+
+def _fuchsia_package_help_impl(ctx, make_shell_task):
+ help = make_help_executable(ctx, dict((
+ [(verbs.noverb, "Run all test components within this test package.")] if ctx.attr.is_test and ctx.attr.components else []
+ ) + [
+ (verbs.help, "Print this help message."),
+ (verbs.debug_symbols, "Register this package's debug symbols."),
+ (verbs.publish, "Publish this package and register debug symbols."),
+ ] + [
+ (_to_verb(component), "Publish this package and run '%s' with debug symbols." % component)
+ for component in ctx.attr.components
+ ] + [
+ (_to_verb(tool), "Publish this package and run '%s' with debug symbols" % tool)
+ for tool in ctx.attr.tools
+ ]), name = ctx.attr.top_level_name)
+ return make_shell_task([help])
+
+(
+ __fuchsia_package_help,
+ _fuchsia_package_help_for_test,
+ _fuchsia_package_help,
+) = shell_task_rule(
+ implementation = _fuchsia_package_help_impl,
+ doc = "Prints valid runnable sub-targets in a package.",
+ attrs = {
+ "is_test": attr.bool(
+ doc = "Whether the package is a test package.",
+ mandatory = True,
+ ),
+ "package": attr.label(
+ doc = "The package.",
+ providers = [FuchsiaPackageInfo],
+ mandatory = True,
+ ),
+ "components": attr.string_list(
+ doc = "The component names.",
+ mandatory = True,
+ ),
+ "tools": attr.string_list(
+ doc = "The driver tool names.",
+ mandatory = True,
+ ),
+ "debug_symbols_task": attr.label(
+ doc = "The debug symbols task associated with the package.",
+ providers = [FuchsiaWorkflowInfo],
+ mandatory = True,
+ ),
+ "publish_task": attr.label(
+ doc = "The package publishing task associated with the package.",
+ providers = [FuchsiaWorkflowInfo],
+ mandatory = True,
+ ),
+ "top_level_name": attr.string(
+ doc = "The top level target name associated with these tasks",
+ mandatory = True,
+ ),
+ },
+)
+
+def _fuchsia_package_default_task_impl(ctx, make_workflow):
+ default_workflow = make_workflow(sequence = [
+ ctx.attr.debug_symbols_task,
+ ctx.attr.publish_task,
+ ctx.attr.publish_task,
+ ] + ctx.attr.component_run_tasks + [
+ ctx.attr.publish_cleanup_task,
+ ] if (
+ ctx.attr.is_test and ctx.attr.component_run_tasks
+ ) else [ctx.attr.help_task])
+ return default_workflow + [
+ ctx.attr.package[FuchsiaPackageInfo],
+ ctx.attr.package[FuchsiaDebugSymbolInfo],
+ ]
+
+(
+ __fuchsia_package_default_task,
+ _fuchsia_package_default_task_for_test,
+ _fuchsia_package_default_task,
+) = fuchsia_workflow_rule(
+ implementation = _fuchsia_package_default_task_impl,
+ doc = "Runs all test components for test packages, or prints a help message.",
+ attrs = {
+ "is_test": attr.bool(
+ doc = "Whether the package is a test package.",
+ mandatory = True,
+ ),
+ "help_task": attr.label(
+ doc = "The help task describing valid package subtargets.",
+ providers = [FuchsiaWorkflowInfo],
+ mandatory = True,
+ ),
+ "debug_symbols_task": attr.label(
+ doc = "The debug symbols task associated with the package.",
+ providers = [FuchsiaWorkflowInfo],
+ mandatory = True,
+ ),
+ "publish_task": attr.label(
+ doc = "The package publishing task associated with the package.",
+ providers = [FuchsiaWorkflowInfo],
+ mandatory = True,
+ ),
+ "publish_cleanup_task": attr.label(
+ doc = "The package publishing cleanup task associated with the package.",
+ providers = [FuchsiaWorkflowInfo],
+ mandatory = True,
+ ),
+ "component_run_tasks": attr.label_list(
+ doc = "The component run tasks.",
+ providers = [FuchsiaWorkflowInfo],
+ mandatory = True,
+ ),
+ "package": attr.label(
+ doc = "The package.",
+ providers = [FuchsiaPackageInfo],
+ mandatory = True,
+ ),
+ },
+)
+
+def fuchsia_package_tasks(
+ *,
+ name,
+ package,
+ components,
+ tools = {},
+ is_test = False,
+ tags = [],
+ **kwargs):
+ # TODO(fxbug.dev/98996): Use ffx isolation. ffx test run currently needs
+ # to access ~/.local/share/Fuchsia/ffx/ or else it crashes.
+ top_level_tags = tags + (["no-sandbox", "no-cache"] if is_test else [])
+
+ # Mark test children as manual.
+ manual_test = ["manual"] if is_test else []
+
+ # Override testonly since it's used to determine test vs non-test rule
+ # variant selection for workflows.
+ kwargs["testonly"] = is_test
+
+ # For `bazel run :pkg.debug_symbols`.
+ debug_symbols_task = verbs.debug_symbols(name)
+ fuchsia_task_register_debug_symbols(
+ name = debug_symbols_task,
+ deps = [package],
+ apply_fuchsia_transition = True,
+ tags = top_level_tags,
+ **kwargs
+ )
+
+ # For `bazel run :pkg.publish`.
+ publish_task = verbs.publish(name)
+ anonymous_publish_task = "%s_anonymous" % publish_task
+ anonymous_repo_name = "bazel.%s" % normalized_target_name(anonymous_publish_task)
+ fuchsia_task_publish(
+ name = anonymous_publish_task,
+ packages = [package],
+ package_repository_name = anonymous_repo_name,
+ **kwargs
+ )
+ fuchsia_task_ffx(
+ name = verbs.delete_repo(anonymous_publish_task),
+ arguments = [
+ "repository",
+ "remove",
+ anonymous_repo_name,
+ ],
+ **kwargs
+ )
+ publish_only_task = "%s_only" % publish_task
+ fuchsia_task_publish(
+ name = publish_only_task,
+ packages = [package],
+ **kwargs
+ )
+ fuchsia_workflow(
+ name = publish_task,
+ sequence = [
+ debug_symbols_task,
+ publish_only_task,
+ ],
+ apply_fuchsia_transition = True,
+ tags = top_level_tags,
+ **kwargs
+ )
+
+ # For `bazel run :pkg.help`.
+ help_task = verbs.help(name)
+ _fuchsia_package_help(
+ name = help_task,
+ package = package,
+ components = components.keys(),
+ tools = tools,
+ debug_symbols_task = debug_symbols_task,
+ publish_task = publish_task,
+ top_level_name = name,
+ is_test = is_test,
+ apply_fuchsia_transition = True,
+ tags = top_level_tags,
+ **kwargs
+ )
+
+ # For `bazel run :pkg.component`.
+ component_run_tasks = []
+ for label, component in components.items():
+ component_run_task = _to_verb(label)(name)
+ component_run_tasks.append("%s.run_only" % component_run_task)
+ fuchsia_task_run_component(
+ name = component_run_tasks[-1],
+ default_argument_scope = "global",
+ repository = anonymous_repo_name,
+ package = package,
+ component = component,
+ tags = tags,
+ **kwargs
+ )
+
+ fuchsia_workflow(
+ name = component_run_task,
+ sequence = [
+ debug_symbols_task,
+ anonymous_publish_task,
+ component_run_tasks[-1],
+ verbs.delete_repo(anonymous_publish_task),
+ ],
+ apply_fuchsia_transition = True,
+ tags = top_level_tags + manual_test,
+ **kwargs
+ )
+
+ # For `bazel run :pkg.tool`.
+ for label, tool in tools.items():
+ tool_run_task = _to_verb(label)(name)
+ fuchsia_task_run_driver_tool(
+ name = "%s.run_only" % tool_run_task,
+ default_argument_scope = "global",
+ repository = anonymous_repo_name,
+ package = package,
+ tool = tool,
+ tags = tags,
+ **kwargs
+ )
+
+ fuchsia_workflow(
+ name = tool_run_task,
+ sequence = [
+ debug_symbols_task,
+ anonymous_publish_task,
+ "%s.run_only" % tool_run_task,
+ verbs.delete_repo(anonymous_publish_task),
+ ],
+ apply_fuchsia_transition = True,
+ tags = top_level_tags,
+ **kwargs
+ )
+
+ # For `bazel run :pkg`.
+ _fuchsia_package_default_task(
+ name = name,
+ help_task = help_task,
+ debug_symbols_task = debug_symbols_task,
+ publish_task = anonymous_publish_task,
+ publish_cleanup_task = verbs.delete_repo(anonymous_publish_task),
+ component_run_tasks = component_run_tasks,
+ is_test = is_test,
+ package = package,
+ apply_fuchsia_transition = True,
+ tags = top_level_tags,
+ **kwargs
+ )
diff --git a/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_task_publish.bzl b/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_task_publish.bzl
index 4757c47..fc5eedb 100644
--- a/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_task_publish.bzl
+++ b/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_task_publish.bzl
@@ -5,9 +5,9 @@
"""Publishes packages as a workflow task."""
load("@rules_fuchsia//fuchsia/private:providers.bzl", "FuchsiaPackageGroupInfo", "FuchsiaPackageInfo")
-load(":fuchsia_shell_task.bzl", "shell_task_rule")
+load(":fuchsia_task.bzl", "fuchsia_task_rule")
-def _fuchsia_task_publish_impl(ctx, make_shell_task):
+def _fuchsia_task_publish_impl(ctx, make_fuchsia_task):
sdk = ctx.toolchains["@rules_fuchsia//fuchsia:toolchain"]
far_files = [
pkg.far_file
@@ -15,11 +15,13 @@
for pkg in (dep[FuchsiaPackageGroupInfo].packages if FuchsiaPackageGroupInfo in dep else [dep[FuchsiaPackageInfo]])
]
- repo_name_args = ["--repo_name", ctx.attr.package_repository_name] if ctx.attr.package_repository_name else []
-
- return make_shell_task(
- command = [
- ctx.attr._publish_packages_tool,
+ repo_name_args = [
+ "--repo_name",
+ ctx.attr.package_repository_name,
+ ] if ctx.attr.package_repository_name else []
+ return make_fuchsia_task(
+ task_runner = ctx.attr._publish_packages_tool,
+ prepend_args = [
"--ffx",
sdk.ffx,
"--pm",
@@ -33,7 +35,7 @@
_fuchsia_task_publish,
_fuchsia_task_publish_for_test,
fuchsia_task_publish,
-) = shell_task_rule(
+) = fuchsia_task_rule(
implementation = _fuchsia_task_publish_impl,
doc = """A workflow task that publishes multiple fuchsia packages.""",
toolchains = ["@rules_fuchsia//fuchsia:toolchain"],
@@ -43,7 +45,7 @@
providers = [[FuchsiaPackageInfo], [FuchsiaPackageGroupInfo]],
),
"package_repository_name": attr.string(
- doc = "Repository name to publish these packages to",
+ doc = "Optionally specify the repository name to publish these packages to.",
),
"_publish_packages_tool": attr.label(
doc = "The publish_packages tool.",
diff --git a/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_task_run_component.bzl b/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_task_run_component.bzl
index 77f3ef7..b075d66 100644
--- a/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_task_run_component.bzl
+++ b/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_task_run_component.bzl
@@ -2,28 +2,89 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-"""ffx component run invokation as a workflow task."""
+"""Runs components, tests components, or register drivers within a package."""
-load(":fuchsia_task_ffx.bzl", "fuchsia_task_ffx")
+load(":fuchsia_task.bzl", "fuchsia_task_rule")
+load(":providers.bzl", "FuchsiaComponentInfo", "FuchsiaPackageInfo")
-def fuchsia_task_run_component(
- *,
- name,
- # TODO(fxbug.dev/113205): Generate a default moniker.
- moniker,
- component_url,
- arguments = [],
- recreate = True,
- **kwargs):
- fuchsia_task_ffx(
- name = name,
- arguments = [
- "component",
- "run",
- moniker,
- component_url,
- ] + (
- ["--recreate"] if recreate else []
- ) + arguments,
- **kwargs
- )
+def _fuchsia_task_run_component_impl(ctx, make_fuchsia_task):
+ sdk = ctx.toolchains["@rules_fuchsia//fuchsia:toolchain"]
+ repo = ctx.attr.repository
+ package = ctx.attr.package[FuchsiaPackageInfo].package_name
+ component = ctx.attr.component[FuchsiaComponentInfo]
+ component_name = component.name
+ manifest = component.manifest.basename
+ url = "fuchsia-pkg://%s/%s#meta/%s" % (repo, package, manifest)
+ moniker = ctx.attr.moniker or "/core/ffx-laboratory:%s" % component_name
+ if component.is_driver:
+ return make_fuchsia_task(
+ ctx.attr._register_driver_tool,
+ [
+ "--ffx",
+ sdk.ffx,
+ "--url",
+ url,
+ ],
+ )
+ elif component.is_test:
+ return make_fuchsia_task(
+ ctx.attr._run_test_component_tool,
+ [
+ "--ffx",
+ sdk.ffx,
+ "--url",
+ url,
+ ],
+ )
+ else:
+ return make_fuchsia_task(
+ ctx.attr._run_component_tool,
+ [
+ "--ffx",
+ sdk.ffx,
+ "--moniker",
+ moniker,
+ "--url",
+ url,
+ ],
+ )
+
+(
+ _fuchsia_task_run_component,
+ _fuchsia_task_run_component_for_test,
+ fuchsia_task_run_component,
+) = fuchsia_task_rule(
+ implementation = _fuchsia_task_run_component_impl,
+ toolchains = ["@rules_fuchsia//fuchsia:toolchain"],
+ attrs = {
+ "repository": attr.string(
+ doc = "The repository that has the published package.",
+ mandatory = True,
+ ),
+ "package": attr.label(
+ doc = "The package containing the component.",
+ providers = [FuchsiaPackageInfo],
+ mandatory = True,
+ ),
+ "moniker": attr.string(
+ doc = "The moniker to run the component in. Only used for non-test non-driver components.",
+ ),
+ "component": attr.label(
+ doc = "The component to run.",
+ providers = [FuchsiaComponentInfo],
+ mandatory = True,
+ ),
+ "_register_driver_tool": attr.label(
+ doc = "The tool used to run components",
+ default = "//fuchsia/tools:register_driver",
+ ),
+ "_run_test_component_tool": attr.label(
+ doc = "The tool used to run components",
+ default = "//fuchsia/tools:run_test_component",
+ ),
+ "_run_component_tool": attr.label(
+ doc = "The tool used to run components",
+ default = "//fuchsia/tools:run_component",
+ ),
+ },
+)
diff --git a/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_task_run_driver_tool.bzl b/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_task_run_driver_tool.bzl
new file mode 100644
index 0000000..7495e2b
--- /dev/null
+++ b/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_task_run_driver_tool.bzl
@@ -0,0 +1,43 @@
+# 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.
+
+"""Runs driver tools delivered within a package."""
+
+load(":fuchsia_task_ffx.bzl", "ffx_task_rule")
+load(":providers.bzl", "FuchsiaDriverToolInfo", "FuchsiaPackageInfo")
+
+def _fuchsia_task_run_driver_tool_impl(ctx, make_ffx_task):
+ repo = ctx.attr.repository
+ package = ctx.attr.package[FuchsiaPackageInfo].package_name
+ tool_binary = ctx.attr.tool[FuchsiaDriverToolInfo].binary.dest
+ url = "fuchsia-pkg://%s/%s#%s" % (repo, package, tool_binary)
+ return make_ffx_task(prepend_args = [
+ "driver",
+ "run-tool",
+ url,
+ ])
+
+(
+ _fuchsia_task_run_driver_tool,
+ _fuchsia_task_run_driver_tool_for_test,
+ fuchsia_task_run_driver_tool,
+) = ffx_task_rule(
+ implementation = _fuchsia_task_run_driver_tool_impl,
+ attrs = {
+ "repository": attr.string(
+ doc = "The repository that has the published package.",
+ mandatory = True,
+ ),
+ "package": attr.label(
+ doc = "The package containing the driver tool.",
+ providers = [FuchsiaPackageInfo],
+ mandatory = True,
+ ),
+ "tool": attr.label(
+ doc = "The driver tool to run.",
+ providers = [FuchsiaDriverToolInfo],
+ mandatory = True,
+ ),
+ },
+)
diff --git a/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_task_verbs.bzl b/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_task_verbs.bzl
index de90363..602c6f4 100644
--- a/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_task_verbs.bzl
+++ b/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_task_verbs.bzl
@@ -2,37 +2,56 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-def _make_verb(verb):
+def _make_verb(verb = None):
def _make(name):
- return name + "." + verb
+ return name + "." + verb if verb else name
return _make
-def make_help_executable(ctx, verbs):
- exe = ctx.actions.declare_file(ctx.label.name + "_help_text.sh")
- tasks = ['echo " - {}: {}"'.format(verb(ctx.label.name), help) for (verb, help) in verbs.items()]
+def make_help_executable(ctx, verbs, name = None):
+ name = name or ctx.label.name
+ exe = ctx.actions.declare_file(name + "_help_text.sh")
+ tasks = ['echo " - {}: {}"'.format(verb(name), help) for (verb, help) in verbs.items()]
ctx.actions.write(
exe,
"""
- echo "------------------------------------------------------"
- echo "ERROR: The target {name} cannot be run directly."
- echo "To interact with this object use the following tasks:"
+ echo "------------------------------------------------------"{default_target_invalid_str}
+ echo "USAGE: To interact with this object use the following tasks:"
{tasks}
echo "------------------------------------------------------"
- """.format(name = ctx.label.name, tasks = "\n".join(tasks)),
+ """.format(
+ default_target_invalid_str = "" if _verbs.noverb in verbs else """
+echo "ERROR: The target '%s' cannot be run directly." """ % name,
+ tasks = "\n".join(tasks),
+ ),
is_executable = True,
)
return exe
-verbs = struct(
- create = _make_verb("create"),
- delete = _make_verb("delete"),
- delete_repo = _make_verb("delete_repo"),
- fetch = _make_verb("fetch"),
- make_default = _make_verb("make_default"),
- reboot = _make_verb("reboot"),
- remove = _make_verb("remove"),
- start = _make_verb("start"),
- stop = _make_verb("stop"),
- wait = _make_verb("wait"),
-)
+def _make_verbs(*verbs):
+ return struct(
+ noverb = _make_verb(),
+ custom = _make_verb,
+ **{
+ verb: _make_verb(verb)
+ for verb in verbs
+ }
+ )
+
+_verbs = _make_verbs(*"""
+create
+debug_symbols
+delete
+delete_repo
+fetch
+help
+make_default
+publish
+reboot
+remove
+start
+stop
+wait
+""".strip().split("\n"))
+
+verbs = _verbs
diff --git a/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_workflow.bzl b/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_workflow.bzl
index 87c23b2..8c0825f 100644
--- a/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_workflow.bzl
+++ b/bazel_rules_fuchsia/fuchsia/private/workflows/fuchsia_workflow.bzl
@@ -27,23 +27,37 @@
initial[k] = v
return initial
-def _fuchsia_workflow_impl(ctx, make_workflow, collect_arguments):
- workflow_args, runfiles = collect_arguments()
- return make_workflow(
- FuchsiaWorkflowInfo(
- entities = _collect_entities({
- ctx.label: FuchsiaWorkflowEntityInfo(
- sequence = [dep[FuchsiaWorkflowInfo].entrypoint for dep in ctx.attr.sequence],
- args = workflow_args,
+def fuchsia_workflow_rule(*, implementation, **kwargs):
+ """Starlark higher-order rule for specifying a sequence of workflow entities."""
+
+ def _fuchsia_workflow_impl(ctx, make_workflow_entity, collect_arguments):
+ def _make_workflow(sequence, prepend_args = [], runfiles = []):
+ workflow_args, runfiles = collect_arguments(prepend_args, runfiles)
+ return make_workflow_entity(
+ FuchsiaWorkflowInfo(
+ entities = _collect_entities({
+ ctx.label: FuchsiaWorkflowEntityInfo(
+ sequence = [dep[FuchsiaWorkflowInfo].entrypoint for dep in sequence],
+ args = workflow_args,
+ ),
+ }, [dep[FuchsiaWorkflowInfo].entities for dep in sequence]),
+ entrypoint = ctx.label,
),
- }, [dep[FuchsiaWorkflowInfo].entities for dep in ctx.attr.sequence]),
- entrypoint = ctx.label,
- ),
- ctx.attr.sequence,
- runfiles,
+ sequence,
+ runfiles,
+ )
+
+ return implementation(ctx, _make_workflow)
+
+ return workflow_entity_rule(
+ implementation = _fuchsia_workflow_impl,
+ **kwargs
)
-_fuchsia_workflow, _fuchsia_workflow_for_test, fuchsia_workflow = workflow_entity_rule(
+def _fuchsia_workflow_impl(ctx, make_workflow):
+ return make_workflow(ctx.attr.sequence)
+
+_fuchsia_workflow, _fuchsia_workflow_for_test, fuchsia_workflow = fuchsia_workflow_rule(
implementation = _fuchsia_workflow_impl,
doc = """A grouping of tasks to be run sequentially.""",
attrs = {
diff --git a/bazel_rules_fuchsia/fuchsia/private/workflows/providers.bzl b/bazel_rules_fuchsia/fuchsia/private/workflows/providers.bzl
index 6553024..e058815 100644
--- a/bazel_rules_fuchsia/fuchsia/private/workflows/providers.bzl
+++ b/bazel_rules_fuchsia/fuchsia/private/workflows/providers.bzl
@@ -6,7 +6,10 @@
load(
"@rules_fuchsia//fuchsia/private:providers.bzl",
+ _FuchsiaComponentInfo = "FuchsiaComponentInfo",
_FuchsiaDebugSymbolInfo = "FuchsiaDebugSymbolInfo",
+ _FuchsiaDriverToolInfo = "FuchsiaDriverToolInfo",
+ _FuchsiaPackageInfo = "FuchsiaPackageInfo",
_FuchsiaProductBundleInfo = "FuchsiaProductBundleInfo",
_FuchsiaProvidersInfo = "FuchsiaProvidersInfo",
)
@@ -36,6 +39,9 @@
},
)
+FuchsiaComponentInfo = _FuchsiaComponentInfo
FuchsiaDebugSymbolInfo = _FuchsiaDebugSymbolInfo
+FuchsiaDriverToolInfo = _FuchsiaDriverToolInfo
+FuchsiaPackageInfo = _FuchsiaPackageInfo
FuchsiaProductBundleInfo = _FuchsiaProductBundleInfo
FuchsiaProvidersInfo = _FuchsiaProvidersInfo
diff --git a/bazel_rules_fuchsia/fuchsia/private/workflows/utils.bzl b/bazel_rules_fuchsia/fuchsia/private/workflows/utils.bzl
index e5f6185..44d83d6 100644
--- a/bazel_rules_fuchsia/fuchsia/private/workflows/utils.bzl
+++ b/bazel_rules_fuchsia/fuchsia/private/workflows/utils.bzl
@@ -10,6 +10,8 @@
_alias = "alias",
_collect_runfiles = "collect_runfiles",
_flatten = "flatten",
+ _label_name = "label_name",
+ _normalized_target_name = "normalized_target_name",
_rule_variants = "rule_variants",
_wrap_executable = "wrap_executable",
)
@@ -17,6 +19,8 @@
alias = _alias
collect_runfiles = _collect_runfiles
flatten = _flatten
+label_name = _label_name
+normalized_target_name = _normalized_target_name
rule_variants = _rule_variants
with_fuchsia_transition = _with_fuchsia_transition
wrap_executable = _wrap_executable
diff --git a/bazel_rules_fuchsia/fuchsia/tools/BUILD.bazel b/bazel_rules_fuchsia/fuchsia/tools/BUILD.bazel
index 5e9e515..42de923 100644
--- a/bazel_rules_fuchsia/fuchsia/tools/BUILD.bazel
+++ b/bazel_rules_fuchsia/fuchsia/tools/BUILD.bazel
@@ -69,15 +69,34 @@
name = "fuchsia_shell_task",
srcs = ["fuchsia_shell_task.py"],
python_version = "PY3",
- deps = [
- ":fuchsia_task_lib",
- ],
+ deps = [":fuchsia_task_lib"],
)
py_binary(
name = "register_debug_symbols",
srcs = ["register_debug_symbols.py"],
python_version = "PY3",
+ deps = [":fuchsia_task_lib"],
+)
+
+py_binary(
+ name = "register_driver",
+ srcs = ["register_driver.py"],
+ python_version = "PY3",
+ deps = [":fuchsia_task_lib"],
+)
+
+py_binary(
+ name = "run_test_component",
+ srcs = ["run_test_component.py"],
+ python_version = "PY3",
+ deps = [":fuchsia_task_lib"],
+)
+
+py_binary(
+ name = "run_component",
+ srcs = ["run_component.py"],
+ python_version = "PY3",
)
py_binary(
diff --git a/bazel_rules_fuchsia/fuchsia/tools/fuchsia_task_lib.py b/bazel_rules_fuchsia/fuchsia/tools/fuchsia_task_lib.py
index 2d69507..2209a88 100644
--- a/bazel_rules_fuchsia/fuchsia/tools/fuchsia_task_lib.py
+++ b/bazel_rules_fuchsia/fuchsia/tools/fuchsia_task_lib.py
@@ -48,37 +48,6 @@
# so don't apply the style.
return text
-
-class TaskResult:
- def __init__(self, property: str, value: Any, is_environment_variable: bool = False) -> None:
- self._property = property
- self._value = value
- self._is_environment_variable = is_environment_variable
-
- @property
- def value(self) -> Any:
- return self._value
-
- @property
- def is_environment_variable(self) -> bool:
- return self._is_environment_variable
-
- @property
- def property(self) -> str:
- return self._property
-
- @classmethod
- def from_dict(cls, entity: Dict[str, Any]) -> 'TaskResult':
- return TaskResult(**entity)
-
- def to_dict(self) -> Dict[str, Any]:
- return {
- 'property': self.property,
- 'value': self.value,
- 'is_environment_variable': self.is_environment_variable,
- }
-
-
@total_ordering
class ArgumentScope(Enum):
# Captures arguments that are passed directly to the current task:
@@ -185,7 +154,7 @@
*,
task_name: str,
is_final_task: bool,
- workflow_state: List[TaskResult],
+ workflow_state: Dict[str, Any],
) -> None:
self._task_name = task_name
self._is_final_task = is_final_task
@@ -195,11 +164,7 @@
def apply_environment(self) -> None:
original_environ = os.environ.copy()
try:
- os.environ.update({
- result.property: result.value
- for result in self.workflow_state
- if result.is_environment_variable
- })
+ os.environ.update(self.workflow_state['environment_variables'] or {})
yield
finally:
os.environ.clear()
@@ -219,13 +184,9 @@
return self._is_final_task
@property
- def workflow_state(self) -> List[TaskResult]:
+ def workflow_state(self) -> Dict[str, Any]:
return self._workflow_state
- @workflow_state.setter
- def workflow_state(self, value) -> None:
- self._workflow_state = value
-
def get_task_arguments(self, scope: ArgumentScope) -> List[str]:
return ScopedArgumentParser.get_arguments(scope)
@@ -262,14 +223,11 @@
task = cls(
task_name=workflow_args.workflow_task_name,
is_final_task=workflow_args.workflow_final_task,
- workflow_state=[
- TaskResult.from_dict(result)
- for result in (
- json.loads(workflow_args.workflow_previous_state.read_text())
- if workflow_args.workflow_previous_state
- else []
- )
- ],
+ workflow_state=(
+ json.loads(workflow_args.workflow_previous_state.read_text())
+ if workflow_args.workflow_previous_state
+ else {'environment_variables': {}}
+ ),
)
try:
with task.apply_environment():
@@ -280,9 +238,7 @@
except KeyboardInterrupt:
sys.exit(1)
if workflow_args.workflow_next_state:
- workflow_args.workflow_next_state.write_text(
- json.dumps([result.to_dict() for result in task.workflow_state])
- )
+ workflow_args.workflow_next_state.write_text(json.dumps(task.workflow_state))
if __name__ == '__main__':
FuchsiaTask.main()
diff --git a/bazel_rules_fuchsia/fuchsia/tools/publish_packages.py b/bazel_rules_fuchsia/fuchsia/tools/publish_packages.py
index c951680..225eca7 100644
--- a/bazel_rules_fuchsia/fuchsia/tools/publish_packages.py
+++ b/bazel_rules_fuchsia/fuchsia/tools/publish_packages.py
@@ -11,6 +11,8 @@
from pathlib import Path
from shutil import rmtree
+from fuchsia_task_lib import *
+
def run(*command):
try:
return subprocess.check_output(
@@ -19,216 +21,205 @@
).strip()
except subprocess.CalledProcessError as e:
print(e.stdout)
- raise e
+ raise TaskExecutionException(f'Command {command} failed.')
-def parse_args():
- '''Parses arguments.'''
- parser = argparse.ArgumentParser()
+class FuchsiaTaskPublish(FuchsiaTask):
- def path_arg(type='file'):
- def arg(path):
- path = Path(path)
- if path.is_file() != (type == 'file') or path.is_dir() != (type == 'directory'):
- parser.error(f'Path "{path}" is not a {type}!')
- return path
- return arg
+ def parse_args(self, parser: ScopedArgumentParser) -> argparse.Namespace:
+ '''Parses arguments.'''
- parser.add_argument(
- '--ffx',
- type=path_arg(),
- help='A path to the ffx tool.',
- required=True,
- )
- parser.add_argument(
- '--pm',
- type=path_arg(),
- help='A path to the pm tool.',
- required=True,
- )
- parser.add_argument(
- '--packages',
- help='Paths to far files to package.',
- nargs='+',
- type=path_arg(),
- required=True,
- )
- parser.add_argument(
- '--repo_name',
- help='Optionally specify the repository name.',
- )
- parser.add_argument(
- '--target',
- help='Optionally specify the target fuchsia device.',
- required=False,
- )
+ parser.add_argument(
+ '--ffx',
+ type=parser.path_arg(),
+ help='A path to the ffx tool.',
+ required=True,
+ )
+ parser.add_argument(
+ '--pm',
+ type=parser.path_arg(),
+ help='A path to the pm tool.',
+ required=True,
+ )
+ parser.add_argument(
+ '--packages',
+ help='Paths to far files to package.',
+ nargs='+',
+ type=parser.path_arg(),
+ required=True,
+ )
+ parser.add_argument(
+ '--repo_name',
+ help='Optionally specify the repository name.',
+ scope=ArgumentScope.GLOBAL,
+ )
+ parser.add_argument(
+ '--target',
+ help='Optionally specify the target fuchsia device.',
+ required=False,
+ scope=ArgumentScope.GLOBAL,
+ )
- # Private arguments.
- # Whether to make the repo default.
- parser.add_argument(
- '--prompt_make_repo_default',
- help=argparse.SUPPRESS,
- required=False
- )
- # Whether to make the repo default.
- parser.add_argument(
- '--prompt_repo_cleanup',
- help=argparse.SUPPRESS,
- required=False
- )
- # The effective repo path to publish to.
- parser.add_argument(
- '--repo_path',
- help=argparse.SUPPRESS,
- required=False,
- )
- return parser.parse_args()
+ # Private arguments.
+ # Whether to make the repo default.
+ parser.add_argument(
+ '--make_repo_default',
+ action='store_true',
+ help=argparse.SUPPRESS,
+ required=False
+ )
+ # The effective repo path to publish to.
+ parser.add_argument(
+ '--repo_path',
+ help=argparse.SUPPRESS,
+ required=False,
+ )
+ return parser.parse_args()
-def ensure_target_device(args):
- args.target = args.target or run(args.ffx, 'target', 'default', 'get')
- print(f'Waiting for {args.target} to come online (60s)')
- run(args.ffx, '--target', args.target, 'target', 'wait', '-t', '60')
+ def enable_ffx_repository(self, args):
+ if run(args.ffx, 'config', 'get', 'repository.server.enabled') != 'true':
+ print('The ffx repository server is not enabled, starting it now...')
+ run(args.ffx, 'repository', 'server', 'start')
-def resolve_repo(args):
- # Determine the repo name we want to use, in this order:
- # 1. User specified argument.
- def user_specified_repo_name():
- if args.repo_name:
- print(f'Using manually specified --repo_name: {args.repo_name}')
- # We shouldn't ask to delete a user specified --repo_name.
- if args.prompt_repo_cleanup is None:
- args.prompt_repo_cleanup = False
- return args.repo_name
- # 2. ffx default repository.
- def ffx_default_repo():
- default = run(args.ffx, 'repository', 'default', 'get')
- if default:
- print(f'Using ffx default repository: {default}')
- # We shouldn't ask to delete the ffx default repo.
- if args.prompt_repo_cleanup is None:
- args.prompt_repo_cleanup = False
- return default
- # 3. A user prompt.
- def prompt_repo():
- print('--repo_name was not specified and there is no default ffx repository set.')
- repo_name = input('Please specify a repo name to publish to: ')
- if args.prompt_make_repo_default is None:
- args.prompt_make_repo_default = input('Would you make this repo your default ffx repo? (y/n): ').lower() == 'y'
- # We shouldn't ask to delete a repo that we're going to make default.
- if args.prompt_repo_cleanup is None:
- args.prompt_repo_cleanup = not args.prompt_make_repo_default
- return repo_name
- args.repo_name = user_specified_repo_name() or ffx_default_repo() or prompt_repo()
+ def ensure_target_device(self, args):
+ args.target = args.target or run(args.ffx, 'target', 'default', 'get')
+ print(f'Waiting for {args.target} to come online (60s)')
+ run(args.ffx, '--target', args.target, 'target', 'wait', '-t', '60')
- # Determine the pm repo path (use the existing one from ffx, or create a new one).
- existing_repos = json.loads(run(
- args.ffx,
- '--machine',
- 'json',
- 'repository',
- 'list',
- ))
- existing_repo = ([
- repo
- for repo in existing_repos
- if repo['name'] == args.repo_name
- ] or [None])[0]
- existing_repo_path = existing_repo and Path(
- existing_repo['spec']['path']
- )
- args.repo_path = existing_repo_path or Path(tempfile.mkdtemp())
+ def resolve_repo(self, args):
+ # Determine the repo name we want to use, in this order:
+ # 1. User specified argument.
+ def user_specified_repo_name():
+ if args.repo_name:
+ print(f'Using manually specified --repo_name: {args.repo_name}')
+ # We shouldn't ask to delete a user specified --repo_name.
+ self.prompt_repo_cleanup = False
+ return args.repo_name
+ # 2. ffx default repository.
+ def ffx_default_repo():
+ default = run(args.ffx, '-c', 'ffx_repository=true', 'repository', 'default', 'get')
+ if default:
+ print(f'Using ffx default repository: {default}')
+ # We shouldn't ask to delete the ffx default repo.
+ self.prompt_repo_cleanup = False
+ return default
+ # 3. A user prompt.
+ def prompt_repo():
+ print('--repo_name was not specified and there is no default ffx repository set.')
+ repo_name = input('Please specify a repo name to publish to: ')
+ if args.make_repo_default is None:
+ args.make_repo_default = input('Would you make this repo your default ffx repo? (y/n): ').lower() == 'y'
+ # We shouldn't ask to delete a repo that we're going to make default.
+ self.prompt_repo_cleanup = not args.make_repo_default
+ return repo_name
+ args.repo_name = user_specified_repo_name() or ffx_default_repo() or prompt_repo()
-def ensure_repo(args):
- # Ensure the ffx repository server.
- if run(args.ffx, 'config', 'get', 'repository.server.enabled') != 'true':
- print('The ffx repository server is not enabled, starting it now...')
- run(args.ffx, 'repository', 'server', 'start')
+ # Determine the pm repo path (use the existing one from ffx, or create a new one).
+ existing_repos = json.loads(run(
+ args.ffx,
+ '--machine',
+ 'json',
+ 'repository',
+ 'list',
+ ))
+ existing_repo = ([
+ repo
+ for repo in existing_repos
+ if repo['name'] == args.repo_name
+ ] or [None])[0]
+ existing_repo_path = existing_repo and Path(
+ existing_repo['spec']['path']
+ )
+ args.repo_path = existing_repo_path or Path(tempfile.mkdtemp())
- # Ensure pm repo.
- if (args.repo_path / 'repository').is_dir():
- print(f'Using existing pm repo: {args.repo_path}')
- else:
- print(f'Creating a new pm repository: {args.repo_path}')
- run(args.pm, 'newrepo', '-vt', '-repo', args.repo_path)
+ def ensure_repo(self, args):
+ # Ensure pm repo.
+ if (args.repo_path / 'repository').is_dir():
+ print(f'Using existing pm repo: {args.repo_path}')
+ else:
+ print(f'Creating a new pm repository: {args.repo_path}')
+ run(args.pm, 'newrepo', '-vt', '-repo', args.repo_path)
- # Ensure ffx repository.
- print(f'Associating {args.repo_name} to {args.repo_path}')
- run(
- args.ffx,
- 'repository',
- 'add-from-pm',
- '--repository',
- args.repo_name,
- args.repo_path,
- )
-
- # Ensure ffx target repository.
- print(f'Registering {args.repo_name} to target device {args.target}')
- run(
- args.ffx,
- '--target',
- args.target,
- 'target',
- 'repository',
- 'register',
- '-r',
- args.repo_name,
- )
-
- # Optionally make the ffx repository default.
- if args.prompt_make_repo_default:
- old_default = run(args.ffx, 'repository', 'default', 'get')
- print(f'Setting default ffx repository "{old_default}" => "{args.repo_name}"')
+ # Ensure ffx repository.
+ print(f'Associating {args.repo_name} to {args.repo_path}')
run(
args.ffx,
'repository',
- 'default',
- 'set',
+ 'add-from-pm',
+ '--repository',
+ args.repo_name,
+ args.repo_path,
+ )
+
+ # Ensure ffx target repository.
+ print(f'Registering {args.repo_name} to target device {args.target}')
+ run(
+ args.ffx,
+ '--target',
+ args.target,
+ 'target',
+ 'repository',
+ 'register',
+ '-r',
args.repo_name,
)
-def publish_packages(args):
- # TODO(fxbug.dev/110617): Publish all packages with 1 command invocation.
- print(f'Publishing packages: {args.packages}')
- for package in args.packages:
- run(
- args.pm,
- 'publish',
- '-vt',
- '-a',
- '-f',
- package,
- '-repo',
- args.repo_path,
- )
- print(f'Published {len(args.packages)} packages')
+ # Optionally make the ffx repository default.
+ if args.make_repo_default:
+ old_default = run(args.ffx, 'repository', 'default', 'get')
+ print(f'Setting default ffx repository "{old_default}" => "{args.repo_name}"')
+ run(
+ args.ffx,
+ 'repository',
+ 'default',
+ 'set',
+ args.repo_name,
+ )
-def teardown(args):
- if args.prompt_repo_cleanup != False:
- input('Press enter to delete this repository, or ^C to quit.')
+ def publish_packages(self, args):
+ # TODO(fxbug.dev/110617): Publish all packages with 1 command invocation.
+ print(f'Publishing packages: {args.packages}')
+ for package in args.packages:
+ run(
+ args.pm,
+ 'publish',
+ '-vt',
+ '-a',
+ '-f',
+ package,
+ '-repo',
+ args.repo_path,
+ )
+ print(f'Published {len(args.packages)} packages')
- # Delete the pm repository.
- rmtree(args.repo_path)
- print(f'Deleted {args.repo_path}')
+ def teardown(self, args):
+ if self.prompt_repo_cleanup:
+ input('Press enter to delete this repository, or ^C to quit.')
- # Remove the ffx repository.
- run('ffx', 'repository', 'remove', args.repo_name)
- print(f'Removed the ffx repository {args.repo_name}')
+ # Delete the pm repository.
+ rmtree(args.repo_path)
+ print(f'Deleted {args.repo_path}')
+ # Remove the ffx repository.
+ run('ffx', 'repository', 'remove', args.repo_name)
+ print(f'Removed the ffx repository {args.repo_name}')
-def main():
- # Parse arguments.
- args = parse_args()
+ def run(self, parser: ScopedArgumentParser) -> None:
+ # Parse arguments.
+ args = self.parse_args(parser)
- # Check environment and gather information for publishing.
- ensure_target_device(args)
- resolve_repo(args)
+ # Check environment and gather information for publishing.
+ self.enable_ffx_repository(args)
+ self.ensure_target_device(args)
+ self.resolve_repo(args)
- # Perform the publishing.
- ensure_repo(args)
- publish_packages(args)
+ # Perform the publishing.
+ self.ensure_repo(args)
+ self.publish_packages(args)
- # Optionally cleanup the repo.
- teardown(args)
+ self.workflow_state['environment_variables']['FUCHSIA_REPO_NAME'] = args.repo_name
+
+ # Optionally cleanup the repo.
+ self.teardown(args)
if __name__ == '__main__':
- main()
+ FuchsiaTaskPublish.main()
diff --git a/bazel_rules_fuchsia/fuchsia/tools/register_driver.py b/bazel_rules_fuchsia/fuchsia/tools/register_driver.py
new file mode 100644
index 0000000..c5254a3
--- /dev/null
+++ b/bazel_rules_fuchsia/fuchsia/tools/register_driver.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python3
+# 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.
+
+import argparse
+import subprocess
+
+from fuchsia_task_lib import *
+
+
+class FuchsiaTaskRegisterDriver(FuchsiaTask):
+ def parse_args(self, parser: ScopedArgumentParser) -> argparse.Namespace:
+ '''Parses arguments.'''
+
+ parser.add_argument(
+ '--ffx',
+ type=parser.path_arg(),
+ help='A path to the ffx tool.',
+ required=True,
+ )
+ parser.add_argument(
+ '--url',
+ type=str,
+ help='The full component url.',
+ required=True,
+ )
+ parser.add_argument(
+ '--target',
+ help='Optionally specify the target fuchsia device.',
+ required=False,
+ scope=ArgumentScope.GLOBAL,
+ )
+ return parser.parse_args()
+
+
+ def run(self, parser: ScopedArgumentParser) -> None:
+ args = self.parse_args(parser)
+ ffx = [args.ffx] + (['--target', args.target] if args.target else [])
+
+ subprocess.check_call([
+ *ffx,
+ 'driver',
+ 'register',
+ args.url,
+ ])
+
+
+if __name__ == '__main__':
+ FuchsiaTaskRegisterDriver.main()
diff --git a/bazel_rules_fuchsia/fuchsia/tools/run_component.py b/bazel_rules_fuchsia/fuchsia/tools/run_component.py
new file mode 100644
index 0000000..f1062f9
--- /dev/null
+++ b/bazel_rules_fuchsia/fuchsia/tools/run_component.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python3
+# 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.
+
+import argparse
+import subprocess
+
+from fuchsia_task_lib import *
+
+
+class FuchsiaTaskRunComponent(FuchsiaTask):
+ def parse_args(self, parser: ScopedArgumentParser) -> argparse.Namespace:
+ '''Parses arguments.'''
+
+ parser.add_argument(
+ '--ffx',
+ type=parser.path_arg(),
+ help='A path to the ffx tool.',
+ required=True,
+ )
+ parser.add_argument(
+ '--moniker',
+ type=str,
+ help='The moniker to add the component to.',
+ required=True,
+ )
+ parser.add_argument(
+ '--url',
+ type=str,
+ help='The full component url.',
+ required=True,
+ )
+ parser.add_argument(
+ '--session',
+ action='store_true',
+ help='Whether to add this component to the session.',
+ required=False,
+ )
+ parser.add_argument(
+ '--target',
+ help='Optionally specify the target fuchsia device.',
+ required=False,
+ scope=ArgumentScope.GLOBAL,
+ )
+ return parser.parse_args()
+
+
+ def run(self, parser: ScopedArgumentParser) -> None:
+ args = self.parse_args(parser)
+ ffx = [args.ffx] + (['--target', args.target] if args.target else [])
+
+ if args.session:
+ subprocess.check_call([
+ *ffx,
+ 'session',
+ 'add',
+ args.url,
+ ])
+ else:
+ subprocess.check_call([
+ *ffx,
+ 'component',
+ 'run',
+ args.moniker,
+ args.url,
+ '--recreate',
+ ])
+
+
+if __name__ == '__main__':
+ FuchsiaTaskRunComponent.main()
diff --git a/bazel_rules_fuchsia/fuchsia/tools/run_test_component.py b/bazel_rules_fuchsia/fuchsia/tools/run_test_component.py
new file mode 100644
index 0000000..675365b
--- /dev/null
+++ b/bazel_rules_fuchsia/fuchsia/tools/run_test_component.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python3
+# 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.
+
+import argparse
+import subprocess
+
+from fuchsia_task_lib import *
+
+
+class FuchsiaTaskRunTestComponent(FuchsiaTask):
+ def parse_args(self, parser: ScopedArgumentParser) -> argparse.Namespace:
+ '''Parses arguments.'''
+
+ parser.add_argument(
+ '--ffx',
+ type=parser.path_arg(),
+ help='A path to the ffx tool.',
+ required=True,
+ )
+ parser.add_argument(
+ '--url',
+ type=str,
+ help='The full component url.',
+ required=True,
+ )
+ parser.add_argument(
+ '--target',
+ help='Optionally specify the target fuchsia device.',
+ required=False,
+ scope=ArgumentScope.GLOBAL,
+ )
+ return parser.parse_args()
+
+
+ def run(self, parser: ScopedArgumentParser) -> None:
+ args = self.parse_args(parser)
+ ffx = [args.ffx] + (['--target', args.target] if args.target else [])
+
+ subprocess.check_call([
+ *ffx,
+ 'test',
+ 'run',
+ args.url,
+ ])
+
+
+if __name__ == '__main__':
+ FuchsiaTaskRunTestComponent.main()
diff --git a/tests/examples/hello_world_cpp/BUILD.bazel b/tests/examples/hello_world_cpp/BUILD.bazel
index 87c35f6..51ec84a 100644
--- a/tests/examples/hello_world_cpp/BUILD.bazel
+++ b/tests/examples/hello_world_cpp/BUILD.bazel
@@ -9,7 +9,7 @@
"fuchsia_component",
"fuchsia_component_manifest",
"fuchsia_package",
- "fuchsia_test_package",
+ "fuchsia_unittest_package",
"if_fuchsia",
)
@@ -63,10 +63,10 @@
]),
)
-fuchsia_test_package(
+fuchsia_unittest_package(
name = "test_pkg",
package_name = "hello_tests",
- test_components = [
+ unit_tests = [
":hello_test",
],
visibility = ["//visibility:public"],