Skip to content

Commit

Permalink
RFC: attrs_validators.
Browse files Browse the repository at this point in the history
Summary:
With the impending implementation of `ValidationInfo`, we can kill thousands of genrules in the codebase and migrate to them `attrs_validators` which replaces all the nodes in the graph.

Currently, this taps into `validation_deps` and puts the artifacts as hidden inputs so that they run. When `ValidationInfo` is released I'll update the prelude so that it puts these artifacts into `ValidationInfo` and removes the hack.

## Facebook

Context: https://fb.workplace.com/groups/buck2apple/posts/801963818389446/

Original RFC: https://docs.google.com/document/d/1UccDHLPTnUedB7obVsXEpOgWYs02gpUQnR4QDeBqEHc/edit#heading=h.t4rzlrg1blvd

Reviewed By: johnhaitas, rmaz

Differential Revision: D59920882

fbshipit-source-id: d93395282fe8444d3bc6b965277d03ee30ea7a65
  • Loading branch information
Dustin Shahidehpour authored and facebook-github-bot committed Jul 20, 2024
1 parent 8e07151 commit 8aa9b6b
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 2 deletions.
3 changes: 2 additions & 1 deletion apple/apple_binary.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ load(
"@prelude//:artifact_tset.bzl",
"ArtifactInfoTag",
)
load("@prelude//:attrs_validators.bzl", "get_attrs_validators_outputs")
load("@prelude//:paths.bzl", "paths")
load("@prelude//:validation_deps.bzl", "get_validation_deps_outputs")
load("@prelude//apple:apple_stripping.bzl", "apple_strip_args")
Expand Down Expand Up @@ -120,7 +121,7 @@ def apple_binary_impl(ctx: AnalysisContext) -> [list[Provider], Promise]:
rule_type = "apple_binary",
headers_layout = get_apple_cxx_headers_layout(ctx),
extra_link_flags = extra_link_flags,
extra_hidden = validation_deps_outputs,
extra_hidden = validation_deps_outputs + get_attrs_validators_outputs(ctx),
srcs = cxx_srcs,
additional = CxxRuleAdditionalParams(
srcs = swift_srcs,
Expand Down
3 changes: 2 additions & 1 deletion apple/apple_library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ load(
"make_artifact_tset",
"project_artifacts",
)
load("@prelude//:attrs_validators.bzl", "get_attrs_validators_outputs")
load("@prelude//:validation_deps.bzl", "get_validation_deps_outputs")
load("@prelude//apple:apple_dsym.bzl", "DSYM_SUBTARGET", "get_apple_dsym")
load("@prelude//apple:apple_stripping.bzl", "apple_strip_args")
Expand Down Expand Up @@ -351,7 +352,7 @@ def apple_library_rule_constructor_params_and_swift_providers(ctx: AnalysisConte
is_test = (params.rule_type == "apple_test"),
headers_layout = get_apple_cxx_headers_layout(ctx),
extra_exported_link_flags = params.extra_exported_link_flags,
extra_hidden = validation_deps_outputs,
extra_hidden = validation_deps_outputs + get_attrs_validators_outputs(ctx),
extra_link_flags = [_get_linker_flags(ctx)],
extra_link_input = swift_object_files,
extra_link_input_has_external_debug_info = True,
Expand Down
3 changes: 3 additions & 0 deletions apple/apple_rules_impl.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
# of this source tree.

load("@prelude//:attrs_validators.bzl", "ATTRS_VALIDATORS_NAME", "ATTRS_VALIDATORS_TYPE")
load(
"@prelude//:validation_deps.bzl",
"VALIDATION_DEPS_ATTR_NAME",
Expand Down Expand Up @@ -100,6 +101,7 @@ def _apple_binary_extra_attrs():
"_enable_library_evolution": get_enable_library_evolution(),
"_stripped_default": attrs.bool(default = False),
VALIDATION_DEPS_ATTR_NAME: VALIDATION_DEPS_ATTR_TYPE,
ATTRS_VALIDATORS_NAME: ATTRS_VALIDATORS_TYPE,
}
attribs.update(apple_dsymutil_attrs())
return attribs
Expand Down Expand Up @@ -131,6 +133,7 @@ def _apple_library_extra_attrs():
"_enable_library_evolution": get_enable_library_evolution(),
"_stripped_default": attrs.bool(default = False),
APPLE_ARCHIVE_OBJECTS_LOCALLY_OVERRIDE_ATTR_NAME: attrs.option(attrs.bool(), default = None),
ATTRS_VALIDATORS_NAME: ATTRS_VALIDATORS_TYPE,
VALIDATION_DEPS_ATTR_NAME: VALIDATION_DEPS_ATTR_TYPE,
}
attribs.update(apple_dsymutil_attrs())
Expand Down
2 changes: 2 additions & 0 deletions apple/apple_rules_impl_utility.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
# of this source tree.

load("@prelude//:attrs_validators.bzl", "ATTRS_VALIDATORS_NAME", "ATTRS_VALIDATORS_TYPE")
load("@prelude//apple:apple_bundle_attrs.bzl", "get_apple_info_plist_build_system_identification_attrs")
load("@prelude//apple:apple_bundle_types.bzl", "AppleBundleResourceInfo", "AppleBundleTypeAttributeType")
load("@prelude//apple:apple_code_signing_types.bzl", "CodeSignConfiguration", "CodeSignType")
Expand Down Expand Up @@ -111,6 +112,7 @@ def apple_test_extra_attrs():
# wrap this test library into an `apple_bundle`. Because of this, `apple_test` has attributes
# from both `apple_library` and `apple_bundle`.
attribs = {
ATTRS_VALIDATORS_NAME: ATTRS_VALIDATORS_TYPE,
# Expected by `apple_bundle`, for `apple_test` this field is always None.
"binary": attrs.option(attrs.dep(), default = None),
"enable_library_evolution": attrs.option(attrs.bool(), default = None),
Expand Down
84 changes: 84 additions & 0 deletions attrs_validators.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under both the MIT license found in the
# LICENSE-MIT file in the root directory of this source tree and the Apache
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
# of this source tree.

_RUNNABLE_EXEC_DEP = attrs.exec_dep(providers = [RunInfo])

ATTRS_VALIDATORS_NAME = "attrs_validators"
ATTRS_VALIDATORS_TYPE = attrs.dict(
attrs.string(),
attrs.tuple(
# The list of attrs you want.
# If the attr key isn't available, it'll fail.
attrs.list(attrs.string()),
attrs.one_of(
# The validation script which is going to run.
# It will be passed two positional args:
# - a path to a JSON with the serialized args.
# - a path to a file to write the output.
_RUNNABLE_EXEC_DEP,
attrs.tuple(
_RUNNABLE_EXEC_DEP,
# Additional args to pass to your script.
attrs.list(attrs.arg()),
),
),
),
default = {},
)

def get_attrs_validators_outputs(ctx: AnalysisContext) -> list[Artifact]:
if not hasattr(ctx.attrs, ATTRS_VALIDATORS_NAME):
return []

artifacts = []
for key, (requested_attrs, validator) in ctx.attrs.attrs_validators.items():
if type(validator) == "tuple":
validator, validator_args = validator
else:
validator = validator
validator_args = []

output = ctx.actions.declare_output(key)
ctx.actions.run(
cmd_args([
validator[RunInfo],
_build_attr_json_args(ctx, key, requested_attrs),
output.as_output(),
] + validator_args),
category = "attrs_validator",
identifier = key,
)
artifacts.append(output)

return artifacts

def _build_attr_json_args(ctx: AnalysisContext, key: str, requested_attrs: list[str]):
attr_args = {}
missing_attrs = []
for attr in requested_attrs:
if attr == "configured_target_label":
attr_args["configured_target_label"] = ctx.label.configured_target()
elif attr == "target_label":
attr_args["target_label"] = ctx.label.raw_target()
elif hasattr(ctx.attrs, attr):
attr_args[attr] = getattr(ctx.attrs, attr)
else:
missing_attrs.append(attr)

if missing_attrs:
fail("The following attrs are not available on {}: {}".format(
ctx.label,
", ".join(sorted(missing_attrs)),
))

attr_args = ctx.actions.write_json(
"{}-attrs.json".format(key),
attr_args,
with_inputs = True,
)

return attr_args

0 comments on commit 8aa9b6b

Please sign in to comment.