Skip to main content
Glama
cfg_constructor.bzl8.88 kB
# 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. load("@prelude//utils:graph_utils.bzl", "post_order_traversal") load( ":common.bzl", "apply_buckconfig_backed_modifiers", "get_and_insert_modifier_info", "get_constraint_setting_deps", "json_to_tagged_modifiers", "modifier_to_refs", "resolve_alias", "resolve_modifier", ) load(":name.bzl", "cfg_name") load( ":types.bzl", "BuckconfigBackedModifierInfo", "Modifier", # @unused "ModifierCliLocation", "ModifierTargetLocation", "TaggedModifiers", ) PostConstraintAnalysisParams = record( legacy_platform = PlatformInfo | None, package_modifiers = list[TaggedModifiers], target_modifiers = list[Modifier], cli_modifiers = list[Modifier], extra_data = struct, ) def cfg_constructor_pre_constraint_analysis( *, legacy_platform: PlatformInfo | None, # dict[str, typing.Any] is JSON dictionary form of `TaggedModifier` passed from buck2 core package_modifiers: list[dict[str, typing.Any]] | None, # typing.Any is JSON form of modifier target_modifiers: list[Modifier] | None, cli_modifiers: list[str], rule_name: str, aliases: struct, extra_data: struct, **_kwargs) -> (list[str], PostConstraintAnalysisParams): """ First stage of cfg constructor for modifiers. Args: legacy_platform: PlatformInfo from legacy target platform resolution, if one is specified package_modifiers: A list of modifiers specified from all parent PACKAGE files target_modifier: A list of modifiers specified from buildfile via `metadata` attribute. cli_modifiers: modifiers specified from `--modifier` flag, `?modifier`, or BXL aliases: A struct that contains mapping of modifier aliases to modifier. extra_data: Some extra data that is for extra logging/validation for our internal modifier implementation. Returns `(refs, PostConstraintAnalysisParams)`, where `refs` is a list of fully qualified configuration targets we need providers for. """ package_modifiers = package_modifiers or [] target_modifiers = target_modifiers or [] # Convert JSONs back to TaggedModifiers package_modifiers = [json_to_tagged_modifiers(modifier_json) for modifier_json in package_modifiers] # Filter PACKAGE modifiers based on rule name. # This only filters out PACKAGE modifiers from `extra_cfg_modifiers_per_rule` argument of `set_cfg_modifiers` function. package_modifiers = [tagged_modifiers for tagged_modifiers in package_modifiers if tagged_modifiers.rule_name == None or tagged_modifiers.rule_name == rule_name] # Resolve all aliases in CLI modifiers cli_modifiers = [resolved_modifier for modifier in cli_modifiers for resolved_modifier in resolve_alias(modifier, aliases)] refs = [] buckconfig_backed_modifiers = getattr(extra_data, "buckconfig_backed_modifiers", None) if buckconfig_backed_modifiers: refs.append(buckconfig_backed_modifiers) for tagged_modifiers in package_modifiers: for modifier in tagged_modifiers.modifiers: refs.extend(modifier_to_refs(modifier, tagged_modifiers.location)) for modifier in target_modifiers: refs.extend(modifier_to_refs(modifier, ModifierTargetLocation())) for modifier in cli_modifiers: refs.extend(modifier_to_refs(modifier, ModifierCliLocation())) return refs, PostConstraintAnalysisParams( legacy_platform = legacy_platform, package_modifiers = package_modifiers, target_modifiers = target_modifiers, cli_modifiers = cli_modifiers, extra_data = extra_data, ) def cfg_constructor_post_constraint_analysis( *, refs: dict[str, ProviderCollection], params: PostConstraintAnalysisParams) -> PlatformInfo: """ Second stage of cfg constructor for modifiers. Args: refs: a dictionary of fully qualified target labels for configuration targets with their providers params: `PostConstraintAnalysisParams` returned from first stage of cfg constructor Returns a PlatformInfo """ if not (params.package_modifiers or params.target_modifiers or params.cli_modifiers): # If there is no modifier and legacy platform is specified, # then return the legacy platform as is without changing the label or # configuration. return params.legacy_platform or PlatformInfo( # Empty configuration label = "<empty>", configuration = ConfigurationInfo( constraints = {}, values = {}, ), ) constraint_setting_to_modifier_infos = {} cli_modifier_validation = getattr(params.extra_data, "cli_modifier_validation", None) buckconfig_backed_modifiers = getattr(params.extra_data, "buckconfig_backed_modifiers", None) if buckconfig_backed_modifiers: apply_buckconfig_backed_modifiers(constraint_setting_to_modifier_infos, refs[buckconfig_backed_modifiers][BuckconfigBackedModifierInfo].pre_platform_modifiers) if params.legacy_platform: for constraint_setting, constraint_value_info in params.legacy_platform.configuration.constraints.items(): constraint_setting_to_modifier_infos[constraint_setting] = [constraint_value_info] if buckconfig_backed_modifiers: apply_buckconfig_backed_modifiers(constraint_setting_to_modifier_infos, refs[buckconfig_backed_modifiers][BuckconfigBackedModifierInfo].post_platform_modifiers) for tagged_modifiers in params.package_modifiers: for modifier in tagged_modifiers.modifiers: if modifier: get_and_insert_modifier_info( constraint_setting_to_modifier_infos = constraint_setting_to_modifier_infos, refs = refs, modifier = modifier, location = tagged_modifiers.location, ) for modifier in params.target_modifiers: if modifier: get_and_insert_modifier_info( constraint_setting_to_modifier_infos = constraint_setting_to_modifier_infos, refs = refs, modifier = modifier, location = ModifierTargetLocation(), ) if buckconfig_backed_modifiers: apply_buckconfig_backed_modifiers(constraint_setting_to_modifier_infos, refs[buckconfig_backed_modifiers][BuckconfigBackedModifierInfo].pre_cli_modifiers) for modifier in params.cli_modifiers: if modifier: constraint_setting_label, _ = get_and_insert_modifier_info( constraint_setting_to_modifier_infos = constraint_setting_to_modifier_infos, refs = refs, modifier = modifier, location = ModifierCliLocation(), ) if cli_modifier_validation: cli_modifier_validation(constraint_setting_label, modifier) # Modifiers are resolved in topological ordering of modifier selects. For example, if the CPU modifier # is a modifier_select on OS constraint, then the OS modifier must be resolved before the CPU modifier. # To determine this order, we first construct a dep graph of constraint settings based on the modifier # selects. Then we perform a post order traversal of the said graph. modifier_dep_graph = { constraint_setting: [ dep for modifier_info in modifier_infos for dep in get_constraint_setting_deps(modifier_info) ] for constraint_setting, modifier_infos in constraint_setting_to_modifier_infos.items() } # For topo-sort, we need to fill in empty edges for nodes that have no deps for deps in modifier_dep_graph.values(): for dep in deps: if dep not in modifier_dep_graph: modifier_dep_graph[dep] = [] constraint_setting_order = post_order_traversal(modifier_dep_graph) cfg = ConfigurationInfo( constraints = {}, values = {}, ) for constraint_setting in constraint_setting_order: for modifier_info in constraint_setting_to_modifier_infos.get(constraint_setting) or (): constraint_value = resolve_modifier(cfg, modifier_info) if constraint_value: cfg.constraints[constraint_setting] = constraint_value name = cfg_name(cfg) return PlatformInfo( label = name, configuration = cfg, )

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server