Vendor dependencies
Let's see how I like this workflow.
This commit is contained in:
parent
34d1830413
commit
9c435dc440
7500 changed files with 1665121 additions and 99 deletions
108
vendor/cxx/tools/buck/prelude/apple/apple_asset_catalog.bzl
vendored
Normal file
108
vendor/cxx/tools/buck/prelude/apple/apple_asset_catalog.bzl
vendored
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
# 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//apple:apple_toolchain_types.bzl", "AppleToolchainInfo")
|
||||
load("@prelude//utils:utils.bzl", "flatten")
|
||||
load(":apple_asset_catalog_compilation_options.bzl", "AppleAssetCatalogsCompilationOptions", "get_apple_asset_catalogs_compilation_options") # @unused Used as a type
|
||||
load(":apple_asset_catalog_types.bzl", "AppleAssetCatalogResult", "AppleAssetCatalogSpec", "StringWithSourceTarget")
|
||||
load(":apple_bundle_utility.bzl", "get_bundle_min_target_version", "get_bundle_resource_processing_options")
|
||||
load(":apple_sdk.bzl", "get_apple_sdk_name")
|
||||
load(":apple_sdk_metadata.bzl", "get_apple_sdk_metadata_for_sdk_name")
|
||||
load(":resource_groups.bzl", "create_resource_graph")
|
||||
|
||||
def apple_asset_catalog_impl(ctx: "context") -> ["provider"]:
|
||||
spec = AppleAssetCatalogSpec(
|
||||
app_icon = StringWithSourceTarget(source = ctx.label, value = ctx.attrs.app_icon) if ctx.attrs.app_icon != None else None,
|
||||
dirs = ctx.attrs.dirs,
|
||||
launch_image = StringWithSourceTarget(source = ctx.label, value = ctx.attrs.launch_image) if ctx.attrs.launch_image != None else None,
|
||||
)
|
||||
graph = create_resource_graph(
|
||||
ctx = ctx,
|
||||
labels = ctx.attrs.labels,
|
||||
deps = [],
|
||||
exported_deps = [],
|
||||
asset_catalog_spec = spec,
|
||||
)
|
||||
return [DefaultInfo(default_outputs = []), graph]
|
||||
|
||||
def compile_apple_asset_catalog(ctx: "context", specs: [AppleAssetCatalogSpec.type]) -> [AppleAssetCatalogResult.type, None]:
|
||||
single_spec = _merge_asset_catalog_specs(ctx, specs)
|
||||
if len(single_spec.dirs) == 0:
|
||||
return None
|
||||
plist = ctx.actions.declare_output("AssetCatalog.plist")
|
||||
catalog = ctx.actions.declare_output("AssetCatalogCompiled")
|
||||
processing_options = get_bundle_resource_processing_options(ctx)
|
||||
compilation_options = get_apple_asset_catalogs_compilation_options(ctx)
|
||||
command = _get_actool_command(ctx, single_spec, catalog.as_output(), plist.as_output(), compilation_options)
|
||||
ctx.actions.run(command, prefer_local = processing_options.prefer_local, allow_cache_upload = processing_options.allow_cache_upload, category = "apple_asset_catalog")
|
||||
return AppleAssetCatalogResult(compiled_catalog = catalog, catalog_plist = plist)
|
||||
|
||||
def _merge_asset_catalog_specs(ctx: "context", xs: [AppleAssetCatalogSpec.type]) -> AppleAssetCatalogSpec.type:
|
||||
app_icon = _get_at_most_one_attribute(ctx, xs, "app_icon")
|
||||
launch_image = _get_at_most_one_attribute(ctx, xs, "launch_image")
|
||||
dirs = dedupe(flatten([x.dirs for x in xs]))
|
||||
return AppleAssetCatalogSpec(app_icon = app_icon, dirs = dirs, launch_image = launch_image)
|
||||
|
||||
def _get_at_most_one_attribute(ctx: "context", xs: ["_record"], attr_name: str.type) -> ["StringWithSourceTarget", None]:
|
||||
all_values = dedupe(filter(None, [getattr(x, attr_name) for x in xs]))
|
||||
if len(all_values) > 1:
|
||||
fail("At most one asset catalog in the dependencies of `{}` can have an `{}` attribute. At least 2 catalogs are providing it: `{}` and `{}`.".format(_get_target(ctx), attr_name, all_values[0].source, all_values[1].source))
|
||||
elif len(all_values) == 1:
|
||||
return all_values[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
def _get_target(ctx: "context") -> str.type:
|
||||
return ctx.label.package + ":" + ctx.label.name
|
||||
|
||||
def _get_actool_command(ctx: "context", info: AppleAssetCatalogSpec.type, catalog_output: "output_artifact", plist_output: "output_artifact", compilation_options: AppleAssetCatalogsCompilationOptions.type) -> "cmd_args":
|
||||
external_name = get_apple_sdk_name(ctx)
|
||||
target_device = get_apple_sdk_metadata_for_sdk_name(external_name).target_device_flags
|
||||
|
||||
actool = ctx.attrs._apple_toolchain[AppleToolchainInfo].actool
|
||||
actool_command = cmd_args([
|
||||
actool,
|
||||
"--platform",
|
||||
external_name,
|
||||
"--minimum-deployment-target",
|
||||
get_bundle_min_target_version(ctx),
|
||||
"--compile",
|
||||
catalog_output,
|
||||
"--output-partial-info-plist",
|
||||
plist_output,
|
||||
] +
|
||||
target_device +
|
||||
(
|
||||
["--app-icon", info.app_icon.value] if info.app_icon else []
|
||||
) + (
|
||||
["--launch-image", info.launch_image.value] if info.launch_image else []
|
||||
) + (
|
||||
["--notices"] if compilation_options.enable_notices else []
|
||||
) + (
|
||||
["--warnings"] if compilation_options.enable_warnings else []
|
||||
) + (
|
||||
["--errors"] if compilation_options.enable_errors else []
|
||||
) + (
|
||||
["--compress-pngs"] if compilation_options.compress_pngs else []
|
||||
) +
|
||||
["--optimization", compilation_options.optimization] +
|
||||
["--output-format", compilation_options.output_format] +
|
||||
compilation_options.extra_flags +
|
||||
info.dirs)
|
||||
|
||||
# `actool` expects the output directory to be present.
|
||||
# Use the wrapper script to create the directory first and then actually call `actool`.
|
||||
wrapper_script, _ = ctx.actions.write(
|
||||
"actool_wrapper.sh",
|
||||
[
|
||||
cmd_args(catalog_output, format = "mkdir -p {}"),
|
||||
cmd_args(actool_command, delimiter = " "),
|
||||
],
|
||||
allow_args = True,
|
||||
)
|
||||
command = cmd_args(["/bin/sh", wrapper_script]).hidden([actool_command])
|
||||
return command
|
||||
29
vendor/cxx/tools/buck/prelude/apple/apple_asset_catalog_compilation_options.bzl
vendored
Normal file
29
vendor/cxx/tools/buck/prelude/apple/apple_asset_catalog_compilation_options.bzl
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# 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.
|
||||
|
||||
AppleAssetCatalogsCompilationOptions = record(
|
||||
enable_notices = field(bool.type),
|
||||
enable_warnings = field(bool.type),
|
||||
enable_errors = field(bool.type),
|
||||
compress_pngs = field(bool.type),
|
||||
optimization = field(str.type),
|
||||
output_format = field(str.type),
|
||||
extra_flags = field([str.type]),
|
||||
)
|
||||
|
||||
def get_apple_asset_catalogs_compilation_options(ctx: "context") -> AppleAssetCatalogsCompilationOptions.type:
|
||||
options = ctx.attrs.asset_catalogs_compilation_options
|
||||
|
||||
return AppleAssetCatalogsCompilationOptions(
|
||||
enable_notices = options.get("notices", True),
|
||||
enable_warnings = options.get("warnings", True),
|
||||
enable_errors = options.get("errors", True),
|
||||
compress_pngs = options.get("compress_pngs", True),
|
||||
optimization = options.get("optimization", "space"),
|
||||
output_format = options.get("output_format", "human-readable-text"),
|
||||
extra_flags = options.get("extra_flags", []),
|
||||
)
|
||||
30
vendor/cxx/tools/buck/prelude/apple/apple_asset_catalog_types.bzl
vendored
Normal file
30
vendor/cxx/tools/buck/prelude/apple/apple_asset_catalog_types.bzl
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# 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.
|
||||
|
||||
StringWithSourceTarget = record(
|
||||
# Target providing the string value
|
||||
source = field("label"),
|
||||
value = field("string"),
|
||||
)
|
||||
|
||||
AppleAssetCatalogSpec = record(
|
||||
# At most one per given `apple_bundle` (including all transitive catalog dependencies),
|
||||
# optional reference in a form of a name (extension omitted) of an .appiconset which
|
||||
# contains an image set representing an application icon.
|
||||
# This set should be contained in one of catalogs referenced by `dirs` attribute.
|
||||
app_icon = field([StringWithSourceTarget.type, None]),
|
||||
dirs = field(["artifact"]),
|
||||
# Same as `app_icon` but with an application launch image semantics.
|
||||
launch_image = field([StringWithSourceTarget.type, None]),
|
||||
)
|
||||
|
||||
AppleAssetCatalogResult = record(
|
||||
# Directory which contains compiled assets ready to be copied into application bundle
|
||||
compiled_catalog = field("artifact"),
|
||||
# .plist file to be merged into main application Info.plist file, containing information about compiled assets
|
||||
catalog_plist = field("artifact"),
|
||||
)
|
||||
88
vendor/cxx/tools/buck/prelude/apple/apple_binary.bzl
vendored
Normal file
88
vendor/cxx/tools/buck/prelude/apple/apple_binary.bzl
vendored
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
# 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//apple:apple_stripping.bzl", "apple_strip_args")
|
||||
load("@prelude//cxx:cxx.bzl", "get_srcs_with_flags")
|
||||
load("@prelude//cxx:cxx_executable.bzl", "cxx_executable")
|
||||
load("@prelude//cxx:cxx_library_utility.bzl", "cxx_attr_deps", "cxx_attr_exported_deps")
|
||||
load("@prelude//cxx:cxx_types.bzl", "CxxRuleConstructorParams")
|
||||
load(
|
||||
"@prelude//cxx:link_groups.bzl",
|
||||
"get_link_group_info",
|
||||
)
|
||||
load(
|
||||
"@prelude//cxx:preprocessor.bzl",
|
||||
"CPreprocessor",
|
||||
)
|
||||
load(":apple_bundle_types.bzl", "AppleMinDeploymentVersionInfo")
|
||||
load(":apple_code_signing_types.bzl", "AppleEntitlementsInfo")
|
||||
load(":apple_dsym.bzl", "AppleDebuggableInfo", "DEBUGINFO_SUBTARGET", "DSYM_SUBTARGET", "get_apple_dsym")
|
||||
load(":apple_frameworks.bzl", "get_framework_search_path_flags")
|
||||
load(":apple_link_postprocessor.bzl", "get_apple_link_postprocessor")
|
||||
load(":apple_target_sdk_version.bzl", "get_min_deployment_version_for_node", "get_min_deployment_version_target_linker_flags", "get_min_deployment_version_target_preprocessor_flags")
|
||||
load(":apple_utility.bzl", "get_apple_cxx_headers_layout")
|
||||
load(":resource_groups.bzl", "create_resource_graph")
|
||||
load(":xcode.bzl", "apple_populate_xcode_attributes")
|
||||
|
||||
def apple_binary_impl(ctx: "context") -> ["provider"]:
|
||||
extra_link_flags = get_min_deployment_version_target_linker_flags(ctx) + _entitlements_link_flags(ctx)
|
||||
framework_search_path_pre = CPreprocessor(
|
||||
args = [get_framework_search_path_flags(ctx)],
|
||||
)
|
||||
constructor_params = CxxRuleConstructorParams(
|
||||
rule_type = "apple_binary",
|
||||
headers_layout = get_apple_cxx_headers_layout(ctx),
|
||||
extra_exported_link_flags = extra_link_flags,
|
||||
srcs = get_srcs_with_flags(ctx),
|
||||
extra_preprocessors = get_min_deployment_version_target_preprocessor_flags(ctx) + [framework_search_path_pre],
|
||||
strip_executable = ctx.attrs.stripped,
|
||||
strip_args_factory = apple_strip_args,
|
||||
cxx_populate_xcode_attributes_func = apple_populate_xcode_attributes,
|
||||
link_postprocessor = get_apple_link_postprocessor(ctx),
|
||||
link_group_info = get_link_group_info(ctx),
|
||||
)
|
||||
(cxx_output, _comp_db_info, xcode_data_info) = cxx_executable(ctx, constructor_params)
|
||||
|
||||
dsym_artifact = get_apple_dsym(
|
||||
ctx = ctx,
|
||||
executable = cxx_output.binary,
|
||||
external_debug_info = cxx_output.external_debug_info,
|
||||
action_identifier = cxx_output.binary.short_path,
|
||||
)
|
||||
cxx_output.sub_targets[DSYM_SUBTARGET] = [DefaultInfo(default_outputs = [dsym_artifact])]
|
||||
|
||||
cxx_output.sub_targets[DEBUGINFO_SUBTARGET] = [DefaultInfo(other_outputs = cxx_output.external_debug_info)]
|
||||
|
||||
min_version = get_min_deployment_version_for_node(ctx)
|
||||
min_version_providers = [AppleMinDeploymentVersionInfo(version = min_version)] if min_version != None else []
|
||||
|
||||
resource_graph = create_resource_graph(
|
||||
ctx = ctx,
|
||||
labels = ctx.attrs.labels,
|
||||
deps = cxx_attr_deps(ctx),
|
||||
exported_deps = cxx_attr_exported_deps(ctx),
|
||||
)
|
||||
|
||||
return [
|
||||
DefaultInfo(default_outputs = [cxx_output.binary], sub_targets = cxx_output.sub_targets),
|
||||
RunInfo(args = cmd_args(cxx_output.binary).hidden(cxx_output.runtime_files)),
|
||||
AppleEntitlementsInfo(entitlements_file = ctx.attrs.entitlements_file),
|
||||
AppleDebuggableInfo(dsyms = [dsym_artifact], external_debug_info = cxx_output.external_debug_info),
|
||||
xcode_data_info,
|
||||
] + [resource_graph] + min_version_providers
|
||||
|
||||
def _entitlements_link_flags(ctx: "context") -> [""]:
|
||||
return [
|
||||
"-Xlinker",
|
||||
"-sectcreate",
|
||||
"-Xlinker",
|
||||
"__TEXT",
|
||||
"-Xlinker",
|
||||
"__entitlements",
|
||||
"-Xlinker",
|
||||
ctx.attrs.entitlements_file,
|
||||
] if ctx.attrs.entitlements_file else []
|
||||
181
vendor/cxx/tools/buck/prelude/apple/apple_bundle.bzl
vendored
Normal file
181
vendor/cxx/tools/buck/prelude/apple/apple_bundle.bzl
vendored
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
# 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//apple:apple_toolchain_types.bzl", "AppleToolchainInfo")
|
||||
load(
|
||||
"@prelude//ide_integrations:xcode.bzl",
|
||||
"XCODE_DATA_SUB_TARGET",
|
||||
"generate_xcode_data",
|
||||
)
|
||||
load("@prelude//utils:utils.bzl", "expect", "flatten")
|
||||
load(":apple_bundle_destination.bzl", "AppleBundleDestination")
|
||||
load(":apple_bundle_part.bzl", "AppleBundlePart", "assemble_bundle", "bundle_output")
|
||||
load(":apple_bundle_resources.bzl", "get_apple_bundle_resource_part_list", "get_is_watch_bundle")
|
||||
load(":apple_bundle_types.bzl", "AppleBundleInfo", "AppleBundleResourceInfo")
|
||||
load(":apple_bundle_utility.bzl", "get_bundle_min_target_version", "get_product_name")
|
||||
load(":apple_dsym.bzl", "AppleDebuggableInfo", "DEBUGINFO_SUBTARGET", "DSYM_SUBTARGET")
|
||||
load(":apple_sdk.bzl", "get_apple_sdk_name")
|
||||
load(":xcode.bzl", "apple_xcode_data_add_xctoolchain")
|
||||
|
||||
INSTALL_DATA_SUB_TARGET = "install-data"
|
||||
_INSTALL_DATA_FILE_NAME = "install_apple_data.json"
|
||||
|
||||
_PLIST = "plist"
|
||||
|
||||
_XCTOOLCHAIN_SUB_TARGET = "xctoolchain"
|
||||
|
||||
AppleBundlePartListConstructorParams = record(
|
||||
# The binaries/executables, required to create a bundle
|
||||
binaries = field([AppleBundlePart.type]),
|
||||
)
|
||||
|
||||
AppleBundlePartListOutput = record(
|
||||
# The parts to be copied into an Apple bundle, *including* binaries
|
||||
parts = field([AppleBundlePart.type]),
|
||||
# Part that holds the info.plist
|
||||
info_plist_part = field(AppleBundlePart.type),
|
||||
)
|
||||
|
||||
AppleBundleBinaryOutput = record(
|
||||
binary = field("artifact"),
|
||||
# In the case of watchkit, the `ctx.attrs.binary`'s not set, and we need to create a stub binary.
|
||||
is_watchkit_stub_binary = field(bool.type, False),
|
||||
)
|
||||
|
||||
def _get_binary(ctx: "context") -> AppleBundleBinaryOutput.type:
|
||||
# No binary means we are building watchOS bundle. In v1 bundle binary is present, but its sources are empty.
|
||||
if ctx.attrs.binary == None:
|
||||
return AppleBundleBinaryOutput(
|
||||
binary = _get_watch_kit_stub_artifact(ctx),
|
||||
is_watchkit_stub_binary = True,
|
||||
)
|
||||
|
||||
binary_info = ctx.attrs.binary[DefaultInfo].default_outputs
|
||||
if len(binary_info) != 1:
|
||||
fail("Expected single output artifact. Make sure the implementation of rule from `binary` attribute is correct.")
|
||||
return AppleBundleBinaryOutput(binary = binary_info[0])
|
||||
|
||||
def _get_binary_bundle_parts(ctx: "context", binary_output: AppleBundleBinaryOutput.type) -> [AppleBundlePart.type]:
|
||||
result = []
|
||||
|
||||
if binary_output.is_watchkit_stub_binary:
|
||||
# If we're using a stub binary from watchkit, we also need to add extra part for stub.
|
||||
result.append(AppleBundlePart(source = binary_output.binary, destination = AppleBundleDestination("watchkitstub"), new_name = "WK"))
|
||||
result.append(AppleBundlePart(source = binary_output.binary, destination = AppleBundleDestination("executables"), new_name = get_product_name(ctx)))
|
||||
return result
|
||||
|
||||
def _get_watch_kit_stub_artifact(ctx: "context") -> "artifact":
|
||||
expect(ctx.attrs.binary == None, "Stub is useful only when binary is not set which means watchOS bundle is built.")
|
||||
stub_binary = ctx.attrs._apple_toolchain[AppleToolchainInfo].watch_kit_stub_binary
|
||||
if stub_binary == None:
|
||||
fail("Expected Watch Kit stub binary to be provided when bundle binary is not set.")
|
||||
return stub_binary
|
||||
|
||||
def _apple_bundle_run_validity_checks(ctx: "context"):
|
||||
if ctx.attrs.extension == None:
|
||||
fail("`extension` attribute is required")
|
||||
|
||||
def _get_debuggable_deps(ctx: "context") -> ["AppleDebuggableInfo"]:
|
||||
deps = ctx.attrs.deps
|
||||
|
||||
# No binary means we are building watchOS bundle. In v1 bundle binary is present, but its sources are empty.
|
||||
if ctx.attrs.binary:
|
||||
deps.append(ctx.attrs.binary)
|
||||
|
||||
return filter(
|
||||
None,
|
||||
[dep.get(AppleDebuggableInfo) for dep in deps],
|
||||
)
|
||||
|
||||
def get_apple_bundle_part_list(ctx: "context", params: AppleBundlePartListConstructorParams.type) -> AppleBundlePartListOutput.type:
|
||||
resource_part_list = None
|
||||
if hasattr(ctx.attrs, "_resource_bundle") and ctx.attrs._resource_bundle != None:
|
||||
resource_info = ctx.attrs._resource_bundle[AppleBundleResourceInfo]
|
||||
if resource_info != None:
|
||||
resource_part_list = resource_info.resource_output
|
||||
|
||||
if resource_part_list == None:
|
||||
resource_part_list = get_apple_bundle_resource_part_list(ctx)
|
||||
|
||||
return AppleBundlePartListOutput(
|
||||
parts = resource_part_list.resource_parts + params.binaries,
|
||||
info_plist_part = resource_part_list.info_plist_part,
|
||||
)
|
||||
|
||||
def apple_bundle_impl(ctx: "context") -> ["provider"]:
|
||||
_apple_bundle_run_validity_checks(ctx)
|
||||
|
||||
binary_outputs = _get_binary(ctx)
|
||||
apple_bundle_part_list_output = get_apple_bundle_part_list(ctx, AppleBundlePartListConstructorParams(binaries = _get_binary_bundle_parts(ctx, binary_outputs)))
|
||||
|
||||
sub_targets = {}
|
||||
|
||||
debuggable_deps = _get_debuggable_deps(ctx)
|
||||
|
||||
dsym_artifacts = flatten([info.dsyms for info in debuggable_deps])
|
||||
if dsym_artifacts:
|
||||
sub_targets[DSYM_SUBTARGET] = [DefaultInfo(default_outputs = dsym_artifacts)]
|
||||
|
||||
external_debug_info = flatten([info.external_debug_info for info in debuggable_deps])
|
||||
sub_targets[DEBUGINFO_SUBTARGET] = [DefaultInfo(other_outputs = external_debug_info)]
|
||||
|
||||
bundle = bundle_output(ctx)
|
||||
|
||||
assemble_bundle(ctx, bundle, apple_bundle_part_list_output.parts, apple_bundle_part_list_output.info_plist_part)
|
||||
|
||||
sub_targets[_PLIST] = [DefaultInfo(default_outputs = [apple_bundle_part_list_output.info_plist_part.source])]
|
||||
|
||||
sub_targets[_XCTOOLCHAIN_SUB_TARGET] = ctx.attrs._apple_xctoolchain.providers
|
||||
|
||||
# Define the xcode data sub target
|
||||
xcode_data_default_info, xcode_data_info = generate_xcode_data(ctx, "apple_bundle", bundle, _xcode_populate_attributes, processed_info_plist = apple_bundle_part_list_output.info_plist_part.source)
|
||||
sub_targets[XCODE_DATA_SUB_TARGET] = xcode_data_default_info
|
||||
install_data = generate_install_data(ctx)
|
||||
|
||||
return [
|
||||
DefaultInfo(default_outputs = [bundle], sub_targets = sub_targets),
|
||||
AppleBundleInfo(bundle = bundle, binary_name = get_product_name(ctx), is_watchos = get_is_watch_bundle(ctx)),
|
||||
AppleDebuggableInfo(dsyms = dsym_artifacts, external_debug_info = external_debug_info),
|
||||
InstallInfo(
|
||||
installer = ctx.attrs._apple_installer,
|
||||
files = {
|
||||
"app_bundle": bundle,
|
||||
"options": install_data,
|
||||
},
|
||||
),
|
||||
xcode_data_info,
|
||||
]
|
||||
|
||||
def _xcode_populate_attributes(ctx, processed_info_plist: "artifact") -> {str.type: ""}:
|
||||
data = {
|
||||
"deployment_version": get_bundle_min_target_version(ctx),
|
||||
"info_plist": ctx.attrs.info_plist,
|
||||
"processed_info_plist": processed_info_plist,
|
||||
"product_name": get_product_name(ctx),
|
||||
"sdk": get_apple_sdk_name(ctx),
|
||||
}
|
||||
|
||||
apple_xcode_data_add_xctoolchain(ctx, data)
|
||||
return data
|
||||
|
||||
def generate_install_data(
|
||||
ctx: "context",
|
||||
populate_rule_specific_attributes_func: ["function", None] = None,
|
||||
**kwargs) -> "artifact":
|
||||
data = {
|
||||
"fullyQualifiedName": ctx.label,
|
||||
## TODO(T110665037): populate full path similar to bundle_spec.json
|
||||
"info_plist": ctx.attrs.info_plist,
|
||||
"use_idb": "true",
|
||||
## TODO(T110665037): read from .buckconfig
|
||||
"xcode_developer_path": "/Applications/Xcode_13.4.0_fb.app/Contents/Developer",
|
||||
}
|
||||
|
||||
if populate_rule_specific_attributes_func:
|
||||
data.update(populate_rule_specific_attributes_func(ctx, **kwargs))
|
||||
|
||||
return ctx.actions.write_json(_INSTALL_DATA_FILE_NAME, data)
|
||||
20
vendor/cxx/tools/buck/prelude/apple/apple_bundle_config.bzl
vendored
Normal file
20
vendor/cxx/tools/buck/prelude/apple/apple_bundle_config.bzl
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# 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.
|
||||
|
||||
def _maybe_get_bool(config: str.type, default: [None, bool.type]) -> [None, bool.type]:
|
||||
result = read_config("apple", config, None)
|
||||
if result == None:
|
||||
return default
|
||||
return result.lower() == "true"
|
||||
|
||||
def apple_bundle_config() -> {str.type: ""}:
|
||||
return {
|
||||
"_codesign_type": read_config("apple", "codesign_type_override", None),
|
||||
"_compile_resources_locally_override": _maybe_get_bool("compile_resources_locally_override", None),
|
||||
"_incremental_bundling_enabled": _maybe_get_bool("incremental_bundling_enabled", True),
|
||||
"_profile_bundling_enabled": _maybe_get_bool("profile_bundling_enabled", False),
|
||||
}
|
||||
132
vendor/cxx/tools/buck/prelude/apple/apple_bundle_destination.bzl
vendored
Normal file
132
vendor/cxx/tools/buck/prelude/apple/apple_bundle_destination.bzl
vendored
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
# 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//:paths.bzl", "paths")
|
||||
|
||||
# Abstraction of a place in a resulting bundle where file or directory will be copied. Actual value
|
||||
# of path relative to bundle root depends on a platform. This class is an implementation detail and
|
||||
# is not exposed to user unlike `AppleResourceDestination`.
|
||||
# v1 code is `com/facebook/buck/apple/AppleBundleDestination.java`
|
||||
AppleBundleDestination = enum(
|
||||
"resources",
|
||||
"frameworks",
|
||||
"executables",
|
||||
"plugins",
|
||||
"xpcservices",
|
||||
"metadata",
|
||||
"watchapp",
|
||||
"headers",
|
||||
"modules",
|
||||
"quicklook",
|
||||
"watchkitstub",
|
||||
"bundleroot",
|
||||
"loginitems",
|
||||
)
|
||||
|
||||
AppleBundleDestinationPaths = record(
|
||||
resources = field(str.type, ""),
|
||||
frameworks = field(str.type, ""),
|
||||
executables = field(str.type, ""),
|
||||
plugins = field(str.type, ""),
|
||||
xpcservices = field(str.type, ""),
|
||||
metadata = field(str.type, ""),
|
||||
watchapp = field(str.type, ""),
|
||||
headers = field(str.type, ""),
|
||||
modules = field(str.type, ""),
|
||||
quicklook = field(str.type, ""),
|
||||
watchkitstub = field(str.type, ""),
|
||||
bundleroot = field(str.type, ""),
|
||||
loginitems = field(str.type, ""),
|
||||
)
|
||||
|
||||
_IOSBundleDestinationPaths = AppleBundleDestinationPaths(
|
||||
frameworks = "Frameworks",
|
||||
plugins = "PlugIns",
|
||||
xpcservices = "XPCServices",
|
||||
watchapp = "Watch",
|
||||
quicklook = "Library/QuickLook",
|
||||
watchkitstub = "_WatchKitStub",
|
||||
)
|
||||
|
||||
_IOSFrameworkBundleDestinationPaths = AppleBundleDestinationPaths(
|
||||
frameworks = "Frameworks",
|
||||
xpcservices = "XPCServices",
|
||||
headers = "Headers",
|
||||
modules = "Modules",
|
||||
)
|
||||
|
||||
macOS_content_path = "Contents"
|
||||
_MacOSBundleDestinationPaths = AppleBundleDestinationPaths(
|
||||
resources = paths.join(macOS_content_path, "Resources"),
|
||||
frameworks = paths.join(macOS_content_path, "Frameworks"),
|
||||
executables = paths.join(macOS_content_path, "MacOS"),
|
||||
plugins = paths.join(macOS_content_path, "PlugIns"),
|
||||
xpcservices = paths.join(macOS_content_path, "XPCServices"),
|
||||
metadata = macOS_content_path,
|
||||
watchapp = macOS_content_path,
|
||||
headers = macOS_content_path,
|
||||
modules = macOS_content_path,
|
||||
quicklook = paths.join(macOS_content_path, "Library/QuickLook"),
|
||||
watchkitstub = macOS_content_path,
|
||||
bundleroot = macOS_content_path,
|
||||
loginitems = paths.join(macOS_content_path, "Library/LoginItems"),
|
||||
)
|
||||
|
||||
_MacOSFrameworkBundleDestinationPaths = AppleBundleDestinationPaths(
|
||||
resources = "Resources",
|
||||
frameworks = "Frameworks",
|
||||
xpcservices = "XPCServices",
|
||||
metadata = "Resources",
|
||||
headers = "Headers",
|
||||
modules = "Modules",
|
||||
)
|
||||
|
||||
def _get_apple_bundle_destinations_for_sdk_name(name: str.type) -> AppleBundleDestinationPaths.type:
|
||||
if name == "macosx" or name == "maccatalyst":
|
||||
return _MacOSBundleDestinationPaths
|
||||
else:
|
||||
return _IOSBundleDestinationPaths
|
||||
|
||||
def _get_apple_framework_bundle_destinations_for_sdk_name(name: str.type) -> AppleBundleDestinationPaths.type:
|
||||
if name == "macosx" or name == "maccatalyst":
|
||||
return _MacOSFrameworkBundleDestinationPaths
|
||||
else:
|
||||
return _IOSFrameworkBundleDestinationPaths
|
||||
|
||||
def bundle_relative_path_for_destination(destination: AppleBundleDestination.type, sdk_name: str.type, extension: str.type) -> str.type:
|
||||
if extension == "framework":
|
||||
bundle_destinations = _get_apple_framework_bundle_destinations_for_sdk_name(sdk_name)
|
||||
else:
|
||||
bundle_destinations = _get_apple_bundle_destinations_for_sdk_name(sdk_name)
|
||||
|
||||
if destination.value == "resources":
|
||||
return bundle_destinations.resources
|
||||
elif destination.value == "frameworks":
|
||||
return bundle_destinations.frameworks
|
||||
elif destination.value == "executables":
|
||||
return bundle_destinations.executables
|
||||
elif destination.value == "plugins":
|
||||
return bundle_destinations.plugins
|
||||
elif destination.value == "xpcservices":
|
||||
return bundle_destinations.xpcservices
|
||||
elif destination.value == "metadata":
|
||||
return bundle_destinations.metadata
|
||||
elif destination.value == "watchapp":
|
||||
return bundle_destinations.watchapp
|
||||
elif destination.value == "headers":
|
||||
return bundle_destinations.headers
|
||||
elif destination.value == "modules":
|
||||
return bundle_destinations.modules
|
||||
elif destination.value == "quicklook":
|
||||
return bundle_destinations.quicklook
|
||||
elif destination.value == "watchkitstub":
|
||||
return bundle_destinations.watchkitstub
|
||||
elif destination.value == "bundleroot":
|
||||
return bundle_destinations.bundleroot
|
||||
elif destination.value == "loginitems":
|
||||
return bundle_destinations.loginitems
|
||||
fail("Unsupported Apple bundle destination {}".format(destination))
|
||||
90
vendor/cxx/tools/buck/prelude/apple/apple_bundle_macro_layer.bzl
vendored
Normal file
90
vendor/cxx/tools/buck/prelude/apple/apple_bundle_macro_layer.bzl
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
# 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(":apple_bundle_config.bzl", "apple_bundle_config")
|
||||
load(":apple_info_plist_substitutions_parsing.bzl", "parse_codesign_entitlements")
|
||||
|
||||
_RESOURCE_BUNDLE_FIELDS = [
|
||||
"asset_catalogs_compilation_options",
|
||||
"binary",
|
||||
"default_target_platform",
|
||||
"deps",
|
||||
"extension",
|
||||
"ibtool_flags",
|
||||
"ibtool_module_flag",
|
||||
"info_plist",
|
||||
"info_plist_substitutions",
|
||||
"product_name",
|
||||
"resource_group",
|
||||
"resource_group_map",
|
||||
]
|
||||
|
||||
def apple_bundle_macro_impl(apple_bundle_rule = None, apple_resource_bundle_rule = None, **kwargs):
|
||||
info_plist_substitutions = kwargs.get("info_plist_substitutions")
|
||||
kwargs.update(apple_bundle_config())
|
||||
|
||||
resource_bundle_target_name = None
|
||||
|
||||
# The `apple_resource_bundle()` target will _always_ be Xcode-based, so resources can always be used
|
||||
# from there. `resources_toolchain_enabled` exists only as a killswitch (or for testing/debugging purposes).
|
||||
# By default, we consistently get all resources from `apple_resource_bundle()` target across all OSes and
|
||||
# toolchains.
|
||||
resources_toolchain_enabled = (read_config("apple", "resources_toolchain_enabled", "true").lower() == "true")
|
||||
if resources_toolchain_enabled:
|
||||
resource_bundle_name = kwargs["name"] + "__ResourceBundle_Private"
|
||||
resource_bundle_kwargs = {
|
||||
"_bundle_target_name": kwargs["name"],
|
||||
"_compile_resources_locally_override": kwargs["_compile_resources_locally_override"],
|
||||
}
|
||||
for field_name in _RESOURCE_BUNDLE_FIELDS:
|
||||
resource_bundle_kwargs[field_name] = kwargs.get(field_name)
|
||||
|
||||
# TODO(T125269558): Remove usage of apple_resource_bundle() once we have exec groups.
|
||||
apple_resource_bundle_rule(
|
||||
name = resource_bundle_name,
|
||||
**resource_bundle_kwargs
|
||||
)
|
||||
|
||||
resource_bundle_target_name = ":{}".format(resource_bundle_name)
|
||||
|
||||
# Splitting the resource compilation into another rule means we can have
|
||||
# different exec platforms for the resource compilation and for the rest
|
||||
# of the bundling process. This allows us to send resource compilations
|
||||
# directly to RE.
|
||||
#
|
||||
# +-------------------------------------------------+
|
||||
# | apple_bundle() |
|
||||
# | Exec Platform: macOS/Linux |
|
||||
# | +--------+ +--------+ +------------------+ |
|
||||
# +---+ binary +--+ deps +-+ _resource_bundle +---+
|
||||
# +--------+ +--------+ +------------------+
|
||||
# | | |
|
||||
# | | |
|
||||
# | | +---------------+
|
||||
# | | |
|
||||
# | | |
|
||||
# | | v
|
||||
# | | +---------------------------------+
|
||||
# | +-----+ | apple_resource_bundle() |
|
||||
# | | | Exec Platform: macOS-only |
|
||||
# | | | +--------+ +--------+ |
|
||||
# | | +-----+ binary +--+ deps +------+
|
||||
# | | +--------+ +--------+
|
||||
# | | | |
|
||||
# | | | |
|
||||
# | v | |
|
||||
# | +-------------------+ | |
|
||||
# | | Dependencies |<--------+-----------+
|
||||
# | +-------------------+ |
|
||||
# | +-------------------+ |
|
||||
# +------>| Binary |<--------+
|
||||
# +-------------------+
|
||||
apple_bundle_rule(
|
||||
_codesign_entitlements = parse_codesign_entitlements(info_plist_substitutions),
|
||||
_resource_bundle = resource_bundle_target_name,
|
||||
**kwargs
|
||||
)
|
||||
171
vendor/cxx/tools/buck/prelude/apple/apple_bundle_part.bzl
vendored
Normal file
171
vendor/cxx/tools/buck/prelude/apple/apple_bundle_part.bzl
vendored
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
# 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//:paths.bzl", "paths")
|
||||
load(":apple_bundle_destination.bzl", "AppleBundleDestination", "bundle_relative_path_for_destination")
|
||||
load(":apple_bundle_utility.bzl", "get_extension_attr", "get_product_name")
|
||||
load(":apple_code_signing_types.bzl", "AppleEntitlementsInfo", "CodeSignType")
|
||||
load(":apple_sdk.bzl", "get_apple_sdk_name")
|
||||
load(":apple_sdk_metadata.bzl", "get_apple_sdk_metadata_for_sdk_name")
|
||||
load(":apple_toolchain_types.bzl", "AppleToolchainInfo", "AppleToolsInfo")
|
||||
|
||||
# Defines where and what should be copied into
|
||||
AppleBundlePart = record(
|
||||
# A file of directory which content should be copied
|
||||
source = field("artifact"),
|
||||
# Where the source should be copied, the actual destination directory
|
||||
# inside bundle depends on target platform
|
||||
destination = AppleBundleDestination.type,
|
||||
# New file name if it should be renamed before copying.
|
||||
# Empty string value is applicable only when `source` is a directory,
|
||||
# in such case only content of the directory will be copied, as opposed to the directory itself.
|
||||
# When value is `None`, directory or file will be copied as it is, without renaming.
|
||||
new_name = field([str.type, None], None),
|
||||
# Marks parts which should be code signed separately from the whole bundle.
|
||||
codesign_on_copy = field(bool.type, False),
|
||||
)
|
||||
|
||||
def bundle_output(ctx: "context") -> "artifact":
|
||||
bundle_dir_name = _get_bundle_dir_name(ctx)
|
||||
output = ctx.actions.declare_output(bundle_dir_name)
|
||||
return output
|
||||
|
||||
def assemble_bundle(ctx: "context", bundle: "artifact", parts: [AppleBundlePart.type], info_plist_part: [AppleBundlePart.type, None]) -> None:
|
||||
all_parts = parts + [info_plist_part] if info_plist_part else []
|
||||
spec_file = _bundle_spec_json(ctx, all_parts)
|
||||
|
||||
tools = ctx.attrs._apple_tools[AppleToolsInfo]
|
||||
tool = tools.assemble_bundle
|
||||
|
||||
codesign_args = []
|
||||
codesign_type = _detect_codesign_type(ctx)
|
||||
|
||||
if codesign_type.value in ["distribution", "adhoc"]:
|
||||
codesign_args = [
|
||||
"--codesign",
|
||||
"--codesign-tool",
|
||||
ctx.attrs._apple_toolchain[AppleToolchainInfo].codesign,
|
||||
]
|
||||
|
||||
external_name = get_apple_sdk_name(ctx)
|
||||
platform_args = ["--platform", external_name]
|
||||
codesign_args.extend(platform_args)
|
||||
|
||||
if codesign_type.value != "adhoc":
|
||||
provisioning_profiles = ctx.attrs._provisioning_profiles[DefaultInfo]
|
||||
provisioning_profiles_args = ["--profiles-dir"] + provisioning_profiles.default_outputs
|
||||
codesign_args.extend(provisioning_profiles_args)
|
||||
|
||||
# TODO(T116604880): use `apple.use_entitlements_when_adhoc_code_signing` buckconfig value
|
||||
maybe_entitlements = _entitlements_file(ctx)
|
||||
entitlements_args = ["--entitlements", maybe_entitlements] if maybe_entitlements else []
|
||||
codesign_args.extend(entitlements_args)
|
||||
|
||||
identities_command = ctx.attrs._apple_toolchain[AppleToolchainInfo].codesign_identities_command
|
||||
identities_command_args = ["--codesign-identities-command", cmd_args(identities_command)] if identities_command else []
|
||||
codesign_args.extend(identities_command_args)
|
||||
else:
|
||||
codesign_args.append("--ad-hoc")
|
||||
|
||||
info_plist_args = [
|
||||
"--info-plist-source",
|
||||
info_plist_part.source,
|
||||
"--info-plist-destination",
|
||||
_bundle_relative_destination_path(ctx, info_plist_part),
|
||||
] if info_plist_part else []
|
||||
codesign_args.extend(info_plist_args)
|
||||
elif codesign_type.value == "skip":
|
||||
pass
|
||||
else:
|
||||
fail("Code sign type `{}` not supported".format(codesign_type))
|
||||
|
||||
command = cmd_args([
|
||||
tool,
|
||||
"--output",
|
||||
bundle.as_output(),
|
||||
"--spec",
|
||||
spec_file,
|
||||
] + codesign_args)
|
||||
command.hidden([part.source for part in all_parts])
|
||||
run_incremental_args = {}
|
||||
incremental_state = ctx.actions.declare_output("incremental_state.json").as_output()
|
||||
|
||||
# Fallback to value from buckconfig
|
||||
incremental_bundling_enabled = ctx.attrs.incremental_bundling_enabled or ctx.attrs._incremental_bundling_enabled
|
||||
|
||||
if incremental_bundling_enabled:
|
||||
command.add("--incremental-state", incremental_state)
|
||||
run_incremental_args = {
|
||||
"metadata_env_var": "ACTION_METADATA",
|
||||
"metadata_path": "action_metadata.json",
|
||||
"no_outputs_cleanup": True,
|
||||
}
|
||||
category = "apple_assemble_bundle_incremental"
|
||||
else:
|
||||
# overwrite file with incremental state so if previous and next builds are incremental
|
||||
# (as opposed to the current non-incremental one), next one won't assume there is a
|
||||
# valid incremental state.
|
||||
command.hidden(ctx.actions.write_json(incremental_state, {}))
|
||||
category = "apple_assemble_bundle"
|
||||
|
||||
if ctx.attrs._profile_bundling_enabled:
|
||||
profile_output = ctx.actions.declare_output("bundling_profile.txt").as_output()
|
||||
command.add("--profile-output", profile_output)
|
||||
|
||||
force_local_bundling = codesign_type.value != "skip"
|
||||
ctx.actions.run(
|
||||
command,
|
||||
local_only = force_local_bundling,
|
||||
prefer_local = not force_local_bundling,
|
||||
category = category,
|
||||
**run_incremental_args
|
||||
)
|
||||
|
||||
def _get_bundle_dir_name(ctx: "context") -> str.type:
|
||||
return paths.replace_extension(get_product_name(ctx), "." + get_extension_attr(ctx))
|
||||
|
||||
def _bundle_relative_destination_path(ctx: "context", part: AppleBundlePart.type) -> str.type:
|
||||
bundle_relative_path = bundle_relative_path_for_destination(part.destination, get_apple_sdk_name(ctx), ctx.attrs.extension)
|
||||
destination_file_or_directory_name = part.new_name if part.new_name != None else paths.basename(part.source.short_path)
|
||||
return paths.join(bundle_relative_path, destination_file_or_directory_name)
|
||||
|
||||
# Returns JSON to be passed into bundle assembling tool. It should contain a dictionary which maps bundle relative destination paths to source paths."
|
||||
def _bundle_spec_json(ctx: "context", parts: [AppleBundlePart.type]) -> "artifact":
|
||||
specs = []
|
||||
|
||||
for part in parts:
|
||||
part_spec = {
|
||||
"dst": _bundle_relative_destination_path(ctx, part),
|
||||
"src": part.source,
|
||||
}
|
||||
if part.codesign_on_copy:
|
||||
part_spec["codesign_on_copy"] = True
|
||||
specs.append(part_spec)
|
||||
|
||||
return ctx.actions.write_json("bundle_spec.json", specs)
|
||||
|
||||
def _detect_codesign_type(ctx: "context") -> CodeSignType.type:
|
||||
if ctx.attrs.extension not in ["app", "appex"]:
|
||||
# Only code sign application bundles and extensions
|
||||
return CodeSignType("skip")
|
||||
|
||||
if ctx.attrs._codesign_type:
|
||||
return CodeSignType(ctx.attrs._codesign_type)
|
||||
sdk_name = get_apple_sdk_name(ctx)
|
||||
is_ad_hoc_sufficient = get_apple_sdk_metadata_for_sdk_name(sdk_name).is_ad_hoc_code_sign_sufficient
|
||||
return CodeSignType("adhoc" if is_ad_hoc_sufficient else "distribution")
|
||||
|
||||
def _entitlements_file(ctx: "context") -> ["artifact", None]:
|
||||
if not ctx.attrs.binary:
|
||||
return None
|
||||
|
||||
# The `binary` attribute can be either an apple_binary or a dynamic library from apple_library
|
||||
binary_entitlement_info = ctx.attrs.binary[AppleEntitlementsInfo]
|
||||
if binary_entitlement_info and binary_entitlement_info.entitlements_file:
|
||||
return binary_entitlement_info.entitlements_file
|
||||
|
||||
return ctx.attrs._codesign_entitlements
|
||||
344
vendor/cxx/tools/buck/prelude/apple/apple_bundle_resources.bzl
vendored
Normal file
344
vendor/cxx/tools/buck/prelude/apple/apple_bundle_resources.bzl
vendored
Normal file
|
|
@ -0,0 +1,344 @@
|
|||
# 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//:paths.bzl", "paths")
|
||||
load("@prelude//:resources.bzl", "gather_resources")
|
||||
load("@prelude//apple:apple_toolchain_types.bzl", "AppleToolchainInfo")
|
||||
load("@prelude//utils:utils.bzl", "expect", "flatten_dict")
|
||||
load(
|
||||
":apple_asset_catalog.bzl",
|
||||
"compile_apple_asset_catalog",
|
||||
)
|
||||
load(
|
||||
":apple_asset_catalog_types.bzl",
|
||||
"AppleAssetCatalogSpec", # @unused Used as a type
|
||||
)
|
||||
load(":apple_bundle_destination.bzl", "AppleBundleDestination")
|
||||
load(":apple_bundle_part.bzl", "AppleBundlePart")
|
||||
load(":apple_bundle_types.bzl", "AppleBundleInfo")
|
||||
load(":apple_bundle_utility.bzl", "get_bundle_resource_processing_options", "get_extension_attr", "get_product_name")
|
||||
load(":apple_core_data.bzl", "compile_apple_core_data")
|
||||
load(
|
||||
":apple_core_data_types.bzl",
|
||||
"AppleCoreDataSpec", # @unused Used as a type
|
||||
)
|
||||
load(":apple_info_plist.bzl", "process_info_plist", "process_plist")
|
||||
load(
|
||||
":apple_resource_types.bzl",
|
||||
"AppleResourceDestination",
|
||||
"AppleResourceSpec", # @unused Used as a type
|
||||
)
|
||||
load(":apple_resource_utility.bzl", "apple_bundle_destination_from_resource_destination")
|
||||
load(
|
||||
":resource_groups.bzl",
|
||||
"create_resource_graph",
|
||||
"get_filtered_resources",
|
||||
"get_resource_graph_node_map_func",
|
||||
"get_resource_group_info",
|
||||
)
|
||||
|
||||
AppleBundleResourcePartListOutput = record(
|
||||
# Resource parts to be copied into an Apple bundle, *excluding* binaries
|
||||
resource_parts = field([AppleBundlePart.type]),
|
||||
# Part that holds the info.plist
|
||||
info_plist_part = field(AppleBundlePart.type),
|
||||
)
|
||||
|
||||
def get_apple_bundle_resource_part_list(ctx: "context") -> AppleBundleResourcePartListOutput.type:
|
||||
parts = []
|
||||
|
||||
parts.extend(_create_pkg_info_if_needed(ctx))
|
||||
|
||||
(resource_specs, asset_catalog_specs, core_data_specs) = _select_resources(ctx)
|
||||
|
||||
# If we've pulled in native/C++ resources from deps, inline them into the
|
||||
# bundle under the `CxxResources` namespace.
|
||||
cxx_resources = flatten_dict(gather_resources(
|
||||
label = ctx.label,
|
||||
deps = ctx.attrs.deps,
|
||||
).values())
|
||||
if cxx_resources:
|
||||
cxx_res_dir = ctx.actions.copied_dir(
|
||||
"CxxResources",
|
||||
{
|
||||
name: resource
|
||||
for name, (resource, _) in cxx_resources.items()
|
||||
},
|
||||
)
|
||||
resource_specs.append(
|
||||
AppleResourceSpec(
|
||||
dirs = [cxx_res_dir],
|
||||
destination = AppleResourceDestination("resources"),
|
||||
),
|
||||
)
|
||||
|
||||
asset_catalog_result = compile_apple_asset_catalog(ctx, asset_catalog_specs)
|
||||
if asset_catalog_result != None:
|
||||
asset_catalog_part = AppleBundlePart(
|
||||
source = asset_catalog_result.compiled_catalog,
|
||||
destination = AppleBundleDestination("resources"),
|
||||
# We only interested in directory contents
|
||||
new_name = "",
|
||||
)
|
||||
parts.append(asset_catalog_part)
|
||||
|
||||
extra_plist = asset_catalog_result.catalog_plist if asset_catalog_result != None else None
|
||||
info_plist_part = process_info_plist(ctx = ctx, override_input = extra_plist)
|
||||
|
||||
core_data_result = compile_apple_core_data(ctx, core_data_specs, get_product_name(ctx))
|
||||
if core_data_result != None:
|
||||
core_data_part = AppleBundlePart(
|
||||
source = core_data_result,
|
||||
destination = AppleBundleDestination("resources"),
|
||||
# We only interested in directory contents
|
||||
new_name = "",
|
||||
)
|
||||
parts.append(core_data_part)
|
||||
|
||||
parts.extend(_copy_resources(ctx, resource_specs))
|
||||
parts.extend(_copy_first_level_bundles(ctx))
|
||||
|
||||
return AppleBundleResourcePartListOutput(
|
||||
resource_parts = parts,
|
||||
info_plist_part = info_plist_part,
|
||||
)
|
||||
|
||||
# Same logic as in v1, see `buck_client/src/com/facebook/buck/apple/ApplePkgInfo.java`
|
||||
def _create_pkg_info_if_needed(ctx: "context") -> [AppleBundlePart.type]:
|
||||
extension = get_extension_attr(ctx)
|
||||
if extension == "xpc" or extension == "qlgenerator":
|
||||
return []
|
||||
artifact = ctx.actions.write("PkgInfo", "APPLWRUN\n")
|
||||
return [AppleBundlePart(source = artifact, destination = AppleBundleDestination("metadata"))]
|
||||
|
||||
def _select_resources(ctx: "context") -> (([AppleResourceSpec.type], [AppleAssetCatalogSpec.type], [AppleCoreDataSpec.type])):
|
||||
resource_group_info = get_resource_group_info(ctx)
|
||||
if resource_group_info:
|
||||
resource_groups_deps = [mapping.root.node for group in resource_group_info.groups for mapping in group.mappings if mapping.root != None]
|
||||
resource_group_mappings = resource_group_info.mappings
|
||||
else:
|
||||
resource_groups_deps = []
|
||||
resource_group_mappings = {}
|
||||
deps = ctx.attrs.deps + filter(None, [ctx.attrs.binary])
|
||||
resource_graph = create_resource_graph(
|
||||
ctx = ctx,
|
||||
labels = [],
|
||||
deps = deps + resource_groups_deps,
|
||||
exported_deps = [],
|
||||
)
|
||||
resource_graph_node_map_func = get_resource_graph_node_map_func(resource_graph)
|
||||
return get_filtered_resources(ctx.label, resource_graph_node_map_func, ctx.attrs.resource_group, resource_group_mappings)
|
||||
|
||||
def _copy_resources(ctx: "context", specs: [AppleResourceSpec.type]) -> [AppleBundlePart.type]:
|
||||
result = []
|
||||
|
||||
for spec in specs:
|
||||
bundle_destination = apple_bundle_destination_from_resource_destination(spec.destination)
|
||||
result += [_process_apple_resource_file_if_needed(
|
||||
ctx = ctx,
|
||||
file = x,
|
||||
destination = bundle_destination,
|
||||
destination_relative_path = None,
|
||||
codesign_on_copy = spec.codesign_files_on_copy,
|
||||
) for x in spec.files]
|
||||
result += _bundle_parts_for_dirs(spec.dirs, bundle_destination, False)
|
||||
result += _bundle_parts_for_dirs(spec.content_dirs, bundle_destination, True)
|
||||
result += _bundle_parts_for_variant_files(ctx, spec)
|
||||
|
||||
return result
|
||||
|
||||
def _copy_first_level_bundles(ctx: "context") -> [AppleBundlePart.type]:
|
||||
first_level_bundle_infos = filter(None, [dep.get(AppleBundleInfo) for dep in ctx.attrs.deps])
|
||||
return filter(None, [_copied_bundle_spec(info) for info in first_level_bundle_infos])
|
||||
|
||||
def _copied_bundle_spec(bundle_info: AppleBundleInfo.type) -> [None, AppleBundlePart.type]:
|
||||
bundle = bundle_info.bundle
|
||||
bundle_extension = paths.split_extension(bundle.short_path)[1]
|
||||
if bundle_extension == ".framework":
|
||||
destination = AppleBundleDestination("frameworks")
|
||||
codesign_on_copy = True
|
||||
elif bundle_extension == ".app":
|
||||
expect(bundle_info.is_watchos != None, "Field should be set for bundles with extension {}".format(bundle_extension))
|
||||
destination = AppleBundleDestination("watchapp" if bundle_info.is_watchos else "plugins")
|
||||
codesign_on_copy = False
|
||||
elif bundle_extension == ".appex":
|
||||
destination = AppleBundleDestination("plugins")
|
||||
codesign_on_copy = False
|
||||
else:
|
||||
fail("Extension `{}` is not yet supported.".format(bundle_extension))
|
||||
return AppleBundlePart(
|
||||
source = bundle,
|
||||
destination = destination,
|
||||
codesign_on_copy = codesign_on_copy,
|
||||
)
|
||||
|
||||
def _bundle_parts_for_dirs(generated_dirs: ["artifact"], destination: AppleBundleDestination.type, copy_contents_only: bool.type) -> [AppleBundlePart.type]:
|
||||
return [AppleBundlePart(
|
||||
source = generated_dir,
|
||||
destination = destination,
|
||||
new_name = "" if copy_contents_only else None,
|
||||
) for generated_dir in generated_dirs]
|
||||
|
||||
def _bundle_parts_for_variant_files(ctx: "context", spec: AppleResourceSpec.type) -> [AppleBundlePart.type]:
|
||||
result = []
|
||||
|
||||
# By definition, all variant files go into the resources destination
|
||||
bundle_destination = AppleBundleDestination("resources")
|
||||
for variant_file in spec.variant_files:
|
||||
variant_dest_subpath = _get_dest_subpath_for_variant_file(variant_file)
|
||||
bundle_part = _process_apple_resource_file_if_needed(
|
||||
ctx = ctx,
|
||||
file = variant_file,
|
||||
destination = bundle_destination,
|
||||
destination_relative_path = variant_dest_subpath,
|
||||
)
|
||||
result.append(bundle_part)
|
||||
|
||||
for locale, variant_files in spec.named_variant_files.items():
|
||||
if not locale.endswith(".lproj"):
|
||||
fail("Keys for named variant files have to end with '.lproj' suffix, got {}".format(locale))
|
||||
result += [
|
||||
_process_apple_resource_file_if_needed(
|
||||
ctx = ctx,
|
||||
file = variant_file,
|
||||
destination = bundle_destination,
|
||||
destination_relative_path = paths.join(locale, paths.basename(variant_file.short_path)),
|
||||
)
|
||||
for variant_file in variant_files
|
||||
]
|
||||
|
||||
return result
|
||||
|
||||
def _run_ibtool(
|
||||
ctx: "context",
|
||||
raw_file: "artifact",
|
||||
output: "output_artifact",
|
||||
action_flags: [str.type],
|
||||
target_device: [None, str.type],
|
||||
action_identifier: str.type,
|
||||
output_is_dir: bool.type) -> None:
|
||||
# TODO(T110378103): detect and add minimum deployment target automatically
|
||||
# TODO(T110378113): add support for ibtool modules (turned on by `ibtool_module_flag` field of `apple_bundle` rule)
|
||||
|
||||
# Equivalent of `AppleProcessResources::BASE_IBTOOL_FLAGS` from v1
|
||||
base_flags = ["--output-format", "human-readable-text", "--notices", "--warnings", "--errors"]
|
||||
|
||||
ibtool = ctx.attrs._apple_toolchain[AppleToolchainInfo].ibtool
|
||||
ibtool_command = [ibtool] + base_flags + (ctx.attrs.ibtool_flags or [])
|
||||
if target_device != None:
|
||||
ibtool_command.extend(["--target-device", target_device])
|
||||
ibtool_command.extend(action_flags)
|
||||
if output_is_dir:
|
||||
ibtool_command.append('"$TMPDIR"')
|
||||
else:
|
||||
ibtool_command.append(output)
|
||||
ibtool_command.append(raw_file)
|
||||
|
||||
if output_is_dir:
|
||||
# Sandboxing and fs isolation on RE machines results in Xcode tools failing
|
||||
# when those are working in freshly created directories in buck-out.
|
||||
# See https://fb.workplace.com/groups/1042353022615812/permalink/1872164996301273/
|
||||
# As a workaround create a directory in tmp, use it for Xcode tools, then
|
||||
# copy the result to buck-out.
|
||||
wrapper_script, _ = ctx.actions.write(
|
||||
"ibtool_wrapper.sh",
|
||||
[
|
||||
cmd_args('export TMPDIR="$(mktemp -d)"'),
|
||||
cmd_args(cmd_args(ibtool_command), delimiter = " "),
|
||||
cmd_args(output, format = 'mkdir -p {} && cp -r "$TMPDIR"/ {}'),
|
||||
],
|
||||
allow_args = True,
|
||||
)
|
||||
command = cmd_args(["/bin/sh", wrapper_script]).hidden([ibtool_command, output])
|
||||
else:
|
||||
command = ibtool_command
|
||||
|
||||
processing_options = get_bundle_resource_processing_options(ctx)
|
||||
ctx.actions.run(command, prefer_local = processing_options.prefer_local, allow_cache_upload = processing_options.allow_cache_upload, category = "apple_ibtool", identifier = action_identifier)
|
||||
|
||||
def _compile_ui_resource(
|
||||
ctx: "context",
|
||||
raw_file: "artifact",
|
||||
output: "output_artifact",
|
||||
target_device: [None, str.type] = None,
|
||||
output_is_dir: bool.type = False) -> None:
|
||||
_run_ibtool(
|
||||
ctx = ctx,
|
||||
raw_file = raw_file,
|
||||
output = output,
|
||||
action_flags = ["--compile"],
|
||||
target_device = target_device,
|
||||
action_identifier = "compile_" + raw_file.basename,
|
||||
output_is_dir = output_is_dir,
|
||||
)
|
||||
|
||||
def _link_ui_resource(
|
||||
ctx: "context",
|
||||
raw_file: "artifact",
|
||||
output: "output_artifact",
|
||||
target_device: [None, str.type] = None,
|
||||
output_is_dir: bool.type = False) -> None:
|
||||
_run_ibtool(
|
||||
ctx = ctx,
|
||||
raw_file = raw_file,
|
||||
output = output,
|
||||
action_flags = ["--link"],
|
||||
target_device = target_device,
|
||||
action_identifier = "link_" + raw_file.basename,
|
||||
output_is_dir = output_is_dir,
|
||||
)
|
||||
|
||||
def _process_apple_resource_file_if_needed(
|
||||
ctx: "context",
|
||||
file: "artifact",
|
||||
destination: AppleBundleDestination.type,
|
||||
destination_relative_path: [str.type, None],
|
||||
codesign_on_copy: bool.type = False) -> AppleBundlePart.type:
|
||||
output_dir = "_ProcessedResources"
|
||||
basename = paths.basename(file.short_path)
|
||||
output_is_contents_dir = False
|
||||
if basename.endswith(".plist") or basename.endswith(".stringsdict"):
|
||||
processed = ctx.actions.declare_output(paths.join(output_dir, file.short_path))
|
||||
process_plist(
|
||||
ctx = ctx,
|
||||
input = file,
|
||||
output = processed.as_output(),
|
||||
action_id = destination_relative_path,
|
||||
)
|
||||
elif basename.endswith(".storyboard"):
|
||||
compiled = ctx.actions.declare_output(paths.join(output_dir, paths.replace_extension(file.short_path, ".storyboardc")))
|
||||
if get_is_watch_bundle(ctx):
|
||||
output_is_contents_dir = True
|
||||
_compile_ui_resource(ctx = ctx, raw_file = file, output = compiled.as_output(), target_device = "watch")
|
||||
processed = ctx.actions.declare_output(paths.join(output_dir, paths.replace_extension(file.short_path, "_linked_storyboard")))
|
||||
_link_ui_resource(ctx = ctx, raw_file = compiled, output = processed.as_output(), target_device = "watch", output_is_dir = True)
|
||||
else:
|
||||
processed = compiled
|
||||
_compile_ui_resource(ctx, file, processed.as_output())
|
||||
elif basename.endswith(".xib"):
|
||||
processed = ctx.actions.declare_output(paths.join(output_dir, paths.replace_extension(file.short_path, ".nib")))
|
||||
_compile_ui_resource(ctx, file, processed.as_output())
|
||||
else:
|
||||
processed = file
|
||||
|
||||
# When name is empty string only content of the directory will be copied, as opposed to the directory itself.
|
||||
# When name is `None`, directory or file will be copied as it is, without renaming.
|
||||
new_name = destination_relative_path if destination_relative_path else ("" if output_is_contents_dir else None)
|
||||
return AppleBundlePart(source = processed, destination = destination, new_name = new_name, codesign_on_copy = codesign_on_copy)
|
||||
|
||||
# Returns a path relative to the _parent_ of the lproj dir.
|
||||
# For example, given a variant file with a short path of`XX/YY.lproj/ZZ`
|
||||
# it would return `YY.lproj/ZZ`.
|
||||
def _get_dest_subpath_for_variant_file(variant_file: "artifact") -> str.type:
|
||||
dir_name = paths.basename(paths.dirname(variant_file.short_path))
|
||||
if not dir_name.endswith("lproj"):
|
||||
fail("Variant files have to be in a directory with name ending in '.lproj' but `{}` was not.".format(variant_file.short_path))
|
||||
file_name = paths.basename(variant_file.short_path)
|
||||
return paths.join(dir_name, file_name)
|
||||
|
||||
def get_is_watch_bundle(ctx: "context") -> bool.type:
|
||||
return ctx.attrs._apple_toolchain[AppleToolchainInfo].watch_kit_stub_binary != None
|
||||
31
vendor/cxx/tools/buck/prelude/apple/apple_bundle_types.bzl
vendored
Normal file
31
vendor/cxx/tools/buck/prelude/apple/apple_bundle_types.bzl
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# 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.
|
||||
|
||||
# Provider flagging that result of the rule contains Apple bundle.
|
||||
# It might be copied into main bundle to appropriate place if rule
|
||||
# with this provider is a dependency of `apple_bundle`.
|
||||
AppleBundleInfo = provider(fields = [
|
||||
# Result bundle; `artifact`
|
||||
"bundle",
|
||||
# The name of the executable within the bundle.
|
||||
# `str.type`
|
||||
"binary_name",
|
||||
# If the bundle was built for watchOS Apple platform, this affects packaging.
|
||||
# Might be omitted for certain types of bundle (e.g. frameworks) when packaging doesn't depend on it.
|
||||
# [None, `bool.type`]
|
||||
"is_watchos",
|
||||
])
|
||||
|
||||
# Provider which helps to propagate minimum deployment version up the target graph.
|
||||
AppleMinDeploymentVersionInfo = provider(fields = [
|
||||
# `str.type`
|
||||
"version",
|
||||
])
|
||||
|
||||
AppleBundleResourceInfo = provider(fields = [
|
||||
"resource_output", # AppleBundleResourcePartListOutput.type
|
||||
])
|
||||
62
vendor/cxx/tools/buck/prelude/apple/apple_bundle_utility.bzl
vendored
Normal file
62
vendor/cxx/tools/buck/prelude/apple/apple_bundle_utility.bzl
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# 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:utils.bzl", "value_or")
|
||||
load(":apple_bundle_types.bzl", "AppleMinDeploymentVersionInfo")
|
||||
load(":apple_resource_types.bzl", "AppleResourceProcessingOptions")
|
||||
load(":apple_target_sdk_version.bzl", "get_min_deployment_version_for_node")
|
||||
load(":apple_toolchain_types.bzl", "AppleToolchainInfo")
|
||||
|
||||
# `ctx` in all functions below is expected to be of `apple_bundle` or `apple_test` rule
|
||||
|
||||
def _get_bundle_target_name(ctx: "context"):
|
||||
if hasattr(ctx.attrs, "_bundle_target_name"):
|
||||
# `apple_resource_bundle` rules are proxies for the real rules,
|
||||
# so make sure we return the real target name rather the proxy one
|
||||
return ctx.attrs._bundle_target_name
|
||||
return ctx.attrs.name
|
||||
|
||||
def get_product_name(ctx: "context") -> str.type:
|
||||
return ctx.attrs.product_name if hasattr(ctx.attrs, "product_name") and ctx.attrs.product_name != None else _get_bundle_target_name(ctx)
|
||||
|
||||
def get_extension_attr(ctx: "context") -> "":
|
||||
return ctx.attrs.extension
|
||||
|
||||
# Derives the effective deployment target for the bundle. It's
|
||||
# usually the deployment target of the binary if present,
|
||||
# otherwise it falls back to other values (see implementation).
|
||||
def get_bundle_min_target_version(ctx: "context") -> str.type:
|
||||
binary_min_version = None
|
||||
|
||||
# Could be not set for e.g. watchOS bundles which have a stub
|
||||
# binary that comes from the apple_toolchain(), not from the
|
||||
# apple_bundle() itself (i.e., binary field will be None).
|
||||
#
|
||||
# TODO(T114147746): The top-level stub bundle for a watchOS app
|
||||
# does not have the ability to set its deployment target via
|
||||
# a binary (as that field is empty). If it contains asset
|
||||
# catalogs (can it?), we need to use correct target version.
|
||||
#
|
||||
# The solution might to be support SDK version from
|
||||
# Info.plist (T110378109).
|
||||
if ctx.attrs.binary != None:
|
||||
min_version_info = ctx.attrs.binary[AppleMinDeploymentVersionInfo]
|
||||
if min_version_info != None:
|
||||
binary_min_version = min_version_info.version
|
||||
|
||||
fallback_min_version = get_min_deployment_version_for_node(ctx)
|
||||
min_version = binary_min_version or fallback_min_version
|
||||
|
||||
if min_version != None:
|
||||
return min_version
|
||||
|
||||
# TODO(T110378109): support default value from SDK `Info.plist`
|
||||
fail("Could not determine min target sdk version for bundle: {}".format(ctx.label))
|
||||
|
||||
def get_bundle_resource_processing_options(ctx: "context") -> AppleResourceProcessingOptions.type:
|
||||
compile_resources_locally = value_or(ctx.attrs._compile_resources_locally_override, ctx.attrs._apple_toolchain[AppleToolchainInfo].compile_resources_locally)
|
||||
return AppleResourceProcessingOptions(prefer_local = compile_resources_locally, allow_cache_upload = compile_resources_locally)
|
||||
18
vendor/cxx/tools/buck/prelude/apple/apple_code_signing_types.bzl
vendored
Normal file
18
vendor/cxx/tools/buck/prelude/apple/apple_code_signing_types.bzl
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# 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.
|
||||
|
||||
# Provider which exposes a field from `apple_binary` to `apple_bundle` as it might be used during code signing.
|
||||
AppleEntitlementsInfo = provider(fields = [
|
||||
# Optional "artifact"
|
||||
"entitlements_file",
|
||||
])
|
||||
|
||||
CodeSignType = enum(
|
||||
"skip",
|
||||
"adhoc",
|
||||
"distribution",
|
||||
)
|
||||
69
vendor/cxx/tools/buck/prelude/apple/apple_core_data.bzl
vendored
Normal file
69
vendor/cxx/tools/buck/prelude/apple/apple_core_data.bzl
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
# 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//apple:apple_toolchain_types.bzl", "AppleToolchainInfo")
|
||||
load(":apple_bundle_utility.bzl", "get_bundle_min_target_version", "get_bundle_resource_processing_options")
|
||||
load(":apple_core_data_types.bzl", "AppleCoreDataSpec")
|
||||
load(":apple_sdk.bzl", "get_apple_sdk_name")
|
||||
load(":resource_groups.bzl", "create_resource_graph")
|
||||
|
||||
def apple_core_data_impl(ctx: "context") -> ["provider"]:
|
||||
spec = AppleCoreDataSpec(
|
||||
path = ctx.attrs.path,
|
||||
)
|
||||
graph = create_resource_graph(
|
||||
ctx = ctx,
|
||||
labels = ctx.attrs.labels,
|
||||
deps = [],
|
||||
exported_deps = [],
|
||||
core_data_spec = spec,
|
||||
)
|
||||
return [DefaultInfo(), graph]
|
||||
|
||||
def compile_apple_core_data(ctx: "context", specs: [AppleCoreDataSpec.type], product_name: str.type) -> ["artifact", None]:
|
||||
if len(specs) == 0:
|
||||
return None
|
||||
|
||||
output = ctx.actions.declare_output("AppleCoreDataCompiled")
|
||||
|
||||
# Aggregate all the coredata momc commands together
|
||||
momc_commands = []
|
||||
for spec in specs:
|
||||
momc_command = _get_momc_command(ctx, spec, product_name, cmd_args("$TMPDIR"))
|
||||
momc_commands.append(momc_command)
|
||||
|
||||
# Sandboxing and fs isolation on RE machines results in Xcode tools failing
|
||||
# when those are working in freshly created directories in buck-out.
|
||||
# See https://fb.workplace.com/groups/1042353022615812/permalink/1872164996301273/
|
||||
# As a workaround create a directory in tmp, use it for Xcode tools, then
|
||||
# copy the result to buck-out.
|
||||
wrapper_script, _ = ctx.actions.write(
|
||||
"momc_wrapper.sh",
|
||||
[
|
||||
cmd_args('export TMPDIR="$(mktemp -d)"'),
|
||||
cmd_args(momc_commands),
|
||||
cmd_args(output, format = 'mkdir -p {} && cp -r "$TMPDIR"/ {}'),
|
||||
],
|
||||
allow_args = True,
|
||||
)
|
||||
combined_command = cmd_args(["/bin/sh", wrapper_script]).hidden(momc_commands + [output.as_output()])
|
||||
processing_options = get_bundle_resource_processing_options(ctx)
|
||||
ctx.actions.run(combined_command, prefer_local = processing_options.prefer_local, allow_cache_upload = processing_options.allow_cache_upload, category = "apple_core_data")
|
||||
return output
|
||||
|
||||
def _get_momc_command(ctx: "context", core_data_spec: AppleCoreDataSpec.type, product_name: str.type, output_directory: "cmd_args") -> "cmd_args":
|
||||
return cmd_args([
|
||||
ctx.attrs._apple_toolchain[AppleToolchainInfo].momc,
|
||||
"--sdkroot",
|
||||
ctx.attrs._apple_toolchain[AppleToolchainInfo].sdk_path,
|
||||
"--" + get_apple_sdk_name(ctx) + "-deployment-target",
|
||||
get_bundle_min_target_version(ctx),
|
||||
"--module",
|
||||
product_name,
|
||||
core_data_spec.path,
|
||||
output_directory,
|
||||
], delimiter = " ")
|
||||
10
vendor/cxx/tools/buck/prelude/apple/apple_core_data_types.bzl
vendored
Normal file
10
vendor/cxx/tools/buck/prelude/apple/apple_core_data_types.bzl
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# 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.
|
||||
|
||||
AppleCoreDataSpec = record(
|
||||
path = field("artifact"),
|
||||
)
|
||||
35
vendor/cxx/tools/buck/prelude/apple/apple_dsym.bzl
vendored
Normal file
35
vendor/cxx/tools/buck/prelude/apple/apple_dsym.bzl
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# 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//apple:apple_toolchain_types.bzl", "AppleToolchainInfo")
|
||||
|
||||
DSYM_SUBTARGET = "dsym"
|
||||
DEBUGINFO_SUBTARGET = "debuginfo"
|
||||
|
||||
AppleDebuggableInfo = provider(fields = [
|
||||
"dsyms", # ["artifact"]
|
||||
"external_debug_info", # ["_arglike"]
|
||||
])
|
||||
|
||||
# TODO(T110672942): Things which are still unsupported:
|
||||
# - pass in dsymutil_extra_flags
|
||||
# - oso_prefix
|
||||
# - dsym_verification
|
||||
def get_apple_dsym(ctx: "context", executable: "artifact", external_debug_info: ["_arglike"], action_identifier: "string") -> "artifact":
|
||||
dsymutil = ctx.attrs._apple_toolchain[AppleToolchainInfo].dsymutil
|
||||
output = ctx.actions.declare_output("{}.dSYM".format(executable.short_path))
|
||||
|
||||
cmd = cmd_args([dsymutil, "-o", output.as_output(), executable])
|
||||
|
||||
# Mach-O executables don't contain DWARF data.
|
||||
# Instead, they contain paths to the object files which themselves contain DWARF data.
|
||||
#
|
||||
# So, those object files are needed for dsymutil to be to create the dSYM bundle.
|
||||
cmd.hidden(external_debug_info)
|
||||
ctx.actions.run(cmd, category = "apple_dsym", identifier = action_identifier)
|
||||
|
||||
return output
|
||||
1062
vendor/cxx/tools/buck/prelude/apple/apple_framework_versions.bzl
vendored
Normal file
1062
vendor/cxx/tools/buck/prelude/apple/apple_framework_versions.bzl
vendored
Normal file
File diff suppressed because it is too large
Load diff
165
vendor/cxx/tools/buck/prelude/apple/apple_frameworks.bzl
vendored
Normal file
165
vendor/cxx/tools/buck/prelude/apple/apple_frameworks.bzl
vendored
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
# 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//:paths.bzl", "paths")
|
||||
load(
|
||||
"@prelude//linking:link_info.bzl",
|
||||
"FrameworksLinkable",
|
||||
"LinkArgs",
|
||||
"LinkInfo",
|
||||
"LinkInfos",
|
||||
"LinkInfosTSet",
|
||||
"LinkableType",
|
||||
"get_link_args",
|
||||
"merge_framework_linkables",
|
||||
)
|
||||
load("@prelude//utils:utils.bzl", "expect")
|
||||
load(":apple_framework_versions.bzl", "get_framework_linker_args")
|
||||
load(":apple_toolchain_types.bzl", "AppleToolchainInfo")
|
||||
|
||||
_IMPLICIT_SDKROOT_FRAMEWORK_SEARCH_PATHS = [
|
||||
"$SDKROOT/Library/Frameworks",
|
||||
"$SDKROOT/System/Library/Frameworks",
|
||||
]
|
||||
|
||||
def create_frameworks_linkable(ctx: "context") -> [FrameworksLinkable.type, None]:
|
||||
if not ctx.attrs.libraries and not ctx.attrs.frameworks:
|
||||
return None
|
||||
|
||||
return FrameworksLinkable(
|
||||
library_names = [_library_name(x) for x in ctx.attrs.libraries],
|
||||
unresolved_framework_paths = _get_non_sdk_unresolved_framework_directories(ctx.attrs.frameworks),
|
||||
framework_names = [to_framework_name(x) for x in ctx.attrs.frameworks],
|
||||
)
|
||||
|
||||
def _get_apple_frameworks_linker_flags(ctx: "context", linkable: [FrameworksLinkable.type, None]) -> "cmd_args":
|
||||
if not linkable:
|
||||
return cmd_args()
|
||||
|
||||
expanded_frameworks_paths = _expand_sdk_framework_paths(ctx, linkable.unresolved_framework_paths)
|
||||
flags = _get_framework_search_path_flags(expanded_frameworks_paths)
|
||||
flags.add(get_framework_linker_args(ctx, linkable.framework_names))
|
||||
|
||||
for library_name in linkable.library_names:
|
||||
flags.add("-l" + library_name)
|
||||
|
||||
return flags
|
||||
|
||||
def get_framework_search_path_flags(ctx: "context") -> "cmd_args":
|
||||
unresolved_framework_dirs = _get_non_sdk_unresolved_framework_directories(ctx.attrs.frameworks)
|
||||
expanded_framework_dirs = _expand_sdk_framework_paths(ctx, unresolved_framework_dirs)
|
||||
return _get_framework_search_path_flags(expanded_framework_dirs)
|
||||
|
||||
def _get_framework_search_path_flags(frameworks: ["cmd_args"]) -> "cmd_args":
|
||||
flags = cmd_args()
|
||||
for directory in frameworks:
|
||||
flags.add(["-F", directory])
|
||||
|
||||
return flags
|
||||
|
||||
def _get_non_sdk_unresolved_framework_directories(frameworks: [""]) -> [""]:
|
||||
# We don't want to include SDK directories as those are already added via `isysroot` flag in toolchain definition.
|
||||
# Adding those directly via `-F` will break building Catalyst applications as frameworks from support directory
|
||||
# won't be found and those for macOS platform will be used.
|
||||
return dedupe(filter(None, [_non_sdk_unresolved_framework_directory(x) for x in frameworks]))
|
||||
|
||||
def to_framework_name(framework_path: str.type) -> str.type:
|
||||
name, ext = paths.split_extension(paths.basename(framework_path))
|
||||
expect(ext == ".framework", "framework `{}` missing `.framework` suffix", framework_path)
|
||||
return name
|
||||
|
||||
def _library_name(library: str.type) -> str.type:
|
||||
name = paths.basename(library)
|
||||
if not name.startswith("lib"):
|
||||
fail("unexpected library: {}".format(library))
|
||||
return paths.split_extension(name[3:])[0]
|
||||
|
||||
def _expand_sdk_framework_paths(ctx: "context", unresolved_framework_paths: [str.type]) -> ["cmd_args"]:
|
||||
return [_expand_sdk_framework_path(ctx, unresolved_framework_path) for unresolved_framework_path in unresolved_framework_paths]
|
||||
|
||||
def _expand_sdk_framework_path(ctx: "context", framework_path: str.type) -> "cmd_args":
|
||||
apple_toolchain_info = ctx.attrs._apple_toolchain[AppleToolchainInfo]
|
||||
path_expansion_map = {
|
||||
"$PLATFORM_DIR/": apple_toolchain_info.platform_path,
|
||||
"$SDKROOT/": apple_toolchain_info.sdk_path,
|
||||
}
|
||||
|
||||
for (trailing_path_variable, path_value) in path_expansion_map.items():
|
||||
(before, separator, relative_path) = framework_path.partition(trailing_path_variable)
|
||||
if separator == trailing_path_variable:
|
||||
if len(before) > 0:
|
||||
fail("Framework symbolic path not anchored at the beginning, tried expanding `{}`".format(framework_path))
|
||||
if relative_path.count("$") > 0:
|
||||
fail("Framework path contains multiple symbolic paths, tried expanding `{}`".format(framework_path))
|
||||
if len(relative_path) == 0:
|
||||
fail("Framework symbolic path contains no relative path to expand, tried expanding `{}`, relative path: `{}`, before: `{}`, separator `{}`".format(framework_path, relative_path, before, separator))
|
||||
|
||||
return cmd_args([path_value, relative_path], delimiter = "/")
|
||||
|
||||
if framework_path.find("$") == 0:
|
||||
fail("Failed to expand framework path: {}".format(framework_path))
|
||||
|
||||
return cmd_args(framework_path)
|
||||
|
||||
def _non_sdk_unresolved_framework_directory(framework_path: str.type) -> [str.type, None]:
|
||||
# We must only drop any framework paths that are part of the implicit
|
||||
# framework search paths in the linker + compiler, all other paths
|
||||
# must be expanded and included as part of the command.
|
||||
for implicit_search_path in _IMPLICIT_SDKROOT_FRAMEWORK_SEARCH_PATHS:
|
||||
if framework_path.find(implicit_search_path) == 0:
|
||||
return None
|
||||
return paths.dirname(framework_path)
|
||||
|
||||
def build_link_args_with_deduped_framework_flags(
|
||||
ctx: "context",
|
||||
info: "MergedLinkInfo",
|
||||
frameworks_linkable: ["FrameworksLinkable", None],
|
||||
link_style: "LinkStyle",
|
||||
prefer_stripped: bool.type = False) -> LinkArgs.type:
|
||||
frameworks_link_info = _link_info_from_frameworks_linkable(ctx, [info.frameworks[link_style], frameworks_linkable])
|
||||
if not frameworks_link_info:
|
||||
return get_link_args(info, link_style, prefer_stripped)
|
||||
|
||||
return LinkArgs(
|
||||
tset = (ctx.actions.tset(
|
||||
LinkInfosTSet,
|
||||
value = LinkInfos(default = frameworks_link_info, stripped = frameworks_link_info),
|
||||
children = [info._infos[link_style]],
|
||||
), prefer_stripped),
|
||||
)
|
||||
|
||||
def get_frameworks_link_info_by_deduping_link_infos(
|
||||
ctx: "context",
|
||||
infos: [[LinkInfo.type, None]],
|
||||
framework_linkable: [FrameworksLinkable.type, None]) -> [LinkInfo.type, None]:
|
||||
# When building a framework or executable, all frameworks used by the statically-linked
|
||||
# deps in the subtree need to be linked.
|
||||
#
|
||||
# Without deduping, we've seen the linking step fail because the argsfile
|
||||
# exceeds the acceptable size by the linker.
|
||||
framework_linkables = _extract_framework_linkables(infos)
|
||||
if framework_linkable:
|
||||
framework_linkables.append(framework_linkable)
|
||||
|
||||
return _link_info_from_frameworks_linkable(ctx, framework_linkables)
|
||||
|
||||
def _extract_framework_linkables(link_infos: [[LinkInfo.type], None]) -> [FrameworksLinkable.type]:
|
||||
frameworks_type = LinkableType("frameworks")
|
||||
|
||||
linkables = []
|
||||
for info in link_infos:
|
||||
for linkable in info.linkables:
|
||||
if linkable._type == frameworks_type:
|
||||
linkables.append(linkable)
|
||||
|
||||
return linkables
|
||||
|
||||
def _link_info_from_frameworks_linkable(ctx: "context", framework_linkables: [[FrameworksLinkable.type, None]]) -> [LinkInfo.type, None]:
|
||||
framework_link_args = _get_apple_frameworks_linker_flags(ctx, merge_framework_linkables(framework_linkables))
|
||||
return LinkInfo(
|
||||
pre_flags = [framework_link_args],
|
||||
) if framework_link_args else None
|
||||
139
vendor/cxx/tools/buck/prelude/apple/apple_info_plist.bzl
vendored
Normal file
139
vendor/cxx/tools/buck/prelude/apple/apple_info_plist.bzl
vendored
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
# 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(":apple_bundle_destination.bzl", "AppleBundleDestination")
|
||||
load(":apple_bundle_part.bzl", "AppleBundlePart")
|
||||
load(":apple_bundle_utility.bzl", "get_bundle_min_target_version", "get_product_name")
|
||||
load(":apple_sdk.bzl", "get_apple_sdk_name")
|
||||
load(
|
||||
":apple_sdk_metadata.bzl",
|
||||
"AppleSdkMetadata", # @unused Used as a type
|
||||
"MacOSXCatalystSdkMetadata",
|
||||
"MacOSXSdkMetadata",
|
||||
"WatchOSSdkMetadata",
|
||||
"WatchSimulatorSdkMetadata",
|
||||
"get_apple_sdk_metadata_for_sdk_name",
|
||||
)
|
||||
load(":apple_toolchain_types.bzl", "AppleToolchainInfo", "AppleToolsInfo")
|
||||
|
||||
def process_info_plist(ctx: "context", override_input: ["artifact", None]) -> AppleBundlePart.type:
|
||||
input = _preprocess_info_plist(ctx)
|
||||
output = ctx.actions.declare_output("Info.plist")
|
||||
additional_keys = _additional_keys_as_json_file(ctx)
|
||||
override_keys = _override_keys_as_json_file(ctx)
|
||||
process_plist(
|
||||
ctx = ctx,
|
||||
input = input,
|
||||
output = output.as_output(),
|
||||
override_input = override_input,
|
||||
additional_keys = additional_keys,
|
||||
override_keys = override_keys,
|
||||
)
|
||||
return AppleBundlePart(source = output, destination = AppleBundleDestination("metadata"))
|
||||
|
||||
def _get_plist_run_options() -> {str.type: bool.type}:
|
||||
return {
|
||||
# Output is deterministic, so can be cached
|
||||
"allow_cache_upload": True,
|
||||
# plist generation is cheap and fast, RE network overhead not worth it
|
||||
"prefer_local": True,
|
||||
}
|
||||
|
||||
def _preprocess_info_plist(ctx: "context") -> "artifact":
|
||||
input = ctx.attrs.info_plist
|
||||
output = ctx.actions.declare_output("PreprocessedInfo.plist")
|
||||
substitutions_json = _plist_substitutions_as_json_file(ctx)
|
||||
apple_tools = ctx.attrs._apple_tools[AppleToolsInfo]
|
||||
processor = apple_tools.info_plist_processor
|
||||
command = cmd_args([
|
||||
processor,
|
||||
"preprocess",
|
||||
"--input",
|
||||
input,
|
||||
"--output",
|
||||
output.as_output(),
|
||||
"--product-name",
|
||||
get_product_name(ctx),
|
||||
])
|
||||
if substitutions_json != None:
|
||||
command.add(["--substitutions-json", substitutions_json])
|
||||
ctx.actions.run(command, category = "apple_preprocess_info_plist", **_get_plist_run_options())
|
||||
return output
|
||||
|
||||
def _plist_substitutions_as_json_file(ctx: "context") -> ["artifact", None]:
|
||||
info_plist_substitutions = ctx.attrs.info_plist_substitutions
|
||||
if not info_plist_substitutions:
|
||||
return None
|
||||
|
||||
substitutions_json = ctx.actions.write_json("plist_substitutions.json", info_plist_substitutions)
|
||||
return substitutions_json
|
||||
|
||||
def process_plist(ctx: "context", input: "artifact", output: "output_artifact", override_input: ["artifact", None] = None, additional_keys: ["artifact", None] = None, override_keys: ["artifact", None] = None, action_id: [str.type, None] = None):
|
||||
apple_tools = ctx.attrs._apple_tools[AppleToolsInfo]
|
||||
processor = apple_tools.info_plist_processor
|
||||
override_input_arguments = ["--override-input", override_input] if override_input != None else []
|
||||
additional_keys_arguments = ["--additional-keys", additional_keys] if additional_keys != None else []
|
||||
override_keys_arguments = ["--override-keys", override_keys] if override_keys != None else []
|
||||
command = cmd_args([
|
||||
processor,
|
||||
"process",
|
||||
"--input",
|
||||
input,
|
||||
"--output",
|
||||
output,
|
||||
] + override_input_arguments + additional_keys_arguments + override_keys_arguments)
|
||||
ctx.actions.run(command, category = "apple_process_info_plist", identifier = action_id or input.basename, **_get_plist_run_options())
|
||||
|
||||
def _additional_keys_as_json_file(ctx: "context") -> "artifact":
|
||||
additional_keys = _info_plist_additional_keys(ctx)
|
||||
return ctx.actions.write_json("plist_additional.json", additional_keys)
|
||||
|
||||
def _info_plist_additional_keys(ctx: "context") -> {str.type: ""}:
|
||||
sdk_name = get_apple_sdk_name(ctx)
|
||||
sdk_metadata = get_apple_sdk_metadata_for_sdk_name(sdk_name)
|
||||
result = _extra_mac_info_plist_keys(sdk_metadata, ctx.attrs.extension)
|
||||
result["CFBundleSupportedPlatforms"] = sdk_metadata.info_plist_supported_platforms_values
|
||||
result["DTPlatformName"] = sdk_name
|
||||
sdk_version = ctx.attrs._apple_toolchain[AppleToolchainInfo].sdk_version
|
||||
if sdk_version:
|
||||
result["DTPlatformVersion"] = sdk_version
|
||||
result["DTSDKName"] = sdk_name + sdk_version
|
||||
sdk_build_version = ctx.attrs._apple_toolchain[AppleToolchainInfo].sdk_build_version
|
||||
if sdk_build_version:
|
||||
result["DTPlatformBuild"] = sdk_build_version
|
||||
result["DTSDKBuild"] = sdk_build_version
|
||||
xcode_build_version = ctx.attrs._apple_toolchain[AppleToolchainInfo].xcode_build_version
|
||||
if xcode_build_version:
|
||||
result["DTXcodeBuild"] = xcode_build_version
|
||||
xcode_version = ctx.attrs._apple_toolchain[AppleToolchainInfo].xcode_version
|
||||
if xcode_version:
|
||||
result["DTXcode"] = xcode_version
|
||||
result[sdk_metadata.min_version_plist_info_key] = get_bundle_min_target_version(ctx)
|
||||
return result
|
||||
|
||||
def _extra_mac_info_plist_keys(sdk_metadata: AppleSdkMetadata.type, extension: str.type) -> {str.type: ""}:
|
||||
if sdk_metadata.name == MacOSXSdkMetadata.name and extension == "xpc":
|
||||
return {
|
||||
"NSHighResolutionCapable": True,
|
||||
"NSSupportsAutomaticGraphicsSwitching": True,
|
||||
}
|
||||
else:
|
||||
return {}
|
||||
|
||||
def _override_keys_as_json_file(ctx: "context") -> "artifact":
|
||||
override_keys = _info_plist_override_keys(ctx)
|
||||
return ctx.actions.write_json("plist_override.json", override_keys)
|
||||
|
||||
def _info_plist_override_keys(ctx: "context") -> {str.type: ""}:
|
||||
sdk_name = get_apple_sdk_name(ctx)
|
||||
result = {}
|
||||
if sdk_name == MacOSXSdkMetadata.name:
|
||||
if ctx.attrs.extension != "xpc":
|
||||
result["LSRequiresIPhoneOS"] = False
|
||||
elif sdk_name not in [WatchOSSdkMetadata.name, WatchSimulatorSdkMetadata.name, MacOSXCatalystSdkMetadata.name]:
|
||||
result["LSRequiresIPhoneOS"] = True
|
||||
return result
|
||||
60
vendor/cxx/tools/buck/prelude/apple/apple_info_plist_substitutions_parsing.bzl
vendored
Normal file
60
vendor/cxx/tools/buck/prelude/apple/apple_info_plist_substitutions_parsing.bzl
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# 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.
|
||||
|
||||
# `apple_bundle.info_plist_substitutions` might contain `CODE_SIGN_ENTITLEMENTS` key which (as per v1 documentation):
|
||||
#
|
||||
# > Code signing will embed entitlements pointed to by the entitlements_file arg in the bundle's apple_binary.
|
||||
# > This is the preferred way to specify entitlements when building with Buck.
|
||||
# > If the entitlements file is not present, it falls back to the CODE_SIGN_ENTITLEMENTS entry in info_plist_substitutions.
|
||||
#
|
||||
# In order to properly depend on this fallback entitlements file (and manipulate it) we have to convert this text entry into the source artifact.
|
||||
# We only can do that on macro layer, hence the purpose of the following code.
|
||||
|
||||
_SOURCE_ROOT_PREFIX = "$(SOURCE_ROOT)/"
|
||||
_CODE_SIGN_ENTITLEMENTS_KEY = "CODE_SIGN_ENTITLEMENTS"
|
||||
|
||||
def _find_first_variable(string: str.type) -> [(str.type, (str.type, str.type)), None]:
|
||||
"""
|
||||
If variable like `$(FOO)` is not found in `string` returns `None`, else returns tuple
|
||||
with first element equal to variable name (e.g. `FOO`) and second element equal to tuple
|
||||
of part before and after this variable.
|
||||
"""
|
||||
expansion_start = "$("
|
||||
expansion_end = ")"
|
||||
variable_start = string.find(expansion_start)
|
||||
if variable_start == -1:
|
||||
return None
|
||||
variable_end = string.find(expansion_end, variable_start)
|
||||
if variable_end == -1:
|
||||
fail("Expected variable expansion in string: `{}`".format(string))
|
||||
variable = string[variable_start + len(expansion_start):variable_end - len(expansion_end) + 1]
|
||||
prefix = string[:variable_start]
|
||||
suffix = string[variable_end + 1:]
|
||||
return (variable, (prefix, suffix))
|
||||
|
||||
def _expand_codesign_entitlements_path(info_plist_substitutions: {str.type: str.type}, path: str.type) -> str.type:
|
||||
path = path.strip()
|
||||
for _ in range(100):
|
||||
if path.startswith(_SOURCE_ROOT_PREFIX):
|
||||
path = path[len(_SOURCE_ROOT_PREFIX):]
|
||||
maybe_variable = _find_first_variable(path)
|
||||
if not maybe_variable:
|
||||
return path
|
||||
(key, (prefix, suffix)) = maybe_variable
|
||||
maybe_value = info_plist_substitutions.get(key)
|
||||
if not maybe_value:
|
||||
fail("Expected to find value for `{}` in `info_plist_substitutions` dictionary `{}`".format(key, info_plist_substitutions))
|
||||
path = prefix + maybe_value + suffix
|
||||
fail("Too many iteration (loop might be present) to expand `{}` with substitutions `{}`".format(path, info_plist_substitutions))
|
||||
|
||||
def parse_codesign_entitlements(info_plist_substitutions: [{str.type: str.type}, None]) -> [str.type, None]:
|
||||
if not info_plist_substitutions:
|
||||
return None
|
||||
maybe_path = info_plist_substitutions.get(_CODE_SIGN_ENTITLEMENTS_KEY)
|
||||
if not maybe_path:
|
||||
return None
|
||||
return _expand_codesign_entitlements_path(info_plist_substitutions, maybe_path)
|
||||
216
vendor/cxx/tools/buck/prelude/apple/apple_library.bzl
vendored
Normal file
216
vendor/cxx/tools/buck/prelude/apple/apple_library.bzl
vendored
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
# 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//apple:apple_dsym.bzl", "AppleDebuggableInfo", "DEBUGINFO_SUBTARGET", "DSYM_SUBTARGET", "get_apple_dsym")
|
||||
load("@prelude//apple:apple_stripping.bzl", "apple_strip_args")
|
||||
load("@prelude//apple:swift_compilation.bzl", "compile_swift", "get_swift_dependency_info", "get_swift_pcm_compile_info")
|
||||
load("@prelude//cxx:cxx.bzl", "get_srcs_with_flags")
|
||||
load("@prelude//cxx:cxx_library.bzl", "cxx_library_parameterized")
|
||||
load("@prelude//cxx:cxx_library_utility.bzl", "cxx_attr_deps", "cxx_attr_exported_deps")
|
||||
load("@prelude//cxx:cxx_types.bzl", "CxxRuleAdditionalParams", "CxxRuleConstructorParams", "CxxRuleProviderParams", "CxxRuleSubTargetParams")
|
||||
load("@prelude//cxx:headers.bzl", "cxx_attr_exported_headers")
|
||||
load(
|
||||
"@prelude//cxx:linker.bzl",
|
||||
"SharedLibraryFlagOverrides",
|
||||
)
|
||||
load(
|
||||
"@prelude//cxx:preprocessor.bzl",
|
||||
"CPreprocessor",
|
||||
)
|
||||
load("@prelude//linking:link_info.bzl", "LinkStyle")
|
||||
load(":apple_bundle_types.bzl", "AppleMinDeploymentVersionInfo")
|
||||
load(":apple_frameworks.bzl", "get_framework_search_path_flags")
|
||||
load(":apple_link_postprocessor.bzl", "get_apple_link_postprocessor")
|
||||
load(":apple_modular_utility.bzl", "MODULE_CACHE_PATH")
|
||||
load(":apple_target_sdk_version.bzl", "get_min_deployment_version_for_node", "get_min_deployment_version_target_linker_flags", "get_min_deployment_version_target_preprocessor_flags")
|
||||
load(":apple_utility.bzl", "get_apple_cxx_headers_layout", "get_module_name")
|
||||
load(":modulemap.bzl", "preprocessor_info_for_modulemap")
|
||||
load(":resource_groups.bzl", "create_resource_graph")
|
||||
load(":xcode.bzl", "apple_populate_xcode_attributes")
|
||||
|
||||
AppleLibraryAdditionalParams = record(
|
||||
# Name of the top level rule utilizing the apple_library rule.
|
||||
rule_type = str.type,
|
||||
# Extra flags to be passed to the linker.
|
||||
extra_exported_link_flags = field(["_arglike"], []),
|
||||
# Extra flags to be passed to the Swift compiler.
|
||||
extra_swift_compiler_flags = field(["_arglike"], []),
|
||||
# Linker flags that tell the linker to create shared libraries, overriding the default shared library flags.
|
||||
# e.g. when building Apple tests, we want to link with `-bundle` instead of `-shared` to allow
|
||||
# linking against the bundle loader.
|
||||
shared_library_flags = field([SharedLibraryFlagOverrides.type, None], None),
|
||||
# Function to use for setting Xcode attributes for the Xcode data sub target.
|
||||
populate_xcode_attributes_func = field("function", apple_populate_xcode_attributes),
|
||||
# Define which sub targets to generate.
|
||||
generate_sub_targets = field(CxxRuleSubTargetParams.type, CxxRuleSubTargetParams()),
|
||||
# Define which providers to generate.
|
||||
generate_providers = field(CxxRuleProviderParams.type, CxxRuleProviderParams()),
|
||||
# Forces link group linking logic, even when there's no mapping. Link group linking
|
||||
# without a mapping is equivalent to statically linking the whole transitive dep graph.
|
||||
force_link_group_linking = field(bool.type, False),
|
||||
)
|
||||
|
||||
def apple_library_impl(ctx: "context") -> ["provider"]:
|
||||
constructor_params, swift_providers, exported_pre = apple_library_rule_constructor_params_and_swift_providers(ctx, AppleLibraryAdditionalParams(rule_type = "apple_library"))
|
||||
|
||||
resource_graph = create_resource_graph(
|
||||
ctx = ctx,
|
||||
labels = ctx.attrs.labels,
|
||||
deps = cxx_attr_deps(ctx),
|
||||
exported_deps = cxx_attr_exported_deps(ctx),
|
||||
)
|
||||
|
||||
output = cxx_library_parameterized(ctx, constructor_params)
|
||||
swift_pcm_compile = get_swift_pcm_compile_info(ctx, output.propagated_exported_preprocessor_info, exported_pre)
|
||||
|
||||
providers = output.providers + [resource_graph] + swift_providers + ([swift_pcm_compile] if swift_pcm_compile else [])
|
||||
return providers
|
||||
|
||||
def apple_library_rule_constructor_params_and_swift_providers(ctx: "context", params: AppleLibraryAdditionalParams.type) -> (CxxRuleConstructorParams.type, ["provider"], [CPreprocessor.type, None]):
|
||||
cxx_srcs, swift_srcs = _filter_swift_srcs(ctx)
|
||||
|
||||
# First create a modulemap if necessary. This is required for importing
|
||||
# ObjC code in Swift so must be done before Swift compilation.
|
||||
exported_hdrs = cxx_attr_exported_headers(ctx, get_apple_cxx_headers_layout(ctx))
|
||||
if (ctx.attrs.modular or swift_srcs) and exported_hdrs:
|
||||
modulemap_pre = preprocessor_info_for_modulemap(ctx, "exported", exported_hdrs, None)
|
||||
else:
|
||||
modulemap_pre = None
|
||||
|
||||
swift_compile = compile_swift(ctx, swift_srcs, exported_hdrs, modulemap_pre, params.extra_swift_compiler_flags)
|
||||
swift_object_files = swift_compile.object_files if swift_compile else []
|
||||
|
||||
swift_pre = CPreprocessor()
|
||||
if swift_compile:
|
||||
# If we have Swift we export the extended modulemap that includes
|
||||
# the ObjC exported headers and the -Swift.h header.
|
||||
exported_pre = swift_compile.exported_pre
|
||||
|
||||
# We also include the -Swift.h header to this libraries preprocessor
|
||||
# info, so that we can import it unprefixed in this module.
|
||||
swift_pre = swift_compile.pre
|
||||
elif modulemap_pre:
|
||||
# Otherwise if this library is modular we export a modulemap of
|
||||
# the ObjC exported headers.
|
||||
exported_pre = modulemap_pre
|
||||
else:
|
||||
exported_pre = None
|
||||
|
||||
swift_providers = swift_compile.providers if swift_compile else [get_swift_dependency_info(ctx, exported_pre, None)]
|
||||
swift_argsfile = swift_compile.swift_argsfile if swift_compile else None
|
||||
|
||||
modular_pre = CPreprocessor(
|
||||
uses_modules = ctx.attrs.uses_modules,
|
||||
modular_args = [
|
||||
"-fcxx-modules",
|
||||
"-fmodules",
|
||||
"-fmodule-name=" + get_module_name(ctx),
|
||||
"-fmodules-cache-path=" + MODULE_CACHE_PATH,
|
||||
# TODO(T123756899): We have to use this hack to make compilation work
|
||||
# when Clang modules are enabled and using toolchains. That's because
|
||||
# resource-dir is passed as a relative path (so that no abs paths appear
|
||||
# in any .pcm). The compiler will then expand and generate #include paths
|
||||
# that won't work unless we have the directive below.
|
||||
"-I.",
|
||||
],
|
||||
)
|
||||
|
||||
framework_search_path_pre = CPreprocessor(
|
||||
args = [get_framework_search_path_flags(ctx)],
|
||||
)
|
||||
return CxxRuleConstructorParams(
|
||||
rule_type = params.rule_type,
|
||||
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_link_flags = [_get_linker_flags(ctx, swift_providers)],
|
||||
extra_link_input = swift_object_files,
|
||||
extra_preprocessors = get_min_deployment_version_target_preprocessor_flags(ctx) + [framework_search_path_pre, swift_pre, modular_pre],
|
||||
extra_exported_preprocessors = filter(None, [exported_pre]),
|
||||
srcs = cxx_srcs,
|
||||
additional = CxxRuleAdditionalParams(
|
||||
srcs = swift_srcs,
|
||||
argsfiles = [swift_argsfile] if swift_argsfile else [],
|
||||
# We need to add any swift modules that we include in the link, as
|
||||
# these will end up as `N_AST` entries that `dsymutil` will need to
|
||||
# follow.
|
||||
external_debug_info = [_get_transitive_swiftmodule_paths(swift_providers)],
|
||||
),
|
||||
link_style_sub_targets_and_providers_factory = _get_shared_link_style_sub_targets_and_providers,
|
||||
shared_library_flags = params.shared_library_flags,
|
||||
# apple_library's 'stripped' arg only applies to shared subtargets, or,
|
||||
# targets with 'preferred_linkage = "shared"'
|
||||
strip_executable = ctx.attrs.stripped,
|
||||
strip_args_factory = apple_strip_args,
|
||||
force_link_group_linking = params.force_link_group_linking,
|
||||
cxx_populate_xcode_attributes_func = lambda local_ctx, **kwargs: _xcode_populate_attributes(ctx = local_ctx, swift_argsfile = swift_argsfile, populate_xcode_attributes_func = params.populate_xcode_attributes_func, **kwargs),
|
||||
generate_sub_targets = params.generate_sub_targets,
|
||||
generate_providers = params.generate_providers,
|
||||
link_postprocessor = get_apple_link_postprocessor(ctx),
|
||||
), swift_providers, exported_pre
|
||||
|
||||
def _filter_swift_srcs(ctx: "context") -> (["CxxSrcWithFlags"], ["CxxSrcWithFlags"]):
|
||||
cxx_srcs = []
|
||||
swift_srcs = []
|
||||
for s in get_srcs_with_flags(ctx):
|
||||
if s.file.extension == ".swift":
|
||||
swift_srcs.append(s)
|
||||
else:
|
||||
cxx_srcs.append(s)
|
||||
|
||||
return cxx_srcs, swift_srcs
|
||||
|
||||
def _get_shared_link_style_sub_targets_and_providers(
|
||||
link_style: LinkStyle.type,
|
||||
ctx: "context",
|
||||
executable: "artifact",
|
||||
external_debug_info: ["_arglike"],
|
||||
_dwp: ["artifact", None]) -> ({str.type: ["provider"]}, ["provider"]):
|
||||
if link_style != LinkStyle("shared"):
|
||||
return ({}, [])
|
||||
|
||||
min_version = get_min_deployment_version_for_node(ctx)
|
||||
min_version_providers = [AppleMinDeploymentVersionInfo(version = min_version)] if min_version != None else []
|
||||
|
||||
dsym_artifact = get_apple_dsym(
|
||||
ctx = ctx,
|
||||
executable = executable,
|
||||
external_debug_info = external_debug_info,
|
||||
action_identifier = executable.short_path,
|
||||
)
|
||||
return ({
|
||||
DSYM_SUBTARGET: [DefaultInfo(default_outputs = [dsym_artifact])],
|
||||
DEBUGINFO_SUBTARGET: [DefaultInfo(other_outputs = external_debug_info)],
|
||||
}, [AppleDebuggableInfo(dsyms = [dsym_artifact], external_debug_info = external_debug_info)] + min_version_providers)
|
||||
|
||||
def _get_transitive_swiftmodule_paths(swift_providers: ["provider"]) -> "cmd_args":
|
||||
cmd = cmd_args()
|
||||
for p in swift_providers:
|
||||
if hasattr(p, "transitive_swiftmodule_paths"):
|
||||
cmd.add(p.transitive_swiftmodule_paths.project_as_args("hidden"))
|
||||
return cmd
|
||||
|
||||
def _get_linker_flags(ctx: "context", swift_providers: ["provider"]) -> "cmd_args":
|
||||
cmd = cmd_args(get_min_deployment_version_target_linker_flags(ctx))
|
||||
for p in swift_providers:
|
||||
if hasattr(p, "transitive_swiftmodule_paths"):
|
||||
cmd.add(p.transitive_swiftmodule_paths.project_as_args("linker_args"))
|
||||
|
||||
return cmd
|
||||
|
||||
def _xcode_populate_attributes(
|
||||
ctx,
|
||||
srcs: ["CxxSrcWithFlags"],
|
||||
argsfiles_by_ext: {str.type: "artifact"},
|
||||
swift_argsfile: ["CxxAdditionalArgsfileParams", None],
|
||||
populate_xcode_attributes_func: "function",
|
||||
**_kwargs) -> {str.type: ""}:
|
||||
if swift_argsfile:
|
||||
argsfiles_by_ext[swift_argsfile.extension] = swift_argsfile.file
|
||||
|
||||
data = populate_xcode_attributes_func(ctx, srcs = srcs, argsfiles_by_ext = argsfiles_by_ext, product_name = ctx.attrs.name)
|
||||
return data
|
||||
11
vendor/cxx/tools/buck/prelude/apple/apple_link_postprocessor.bzl
vendored
Normal file
11
vendor/cxx/tools/buck/prelude/apple/apple_link_postprocessor.bzl
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# 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.
|
||||
|
||||
def get_apple_link_postprocessor(ctx):
|
||||
if ctx.attrs.link_postprocessor:
|
||||
return cmd_args(ctx.attrs.link_postprocessor[RunInfo])
|
||||
return None
|
||||
43
vendor/cxx/tools/buck/prelude/apple/apple_macro_layer.bzl
vendored
Normal file
43
vendor/cxx/tools/buck/prelude/apple/apple_macro_layer.bzl
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# 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(
|
||||
":apple_rules_impl_utility.bzl",
|
||||
"APPLE_ARCHIVE_OBJECTS_LOCALLY_OVERRIDE_ATTR_NAME",
|
||||
"APPLE_LINK_BINARIES_LOCALLY_OVERRIDE_ATTR_NAME",
|
||||
"APPLE_LINK_LIBRARIES_LOCALLY_OVERRIDE_ATTR_NAME",
|
||||
)
|
||||
|
||||
_APPLE_LIBRARY_LOCAL_EXECUTION_OVERRIDES = {
|
||||
APPLE_LINK_LIBRARIES_LOCALLY_OVERRIDE_ATTR_NAME: ("apple", "link_libraries_locally_override"),
|
||||
APPLE_ARCHIVE_OBJECTS_LOCALLY_OVERRIDE_ATTR_NAME: ("apple", "archive_objects_locally_override"),
|
||||
}
|
||||
|
||||
_APPLE_BINARY_LOCAL_EXECUTION_OVERRIDES = {
|
||||
APPLE_LINK_BINARIES_LOCALLY_OVERRIDE_ATTR_NAME: ("apple", "link_binaries_locally_override"),
|
||||
}
|
||||
|
||||
def apple_macro_layer_set_bool_override_attrs_from_config(attrib_map: {str.type: (str.type, str.type)}) -> {str.type: "selector"}:
|
||||
attribs = {}
|
||||
for (attrib_name, (config_section, config_key)) in attrib_map.items():
|
||||
config_value = read_config(config_section, config_key, None)
|
||||
if config_value != None:
|
||||
config_truth_value = config_value.lower() == "true"
|
||||
attribs[attrib_name] = select({
|
||||
"DEFAULT": config_truth_value,
|
||||
# Do not set attribute value for host tools
|
||||
"ovr_config//platform/macos/constraints:execution-platform-transitioned": None,
|
||||
})
|
||||
return attribs
|
||||
|
||||
def apple_library_macro_impl(apple_library_rule = None, **kwargs):
|
||||
kwargs.update(apple_macro_layer_set_bool_override_attrs_from_config(_APPLE_LIBRARY_LOCAL_EXECUTION_OVERRIDES))
|
||||
apple_library_rule(**kwargs)
|
||||
|
||||
def apple_binary_macro_impl(apple_binary_rule = None, **kwargs):
|
||||
kwargs.update(apple_macro_layer_set_bool_override_attrs_from_config(_APPLE_BINARY_LOCAL_EXECUTION_OVERRIDES))
|
||||
apple_binary_rule(**kwargs)
|
||||
14
vendor/cxx/tools/buck/prelude/apple/apple_modular_utility.bzl
vendored
Normal file
14
vendor/cxx/tools/buck/prelude/apple/apple_modular_utility.bzl
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# 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.
|
||||
|
||||
# We use a fixed module cache location. This works around issues with
|
||||
# multi-user setups with MobileOnDemand and allows us to share the
|
||||
# module cache with Xcode, LLDB and arc focus.
|
||||
#
|
||||
# TODO(T123737676): This needs to be changed to use $TMPDIR in a
|
||||
# wrapper for modular clang compilation.
|
||||
MODULE_CACHE_PATH = "/tmp/buck-module-cache"
|
||||
23
vendor/cxx/tools/buck/prelude/apple/apple_package.bzl
vendored
Normal file
23
vendor/cxx/tools/buck/prelude/apple/apple_package.bzl
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# 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.
|
||||
|
||||
def apple_package_impl(ctx: "context") -> ["provider"]:
|
||||
bundle = ctx.attrs.bundle
|
||||
ipa_name = "{}.ipa".format(bundle.label.name)
|
||||
app = bundle[DefaultInfo].default_outputs[0]
|
||||
|
||||
payload = ctx.actions.copy_file("Payload", app)
|
||||
|
||||
package = ctx.actions.declare_output(ipa_name)
|
||||
|
||||
# TODO(T96496412): Add support for compression levels and SwiftSupport
|
||||
# TODO(T110378117): Pull this into a shared zip utility function
|
||||
|
||||
zip = cmd_args(["(cd \"", cmd_args(payload).parent(), "\" && zip -X -r - \"", payload.basename, "\") > ", package.as_output()], delimiter = "")
|
||||
ctx.actions.run(["sh", "-c", zip], category = "apple_package_zip")
|
||||
|
||||
return [DefaultInfo(default_outputs = [package])]
|
||||
29
vendor/cxx/tools/buck/prelude/apple/apple_resource.bzl
vendored
Normal file
29
vendor/cxx/tools/buck/prelude/apple/apple_resource.bzl
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# 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(":apple_resource_types.bzl", "AppleResourceDestination", "AppleResourceSpec")
|
||||
load(":resource_groups.bzl", "create_resource_graph")
|
||||
|
||||
def apple_resource_impl(ctx: "context") -> ["provider"]:
|
||||
destination = ctx.attrs.destination or "resources"
|
||||
resource_spec = AppleResourceSpec(
|
||||
files = ctx.attrs.files,
|
||||
dirs = ctx.attrs.dirs,
|
||||
content_dirs = ctx.attrs.content_dirs,
|
||||
destination = AppleResourceDestination(destination),
|
||||
variant_files = ctx.attrs.variants or [],
|
||||
named_variant_files = ctx.attrs.named_variants or {},
|
||||
codesign_files_on_copy = ctx.attrs.codesign_on_copy,
|
||||
)
|
||||
graph = create_resource_graph(
|
||||
ctx = ctx,
|
||||
labels = ctx.attrs.labels,
|
||||
deps = [],
|
||||
exported_deps = [],
|
||||
resource_spec = resource_spec,
|
||||
)
|
||||
return [DefaultInfo(), graph]
|
||||
34
vendor/cxx/tools/buck/prelude/apple/apple_resource_types.bzl
vendored
Normal file
34
vendor/cxx/tools/buck/prelude/apple/apple_resource_types.bzl
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# 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.
|
||||
|
||||
# Represents the values for the `destination` field of `apple_resource`
|
||||
AppleResourceDestination = enum(
|
||||
"resources",
|
||||
"frameworks",
|
||||
"executables",
|
||||
"plugins",
|
||||
"xpcservices",
|
||||
)
|
||||
|
||||
# Defines _where_ resources need to be placed in an `apple_bundle`
|
||||
AppleResourceSpec = record(
|
||||
files = field(["artifact"], []),
|
||||
dirs = field(["artifact"], []),
|
||||
content_dirs = field(["artifact"], []),
|
||||
destination = AppleResourceDestination.type,
|
||||
variant_files = field(["artifact"], []),
|
||||
# Map from locale to list of files for that locale, e.g.
|
||||
# `{ "ru.lproj" : ["Localizable.strings"] }`
|
||||
named_variant_files = field({str.type: ["artifact"]}, {}),
|
||||
codesign_files_on_copy = field(bool.type, False),
|
||||
)
|
||||
|
||||
# Used when invoking `ibtool`, `actool` and `momc`
|
||||
AppleResourceProcessingOptions = record(
|
||||
prefer_local = field(bool.type, False),
|
||||
allow_cache_upload = field(bool.type, False),
|
||||
)
|
||||
15
vendor/cxx/tools/buck/prelude/apple/apple_resource_utility.bzl
vendored
Normal file
15
vendor/cxx/tools/buck/prelude/apple/apple_resource_utility.bzl
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# 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(":apple_bundle_destination.bzl", "AppleBundleDestination")
|
||||
load(
|
||||
":apple_resource_types.bzl",
|
||||
"AppleResourceDestination", # @unused Used as a type
|
||||
)
|
||||
|
||||
def apple_bundle_destination_from_resource_destination(res_destination: AppleResourceDestination.type) -> AppleBundleDestination.type:
|
||||
return AppleBundleDestination(res_destination.value)
|
||||
190
vendor/cxx/tools/buck/prelude/apple/apple_rules_impl.bzl
vendored
Normal file
190
vendor/cxx/tools/buck/prelude/apple/apple_rules_impl.bzl
vendored
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
# 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//:attributes.bzl", "LinkableDepType", "Linkage")
|
||||
load("@prelude//cxx:headers.bzl", "CPrecompiledHeaderInfo")
|
||||
load("@prelude//cxx:omnibus.bzl", "omnibus_environment_attr")
|
||||
load("@prelude//cxx/user:link_group_map.bzl", "link_group_map_attr")
|
||||
load(":apple_asset_catalog.bzl", "apple_asset_catalog_impl")
|
||||
load(":apple_binary.bzl", "apple_binary_impl")
|
||||
load(":apple_bundle.bzl", "apple_bundle_impl")
|
||||
load(":apple_code_signing_types.bzl", "CodeSignType")
|
||||
load(":apple_core_data.bzl", "apple_core_data_impl")
|
||||
load(":apple_library.bzl", "apple_library_impl")
|
||||
load(":apple_package.bzl", "apple_package_impl")
|
||||
load(":apple_resource.bzl", "apple_resource_impl")
|
||||
load(
|
||||
":apple_rules_impl_utility.bzl",
|
||||
"APPLE_ARCHIVE_OBJECTS_LOCALLY_OVERRIDE_ATTR_NAME",
|
||||
"APPLE_LINK_BINARIES_LOCALLY_OVERRIDE_ATTR_NAME",
|
||||
"APPLE_LINK_LIBRARIES_LOCALLY_OVERRIDE_ATTR_NAME",
|
||||
"apple_bundle_extra_attrs",
|
||||
"get_apple_toolchain_attr",
|
||||
"get_apple_xctoolchain_attr",
|
||||
"get_apple_xctoolchain_bundle_id_attr",
|
||||
)
|
||||
load(":apple_test.bzl", "apple_test_impl")
|
||||
load(":apple_toolchain.bzl", "apple_toolchain_impl")
|
||||
load(":apple_toolchain_types.bzl", "AppleToolsInfo")
|
||||
load(":prebuilt_apple_framework.bzl", "prebuilt_apple_framework_impl")
|
||||
load(":swift_toolchain.bzl", "swift_toolchain_impl")
|
||||
load(":xcode_postbuild_script.bzl", "xcode_postbuild_script_impl")
|
||||
load(":xcode_prebuild_script.bzl", "xcode_prebuild_script_impl")
|
||||
|
||||
implemented_rules = {
|
||||
"apple_asset_catalog": apple_asset_catalog_impl,
|
||||
"apple_binary": apple_binary_impl,
|
||||
"apple_bundle": apple_bundle_impl,
|
||||
"apple_library": apple_library_impl,
|
||||
"apple_package": apple_package_impl,
|
||||
"apple_resource": apple_resource_impl,
|
||||
"apple_test": apple_test_impl,
|
||||
"apple_toolchain": apple_toolchain_impl,
|
||||
"core_data_model": apple_core_data_impl,
|
||||
"prebuilt_apple_framework": prebuilt_apple_framework_impl,
|
||||
"swift_toolchain": swift_toolchain_impl,
|
||||
"xcode_postbuild_script": xcode_postbuild_script_impl,
|
||||
"xcode_prebuild_script": xcode_prebuild_script_impl,
|
||||
}
|
||||
|
||||
extra_attributes = {
|
||||
"apple_asset_catalog": {
|
||||
"dirs": attrs.list(attrs.source(allow_directory = True), default = []),
|
||||
},
|
||||
"apple_binary": {
|
||||
"binary_linker_flags": attrs.list(attrs.arg(), default = []),
|
||||
"enable_distributed_thinlto": attrs.bool(default = False),
|
||||
"extra_xcode_sources": attrs.list(attrs.source(allow_directory = True), default = []),
|
||||
"link_group_map": link_group_map_attr(),
|
||||
"link_postprocessor": attrs.option(attrs.exec_dep(), default = None),
|
||||
"precompiled_header": attrs.option(attrs.dep(providers = [CPrecompiledHeaderInfo]), default = None),
|
||||
"prefer_stripped_objects": attrs.bool(default = False),
|
||||
"preferred_linkage": attrs.enum(Linkage, default = "any"),
|
||||
"stripped": attrs.bool(default = False),
|
||||
"_apple_toolchain": get_apple_toolchain_attr(),
|
||||
"_apple_xctoolchain": get_apple_xctoolchain_attr(),
|
||||
"_apple_xctoolchain_bundle_id": get_apple_xctoolchain_bundle_id_attr(),
|
||||
"_omnibus_environment": omnibus_environment_attr(),
|
||||
APPLE_LINK_BINARIES_LOCALLY_OVERRIDE_ATTR_NAME: attrs.option(attrs.bool(), default = None),
|
||||
},
|
||||
"apple_bundle": apple_bundle_extra_attrs(),
|
||||
"apple_library": {
|
||||
"extra_xcode_sources": attrs.list(attrs.source(allow_directory = True), default = []),
|
||||
"link_group_map": link_group_map_attr(),
|
||||
"link_postprocessor": attrs.option(attrs.exec_dep(), default = None),
|
||||
"precompiled_header": attrs.option(attrs.dep(providers = [CPrecompiledHeaderInfo]), default = None),
|
||||
"preferred_linkage": attrs.enum(Linkage, default = "any"),
|
||||
"serialize_debugging_options": attrs.bool(default = True),
|
||||
"stripped": attrs.bool(default = False),
|
||||
"use_archive": attrs.option(attrs.bool(), default = None),
|
||||
"_apple_toolchain": get_apple_toolchain_attr(),
|
||||
# FIXME: prelude// should be standalone (not refer to fbsource//)
|
||||
"_apple_tools": attrs.exec_dep(default = "fbsource//xplat/buck2/platform/apple:apple-tools", providers = [AppleToolsInfo]),
|
||||
"_apple_xctoolchain": get_apple_xctoolchain_attr(),
|
||||
"_apple_xctoolchain_bundle_id": get_apple_xctoolchain_bundle_id_attr(),
|
||||
"_omnibus_environment": omnibus_environment_attr(),
|
||||
APPLE_LINK_LIBRARIES_LOCALLY_OVERRIDE_ATTR_NAME: attrs.option(attrs.bool(), default = None),
|
||||
APPLE_ARCHIVE_OBJECTS_LOCALLY_OVERRIDE_ATTR_NAME: attrs.option(attrs.bool(), default = None),
|
||||
},
|
||||
"apple_resource": {
|
||||
"codesign_on_copy": attrs.bool(default = False),
|
||||
"content_dirs": attrs.list(attrs.source(allow_directory = True), default = []),
|
||||
"dirs": attrs.list(attrs.source(allow_directory = True), default = []),
|
||||
},
|
||||
# To build an `apple_test`, one needs to first build a shared `apple_library` then
|
||||
# wrap this test library into an `apple_bundle`. Because of this, `apple_test` has attributes
|
||||
# from both `apple_library` and `apple_bundle`.
|
||||
"apple_test": {
|
||||
# Expected by `apple_bundle`, for `apple_test` this field is always None.
|
||||
"binary": attrs.option(attrs.dep(), default = None),
|
||||
# The resulting test bundle should have .xctest extension.
|
||||
"extension": attrs.string(default = "xctest"),
|
||||
"extra_xcode_sources": attrs.list(attrs.source(allow_directory = True), default = []),
|
||||
"link_postprocessor": attrs.option(attrs.exec_dep(), default = None),
|
||||
# Used to create the shared test library. Any library deps whose `preferred_linkage` isn't "shared" will
|
||||
# be treated as "static" deps and linked into the shared test library.
|
||||
"link_style": attrs.enum(LinkableDepType, default = "static"),
|
||||
# The test source code and lib dependencies should be built into a shared library.
|
||||
"preferred_linkage": attrs.enum(Linkage, default = "shared"),
|
||||
# Expected by `apple_bundle`, for `apple_test` this field is always None.
|
||||
"resource_group": attrs.option(attrs.string(), default = None),
|
||||
# Expected by `apple_bundle`, for `apple_test` this field is always None.
|
||||
"resource_group_map": attrs.option(attrs.string(), default = None),
|
||||
"stripped": attrs.bool(default = False),
|
||||
"_apple_toolchain": get_apple_toolchain_attr(),
|
||||
# FIXME: prelude// should be standalone (not refer to fbsource//)
|
||||
"_apple_tools": attrs.exec_dep(default = "fbsource//xplat/buck2/platform/apple:apple-tools", providers = [AppleToolsInfo]),
|
||||
"_apple_xctoolchain": get_apple_xctoolchain_attr(),
|
||||
"_apple_xctoolchain_bundle_id": get_apple_xctoolchain_bundle_id_attr(),
|
||||
"_codesign_type": attrs.option(attrs.enum(CodeSignType.values()), default = None),
|
||||
"_compile_resources_locally_override": attrs.option(attrs.bool(), default = None),
|
||||
"_incremental_bundling_enabled": attrs.bool(default = False),
|
||||
"_omnibus_environment": omnibus_environment_attr(),
|
||||
"_profile_bundling_enabled": attrs.bool(default = False),
|
||||
APPLE_LINK_LIBRARIES_LOCALLY_OVERRIDE_ATTR_NAME: attrs.option(attrs.bool(), default = None),
|
||||
},
|
||||
"apple_toolchain": {
|
||||
# The Buck v1 attribute specs defines those as `attrs.source()` but
|
||||
# we want to properly handle any runnable tools that might have
|
||||
# addition runtime requirements.
|
||||
"actool": attrs.dep(providers = [RunInfo]),
|
||||
"codesign": attrs.dep(providers = [RunInfo]),
|
||||
"codesign_allocate": attrs.dep(providers = [RunInfo]),
|
||||
"codesign_identities_command": attrs.option(attrs.dep(providers = [RunInfo]), default = None),
|
||||
# Controls invocations of `ibtool`, `actool` and `momc`
|
||||
"compile_resources_locally": attrs.bool(default = False),
|
||||
"dsymutil": attrs.dep(providers = [RunInfo]),
|
||||
"dwarfdump": attrs.option(attrs.dep(providers = [RunInfo]), default = None),
|
||||
"ibtool": attrs.dep(providers = [RunInfo]),
|
||||
"libtool": attrs.dep(providers = [RunInfo]),
|
||||
"lipo": attrs.dep(providers = [RunInfo]),
|
||||
"min_version": attrs.option(attrs.string(), default = None),
|
||||
"momc": attrs.dep(providers = [RunInfo]),
|
||||
"platform_path": attrs.option(attrs.source()), # Mark as optional until we remove `_internal_platform_path`
|
||||
"sdk_path": attrs.option(attrs.source()), # Mark as optional until we remove `_internal_sdk_path`
|
||||
"version": attrs.option(attrs.string(), default = None),
|
||||
"xcode_build_version": attrs.option(attrs.string(), default = None),
|
||||
"xcode_version": attrs.option(attrs.string(), default = None),
|
||||
"xctest": attrs.dep(providers = [RunInfo]),
|
||||
# TODO(T111858757): Mirror of `platform_path` but treated as a string. It allows us to
|
||||
# pass abs paths during development and using the currently selected Xcode.
|
||||
"_internal_platform_path": attrs.option(attrs.string()),
|
||||
# TODO(T111858757): Mirror of `sdk_path` but treated as a string. It allows us to
|
||||
# pass abs paths during development and using the currently selected Xcode.
|
||||
"_internal_sdk_path": attrs.option(attrs.string()),
|
||||
},
|
||||
"core_data_model": {
|
||||
"path": attrs.source(allow_directory = True),
|
||||
},
|
||||
"prebuilt_apple_framework": {
|
||||
"framework": attrs.option(attrs.source(allow_directory = True), default = None),
|
||||
"preferred_linkage": attrs.enum(Linkage, default = "any"),
|
||||
"_apple_toolchain": get_apple_toolchain_attr(),
|
||||
"_omnibus_environment": omnibus_environment_attr(),
|
||||
},
|
||||
"scene_kit_assets": {
|
||||
"path": attrs.source(allow_directory = True),
|
||||
},
|
||||
"swift_library": {
|
||||
"preferred_linkage": attrs.enum(Linkage, default = "any"),
|
||||
},
|
||||
"swift_toolchain": {
|
||||
"architecture": attrs.option(attrs.string(), default = None), # TODO(T115173356): Make field non-optional
|
||||
"platform_path": attrs.option(attrs.source()), # Mark as optional until we remove `_internal_platform_path`
|
||||
"sdk_modules": attrs.list(attrs.dep(), default = []), # A list or a root target that represent a graph of sdk modules (e.g Frameworks)
|
||||
"sdk_path": attrs.option(attrs.source()), # Mark as optional until we remove `_internal_sdk_path`
|
||||
"swift_stdlib_tool": attrs.exec_dep(providers = [RunInfo]),
|
||||
"swiftc": attrs.exec_dep(providers = [RunInfo]),
|
||||
# TODO(T111858757): Mirror of `platform_path` but treated as a string. It allows us to
|
||||
# pass abs paths during development and using the currently selected Xcode.
|
||||
"_internal_platform_path": attrs.option(attrs.string(), default = None),
|
||||
# TODO(T111858757): Mirror of `sdk_path` but treated as a string. It allows us to
|
||||
# pass abs paths during development and using the currently selected Xcode.
|
||||
"_internal_sdk_path": attrs.option(attrs.string(), default = None),
|
||||
"_swiftc_wrapper": attrs.dep(providers = [RunInfo], default = "prelude//apple/tools:swift_exec"),
|
||||
},
|
||||
}
|
||||
51
vendor/cxx/tools/buck/prelude/apple/apple_rules_impl_utility.bzl
vendored
Normal file
51
vendor/cxx/tools/buck/prelude/apple/apple_rules_impl_utility.bzl
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# 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//apple:apple_bundle_types.bzl", "AppleBundleResourceInfo")
|
||||
load("@prelude//apple:apple_code_signing_types.bzl", "CodeSignType")
|
||||
load("@prelude//apple:apple_toolchain_types.bzl", "AppleToolchainInfo", "AppleToolsInfo")
|
||||
load("@prelude//apple/user:resource_group_map.bzl", "resource_group_map_attr")
|
||||
|
||||
def get_apple_toolchain_attr():
|
||||
# FIXME: prelude// should be standalone (not refer to fbcode//)
|
||||
return attrs.toolchain_dep(default = "fbcode//buck2/platform/toolchain:apple-default", providers = [AppleToolchainInfo])
|
||||
|
||||
def _get_apple_bundle_toolchain_attr():
|
||||
# FIXME: prelude// should be standalone (not refer to fbcode//)
|
||||
return attrs.toolchain_dep(default = "fbcode//buck2/platform/toolchain:apple-bundle", providers = [AppleToolchainInfo])
|
||||
|
||||
def get_apple_xctoolchain_attr():
|
||||
# FIXME: prelude// should be standalone (not refer to fbcode//)
|
||||
return attrs.toolchain_dep(default = "fbcode//buck2/platform/toolchain:apple-xctoolchain")
|
||||
|
||||
def get_apple_xctoolchain_bundle_id_attr():
|
||||
# FIXME: prelude// should be standalone (not refer to fbcode//)
|
||||
return attrs.toolchain_dep(default = "fbcode//buck2/platform/toolchain:apple-xctoolchain-bundle-id")
|
||||
|
||||
APPLE_LINK_BINARIES_LOCALLY_OVERRIDE_ATTR_NAME = "_link_binaries_locally_override"
|
||||
APPLE_LINK_LIBRARIES_LOCALLY_OVERRIDE_ATTR_NAME = "_link_libraries_locally_override"
|
||||
APPLE_ARCHIVE_OBJECTS_LOCALLY_OVERRIDE_ATTR_NAME = "_archive_objects_locally_override"
|
||||
|
||||
def apple_bundle_extra_attrs():
|
||||
return {
|
||||
"resource_group_map": resource_group_map_attr(),
|
||||
# FIXME: prelude// should be standalone (not refer to buck//)
|
||||
"_apple_installer": attrs.label(default = "buck//src/com/facebook/buck/installer/apple:apple_installer"),
|
||||
"_apple_toolchain": _get_apple_bundle_toolchain_attr(),
|
||||
# FIXME: prelude// should be standalone (not refer to fbsource//)
|
||||
"_apple_tools": attrs.exec_dep(default = "fbsource//xplat/buck2/platform/apple:apple-tools", providers = [AppleToolsInfo]),
|
||||
"_apple_xctoolchain": get_apple_xctoolchain_attr(),
|
||||
"_apple_xctoolchain_bundle_id": get_apple_xctoolchain_bundle_id_attr(),
|
||||
"_codesign_entitlements": attrs.option(attrs.source(), default = None),
|
||||
"_codesign_type": attrs.option(attrs.enum(CodeSignType.values()), default = None),
|
||||
"_compile_resources_locally_override": attrs.option(attrs.bool(), default = None),
|
||||
"_incremental_bundling_enabled": attrs.bool(default = False),
|
||||
"_profile_bundling_enabled": attrs.bool(default = False),
|
||||
# FIXME: prelude// should be standalone (not refer to fbsource//)
|
||||
"_provisioning_profiles": attrs.dep(default = "fbsource//xplat/buck2/platform/apple:provisioning_profiles"),
|
||||
"_resource_bundle": attrs.option(attrs.dep(providers = [AppleBundleResourceInfo]), default = None),
|
||||
}
|
||||
15
vendor/cxx/tools/buck/prelude/apple/apple_sdk.bzl
vendored
Normal file
15
vendor/cxx/tools/buck/prelude/apple/apple_sdk.bzl
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# 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//apple:apple_toolchain_types.bzl", "AppleToolchainInfo")
|
||||
|
||||
def get_apple_sdk_name(ctx: "context") -> str.type:
|
||||
"""
|
||||
Get the SDK defined on the toolchain.
|
||||
Will throw if the `_apple_toolchain` is not present.
|
||||
"""
|
||||
return ctx.attrs._apple_toolchain[AppleToolchainInfo].sdk_name
|
||||
39
vendor/cxx/tools/buck/prelude/apple/apple_sdk_clang_module.bzl
vendored
Normal file
39
vendor/cxx/tools/buck/prelude/apple/apple_sdk_clang_module.bzl
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# 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(":swift_pcm_compilation.bzl", "get_shared_pcm_compilation_args")
|
||||
load(":swift_toolchain_types.bzl", "SdkUncompiledModuleInfo")
|
||||
|
||||
def apple_sdk_clang_module_impl(ctx: "context") -> ["provider"]:
|
||||
cmd = get_shared_pcm_compilation_args(ctx.attrs.target, ctx.attrs.module_name)
|
||||
module_dependency_infos = filter(None, [d.get(SdkUncompiledModuleInfo) for d in ctx.attrs.deps])
|
||||
return [
|
||||
DefaultInfo(),
|
||||
SdkUncompiledModuleInfo(
|
||||
name = ctx.attrs.name,
|
||||
module_name = ctx.attrs.module_name,
|
||||
is_framework = ctx.attrs.is_framework,
|
||||
is_swiftmodule = False,
|
||||
partial_cmd = cmd,
|
||||
input_relative_path = ctx.attrs.modulemap_relative_path,
|
||||
deps = module_dependency_infos,
|
||||
),
|
||||
]
|
||||
|
||||
# This rule represent a Clang module from SDK and forms a graph of dependencies between such modules.
|
||||
apple_sdk_clang_module = rule(
|
||||
impl = apple_sdk_clang_module_impl,
|
||||
attrs = {
|
||||
"deps": attrs.list(attrs.dep(), default = []),
|
||||
"is_framework": attrs.bool(default = False),
|
||||
# This is a real module name, contrary to `name`
|
||||
# which has a special suffix to distinguish Swift and Clang modules with the same name
|
||||
"module_name": attrs.string(),
|
||||
"modulemap_relative_path": attrs.string(),
|
||||
"target": attrs.string(),
|
||||
},
|
||||
)
|
||||
95
vendor/cxx/tools/buck/prelude/apple/apple_sdk_metadata.bzl
vendored
Normal file
95
vendor/cxx/tools/buck/prelude/apple/apple_sdk_metadata.bzl
vendored
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
# 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.
|
||||
|
||||
AppleSdkMetadata = record(
|
||||
name = field(str.type),
|
||||
target_device_flags = field([str.type], []),
|
||||
is_ad_hoc_code_sign_sufficient = field(bool.type),
|
||||
info_plist_supported_platforms_values = field([str.type]),
|
||||
min_version_plist_info_key = field(str.type),
|
||||
)
|
||||
|
||||
IPhoneOSSdkMetadata = AppleSdkMetadata(
|
||||
name = "iphoneos",
|
||||
target_device_flags = ["--target-device", "iphone", "--target-device", "ipad"],
|
||||
is_ad_hoc_code_sign_sufficient = False,
|
||||
info_plist_supported_platforms_values = ["iPhoneOS"],
|
||||
min_version_plist_info_key = "MinimumOSVersion",
|
||||
)
|
||||
|
||||
IPhoneSimulatorSdkMetadata = AppleSdkMetadata(
|
||||
name = "iphonesimulator",
|
||||
target_device_flags = ["--target-device", "iphone", "--target-device", "ipad"],
|
||||
is_ad_hoc_code_sign_sufficient = True,
|
||||
info_plist_supported_platforms_values = ["iPhoneSimulator"],
|
||||
min_version_plist_info_key = "MinimumOSVersion",
|
||||
)
|
||||
|
||||
TVOSSdkMetadata = AppleSdkMetadata(
|
||||
name = "appletvos",
|
||||
target_device_flags = ["--target-device", "tv"],
|
||||
is_ad_hoc_code_sign_sufficient = False,
|
||||
info_plist_supported_platforms_values = ["AppleTVOS"],
|
||||
min_version_plist_info_key = "MinimumOSVersion",
|
||||
)
|
||||
|
||||
TVSimulatorSdkMetadata = AppleSdkMetadata(
|
||||
name = "appletvsimulator",
|
||||
target_device_flags = ["--target-device", "tv"],
|
||||
is_ad_hoc_code_sign_sufficient = True,
|
||||
info_plist_supported_platforms_values = ["AppleTVSimulator"],
|
||||
min_version_plist_info_key = "MinimumOSVersion",
|
||||
)
|
||||
|
||||
WatchOSSdkMetadata = AppleSdkMetadata(
|
||||
name = "watchos",
|
||||
target_device_flags = ["--target-device", "watch"],
|
||||
is_ad_hoc_code_sign_sufficient = False,
|
||||
info_plist_supported_platforms_values = ["WatchOS"],
|
||||
min_version_plist_info_key = "MinimumOSVersion",
|
||||
)
|
||||
|
||||
WatchSimulatorSdkMetadata = AppleSdkMetadata(
|
||||
name = "watchsimulator",
|
||||
target_device_flags = ["--target-device", "watch"],
|
||||
is_ad_hoc_code_sign_sufficient = True,
|
||||
info_plist_supported_platforms_values = ["WatchSimulator"],
|
||||
min_version_plist_info_key = "MinimumOSVersion",
|
||||
)
|
||||
|
||||
MacOSXSdkMetadata = AppleSdkMetadata(
|
||||
name = "macosx",
|
||||
target_device_flags = ["--target-device", "mac"],
|
||||
is_ad_hoc_code_sign_sufficient = True,
|
||||
info_plist_supported_platforms_values = ["MacOSX"],
|
||||
min_version_plist_info_key = "LSMinimumSystemVersion",
|
||||
)
|
||||
|
||||
MacOSXCatalystSdkMetadata = AppleSdkMetadata(
|
||||
name = "maccatalyst",
|
||||
target_device_flags = ["--target-device", "ipad"],
|
||||
is_ad_hoc_code_sign_sufficient = True,
|
||||
info_plist_supported_platforms_values = ["MacOSX"],
|
||||
min_version_plist_info_key = "LSMinimumSystemVersion",
|
||||
)
|
||||
|
||||
_SDK_MAP = {
|
||||
IPhoneOSSdkMetadata.name: IPhoneOSSdkMetadata,
|
||||
IPhoneSimulatorSdkMetadata.name: IPhoneSimulatorSdkMetadata,
|
||||
TVOSSdkMetadata.name: TVOSSdkMetadata,
|
||||
TVSimulatorSdkMetadata.name: TVSimulatorSdkMetadata,
|
||||
WatchOSSdkMetadata.name: WatchOSSdkMetadata,
|
||||
WatchSimulatorSdkMetadata.name: WatchSimulatorSdkMetadata,
|
||||
MacOSXSdkMetadata.name: MacOSXSdkMetadata,
|
||||
MacOSXCatalystSdkMetadata.name: MacOSXCatalystSdkMetadata,
|
||||
}
|
||||
|
||||
def get_apple_sdk_metadata_for_sdk_name(name: str.type) -> AppleSdkMetadata.type:
|
||||
sdk = _SDK_MAP.get(name)
|
||||
if sdk == None:
|
||||
fail("unrecognized sdk name: `{}`".format(name))
|
||||
return sdk
|
||||
45
vendor/cxx/tools/buck/prelude/apple/apple_sdk_module.bzl
vendored
Normal file
45
vendor/cxx/tools/buck/prelude/apple/apple_sdk_module.bzl
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# 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(":apple_sdk_modules_utility.bzl", "SDKDepTSet")
|
||||
load(":apple_sdk_swift_module.bzl", "compile_sdk_swiftinterface")
|
||||
load(":swift_pcm_compilation.bzl", "compile_swift_sdk_pcm")
|
||||
|
||||
# Starting from a root node, this helper function traverses a graph of uncompiled SDK modules
|
||||
# to create a graph of compiled ones.
|
||||
def create_sdk_modules_graph(
|
||||
ctx: "context",
|
||||
sdk_module_providers: {str.type: "SdkCompiledModuleInfo"},
|
||||
uncompiled_sdk_module_info: "SdkUncompiledModuleInfo",
|
||||
toolchain_context: struct.type):
|
||||
# If input_relative_path is None then this module represents a root node of SDK modules graph.
|
||||
# In such case, we need to handle only its deps.
|
||||
if uncompiled_sdk_module_info.input_relative_path == None:
|
||||
for uncompiled_dependency_info in uncompiled_sdk_module_info.deps:
|
||||
create_sdk_modules_graph(ctx, sdk_module_providers, uncompiled_dependency_info, toolchain_context)
|
||||
return
|
||||
|
||||
# If provider is already created, return.
|
||||
if uncompiled_sdk_module_info.name in sdk_module_providers:
|
||||
return
|
||||
|
||||
compiled_dependency_infos_tsets = []
|
||||
for uncompiled_dependency_info in uncompiled_sdk_module_info.deps:
|
||||
create_sdk_modules_graph(ctx, sdk_module_providers, uncompiled_dependency_info, toolchain_context)
|
||||
compiled_dependency_info = sdk_module_providers[uncompiled_dependency_info.name]
|
||||
sdk_dep_tset = ctx.actions.tset(
|
||||
SDKDepTSet,
|
||||
value = compiled_dependency_info,
|
||||
children = [compiled_dependency_info.deps],
|
||||
)
|
||||
compiled_dependency_infos_tsets.append(sdk_dep_tset)
|
||||
|
||||
sdk_deps_set = ctx.actions.tset(SDKDepTSet, children = compiled_dependency_infos_tsets)
|
||||
if uncompiled_sdk_module_info.is_swiftmodule:
|
||||
compile_sdk_swiftinterface(ctx, toolchain_context, sdk_deps_set, uncompiled_sdk_module_info, sdk_module_providers)
|
||||
else:
|
||||
compile_swift_sdk_pcm(ctx, toolchain_context, sdk_deps_set, uncompiled_sdk_module_info, sdk_module_providers)
|
||||
67
vendor/cxx/tools/buck/prelude/apple/apple_sdk_modules_utility.bzl
vendored
Normal file
67
vendor/cxx/tools/buck/prelude/apple/apple_sdk_modules_utility.bzl
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
# 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(":swift_pcm_compilation_types.bzl", "SwiftPCMCompilationInfo")
|
||||
|
||||
def project_as_hidden(module_info: "SdkCompiledModuleInfo"):
|
||||
# NOTE(cjhopman): This would probably be better done by projecting as normal args and the caller putting it in hidden.
|
||||
args = cmd_args()
|
||||
args.hidden(module_info.output_artifact)
|
||||
return args
|
||||
|
||||
def project_as_clang_deps(module_info: "SdkCompiledModuleInfo"):
|
||||
if module_info.is_swiftmodule:
|
||||
return []
|
||||
else:
|
||||
return [
|
||||
"-Xcc",
|
||||
cmd_args(["-fmodule-file=", module_info.module_name, "=", module_info.output_artifact], delimiter = ""),
|
||||
"-Xcc",
|
||||
cmd_args(["-fmodule-map-file=", module_info.input_relative_path], delimiter = ""),
|
||||
]
|
||||
|
||||
SDKDepTSet = transitive_set(args_projections = {
|
||||
"clang_deps": project_as_clang_deps,
|
||||
"hidden": project_as_hidden,
|
||||
})
|
||||
|
||||
def is_sdk_modules_provided(toolchain: "SwiftToolchainInfo") -> bool.type:
|
||||
no_swift_modules = toolchain.compiled_sdk_swift_modules == None or len(toolchain.compiled_sdk_swift_modules) == 0
|
||||
no_clang_modules = toolchain.compiled_sdk_clang_modules == None or len(toolchain.compiled_sdk_clang_modules) == 0
|
||||
if no_swift_modules and no_clang_modules:
|
||||
return False
|
||||
return True
|
||||
|
||||
def get_sdk_deps_tset(
|
||||
ctx: "context",
|
||||
module_name: str.type,
|
||||
deps: ["dependency"],
|
||||
required_modules: [str.type],
|
||||
toolchain: "SwiftToolchainInfo") -> "SDKDepTSet":
|
||||
if not is_sdk_modules_provided(toolchain):
|
||||
fail("SDK deps are not set for swift_toolchain")
|
||||
|
||||
all_sdk_deps = [
|
||||
d[SwiftPCMCompilationInfo].sdk_deps_set
|
||||
for d in deps
|
||||
if SwiftPCMCompilationInfo in d
|
||||
]
|
||||
|
||||
# Adding all direct and transitive SDK dependencies.
|
||||
for sdk_module_dep_name in ctx.attrs.sdk_modules + required_modules:
|
||||
if sdk_module_dep_name not in toolchain.compiled_sdk_swift_modules and sdk_module_dep_name not in toolchain.compiled_sdk_clang_modules:
|
||||
fail("{} depends on a non-existing SDK module: {}".format(module_name, sdk_module_dep_name))
|
||||
|
||||
sdk_compiled_module_info = toolchain.compiled_sdk_swift_modules.get(sdk_module_dep_name) or toolchain.compiled_sdk_clang_modules.get(sdk_module_dep_name)
|
||||
sdk_module_with_transitive_deps_tset = ctx.actions.tset(
|
||||
SDKDepTSet,
|
||||
value = sdk_compiled_module_info,
|
||||
children = [sdk_compiled_module_info.deps],
|
||||
)
|
||||
all_sdk_deps.append(sdk_module_with_transitive_deps_tset)
|
||||
|
||||
return ctx.actions.tset(SDKDepTSet, children = all_sdk_deps)
|
||||
118
vendor/cxx/tools/buck/prelude/apple/apple_sdk_swift_module.bzl
vendored
Normal file
118
vendor/cxx/tools/buck/prelude/apple/apple_sdk_swift_module.bzl
vendored
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
# 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(":apple_utility.bzl", "expand_relative_prefixed_sdk_path", "get_disable_pch_validation_flags")
|
||||
load(":swift_module_map.bzl", "write_swift_module_map")
|
||||
load(":swift_toolchain_types.bzl", "SdkCompiledModuleInfo", "SdkUncompiledModuleInfo")
|
||||
|
||||
def compile_sdk_swiftinterface(
|
||||
ctx: "context",
|
||||
toolchain_context: struct.type,
|
||||
sdk_deps_set: "SDKDepTSet",
|
||||
uncompiled_sdk_module_info: "SdkUncompiledModuleInfo",
|
||||
sdk_module_providers: {str.type: "SdkCompiledModuleInfo"}):
|
||||
uncompiled_module_info_name = uncompiled_sdk_module_info.module_name
|
||||
|
||||
cmd = cmd_args(toolchain_context.compiler)
|
||||
cmd.add(uncompiled_sdk_module_info.partial_cmd)
|
||||
cmd.add(["-sdk", toolchain_context.sdk_path])
|
||||
cmd.add(toolchain_context.compiler_flags)
|
||||
|
||||
if toolchain_context.swift_resource_dir:
|
||||
cmd.add([
|
||||
"-resource-dir",
|
||||
toolchain_context.swift_resource_dir,
|
||||
])
|
||||
|
||||
swift_module_map_artifact = write_swift_module_map(ctx, uncompiled_module_info_name, list(sdk_deps_set.traverse()))
|
||||
cmd.add([
|
||||
"-explicit-swift-module-map-file",
|
||||
swift_module_map_artifact,
|
||||
])
|
||||
|
||||
# sdk_swiftinterface_compile should explicitly depend on its deps that go to swift_modulemap
|
||||
cmd.hidden(sdk_deps_set.project_as_args("hidden"))
|
||||
cmd.add(sdk_deps_set.project_as_args("clang_deps"))
|
||||
|
||||
swiftmodule_output = ctx.actions.declare_output(uncompiled_module_info_name + ".swiftmodule")
|
||||
expanded_swiftinterface_cmd = expand_relative_prefixed_sdk_path(
|
||||
cmd_args(toolchain_context.sdk_path),
|
||||
cmd_args(toolchain_context.swift_resource_dir),
|
||||
uncompiled_sdk_module_info.input_relative_path,
|
||||
)
|
||||
cmd.add([
|
||||
"-o",
|
||||
swiftmodule_output.as_output(),
|
||||
expanded_swiftinterface_cmd,
|
||||
])
|
||||
|
||||
sdk_module_providers[uncompiled_sdk_module_info.name] = SdkCompiledModuleInfo(
|
||||
name = uncompiled_sdk_module_info.name,
|
||||
module_name = uncompiled_module_info_name,
|
||||
is_framework = uncompiled_sdk_module_info.is_framework,
|
||||
is_swiftmodule = True,
|
||||
output_artifact = swiftmodule_output,
|
||||
deps = sdk_deps_set,
|
||||
input_relative_path = expanded_swiftinterface_cmd,
|
||||
)
|
||||
|
||||
ctx.actions.run(cmd, category = "sdk_swiftinterface_compile", identifier = uncompiled_module_info_name)
|
||||
|
||||
def apple_sdk_swift_module_impl(ctx: "context") -> ["provider"]:
|
||||
module_name = ctx.attrs.module_name
|
||||
|
||||
cmd = cmd_args([
|
||||
"-frontend",
|
||||
"-compile-module-from-interface",
|
||||
"-disable-implicit-swift-modules",
|
||||
"-serialize-parseable-module-interface-dependency-hashes",
|
||||
"-disable-modules-validate-system-headers",
|
||||
"-suppress-warnings",
|
||||
"-module-name",
|
||||
module_name,
|
||||
"-target",
|
||||
ctx.attrs.target,
|
||||
"-Xcc",
|
||||
"-fno-implicit-modules",
|
||||
"-Xcc",
|
||||
"-fno-implicit-module-maps",
|
||||
])
|
||||
cmd.add(get_disable_pch_validation_flags())
|
||||
|
||||
if module_name == "Swift" or module_name == "SwiftOnoneSupport":
|
||||
cmd.add([
|
||||
"-parse-stdlib",
|
||||
])
|
||||
|
||||
module_dependency_infos = filter(None, [d.get(SdkUncompiledModuleInfo) for d in ctx.attrs.deps])
|
||||
return [
|
||||
DefaultInfo(),
|
||||
SdkUncompiledModuleInfo(
|
||||
name = ctx.attrs.name,
|
||||
module_name = ctx.attrs.module_name,
|
||||
is_framework = ctx.attrs.is_framework,
|
||||
is_swiftmodule = True,
|
||||
partial_cmd = cmd,
|
||||
input_relative_path = ctx.attrs.swiftinterface_relative_path,
|
||||
deps = module_dependency_infos,
|
||||
),
|
||||
]
|
||||
|
||||
# This rule represent a Swift module from SDK and forms a graph of dependencies between such modules.
|
||||
apple_sdk_swift_module = rule(
|
||||
impl = apple_sdk_swift_module_impl,
|
||||
attrs = {
|
||||
"deps": attrs.list(attrs.dep(), default = []),
|
||||
"is_framework": attrs.bool(default = False),
|
||||
# This is a real module name, contrary to `name`
|
||||
# which has a special suffix to distinguish Swift and Clang modules with the same name
|
||||
"module_name": attrs.string(),
|
||||
# A prefixed path ($SDKROOT/$PLATFORM_DIR) to swiftinterface textual file.
|
||||
"swiftinterface_relative_path": attrs.option(attrs.string(), default = None), # if `swiftinterface` is None represents a Root node.
|
||||
"target": attrs.string(),
|
||||
},
|
||||
)
|
||||
13
vendor/cxx/tools/buck/prelude/apple/apple_stripping.bzl
vendored
Normal file
13
vendor/cxx/tools/buck/prelude/apple/apple_stripping.bzl
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# 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//cxx:cxx_context.bzl", "get_cxx_toolchain_info")
|
||||
|
||||
def apple_strip_args(ctx: "context") -> "cmd_args":
|
||||
cxx_toolchain_info = get_cxx_toolchain_info(ctx)
|
||||
flags = cxx_toolchain_info.strip_flags_info.strip_non_global_flags
|
||||
return cmd_args(flags) if flags != None else cmd_args(["-x", "-T"])
|
||||
79
vendor/cxx/tools/buck/prelude/apple/apple_target_sdk_version.bzl
vendored
Normal file
79
vendor/cxx/tools/buck/prelude/apple/apple_target_sdk_version.bzl
vendored
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
# 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//apple:apple_toolchain_types.bzl", "AppleToolchainInfo")
|
||||
load("@prelude//cxx:preprocessor.bzl", "CPreprocessor")
|
||||
load(":apple_sdk.bzl", "get_apple_sdk_name")
|
||||
|
||||
# TODO(T112099448): In the future, the min version flag should live on the apple_toolchain()
|
||||
# TODO(T113776898): Switch to -mtargetos= flag which should live on the apple_toolchain()
|
||||
_APPLE_MIN_VERSION_FLAG_SDK_MAP = {
|
||||
"iphoneos": "-mios-version-min",
|
||||
"iphonesimulator": "-mios-simulator-version-min",
|
||||
"macosx": "-mmacosx-version-min",
|
||||
"watchos": "-mwatchos-version-min",
|
||||
"watchsimulator": "-mwatchsimulator-version-min",
|
||||
}
|
||||
|
||||
# Returns the target SDK version for apple_(binary|library) and uses
|
||||
# apple_toolchain() min version as a fallback. This is the central place
|
||||
# where the version for a particular node is defined, no other places
|
||||
# should be accessing `attrs.target_sdk_version` or `attrs.min_version`.
|
||||
def get_min_deployment_version_for_node(ctx: "context") -> [None, str.type]:
|
||||
toolchain_min_version = ctx.attrs._apple_toolchain[AppleToolchainInfo].min_version
|
||||
if toolchain_min_version == "":
|
||||
toolchain_min_version = None
|
||||
return getattr(ctx.attrs, "target_sdk_version", None) or toolchain_min_version
|
||||
|
||||
# Returns the min deployment flag to pass to the compiler + linker
|
||||
def _get_min_deployment_version_target_flag(ctx: "context") -> [None, str.type]:
|
||||
target_sdk_version = get_min_deployment_version_for_node(ctx)
|
||||
if target_sdk_version == None:
|
||||
return None
|
||||
|
||||
sdk_name = get_apple_sdk_name(ctx)
|
||||
min_version_flag = _APPLE_MIN_VERSION_FLAG_SDK_MAP.get(sdk_name)
|
||||
if min_version_flag == None:
|
||||
fail("Could not determine min version flag for SDK {}".format(sdk_name))
|
||||
|
||||
return "{}={}".format(min_version_flag, target_sdk_version)
|
||||
|
||||
# There are two main ways in which we can pass target SDK version:
|
||||
# - versioned target triple
|
||||
# - unversioned target triple + version flag
|
||||
#
|
||||
# A versioned target triple overrides any version flags and requires
|
||||
# additional flags to disable the warning/error (`-Woverriding-t-option`),
|
||||
# so we prefer to use an unversioned target triple + version flag.
|
||||
#
|
||||
# Furthermore, we want to ensure that there's _exactly one_ version flag
|
||||
# on a compiler/link line. This makes debugging easier and avoids issues
|
||||
# with multiple layers each adding/overriding target SDK. It also makes
|
||||
# it easier to switch to versioned target triple.
|
||||
#
|
||||
# There are exactly two ways in which to specify the target SDK:
|
||||
# - apple_toolchain.min_version sets the default value
|
||||
# - apple_(binary|library).target_sdk_version sets the per-target value
|
||||
#
|
||||
# apple_toolchain() rules should _never_ add any version flags because
|
||||
# the rule does _not_ know whether a particular target will request a
|
||||
# non-default value. Otherwise, we end up with multiple version flags,
|
||||
# one added by the toolchain and then additional overrides by targets.
|
||||
|
||||
def get_min_deployment_version_target_linker_flags(ctx: "context") -> [str.type]:
|
||||
min_version_flag = _get_min_deployment_version_target_flag(ctx)
|
||||
return [min_version_flag] if min_version_flag != None else []
|
||||
|
||||
def get_min_deployment_version_target_preprocessor_flags(ctx: "context") -> [CPreprocessor.type]:
|
||||
min_version_flag = _get_min_deployment_version_target_flag(ctx)
|
||||
if min_version_flag == None:
|
||||
return []
|
||||
|
||||
args = cmd_args(min_version_flag)
|
||||
return [CPreprocessor(
|
||||
args = [args],
|
||||
)]
|
||||
190
vendor/cxx/tools/buck/prelude/apple/apple_test.bzl
vendored
Normal file
190
vendor/cxx/tools/buck/prelude/apple/apple_test.bzl
vendored
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
# 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//apple:apple_library.bzl", "AppleLibraryAdditionalParams", "apple_library_rule_constructor_params_and_swift_providers")
|
||||
load("@prelude//apple:apple_toolchain_types.bzl", "AppleToolchainInfo")
|
||||
load(
|
||||
"@prelude//cxx:compile.bzl",
|
||||
"CxxSrcWithFlags", # @unused Used as a type
|
||||
)
|
||||
load("@prelude//cxx:cxx_library.bzl", "cxx_library_parameterized")
|
||||
load("@prelude//cxx:cxx_types.bzl", "CxxRuleProviderParams", "CxxRuleSubTargetParams")
|
||||
load(
|
||||
"@prelude//cxx:linker.bzl",
|
||||
"SharedLibraryFlagOverrides",
|
||||
)
|
||||
load(":apple_bundle.bzl", "AppleBundlePartListConstructorParams", "get_apple_bundle_part_list")
|
||||
load(":apple_bundle_destination.bzl", "AppleBundleDestination")
|
||||
load(":apple_bundle_part.bzl", "AppleBundlePart", "assemble_bundle", "bundle_output")
|
||||
load(":apple_bundle_types.bzl", "AppleBundleInfo")
|
||||
load(":xcode.bzl", "apple_populate_xcode_attributes")
|
||||
|
||||
def apple_test_impl(ctx: "context") -> ["provider"]:
|
||||
xctest_bundle = bundle_output(ctx)
|
||||
|
||||
test_host_app_bundle = _get_test_host_app_bundle(ctx)
|
||||
test_host_app_binary = _get_test_host_app_binary(ctx, test_host_app_bundle)
|
||||
|
||||
objc_bridging_header_flags = [
|
||||
# Disable bridging header -> PCH compilation to mitigate an issue in Xcode 13 beta.
|
||||
"-disable-bridging-pch",
|
||||
"-import-objc-header",
|
||||
cmd_args(ctx.attrs.bridging_header),
|
||||
] if ctx.attrs.bridging_header else []
|
||||
|
||||
constructor_params, _, _ = apple_library_rule_constructor_params_and_swift_providers(
|
||||
ctx,
|
||||
AppleLibraryAdditionalParams(
|
||||
rule_type = "apple_test",
|
||||
extra_exported_link_flags = _get_xctest_framework_linker_flags(ctx) + _get_bundle_loader_flags(test_host_app_binary),
|
||||
extra_swift_compiler_flags = _get_xctest_framework_search_paths_flags(ctx) + objc_bridging_header_flags,
|
||||
shared_library_flags = SharedLibraryFlagOverrides(
|
||||
# When `-bundle` is used we can't use the `-install_name` args, thus we keep this field empty.
|
||||
shared_library_name_linker_flags_format = [],
|
||||
# When building Apple tests, we want to link with `-bundle` instead of `-shared` to allow
|
||||
# linking against the bundle loader.
|
||||
shared_library_flags = ["-bundle"],
|
||||
),
|
||||
generate_sub_targets = CxxRuleSubTargetParams(
|
||||
compilation_database = False,
|
||||
headers = False,
|
||||
link_group_map = False,
|
||||
link_style_outputs = False,
|
||||
),
|
||||
generate_providers = CxxRuleProviderParams(
|
||||
compilation_database = True,
|
||||
default = False,
|
||||
linkable_graph = False,
|
||||
link_style_outputs = False,
|
||||
merged_native_link_info = False,
|
||||
omnibus_root = False,
|
||||
preprocessors = False,
|
||||
resources = False,
|
||||
shared_libraries = False,
|
||||
template_placeholders = False,
|
||||
),
|
||||
populate_xcode_attributes_func = lambda local_ctx, **kwargs: _xcode_populate_attributes(ctx = local_ctx, xctest_bundle = xctest_bundle, test_host_app_binary = test_host_app_binary, **kwargs),
|
||||
# We want to statically link the transitive dep graph of the apple_test()
|
||||
# which we can achieve by forcing link group linking with
|
||||
# an empty mapping (i.e., default mapping).
|
||||
force_link_group_linking = True,
|
||||
),
|
||||
)
|
||||
cxx_library_output = cxx_library_parameterized(ctx, constructor_params)
|
||||
|
||||
binary_part = AppleBundlePart(source = cxx_library_output.default_output.default, destination = AppleBundleDestination("executables"), new_name = ctx.attrs.name)
|
||||
part_list_output = get_apple_bundle_part_list(ctx, AppleBundlePartListConstructorParams(binaries = [binary_part]))
|
||||
assemble_bundle(ctx, xctest_bundle, part_list_output.parts, part_list_output.info_plist_part)
|
||||
|
||||
sub_targets = cxx_library_output.sub_targets
|
||||
|
||||
# If the test has a test host, add a subtarget to build the test host app bundle.
|
||||
sub_targets["test-host"] = [DefaultInfo(default_outputs = [test_host_app_bundle])] if test_host_app_bundle else [DefaultInfo()]
|
||||
|
||||
# When interacting with Tpx, we just pass our various inputs via env vars,
|
||||
# since Tpx basiclaly wants structured output for this.
|
||||
env = {"XCTEST_BUNDLE": xctest_bundle}
|
||||
|
||||
if test_host_app_bundle == None:
|
||||
tpx_label = "tpx:apple_test:buck2:logicTest"
|
||||
else:
|
||||
env["HOST_APP_BUNDLE"] = test_host_app_bundle
|
||||
tpx_label = "tpx:apple_test:buck2:appTest"
|
||||
|
||||
labels = ctx.attrs.labels + [tpx_label]
|
||||
labels.append(tpx_label)
|
||||
|
||||
return [
|
||||
DefaultInfo(default_outputs = [xctest_bundle], sub_targets = sub_targets),
|
||||
ExternalRunnerTestInfo(
|
||||
type = "custom", # We inherit a label via the macro layer that overrides this.
|
||||
command = ["false"], # Tpx makes up its own args, we just pass params via the env.
|
||||
env = env,
|
||||
labels = labels,
|
||||
use_project_relative_paths = True,
|
||||
run_from_project_root = True,
|
||||
contacts = ctx.attrs.contacts,
|
||||
executor_overrides = {
|
||||
"ios-simulator": CommandExecutorConfig(
|
||||
local_enabled = False,
|
||||
remote_enabled = True,
|
||||
remote_execution_properties = {
|
||||
"platform": "ios-simulator-pure-re",
|
||||
"subplatform": "iPhone 8.iOS 15.0",
|
||||
"xcode-version": "xcodestable",
|
||||
},
|
||||
remote_execution_use_case = "tpx-default",
|
||||
),
|
||||
"static-listing": CommandExecutorConfig(local_enabled = True, remote_enabled = False),
|
||||
},
|
||||
),
|
||||
cxx_library_output.xcode_data_info,
|
||||
cxx_library_output.cxx_compilationdb_info,
|
||||
]
|
||||
|
||||
def _get_test_host_app_bundle(ctx: "context") -> ["artifact", None]:
|
||||
""" Get the bundle for the test host app, if one exists for this test. """
|
||||
if ctx.attrs.test_host_app:
|
||||
# Copy the test host app bundle into test's output directory
|
||||
original_bundle = ctx.attrs.test_host_app[AppleBundleInfo].bundle
|
||||
test_host_app_bundle = ctx.actions.declare_output(original_bundle.basename)
|
||||
ctx.actions.copy_file(test_host_app_bundle, original_bundle)
|
||||
return test_host_app_bundle
|
||||
|
||||
return None
|
||||
|
||||
def _get_test_host_app_binary(ctx: "context", test_host_app_bundle: ["artifact", None]) -> ["cmd_args", None]:
|
||||
""" Reference to the binary with the test host app bundle, if one exists for this test. Captures the bundle as an artifact in the cmd_args. """
|
||||
if ctx.attrs.test_host_app:
|
||||
return cmd_args([test_host_app_bundle, ctx.attrs.test_host_app[AppleBundleInfo].binary_name], delimiter = "/")
|
||||
|
||||
return None
|
||||
|
||||
def _get_bundle_loader_flags(binary: ["cmd_args", None]) -> [""]:
|
||||
if binary:
|
||||
# During linking we need to link the test shared lib against the test host binary. The
|
||||
# test host binary doesn't need to be embedded in an `apple_bundle`.
|
||||
return ["-bundle_loader", binary]
|
||||
|
||||
return []
|
||||
|
||||
def _xcode_populate_attributes(
|
||||
ctx,
|
||||
srcs: [CxxSrcWithFlags.type],
|
||||
argsfiles_by_ext: {str.type: "artifact"},
|
||||
xctest_bundle: "artifact",
|
||||
test_host_app_binary: ["cmd_args", None],
|
||||
**_kwargs) -> {str.type: ""}:
|
||||
data = apple_populate_xcode_attributes(ctx = ctx, srcs = srcs, argsfiles_by_ext = argsfiles_by_ext, product_name = ctx.attrs.name)
|
||||
data["output"] = xctest_bundle
|
||||
if test_host_app_binary:
|
||||
data["test_host_app_binary"] = test_host_app_binary
|
||||
return data
|
||||
|
||||
def _get_xctest_framework_search_paths(ctx: "context") -> ("cmd_args", "cmd_args"):
|
||||
toolchain = ctx.attrs._apple_toolchain[AppleToolchainInfo]
|
||||
xctest_swiftmodule_search_path = cmd_args([toolchain.platform_path, "Developer/usr/lib"], delimiter = "/")
|
||||
xctest_framework_search_path = cmd_args([toolchain.platform_path, "Developer/Library/Frameworks"], delimiter = "/")
|
||||
return (xctest_swiftmodule_search_path, xctest_framework_search_path)
|
||||
|
||||
def _get_xctest_framework_search_paths_flags(ctx: "context") -> [["cmd_args", str.type]]:
|
||||
xctest_swiftmodule_search_path, xctest_framework_search_path = _get_xctest_framework_search_paths(ctx)
|
||||
return [
|
||||
"-I",
|
||||
xctest_swiftmodule_search_path,
|
||||
"-F",
|
||||
xctest_framework_search_path,
|
||||
]
|
||||
|
||||
def _get_xctest_framework_linker_flags(ctx: "context") -> [["cmd_args", str.type]]:
|
||||
xctest_swiftmodule_search_path, xctest_framework_search_path = _get_xctest_framework_search_paths(ctx)
|
||||
return [
|
||||
"-L",
|
||||
xctest_swiftmodule_search_path,
|
||||
"-F",
|
||||
xctest_framework_search_path,
|
||||
]
|
||||
24
vendor/cxx/tools/buck/prelude/apple/apple_test_macro_layer.bzl
vendored
Normal file
24
vendor/cxx/tools/buck/prelude/apple/apple_test_macro_layer.bzl
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# 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(":apple_bundle_config.bzl", "apple_bundle_config")
|
||||
load(":apple_macro_layer.bzl", "apple_macro_layer_set_bool_override_attrs_from_config")
|
||||
load(
|
||||
":apple_rules_impl_utility.bzl",
|
||||
"APPLE_LINK_LIBRARIES_LOCALLY_OVERRIDE_ATTR_NAME",
|
||||
)
|
||||
|
||||
_APPLE_TEST_LOCAL_EXECUTION_OVERRIDES = {
|
||||
APPLE_LINK_LIBRARIES_LOCALLY_OVERRIDE_ATTR_NAME: ("apple", "link_libraries_locally_override"),
|
||||
}
|
||||
|
||||
def apple_test_macro_impl(apple_test_rule = None, **kwargs):
|
||||
kwargs.update(apple_bundle_config())
|
||||
kwargs.update(apple_macro_layer_set_bool_override_attrs_from_config(_APPLE_TEST_LOCAL_EXECUTION_OVERRIDES))
|
||||
apple_test_rule(
|
||||
**kwargs
|
||||
)
|
||||
43
vendor/cxx/tools/buck/prelude/apple/apple_toolchain.bzl
vendored
Normal file
43
vendor/cxx/tools/buck/prelude/apple/apple_toolchain.bzl
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# 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//apple:apple_toolchain_types.bzl", "AppleToolchainInfo")
|
||||
load("@prelude//apple:swift_toolchain_types.bzl", "SwiftToolchainInfo")
|
||||
load("@prelude//cxx:cxx_toolchain_types.bzl", "CxxPlatformInfo", "CxxToolchainInfo")
|
||||
|
||||
def apple_toolchain_impl(ctx: "context") -> ["provider"]:
|
||||
sdk_path = ctx.attrs._internal_sdk_path or ctx.attrs.sdk_path
|
||||
platform_path = ctx.attrs._internal_platform_path or ctx.attrs.platform_path
|
||||
return [
|
||||
DefaultInfo(),
|
||||
AppleToolchainInfo(
|
||||
actool = ctx.attrs.actool[RunInfo],
|
||||
ibtool = ctx.attrs.ibtool[RunInfo],
|
||||
dsymutil = ctx.attrs.dsymutil[RunInfo],
|
||||
dwarfdump = ctx.attrs.dwarfdump[RunInfo] if ctx.attrs.dwarfdump else None,
|
||||
lipo = ctx.attrs.lipo[RunInfo],
|
||||
cxx_platform_info = ctx.attrs.cxx_toolchain[CxxPlatformInfo],
|
||||
cxx_toolchain_info = ctx.attrs.cxx_toolchain[CxxToolchainInfo],
|
||||
codesign = ctx.attrs.codesign[RunInfo],
|
||||
codesign_allocate = ctx.attrs.codesign_allocate[RunInfo],
|
||||
codesign_identities_command = ctx.attrs.codesign_identities_command[RunInfo] if ctx.attrs.codesign_identities_command else None,
|
||||
compile_resources_locally = ctx.attrs.compile_resources_locally,
|
||||
libtool = ctx.attrs.libtool[RunInfo],
|
||||
momc = ctx.attrs.momc[RunInfo],
|
||||
min_version = ctx.attrs.min_version,
|
||||
xctest = ctx.attrs.xctest[RunInfo],
|
||||
platform_path = platform_path,
|
||||
sdk_name = ctx.attrs.sdk_name,
|
||||
sdk_path = sdk_path,
|
||||
sdk_version = ctx.attrs.version,
|
||||
sdk_build_version = ctx.attrs.build_version,
|
||||
swift_toolchain_info = ctx.attrs.swift_toolchain[SwiftToolchainInfo] if ctx.attrs.swift_toolchain else None,
|
||||
watch_kit_stub_binary = ctx.attrs.watch_kit_stub_binary,
|
||||
xcode_version = ctx.attrs.xcode_version,
|
||||
xcode_build_version = ctx.attrs.xcode_build_version,
|
||||
),
|
||||
]
|
||||
43
vendor/cxx/tools/buck/prelude/apple/apple_toolchain_types.bzl
vendored
Normal file
43
vendor/cxx/tools/buck/prelude/apple/apple_toolchain_types.bzl
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# 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.
|
||||
|
||||
AppleToolchainInfo = provider(fields = [
|
||||
"actool", # "RunInfo"
|
||||
"ibtool", # "RunInfo"
|
||||
"dsymutil", # "RunInfo"
|
||||
"dwarfdump", # ["RunInfo", None]
|
||||
"lipo", # "RunInfo"
|
||||
"cxx_platform_info", # "CxxPlatformInfo"
|
||||
"cxx_toolchain_info", # "CxxToolchainInfo"
|
||||
"codesign", # "RunInfo"
|
||||
"codesign_allocate", # "RunInfo"
|
||||
"codesign_identities_command", # ["RunInfo", None]
|
||||
"compile_resources_locally", # bool.type
|
||||
"libtool", # "RunInfo"
|
||||
"momc", # "RunInfo"
|
||||
"min_version", # [None, str.type]
|
||||
"xctest", # "RunInfo"
|
||||
"platform_path", # [str.type, artifact]
|
||||
# SDK name to be passed to tools (e.g. actool), equivalent to ApplePlatform::getExternalName() in v1.
|
||||
"sdk_name", # str.type
|
||||
"sdk_path", # [str.type, artifact]
|
||||
# TODO(T124581557) Make it non-optional once there is no "selected xcode" toolchain
|
||||
"sdk_version", # [None, str.type]
|
||||
"sdk_build_version", # "[None, str.type]"
|
||||
"swift_toolchain_info", # "SwiftToolchainInfo"
|
||||
"watch_kit_stub_binary", # "artifact"
|
||||
"xcode_version", # "[None, str.type]"
|
||||
"xcode_build_version", # "[None, str.type]"
|
||||
])
|
||||
|
||||
AppleToolsInfo = provider(fields = [
|
||||
"assemble_bundle", # RunInfo
|
||||
"info_plist_processor", # RunInfo
|
||||
"make_modulemap", # "RunInfo"
|
||||
"make_vfsoverlay", # "RunInfo"
|
||||
"swift_objc_header_postprocess", # "RunInfo"
|
||||
])
|
||||
82
vendor/cxx/tools/buck/prelude/apple/apple_utility.bzl
vendored
Normal file
82
vendor/cxx/tools/buck/prelude/apple/apple_utility.bzl
vendored
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
# 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//apple:apple_toolchain_types.bzl", "AppleToolchainInfo")
|
||||
load("@prelude//cxx:headers.bzl", "CxxHeadersLayout", "CxxHeadersNaming")
|
||||
load("@prelude//utils:utils.bzl", "value_or")
|
||||
load(":apple_target_sdk_version.bzl", "get_min_deployment_version_for_node")
|
||||
|
||||
_VERSION_PLACEHOLDER = "(VERSION)"
|
||||
|
||||
# TODO(T115177501): Make target triples part of the toolchains
|
||||
# Map from SDK name -> target triple _without_ leading architecture
|
||||
_TARGET_TRIPLE_MAP = {
|
||||
"iphoneos": "apple-ios{}".format(_VERSION_PLACEHOLDER),
|
||||
"iphonesimulator": "apple-ios{}-simulator".format(_VERSION_PLACEHOLDER),
|
||||
"macosx": "apple-macosx{}".format(_VERSION_PLACEHOLDER),
|
||||
"watchos": "apple-watchos{}".format(_VERSION_PLACEHOLDER),
|
||||
"watchsimulator": "apple-watchos{}-simulator".format(_VERSION_PLACEHOLDER),
|
||||
}
|
||||
|
||||
def get_apple_cxx_headers_layout(ctx: "context") -> CxxHeadersLayout.type:
|
||||
namespace = value_or(ctx.attrs.header_path_prefix, ctx.attrs.name)
|
||||
return CxxHeadersLayout(namespace = namespace, naming = CxxHeadersNaming("apple"))
|
||||
|
||||
def get_module_name(ctx: "context") -> str.type:
|
||||
return ctx.attrs.module_name or ctx.attrs.header_path_prefix or ctx.attrs.name
|
||||
|
||||
def has_apple_toolchain(ctx: "context") -> bool.type:
|
||||
return hasattr(ctx.attrs, "_apple_toolchain")
|
||||
|
||||
def get_versioned_target_triple(ctx: "context") -> str.type:
|
||||
apple_toolchain_info = ctx.attrs._apple_toolchain[AppleToolchainInfo]
|
||||
swift_toolchain_info = apple_toolchain_info.swift_toolchain_info
|
||||
|
||||
architecture = swift_toolchain_info.architecture
|
||||
if architecture == None:
|
||||
fail("Need to set `architecture` field of swift_toolchain(), target: {}".format(ctx.label))
|
||||
|
||||
target_sdk_version = get_min_deployment_version_for_node(ctx) or ""
|
||||
|
||||
sdk_name = apple_toolchain_info.sdk_name
|
||||
target_triple_with_version_placeholder = _TARGET_TRIPLE_MAP.get(sdk_name)
|
||||
if target_triple_with_version_placeholder == None:
|
||||
fail("Could not find target triple for sdk = {}".format(sdk_name))
|
||||
|
||||
versioned_target_triple = target_triple_with_version_placeholder.replace(_VERSION_PLACEHOLDER, target_sdk_version)
|
||||
return "{}-{}".format(architecture, versioned_target_triple)
|
||||
|
||||
def expand_relative_prefixed_sdk_path(
|
||||
sdk_path: "cmd_args",
|
||||
swift_resource_dir: "cmd_args",
|
||||
path_to_expand: str.type) -> "cmd_args":
|
||||
path_expansion_map = {
|
||||
"$RESOURCEDIR": swift_resource_dir,
|
||||
"$SDKROOT": sdk_path,
|
||||
}
|
||||
expanded_cmd = cmd_args()
|
||||
for (path_variable, path_value) in path_expansion_map.items():
|
||||
if path_to_expand.startswith(path_variable):
|
||||
path = path_to_expand[len(path_variable):]
|
||||
if path.find("$") == 0:
|
||||
fail("Failed to expand framework path: {}".format(path))
|
||||
expanded_cmd.add(cmd_args([path_value, path], delimiter = ""))
|
||||
|
||||
return expanded_cmd
|
||||
|
||||
def get_disable_pch_validation_flags() -> [str.type]:
|
||||
"""
|
||||
We need to disable PCH validation for some actions like Swift compilation and Swift PCM generation.
|
||||
Currently, we don't have a mechanism to compile with enabled pch validation and Swift explicit modules,
|
||||
which we need to be able to do while we are waiting for Anonymous targets which will allow us to solve this problem properly.
|
||||
"""
|
||||
return [
|
||||
"-Xcc",
|
||||
"-Xclang",
|
||||
"-Xcc",
|
||||
"-fno-validate-pch",
|
||||
]
|
||||
88
vendor/cxx/tools/buck/prelude/apple/modulemap.bzl
vendored
Normal file
88
vendor/cxx/tools/buck/prelude/apple/modulemap.bzl
vendored
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
# 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//apple:apple_toolchain_types.bzl", "AppleToolsInfo")
|
||||
load(
|
||||
"@prelude//cxx:headers.bzl",
|
||||
"CHeader", # @unused Used as a type
|
||||
)
|
||||
load(
|
||||
"@prelude//cxx:preprocessor.bzl",
|
||||
"CPreprocessor",
|
||||
)
|
||||
load(":apple_utility.bzl", "get_module_name")
|
||||
|
||||
def preprocessor_info_for_modulemap(ctx: "context", name: str.type, headers: [CHeader.type], swift_header: ["artifact", None]) -> "CPreprocessor":
|
||||
# We don't want to name this module.modulemap to avoid implicit importing
|
||||
if name == "module":
|
||||
fail("Don't use the name `module` for modulemaps, this will allow for implicit importing.")
|
||||
|
||||
module_name = get_module_name(ctx)
|
||||
|
||||
# Create a map of header import path to artifact location
|
||||
header_map = {}
|
||||
for h in headers:
|
||||
if h.namespace:
|
||||
header_map["{}/{}".format(h.namespace, h.name)] = h.artifact
|
||||
else:
|
||||
header_map[h.name] = h.artifact
|
||||
|
||||
# We need to include the Swift header in the symlink tree too
|
||||
swift_header_name = "{}/{}-Swift.h".format(module_name, module_name)
|
||||
if swift_header:
|
||||
header_map[swift_header_name] = swift_header
|
||||
|
||||
# Create a symlink dir for the headers to import
|
||||
symlink_tree = ctx.actions.symlinked_dir(name + "_symlink_tree", header_map)
|
||||
|
||||
# Create a modulemap at the root of that tree
|
||||
output = ctx.actions.declare_output(name + ".modulemap")
|
||||
cmd = cmd_args(ctx.attrs._apple_tools[AppleToolsInfo].make_modulemap)
|
||||
cmd.add([
|
||||
"--output",
|
||||
output.as_output(),
|
||||
"--name",
|
||||
get_module_name(ctx),
|
||||
"--symlink-tree",
|
||||
symlink_tree,
|
||||
])
|
||||
|
||||
if swift_header:
|
||||
cmd.add([
|
||||
"--swift-header",
|
||||
swift_header,
|
||||
])
|
||||
|
||||
if ctx.attrs.use_submodules:
|
||||
cmd.add("--use-submodules")
|
||||
|
||||
for hdr in sorted(header_map.keys()):
|
||||
# Don't include the Swift header in the mappings, this is handled separately.
|
||||
if hdr != swift_header_name:
|
||||
cmd.add(hdr)
|
||||
|
||||
ctx.actions.run(cmd, category = "modulemap", identifier = name)
|
||||
|
||||
return CPreprocessor(
|
||||
modular_args = _args_for_modulemap(output, symlink_tree, swift_header),
|
||||
modulemap_path = cmd_args(output).hidden(cmd_args(symlink_tree)),
|
||||
args = _exported_preprocessor_args(symlink_tree),
|
||||
)
|
||||
|
||||
def _args_for_modulemap(
|
||||
modulemap: "artifact",
|
||||
symlink_tree: "artifact",
|
||||
swift_header: ["artifact", None]) -> ["cmd_args"]:
|
||||
cmd = cmd_args(modulemap, format = "-fmodule-map-file={}")
|
||||
cmd.hidden(symlink_tree)
|
||||
if swift_header:
|
||||
cmd.hidden(swift_header)
|
||||
|
||||
return [cmd]
|
||||
|
||||
def _exported_preprocessor_args(symlink_tree: "artifact") -> ["cmd_args"]:
|
||||
return [cmd_args(symlink_tree, format = "-I{}")]
|
||||
105
vendor/cxx/tools/buck/prelude/apple/prebuilt_apple_framework.bzl
vendored
Normal file
105
vendor/cxx/tools/buck/prelude/apple/prebuilt_apple_framework.bzl
vendored
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
# 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//cxx:cxx_library_utility.bzl",
|
||||
"cxx_attr_exported_linker_flags",
|
||||
"cxx_platform_supported",
|
||||
)
|
||||
load(
|
||||
"@prelude//cxx:preprocessor.bzl",
|
||||
"CPreprocessor",
|
||||
"cxx_inherited_preprocessor_infos",
|
||||
"cxx_merge_cpreprocessors",
|
||||
)
|
||||
load(
|
||||
"@prelude//linking:link_groups.bzl",
|
||||
"merge_link_group_lib_info",
|
||||
)
|
||||
load(
|
||||
"@prelude//linking:link_info.bzl",
|
||||
"LinkInfo",
|
||||
"LinkInfos",
|
||||
"LinkStyle",
|
||||
"Linkage",
|
||||
"create_merged_link_info",
|
||||
)
|
||||
load(
|
||||
"@prelude//linking:linkable_graph.bzl",
|
||||
"create_linkable_graph",
|
||||
"create_linkable_graph_node",
|
||||
"create_linkable_node",
|
||||
)
|
||||
load(
|
||||
"@prelude//linking:shared_libraries.bzl",
|
||||
"SharedLibraryInfo",
|
||||
"merge_shared_libraries",
|
||||
)
|
||||
load("@prelude//utils:utils.bzl", "filter_and_map_idx")
|
||||
load(":apple_bundle_types.bzl", "AppleBundleInfo")
|
||||
load(":apple_frameworks.bzl", "to_framework_name")
|
||||
|
||||
def prebuilt_apple_framework_impl(ctx: "context") -> ["provider"]:
|
||||
providers = []
|
||||
|
||||
framework_directory_artifact = ctx.attrs.framework
|
||||
|
||||
# Check this rule's `supported_platforms_regex` with the current platform.
|
||||
if cxx_platform_supported(ctx):
|
||||
# Sandbox the framework, to avoid leaking other frameworks via search paths.
|
||||
framework_name = to_framework_name(framework_directory_artifact.basename)
|
||||
framework_dir = ctx.actions.symlinked_dir(
|
||||
"Frameworks",
|
||||
{framework_name + ".framework": framework_directory_artifact},
|
||||
)
|
||||
|
||||
# Add framework & pp info from deps.
|
||||
inherited_pp_info = cxx_inherited_preprocessor_infos(ctx.attrs.deps)
|
||||
providers.append(cxx_merge_cpreprocessors(
|
||||
ctx,
|
||||
[CPreprocessor(args = ["-F", framework_dir])],
|
||||
inherited_pp_info,
|
||||
))
|
||||
|
||||
# Add framework to link args.
|
||||
# TODO(T110378120): Support shared linking for mac targets:
|
||||
# https://fburl.com/code/pqrtt1qr.
|
||||
args = []
|
||||
args.extend(cxx_attr_exported_linker_flags(ctx))
|
||||
args.extend(["-F", framework_dir])
|
||||
args.extend(["-framework", framework_name])
|
||||
link = LinkInfo(
|
||||
name = framework_name,
|
||||
pre_flags = args,
|
||||
)
|
||||
providers.append(create_merged_link_info(
|
||||
ctx,
|
||||
{link_style: LinkInfos(default = link) for link_style in LinkStyle},
|
||||
))
|
||||
|
||||
# Create, augment and provide the linkable graph.
|
||||
linkable_graph = create_linkable_graph(
|
||||
ctx,
|
||||
node = create_linkable_graph_node(
|
||||
ctx,
|
||||
linkable_node = create_linkable_node(
|
||||
ctx,
|
||||
preferred_linkage = Linkage("shared"),
|
||||
link_infos = {LinkStyle("shared"): LinkInfos(default = link)},
|
||||
),
|
||||
excluded = {ctx.label: None},
|
||||
),
|
||||
)
|
||||
providers.append(linkable_graph)
|
||||
|
||||
# The default output is the provided framework.
|
||||
providers.append(DefaultInfo(default_outputs = [framework_directory_artifact]))
|
||||
providers.append(AppleBundleInfo(bundle = framework_directory_artifact, is_watchos = None))
|
||||
providers.append(merge_link_group_lib_info(deps = ctx.attrs.deps))
|
||||
providers.append(merge_shared_libraries(ctx.actions, deps = filter_and_map_idx(SharedLibraryInfo, ctx.attrs.deps)))
|
||||
|
||||
return providers
|
||||
148
vendor/cxx/tools/buck/prelude/apple/resource_groups.bzl
vendored
Normal file
148
vendor/cxx/tools/buck/prelude/apple/resource_groups.bzl
vendored
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
# 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//cxx:groups.bzl",
|
||||
"MATCH_ALL_LABEL",
|
||||
)
|
||||
load(
|
||||
"@prelude//utils:graph_utils.bzl",
|
||||
"breadth_first_traversal_by",
|
||||
)
|
||||
load(":apple_asset_catalog_types.bzl", "AppleAssetCatalogSpec")
|
||||
load(":apple_core_data_types.bzl", "AppleCoreDataSpec")
|
||||
load(":apple_resource_types.bzl", "AppleResourceSpec")
|
||||
|
||||
ResourceGroupInfo = provider(fields = [
|
||||
"groups", # [Group.type]
|
||||
"groups_hash", # str.type
|
||||
"mappings", # {"label": str.type}
|
||||
])
|
||||
|
||||
ResourceGraphNode = record(
|
||||
label = field("label"),
|
||||
# Attribute labels on the target.
|
||||
labels = field([str.type], []),
|
||||
# Deps of this target which might have resources transitively.
|
||||
deps = field(["label"], []),
|
||||
# Exported deps of this target which might have resources transitively.
|
||||
exported_deps = field(["label"], []),
|
||||
# Actual resource data, present when node corresponds to `apple_resource` target.
|
||||
resource_spec = field([AppleResourceSpec.type, None], None),
|
||||
# Actual asset catalog data, present when node corresponds to `apple_asset_catalog` target.
|
||||
asset_catalog_spec = field([AppleAssetCatalogSpec.type, None], None),
|
||||
# Actual core data, present when node corresponds to `core_data_model` target
|
||||
core_data_spec = field([AppleCoreDataSpec.type, None], None),
|
||||
)
|
||||
|
||||
ResourceGraphTSet = transitive_set()
|
||||
|
||||
ResourceGraph = provider(fields = [
|
||||
"label", # "label"
|
||||
"nodes", # "ResourceGraphTSet"
|
||||
])
|
||||
|
||||
def create_resource_graph(
|
||||
ctx: "context",
|
||||
labels: [str.type],
|
||||
deps: ["dependency"],
|
||||
exported_deps: ["dependency"],
|
||||
resource_spec: [AppleResourceSpec.type, None] = None,
|
||||
asset_catalog_spec: [AppleAssetCatalogSpec.type, None] = None,
|
||||
core_data_spec: [AppleCoreDataSpec.type, None] = None) -> ResourceGraph.type:
|
||||
node = ResourceGraphNode(
|
||||
label = ctx.label,
|
||||
labels = labels,
|
||||
deps = _with_resources_deps(deps),
|
||||
exported_deps = _with_resources_deps(exported_deps),
|
||||
resource_spec = resource_spec,
|
||||
asset_catalog_spec = asset_catalog_spec,
|
||||
core_data_spec = core_data_spec,
|
||||
)
|
||||
all_deps = deps + exported_deps
|
||||
child_nodes = filter(None, [d.get(ResourceGraph) for d in all_deps])
|
||||
return ResourceGraph(
|
||||
label = ctx.label,
|
||||
nodes = ctx.actions.tset(ResourceGraphTSet, value = node, children = [child_node.nodes for child_node in child_nodes]),
|
||||
)
|
||||
|
||||
def get_resource_graph_node_map_func(graph: ResourceGraph.type):
|
||||
def get_resource_graph_node_map() -> {"label": ResourceGraphNode.type}:
|
||||
nodes = graph.nodes.traverse()
|
||||
return {node.label: node for node in filter(None, nodes)}
|
||||
|
||||
return get_resource_graph_node_map
|
||||
|
||||
def _with_resources_deps(deps: ["dependency"]) -> ["label"]:
|
||||
"""
|
||||
Filters dependencies and returns only those which are relevant
|
||||
to working with resources i.e. those which contains resource graph provider.
|
||||
"""
|
||||
graphs = filter(None, [d.get(ResourceGraph) for d in deps])
|
||||
return [g.label for g in graphs]
|
||||
|
||||
def get_resource_group_info(ctx: "context") -> [ResourceGroupInfo.type, None]:
|
||||
"""
|
||||
Parses the currently analyzed context for any resource group definitions
|
||||
and returns a list of all resource groups with their mappings.
|
||||
"""
|
||||
resource_group_map = ctx.attrs.resource_group_map
|
||||
|
||||
if not resource_group_map:
|
||||
return None
|
||||
|
||||
if type(resource_group_map) == "dependency":
|
||||
return resource_group_map[ResourceGroupInfo]
|
||||
|
||||
fail("Resource group maps must be provided as a resource_group_map rule dependency.")
|
||||
|
||||
def get_filtered_resources(
|
||||
root: "label",
|
||||
resource_graph_node_map_func,
|
||||
resource_group: [str.type, None],
|
||||
resource_group_mappings: [{"label": str.type}, None]) -> ([AppleResourceSpec.type], [AppleAssetCatalogSpec.type], [AppleCoreDataSpec.type]):
|
||||
"""
|
||||
Walks the provided DAG and collects resources matching resource groups definition.
|
||||
"""
|
||||
|
||||
resource_graph_node_map = resource_graph_node_map_func()
|
||||
|
||||
def get_traversed_deps(target: "label") -> ["label"]:
|
||||
node = resource_graph_node_map[target] # buildifier: disable=uninitialized
|
||||
return node.exported_deps + node.deps
|
||||
|
||||
targets = breadth_first_traversal_by(
|
||||
resource_graph_node_map,
|
||||
get_traversed_deps(root),
|
||||
get_traversed_deps,
|
||||
)
|
||||
|
||||
resource_specs = []
|
||||
asset_catalog_specs = []
|
||||
core_data_specs = []
|
||||
|
||||
for target in targets:
|
||||
target_resource_group = resource_group_mappings.get(target)
|
||||
|
||||
# Ungrouped targets belong to the unlabeled bundle
|
||||
if ((not target_resource_group and not resource_group) or
|
||||
# Does it match special "MATCH_ALL" mapping?
|
||||
target_resource_group == MATCH_ALL_LABEL or
|
||||
# Does it match currently evaluated group?
|
||||
target_resource_group == resource_group):
|
||||
node = resource_graph_node_map[target]
|
||||
resource_spec = node.resource_spec
|
||||
if resource_spec:
|
||||
resource_specs.append(resource_spec)
|
||||
asset_catalog_spec = node.asset_catalog_spec
|
||||
if asset_catalog_spec:
|
||||
asset_catalog_specs.append(asset_catalog_spec)
|
||||
core_data_spec = node.core_data_spec
|
||||
if core_data_spec:
|
||||
core_data_specs.append(core_data_spec)
|
||||
|
||||
return resource_specs, asset_catalog_specs, core_data_specs
|
||||
474
vendor/cxx/tools/buck/prelude/apple/swift_compilation.bzl
vendored
Normal file
474
vendor/cxx/tools/buck/prelude/apple/swift_compilation.bzl
vendored
Normal file
|
|
@ -0,0 +1,474 @@
|
|||
# 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//:paths.bzl", "paths")
|
||||
load("@prelude//apple:apple_toolchain_types.bzl", "AppleToolsInfo")
|
||||
load(
|
||||
"@prelude//cxx:compile.bzl",
|
||||
"CxxSrcWithFlags", # @unused Used as a type
|
||||
)
|
||||
load("@prelude//cxx:cxx_types.bzl", "CxxAdditionalArgsfileParams")
|
||||
load("@prelude//cxx:headers.bzl", "CHeader")
|
||||
load(
|
||||
"@prelude//cxx:preprocessor.bzl",
|
||||
"CPreprocessor",
|
||||
"cxx_inherited_preprocessor_infos",
|
||||
"cxx_merge_cpreprocessors",
|
||||
)
|
||||
load(":apple_sdk_modules_utility.bzl", "get_sdk_deps_tset", "is_sdk_modules_provided")
|
||||
load(":apple_toolchain_types.bzl", "AppleToolchainInfo")
|
||||
load(":apple_utility.bzl", "get_disable_pch_validation_flags", "get_module_name", "get_versioned_target_triple")
|
||||
load(":modulemap.bzl", "preprocessor_info_for_modulemap")
|
||||
load(":swift_module_map.bzl", "write_swift_module_map_with_swift_deps")
|
||||
load(":swift_pcm_compilation.bzl", "compile_swift_pcm", "get_pcm_deps_tset")
|
||||
|
||||
def _add_swiftmodule_search_path(swiftmodule_path: "artifact"):
|
||||
# Value will contain a path to the artifact,
|
||||
# while we need only the folder which contains the artifact.
|
||||
return ["-I", cmd_args(swiftmodule_path).parent()]
|
||||
|
||||
def _hidden_projection(swiftmodule_path: "artifact"):
|
||||
return swiftmodule_path
|
||||
|
||||
def _linker_args_projection(swiftmodule_path: "artifact"):
|
||||
return cmd_args(swiftmodule_path, format = "-Wl,-add_ast_path,{}")
|
||||
|
||||
SwiftmodulePathsTSet = transitive_set(args_projections = {
|
||||
"hidden": _hidden_projection,
|
||||
"linker_args": _linker_args_projection,
|
||||
"module_search_path": _add_swiftmodule_search_path,
|
||||
})
|
||||
|
||||
ExportedHeadersTSet = transitive_set()
|
||||
|
||||
SwiftDependencyInfo = provider(fields = [
|
||||
"exported_headers", # ExportedHeadersTSet of {"module_name": [exported_headers]}
|
||||
"exported_swiftmodule_paths", # SwiftmodulePathsTSet of artifact that includes only paths through exported_deps, used for compilation
|
||||
"transitive_swiftmodule_paths", # SwiftmodulePathsTSet of artifact that includes all transitive paths, used for linking
|
||||
])
|
||||
|
||||
SwiftCompilationOutput = record(
|
||||
# The object files output from compilation.
|
||||
object_files = field(["artifact"]),
|
||||
# The swiftmodule file output from compilation.
|
||||
swiftmodule = field("artifact"),
|
||||
# The dependency info provider that provides the swiftmodule
|
||||
# search paths required for compilation.
|
||||
providers = field([["SwiftPCMCompilationInfo", "SwiftDependencyInfo"]]),
|
||||
# Preprocessor info required for ObjC compilation of this library.
|
||||
pre = field(CPreprocessor.type),
|
||||
# Exported preprocessor info required for ObjC compilation of rdeps.
|
||||
exported_pre = field(CPreprocessor.type),
|
||||
# Argsfile to compile an object file which is used by some subtargets.
|
||||
swift_argsfile = field("CxxAdditionalArgsfileParams"),
|
||||
)
|
||||
|
||||
_REQUIRED_SDK_MODULES = ["Swift", "SwiftOnoneSupport", "Darwin", "_Concurrency"]
|
||||
|
||||
def compile_swift(
|
||||
ctx: "context",
|
||||
srcs: [CxxSrcWithFlags.type],
|
||||
exported_headers: [CHeader.type],
|
||||
objc_modulemap_pp_info: ["CPreprocessor", None],
|
||||
extra_search_paths_flags: ["_arglike"] = []) -> ["SwiftCompilationOutput", None]:
|
||||
if not srcs:
|
||||
return None
|
||||
|
||||
toolchain = ctx.attrs._apple_toolchain[AppleToolchainInfo].swift_toolchain_info
|
||||
|
||||
module_name = get_module_name(ctx)
|
||||
output_header = ctx.actions.declare_output(module_name + "-Swift.h")
|
||||
output_object = ctx.actions.declare_output(module_name + ".o")
|
||||
output_swiftmodule = ctx.actions.declare_output(module_name + ".swiftmodule")
|
||||
|
||||
shared_flags = _get_shared_flags(
|
||||
ctx,
|
||||
module_name,
|
||||
exported_headers,
|
||||
objc_modulemap_pp_info,
|
||||
extra_search_paths_flags,
|
||||
)
|
||||
|
||||
if toolchain.can_toolchain_emit_obj_c_header_textually:
|
||||
_compile_swiftmodule(ctx, toolchain, shared_flags, srcs, output_swiftmodule, output_header)
|
||||
else:
|
||||
unprocessed_header = ctx.actions.declare_output(module_name + "-SwiftUnprocessed.h")
|
||||
_compile_swiftmodule(ctx, toolchain, shared_flags, srcs, output_swiftmodule, unprocessed_header)
|
||||
_perform_swift_postprocessing(ctx, module_name, unprocessed_header, output_header)
|
||||
|
||||
swift_argsfile = _compile_object(ctx, toolchain, shared_flags, srcs, output_object)
|
||||
|
||||
# Swift libraries extend the ObjC modulemaps to include the -Swift.h header
|
||||
modulemap_pp_info = preprocessor_info_for_modulemap(ctx, "swift-extended", exported_headers, output_header)
|
||||
exported_swift_header = CHeader(
|
||||
artifact = output_header,
|
||||
name = output_header.basename,
|
||||
namespace = module_name,
|
||||
named = False,
|
||||
)
|
||||
exported_pp_info = CPreprocessor(
|
||||
headers = [exported_swift_header],
|
||||
modular_args = modulemap_pp_info.modular_args,
|
||||
args = modulemap_pp_info.args,
|
||||
modulemap_path = modulemap_pp_info.modulemap_path,
|
||||
)
|
||||
|
||||
# We also need to include the unprefixed -Swift.h header in this libraries preprocessor info
|
||||
swift_header = CHeader(
|
||||
artifact = output_header,
|
||||
name = output_header.basename,
|
||||
namespace = "",
|
||||
named = False,
|
||||
)
|
||||
pre = CPreprocessor(headers = [swift_header])
|
||||
|
||||
# Pass up the swiftmodule paths for this module and its exported_deps
|
||||
return SwiftCompilationOutput(
|
||||
object_files = [output_object],
|
||||
swiftmodule = output_swiftmodule,
|
||||
providers = [get_swift_dependency_info(ctx, exported_pp_info, output_swiftmodule)],
|
||||
pre = pre,
|
||||
exported_pre = exported_pp_info,
|
||||
swift_argsfile = swift_argsfile,
|
||||
)
|
||||
|
||||
# Swift headers are postprocessed to make them compatible with Objective-C
|
||||
# compilation that does not use -fmodules. This is a workaround for the bad
|
||||
# performance of -fmodules without Explicit Modules, once Explicit Modules is
|
||||
# supported, this postprocessing should be removed.
|
||||
def _perform_swift_postprocessing(
|
||||
ctx: "context",
|
||||
module_name: "string",
|
||||
unprocessed_header: "artifact",
|
||||
output_header: "artifact"):
|
||||
transitive_exported_headers = {
|
||||
module: module_exported_headers
|
||||
for exported_headers_map in _get_exported_headers_tset(ctx).traverse()
|
||||
if exported_headers_map
|
||||
for module, module_exported_headers in exported_headers_map.items()
|
||||
}
|
||||
deps_json = ctx.actions.write_json(module_name + "-Deps.json", transitive_exported_headers)
|
||||
postprocess_cmd = cmd_args(ctx.attrs._apple_tools[AppleToolsInfo].swift_objc_header_postprocess)
|
||||
postprocess_cmd.add([
|
||||
unprocessed_header,
|
||||
deps_json,
|
||||
output_header.as_output(),
|
||||
])
|
||||
ctx.actions.run(postprocess_cmd, category = "swift_objc_header_postprocess")
|
||||
|
||||
# We use separate actions for swiftmodule and object file output. This
|
||||
# improves build parallelism at the cost of duplicated work, but by disabling
|
||||
# type checking in function bodies the swiftmodule compilation can be done much
|
||||
# faster than object file output.
|
||||
def _compile_swiftmodule(
|
||||
ctx: "context",
|
||||
toolchain: "SwiftToolchainInfo",
|
||||
shared_flags: "cmd_args",
|
||||
srcs: [CxxSrcWithFlags.type],
|
||||
output_swiftmodule: "artifact",
|
||||
output_header: "artifact") -> "CxxAdditionalArgsfileParams":
|
||||
argfile_cmd = cmd_args(shared_flags)
|
||||
argfile_cmd.add([
|
||||
"-Xfrontend",
|
||||
"-experimental-skip-non-inlinable-function-bodies-without-types",
|
||||
"-emit-module",
|
||||
"-emit-objc-header",
|
||||
])
|
||||
cmd = cmd_args([
|
||||
"-emit-module-path",
|
||||
output_swiftmodule.as_output(),
|
||||
"-emit-objc-header-path",
|
||||
output_header.as_output(),
|
||||
])
|
||||
return _compile_with_argsfile(ctx, "swiftmodule_compile", argfile_cmd, srcs, cmd, toolchain)
|
||||
|
||||
def _compile_object(
|
||||
ctx: "context",
|
||||
toolchain: "SwiftToolchainInfo",
|
||||
shared_flags: "cmd_args",
|
||||
srcs: [CxxSrcWithFlags.type],
|
||||
output_object: "artifact") -> "CxxAdditionalArgsfileParams":
|
||||
cmd = cmd_args([
|
||||
"-emit-object",
|
||||
"-o",
|
||||
output_object.as_output(),
|
||||
])
|
||||
return _compile_with_argsfile(ctx, "swift_compile", shared_flags, srcs, cmd, toolchain)
|
||||
|
||||
def _compile_with_argsfile(
|
||||
ctx: "context",
|
||||
name: str.type,
|
||||
shared_flags: "cmd_args",
|
||||
srcs: [CxxSrcWithFlags.type],
|
||||
additional_flags: "cmd_args",
|
||||
toolchain: "SwiftToolchainInfo") -> "CxxAdditionalArgsfileParams":
|
||||
shell_quoted_args = cmd_args(shared_flags, quote = "shell")
|
||||
argfile, _ = ctx.actions.write(name + ".argsfile", shell_quoted_args, allow_args = True)
|
||||
|
||||
cmd = cmd_args(toolchain.compiler)
|
||||
cmd.add(additional_flags)
|
||||
cmd.add(cmd_args(["@", argfile], delimiter = ""))
|
||||
|
||||
cmd.add([s.file for s in srcs])
|
||||
|
||||
# Swift compilation on RE without explicit modules is impractically expensive
|
||||
# because there's no shared module cache across different libraries.
|
||||
prefer_local = not _uses_explicit_modules(ctx)
|
||||
|
||||
# Argsfile should also depend on all artifacts in it, otherwise they won't be materialised.
|
||||
cmd.hidden([shell_quoted_args])
|
||||
|
||||
# If we prefer to execute locally (e.g., for perf reasons), ensure we upload to the cache,
|
||||
# so that CI builds populate caches used by developer machines.
|
||||
ctx.actions.run(cmd, category = name, prefer_local = prefer_local, allow_cache_upload = prefer_local)
|
||||
|
||||
hidden_args = [shared_flags]
|
||||
return CxxAdditionalArgsfileParams(file = argfile, hidden_args = hidden_args, extension = ".swift")
|
||||
|
||||
def _get_shared_flags(
|
||||
ctx: "context",
|
||||
module_name: str.type,
|
||||
objc_headers: [CHeader.type],
|
||||
objc_modulemap_pp_info: ["CPreprocessor", None],
|
||||
extra_search_paths_flags: ["_arglike"] = []) -> "cmd_args":
|
||||
toolchain = ctx.attrs._apple_toolchain[AppleToolchainInfo].swift_toolchain_info
|
||||
cmd = cmd_args()
|
||||
cmd.add([
|
||||
# This allows us to use a relative path for the compiler resource directory.
|
||||
"-working-directory",
|
||||
".",
|
||||
"-sdk",
|
||||
toolchain.sdk_path,
|
||||
"-target",
|
||||
get_versioned_target_triple(ctx),
|
||||
"-wmo",
|
||||
"-module-name",
|
||||
module_name,
|
||||
"-parse-as-library",
|
||||
# Disable Clang module breadcrumbs in the DWARF info. These will not be
|
||||
# debug prefix mapped and are not shareable across machines.
|
||||
"-Xfrontend",
|
||||
"-no-clang-module-breadcrumbs",
|
||||
])
|
||||
|
||||
if _uses_explicit_modules(ctx):
|
||||
cmd.add(get_disable_pch_validation_flags())
|
||||
|
||||
if toolchain.resource_dir:
|
||||
cmd.add([
|
||||
"-resource-dir",
|
||||
toolchain.resource_dir,
|
||||
])
|
||||
|
||||
if ctx.attrs.swift_version:
|
||||
cmd.add(["-swift-version", ctx.attrs.swift_version])
|
||||
|
||||
if ctx.attrs.enable_cxx_interop:
|
||||
cmd.add(["-enable-experimental-cxx-interop"])
|
||||
|
||||
serialize_debugging_options = False
|
||||
if ctx.attrs.serialize_debugging_options:
|
||||
if objc_headers:
|
||||
# TODO(T99100029): We cannot use VFS overlays with Buck2, so we have to disable
|
||||
# serializing debugging options for mixed libraries to debug successfully
|
||||
warning("Mixed libraries cannot serialize debugging options, disabling for module `{}` in rule `{}`".format(module_name, ctx.label))
|
||||
elif not toolchain.prefix_serialized_debugging_options:
|
||||
warning("The current toolchain does not support prefixing serialized debugging options, disabling for module `{}` in rule `{}`".format(module_name, ctx.label))
|
||||
else:
|
||||
# Apply the debug prefix map to Swift serialized debugging info.
|
||||
# This will allow for debugging remotely built swiftmodule files.
|
||||
serialize_debugging_options = True
|
||||
|
||||
if serialize_debugging_options:
|
||||
cmd.add([
|
||||
"-Xfrontend",
|
||||
"-serialize-debugging-options",
|
||||
"-Xfrontend",
|
||||
"-prefix-serialized-debugging-options",
|
||||
])
|
||||
else:
|
||||
cmd.add([
|
||||
"-Xfrontend",
|
||||
"-no-serialize-debugging-options",
|
||||
])
|
||||
|
||||
if toolchain.can_toolchain_emit_obj_c_header_textually:
|
||||
cmd.add([
|
||||
"-Xfrontend",
|
||||
"-emit-objc-header-textually",
|
||||
])
|
||||
|
||||
# Add flags required to import ObjC module dependencies
|
||||
_add_clang_deps_flags(ctx, cmd)
|
||||
_add_swift_deps_flags(ctx, cmd)
|
||||
|
||||
# Add flags for importing the ObjC part of this library
|
||||
_add_mixed_library_flags_to_cmd(cmd, objc_headers, objc_modulemap_pp_info)
|
||||
|
||||
# Add toolchain and target flags last to allow for overriding defaults
|
||||
cmd.add(toolchain.compiler_flags)
|
||||
cmd.add(ctx.attrs.swift_compiler_flags)
|
||||
cmd.add(extra_search_paths_flags)
|
||||
|
||||
return cmd
|
||||
|
||||
def _add_swift_deps_flags(ctx: "context", cmd: "cmd_args"):
|
||||
# If Explicit Modules are enabled, a few things must be provided to a compilation job:
|
||||
# 1. Direct and transitive SDK deps from `sdk_modules` attribute.
|
||||
# 2. Direct and transitive user-defined deps.
|
||||
# 3. Transitive SDK deps of user-defined deps.
|
||||
# (This is the case, when a user-defined dep exports a type from SDK module,
|
||||
# thus such SDK module should be implicitly visible to consumers of that custom dep)
|
||||
if _uses_explicit_modules(ctx):
|
||||
toolchain = ctx.attrs._apple_toolchain[AppleToolchainInfo].swift_toolchain_info
|
||||
module_name = get_module_name(ctx)
|
||||
sdk_deps_tset = get_sdk_deps_tset(
|
||||
ctx,
|
||||
module_name,
|
||||
ctx.attrs.deps + ctx.attrs.exported_deps,
|
||||
_REQUIRED_SDK_MODULES,
|
||||
toolchain,
|
||||
)
|
||||
swift_deps_tset = ctx.actions.tset(
|
||||
SwiftmodulePathsTSet,
|
||||
children = _get_swift_paths_tsets(ctx.attrs.deps + ctx.attrs.exported_deps),
|
||||
)
|
||||
swift_module_map_artifact = write_swift_module_map_with_swift_deps(
|
||||
ctx,
|
||||
module_name,
|
||||
list(sdk_deps_tset.traverse()),
|
||||
list(swift_deps_tset.traverse()),
|
||||
)
|
||||
cmd.add([
|
||||
"-Xfrontend",
|
||||
"-disable-implicit-swift-modules",
|
||||
"-Xfrontend",
|
||||
"-explicit-swift-module-map-file",
|
||||
"-Xfrontend",
|
||||
swift_module_map_artifact,
|
||||
])
|
||||
|
||||
# Add Clang sdk modules which do not go to swift modulemap
|
||||
cmd.add(sdk_deps_tset.project_as_args("clang_deps"))
|
||||
|
||||
# Swift compilation should depend on transitive Swift modules from swift-module-map.
|
||||
cmd.hidden(sdk_deps_tset.project_as_args("hidden"))
|
||||
cmd.hidden(swift_deps_tset.project_as_args("hidden"))
|
||||
else:
|
||||
depset = ctx.actions.tset(SwiftmodulePathsTSet, children = _get_swift_paths_tsets(ctx.attrs.deps + ctx.attrs.exported_deps))
|
||||
cmd.add(depset.project_as_args("module_search_path"))
|
||||
|
||||
def _add_clang_deps_flags(ctx: "context", cmd: "cmd_args") -> None:
|
||||
# If a module uses Explicit Modules, all direct and
|
||||
# transitive Clang deps have to be explicitly added.
|
||||
if _uses_explicit_modules(ctx):
|
||||
pcm_deps_tset = get_pcm_deps_tset(ctx, ctx.attrs.deps + ctx.attrs.exported_deps)
|
||||
cmd.add(pcm_deps_tset.project_as_args("clang_deps"))
|
||||
else:
|
||||
inherited_preprocessor_infos = cxx_inherited_preprocessor_infos(ctx.attrs.deps + ctx.attrs.exported_deps)
|
||||
preprocessors = cxx_merge_cpreprocessors(ctx, [], inherited_preprocessor_infos)
|
||||
cmd.add(cmd_args(preprocessors.set.project_as_args("args"), prepend = "-Xcc"))
|
||||
cmd.add(cmd_args(preprocessors.set.project_as_args("modular_args"), prepend = "-Xcc"))
|
||||
cmd.add(cmd_args(preprocessors.set.project_as_args("include_dirs"), prepend = "-Xcc"))
|
||||
|
||||
def _add_mixed_library_flags_to_cmd(
|
||||
cmd: "cmd_args",
|
||||
objc_headers: [CHeader.type],
|
||||
objc_modulemap_pp_info: ["CPreprocessor", None]) -> None:
|
||||
if not objc_headers:
|
||||
return
|
||||
|
||||
# TODO(T99100029): We cannot use VFS overlays to mask this import from
|
||||
# the debugger as they require absolute paths. Instead we will enforce
|
||||
# that mixed libraries do not have serialized debugging info and rely on
|
||||
# rdeps to serialize the correct paths.
|
||||
for arg in objc_modulemap_pp_info.args:
|
||||
cmd.add("-Xcc")
|
||||
cmd.add(arg)
|
||||
|
||||
for arg in objc_modulemap_pp_info.modular_args:
|
||||
cmd.add("-Xcc")
|
||||
cmd.add(arg)
|
||||
|
||||
cmd.add("-import-underlying-module")
|
||||
|
||||
def _get_swift_paths_tsets(deps: ["dependency"]) -> ["SwiftmodulePathsTSet"]:
|
||||
return [
|
||||
d[SwiftDependencyInfo].exported_swiftmodule_paths
|
||||
for d in deps
|
||||
if SwiftDependencyInfo in d
|
||||
]
|
||||
|
||||
def _get_transitive_swift_paths_tsets(deps: ["dependency"]) -> ["SwiftmodulePathsTSet"]:
|
||||
return [
|
||||
d[SwiftDependencyInfo].transitive_swiftmodule_paths
|
||||
for d in deps
|
||||
if SwiftDependencyInfo in d
|
||||
]
|
||||
|
||||
def _get_exported_headers_tset(ctx: "context", exported_headers: [["string"], None] = None) -> "ExportedHeadersTSet":
|
||||
return ctx.actions.tset(
|
||||
ExportedHeadersTSet,
|
||||
value = {get_module_name(ctx): exported_headers} if exported_headers else None,
|
||||
children = [
|
||||
dep.exported_headers
|
||||
for dep in [x.get(SwiftDependencyInfo) for x in ctx.attrs.exported_deps]
|
||||
if dep and dep.exported_headers
|
||||
],
|
||||
)
|
||||
|
||||
def get_swift_pcm_compile_info(
|
||||
ctx: "context",
|
||||
propagated_exported_preprocessor_info: ["CPreprocessorInfo", None],
|
||||
exported_pre: ["CPreprocessor", None]) -> ["SwiftPCMCompilationInfo", None]:
|
||||
swift_toolchain = ctx.attrs._apple_toolchain[AppleToolchainInfo].swift_toolchain_info
|
||||
|
||||
# If a toolchain supports explicit modules, exported PP exists and a target is modular,
|
||||
# let's precompile a modulemap in order to enable consumptions by Swift.
|
||||
if is_sdk_modules_provided(swift_toolchain) and exported_pre and exported_pre.modulemap_path and ctx.attrs.modular:
|
||||
return compile_swift_pcm(
|
||||
ctx,
|
||||
exported_pre,
|
||||
propagated_exported_preprocessor_info,
|
||||
)
|
||||
return None
|
||||
|
||||
def get_swift_dependency_info(
|
||||
ctx: "context",
|
||||
exported_pre: ["CPreprocessor", None],
|
||||
output_module: ["artifact", None]) -> "SwiftDependencyInfo":
|
||||
all_deps = ctx.attrs.exported_deps + ctx.attrs.deps
|
||||
if ctx.attrs.reexport_all_header_dependencies:
|
||||
exported_deps = all_deps
|
||||
else:
|
||||
exported_deps = ctx.attrs.exported_deps
|
||||
|
||||
exported_headers = [_header_basename(header) for header in ctx.attrs.exported_headers]
|
||||
exported_headers += [header.name for header in exported_pre.headers] if exported_pre else []
|
||||
|
||||
if output_module:
|
||||
exported_swiftmodules = ctx.actions.tset(SwiftmodulePathsTSet, value = output_module, children = _get_swift_paths_tsets(exported_deps))
|
||||
transitive_swiftmodules = ctx.actions.tset(SwiftmodulePathsTSet, value = output_module, children = _get_transitive_swift_paths_tsets(all_deps))
|
||||
else:
|
||||
exported_swiftmodules = ctx.actions.tset(SwiftmodulePathsTSet, children = _get_swift_paths_tsets(exported_deps))
|
||||
transitive_swiftmodules = ctx.actions.tset(SwiftmodulePathsTSet, children = _get_transitive_swift_paths_tsets(all_deps))
|
||||
|
||||
return SwiftDependencyInfo(
|
||||
exported_headers = _get_exported_headers_tset(ctx, exported_headers),
|
||||
exported_swiftmodule_paths = exported_swiftmodules,
|
||||
transitive_swiftmodule_paths = transitive_swiftmodules,
|
||||
)
|
||||
|
||||
def _header_basename(header: ["artifact", "string"]) -> "string":
|
||||
if type(header) == type(""):
|
||||
return paths.basename(header)
|
||||
else:
|
||||
return header.basename
|
||||
|
||||
def _uses_explicit_modules(ctx: "context") -> bool.type:
|
||||
swift_toolchain = ctx.attrs._apple_toolchain[AppleToolchainInfo].swift_toolchain_info
|
||||
return ctx.attrs.uses_explicit_modules and is_sdk_modules_provided(swift_toolchain)
|
||||
40
vendor/cxx/tools/buck/prelude/apple/swift_module_map.bzl
vendored
Normal file
40
vendor/cxx/tools/buck/prelude/apple/swift_module_map.bzl
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# 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.
|
||||
|
||||
def write_swift_module_map(
|
||||
ctx: "context",
|
||||
module_name: str.type,
|
||||
sdk_deps: ["SdkCompiledModuleInfo"]) -> "artifact":
|
||||
return write_swift_module_map_with_swift_deps(ctx, module_name, sdk_deps, [])
|
||||
|
||||
def write_swift_module_map_with_swift_deps(
|
||||
ctx: "context",
|
||||
module_name: str.type,
|
||||
sdk_swift_deps: ["SdkCompiledModuleInfo"],
|
||||
swift_deps: ["artifact"]) -> "artifact":
|
||||
deps = {}
|
||||
for sdk_dep in sdk_swift_deps:
|
||||
if sdk_dep.is_swiftmodule:
|
||||
deps[sdk_dep.module_name] = {
|
||||
"isFramework": sdk_dep.is_framework,
|
||||
"moduleName": sdk_dep.module_name,
|
||||
"modulePath": sdk_dep.output_artifact,
|
||||
}
|
||||
|
||||
for swift_dep in swift_deps:
|
||||
# The swiftmodule filename always matches the module name
|
||||
name = swift_dep.basename[:-12]
|
||||
deps[name] = {
|
||||
"isFramework": False,
|
||||
"moduleName": name,
|
||||
"modulePath": swift_dep,
|
||||
}
|
||||
|
||||
return ctx.actions.write_json(
|
||||
module_name + ".swift_module_map.json",
|
||||
deps.values(),
|
||||
)
|
||||
240
vendor/cxx/tools/buck/prelude/apple/swift_pcm_compilation.bzl
vendored
Normal file
240
vendor/cxx/tools/buck/prelude/apple/swift_pcm_compilation.bzl
vendored
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
# 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(":apple_sdk_modules_utility.bzl", "get_sdk_deps_tset")
|
||||
load(":apple_toolchain_types.bzl", "AppleToolchainInfo")
|
||||
load(":apple_utility.bzl", "expand_relative_prefixed_sdk_path", "get_disable_pch_validation_flags", "get_module_name", "get_versioned_target_triple")
|
||||
load(":swift_pcm_compilation_types.bzl", "SwiftPCMCompilationInfo")
|
||||
load(":swift_toolchain_types.bzl", "SdkCompiledModuleInfo")
|
||||
|
||||
_REQUIRED_SDK_MODULES = ["Foundation"]
|
||||
|
||||
def _project_as_clang_deps(value: "SwiftPCMCompilationInfo"):
|
||||
return [
|
||||
"-Xcc",
|
||||
cmd_args(["-fmodule-file=", value.name, "=", value.pcm_output], delimiter = ""),
|
||||
"-Xcc",
|
||||
cmd_args(["-fmodule-map-file=", value.exported_pre.modulemap_path], delimiter = ""),
|
||||
"-Xcc",
|
||||
] + value.exported_pre.args
|
||||
|
||||
PcmDepTSet = transitive_set(args_projections = {
|
||||
"clang_deps": _project_as_clang_deps,
|
||||
})
|
||||
|
||||
def get_pcm_deps_tset(ctx: "context", deps: ["dependency"]) -> "PcmDepTSet":
|
||||
pcm_deps = [
|
||||
ctx.actions.tset(
|
||||
PcmDepTSet,
|
||||
value = d[SwiftPCMCompilationInfo],
|
||||
children = [d[SwiftPCMCompilationInfo].deps_set],
|
||||
)
|
||||
for d in deps
|
||||
if SwiftPCMCompilationInfo in d
|
||||
]
|
||||
return ctx.actions.tset(PcmDepTSet, children = pcm_deps)
|
||||
|
||||
def compile_swift_sdk_pcm(
|
||||
ctx: "context",
|
||||
toolchain_context: struct.type,
|
||||
sdk_deps_set: "SDKDepTSet",
|
||||
uncompiled_sdk_module_info: "SdkUncompiledModuleInfo",
|
||||
sdk_module_providers: {str.type: "SdkCompiledModuleInfo"}):
|
||||
module_name = uncompiled_sdk_module_info.module_name
|
||||
|
||||
cmd = cmd_args(toolchain_context.compiler)
|
||||
cmd.add(uncompiled_sdk_module_info.partial_cmd)
|
||||
cmd.add(["-sdk", toolchain_context.sdk_path])
|
||||
cmd.add(toolchain_context.compiler_flags)
|
||||
|
||||
if toolchain_context.swift_resource_dir:
|
||||
cmd.add([
|
||||
"-resource-dir",
|
||||
toolchain_context.swift_resource_dir,
|
||||
])
|
||||
|
||||
cmd.add(sdk_deps_set.project_as_args("clang_deps"))
|
||||
|
||||
expanded_modulemap_path_cmd = expand_relative_prefixed_sdk_path(
|
||||
cmd_args(toolchain_context.sdk_path),
|
||||
cmd_args(toolchain_context.swift_resource_dir),
|
||||
uncompiled_sdk_module_info.input_relative_path,
|
||||
)
|
||||
pcm_output = ctx.actions.declare_output(module_name + ".pcm")
|
||||
cmd.add([
|
||||
"-o",
|
||||
pcm_output.as_output(),
|
||||
expanded_modulemap_path_cmd,
|
||||
])
|
||||
|
||||
# For SDK modules we need to set a few more args
|
||||
cmd.add([
|
||||
"-Xcc",
|
||||
"-Xclang",
|
||||
"-Xcc",
|
||||
"-emit-module",
|
||||
"-Xcc",
|
||||
"-Xclang",
|
||||
"-Xcc",
|
||||
"-fsystem-module",
|
||||
])
|
||||
|
||||
_add_sdk_module_search_path(cmd, uncompiled_sdk_module_info, toolchain_context)
|
||||
|
||||
sdk_module_providers[uncompiled_sdk_module_info.name] = SdkCompiledModuleInfo(
|
||||
name = uncompiled_sdk_module_info.name,
|
||||
module_name = module_name,
|
||||
is_framework = uncompiled_sdk_module_info.is_framework,
|
||||
output_artifact = pcm_output,
|
||||
is_swiftmodule = False,
|
||||
deps = sdk_deps_set,
|
||||
input_relative_path = expanded_modulemap_path_cmd,
|
||||
)
|
||||
|
||||
ctx.actions.run(cmd, category = "sdk_swift_pcm_compile", identifier = module_name)
|
||||
|
||||
def compile_swift_pcm(
|
||||
ctx: "context",
|
||||
exported_pre: "CPreprocessor",
|
||||
propagated_exported_preprocessor_info: ["CPreprocessorInfo", None]) -> ["SwiftPCMCompilationInfo", None]:
|
||||
module_name = get_module_name(ctx)
|
||||
modulemap_path = exported_pre.modulemap_path
|
||||
|
||||
toolchain = ctx.attrs._apple_toolchain[AppleToolchainInfo].swift_toolchain_info
|
||||
cmd = cmd_args(toolchain.compiler)
|
||||
cmd.add(get_shared_pcm_compilation_args(get_versioned_target_triple(ctx), module_name))
|
||||
cmd.add(["-sdk", toolchain.sdk_path])
|
||||
cmd.add(toolchain.compiler_flags)
|
||||
|
||||
sdk_deps_tset = get_sdk_deps_tset(
|
||||
ctx,
|
||||
module_name,
|
||||
ctx.attrs.exported_deps,
|
||||
_REQUIRED_SDK_MODULES,
|
||||
toolchain,
|
||||
)
|
||||
cmd.add(sdk_deps_tset.project_as_args("clang_deps"))
|
||||
|
||||
if toolchain.resource_dir:
|
||||
cmd.add([
|
||||
"-resource-dir",
|
||||
toolchain.resource_dir,
|
||||
])
|
||||
|
||||
# To compile a pcm we only use the exported_deps as those are the only
|
||||
# ones that should be transitively exported through public headers
|
||||
pcm_deps_tset = get_pcm_deps_tset(ctx, ctx.attrs.exported_deps)
|
||||
cmd.add(pcm_deps_tset.project_as_args("clang_deps"))
|
||||
|
||||
pcm_output = ctx.actions.declare_output(module_name + ".pcm")
|
||||
cmd.add([
|
||||
"-o",
|
||||
pcm_output.as_output(),
|
||||
modulemap_path,
|
||||
])
|
||||
|
||||
# To correctly resolve modulemap's headers,
|
||||
# a search path to the root of modulemap should be passed.
|
||||
cmd.add([
|
||||
"-Xcc",
|
||||
"-I",
|
||||
"-Xcc",
|
||||
cmd_args(modulemap_path).parent(),
|
||||
])
|
||||
|
||||
# When compiling pcm files, module's exported pps and inherited pps
|
||||
# must be provided to an action like hmaps which are used for headers resolution.
|
||||
if propagated_exported_preprocessor_info:
|
||||
cmd.add(cmd_args(propagated_exported_preprocessor_info.set.project_as_args("args"), prepend = "-Xcc"))
|
||||
|
||||
ctx.actions.run(cmd, category = "swift_pcm_compile", identifier = module_name)
|
||||
|
||||
return SwiftPCMCompilationInfo(
|
||||
name = module_name,
|
||||
pcm_output = pcm_output,
|
||||
exported_pre = exported_pre,
|
||||
deps_set = ctx.actions.tset(
|
||||
PcmDepTSet,
|
||||
children = [pcm_deps_tset],
|
||||
),
|
||||
sdk_deps_set = sdk_deps_tset,
|
||||
)
|
||||
|
||||
def get_shared_pcm_compilation_args(target: str.type, module_name: str.type) -> "cmd_args":
|
||||
cmd = cmd_args()
|
||||
cmd.add([
|
||||
"-emit-pcm",
|
||||
"-target",
|
||||
target,
|
||||
"-module-name",
|
||||
module_name,
|
||||
"-Xfrontend",
|
||||
"-disable-implicit-swift-modules",
|
||||
"-Xcc",
|
||||
"-fno-implicit-modules",
|
||||
"-Xcc",
|
||||
"-fno-implicit-module-maps",
|
||||
# Disable debug info in pcm files. This is required to avoid embedding absolute paths
|
||||
# and ending up with mismatched pcm file sizes.
|
||||
"-Xcc",
|
||||
"-Xclang",
|
||||
"-Xcc",
|
||||
"-fmodule-format=raw",
|
||||
# Embed all input files into the PCM so we don't need to include module map files when
|
||||
# building remotely.
|
||||
# https://github.com/apple/llvm-project/commit/fb1e7f7d1aca7bcfc341e9214bda8b554f5ae9b6
|
||||
"-Xcc",
|
||||
"-Xclang",
|
||||
"-Xcc",
|
||||
"-fmodules-embed-all-files",
|
||||
# Embed all files that were read during compilation into the generated PCM.
|
||||
"-Xcc",
|
||||
"-Xclang",
|
||||
"-Xcc",
|
||||
"-fmodule-file-home-is-cwd",
|
||||
# Once we have an empty working directory the compiler provided headers such as float.h
|
||||
# cannot be found, so add . to the header search paths.
|
||||
"-Xcc",
|
||||
"-I.",
|
||||
])
|
||||
|
||||
cmd.add(get_disable_pch_validation_flags())
|
||||
|
||||
return cmd
|
||||
|
||||
def _remove_path_components_from_right(path: str.type, count: int.type):
|
||||
path_components = path.split("/")
|
||||
removed_path = "/".join(path_components[0:-count])
|
||||
return removed_path
|
||||
|
||||
def _add_sdk_module_search_path(cmd, uncompiled_sdk_module_info, toolchain_context):
|
||||
modulemap_path = uncompiled_sdk_module_info.input_relative_path
|
||||
|
||||
# If this input is a framework we need to search above the
|
||||
# current framework location, otherwise we include the
|
||||
# modulemap root.
|
||||
if uncompiled_sdk_module_info.is_framework:
|
||||
frameworks_dir_path = _remove_path_components_from_right(modulemap_path, 3)
|
||||
expanded_path = expand_relative_prefixed_sdk_path(
|
||||
cmd_args(toolchain_context.sdk_path),
|
||||
cmd_args(toolchain_context.swift_resource_dir),
|
||||
frameworks_dir_path,
|
||||
)
|
||||
else:
|
||||
module_root_path = _remove_path_components_from_right(modulemap_path, 1)
|
||||
expanded_path = expand_relative_prefixed_sdk_path(
|
||||
cmd_args(toolchain_context.sdk_path),
|
||||
cmd_args(toolchain_context.swift_resource_dir),
|
||||
module_root_path,
|
||||
)
|
||||
|
||||
cmd.add([
|
||||
"-Xcc",
|
||||
("-F" if uncompiled_sdk_module_info.is_framework else "-I"),
|
||||
"-Xcc",
|
||||
cmd_args(expanded_path),
|
||||
])
|
||||
14
vendor/cxx/tools/buck/prelude/apple/swift_pcm_compilation_types.bzl
vendored
Normal file
14
vendor/cxx/tools/buck/prelude/apple/swift_pcm_compilation_types.bzl
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# 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.
|
||||
|
||||
SwiftPCMCompilationInfo = provider(fields = [
|
||||
"name",
|
||||
"pcm_output",
|
||||
"exported_pre",
|
||||
"deps_set",
|
||||
"sdk_deps_set", # A TSet of direct and transitive SDK deps.
|
||||
])
|
||||
65
vendor/cxx/tools/buck/prelude/apple/swift_toolchain.bzl
vendored
Normal file
65
vendor/cxx/tools/buck/prelude/apple/swift_toolchain.bzl
vendored
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
# 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(":apple_sdk_module.bzl", "create_sdk_modules_graph")
|
||||
load(":swift_toolchain_types.bzl", "SdkUncompiledModuleInfo", "SwiftToolchainInfo")
|
||||
|
||||
def swift_toolchain_impl(ctx):
|
||||
compiler = cmd_args(ctx.attrs._swiftc_wrapper[RunInfo]).add(ctx.attrs.swiftc[RunInfo])
|
||||
compiler_flags = ctx.attrs.swiftc_flags
|
||||
sdk_path = ctx.attrs._internal_sdk_path or ctx.attrs.sdk_path
|
||||
resource_dir = ctx.attrs.resource_dir
|
||||
|
||||
toolchain_context = struct(
|
||||
compiler = compiler,
|
||||
sdk_path = sdk_path,
|
||||
compiler_flags = compiler_flags,
|
||||
swift_resource_dir = resource_dir,
|
||||
)
|
||||
|
||||
compiled_sdk_module_providers = {}
|
||||
|
||||
sdk_uncompiled_module_infos = filter(None, [d.get(SdkUncompiledModuleInfo) for d in ctx.attrs.sdk_modules])
|
||||
for uncompiled_swift_module_info in sdk_uncompiled_module_infos:
|
||||
create_sdk_modules_graph(
|
||||
ctx,
|
||||
compiled_sdk_module_providers,
|
||||
uncompiled_swift_module_info,
|
||||
toolchain_context,
|
||||
)
|
||||
|
||||
compiled_sdk_swift_module_providers = {
|
||||
info.module_name: info
|
||||
for _, info in compiled_sdk_module_providers.items()
|
||||
if info.is_swiftmodule
|
||||
}
|
||||
|
||||
compiled_sdk_clang_module_providers = {
|
||||
info.module_name: info
|
||||
for _, info in compiled_sdk_module_providers.items()
|
||||
if not info.is_swiftmodule
|
||||
}
|
||||
|
||||
return [
|
||||
DefaultInfo(),
|
||||
SwiftToolchainInfo(
|
||||
architecture = ctx.attrs.architecture,
|
||||
can_toolchain_emit_obj_c_header_textually = ctx.attrs.can_toolchain_emit_obj_c_header_textually,
|
||||
# TODO(T99038725): until we add -debug-compilation-dir we need to wrap
|
||||
# the Swift invocations so that we can apply a debug prefix map for
|
||||
# the current directory while maintaining cache hit.
|
||||
compiled_sdk_clang_modules = compiled_sdk_clang_module_providers,
|
||||
compiled_sdk_swift_modules = compiled_sdk_swift_module_providers,
|
||||
compiler = compiler,
|
||||
compiler_flags = compiler_flags,
|
||||
prefix_serialized_debugging_options = ctx.attrs.prefix_serialized_debug_info,
|
||||
resource_dir = resource_dir,
|
||||
sdk_path = sdk_path,
|
||||
swift_stdlib_tool = ctx.attrs.swift_stdlib_tool[RunInfo],
|
||||
swift_stdlib_tool_flags = ctx.attrs.swift_stdlib_tool_flags,
|
||||
),
|
||||
]
|
||||
46
vendor/cxx/tools/buck/prelude/apple/swift_toolchain_types.bzl
vendored
Normal file
46
vendor/cxx/tools/buck/prelude/apple/swift_toolchain_types.bzl
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# 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.
|
||||
|
||||
#####################################################################
|
||||
# Providers
|
||||
|
||||
SwiftToolchainInfo = provider(fields = [
|
||||
"architecture",
|
||||
"can_toolchain_emit_obj_c_header_textually", # bool
|
||||
"compiled_sdk_clang_modules", # {str.type: SdkCompiledModuleInfo} Expose providers of compiled Clang SDK modules.
|
||||
"compiled_sdk_swift_modules", # {str.type: SdkCompiledModuleInfo} Expose providers of compiled Swift SDK modules.
|
||||
"compiler_flags",
|
||||
"compiler",
|
||||
"prefix_serialized_debugging_options", # bool
|
||||
"resource_dir", # "artifact",
|
||||
"sdk_path",
|
||||
"swift_stdlib_tool_flags",
|
||||
"swift_stdlib_tool",
|
||||
])
|
||||
|
||||
# A provider that represents a non-yet-compiled SDK (Swift or Clang) module,
|
||||
# and doesn't contain any artifacts because Swift toolchain isn't resolved yet.
|
||||
SdkUncompiledModuleInfo = provider(fields = [
|
||||
"name", # A name of a module with `.swift`/`.clang` suffix.
|
||||
"module_name", # A real name of a module, without distinguishing suffixes.
|
||||
"is_framework", # This is mostly needed for the generated Swift module map file.
|
||||
"is_swiftmodule", # If True then represents a swiftinterface, otherwise Clang's modulemap.
|
||||
"partial_cmd", # Partial arguments, required to compile a particular SDK module.
|
||||
"input_relative_path", # A relative prefixed path to a textual swiftinterface/modulemap file within an SDK.
|
||||
"deps", # [SdkUncompiledModuleInfo]
|
||||
])
|
||||
|
||||
# A provider that represents an already-compiled SDK (Swift or Clang) module.
|
||||
SdkCompiledModuleInfo = provider(fields = [
|
||||
"name", # A name of a module with `.swift`/`.clang` suffix.
|
||||
"module_name", # A real name of a module, without distinguishing suffixes.
|
||||
"is_swiftmodule", # If True then contains a compiled swiftmodule, otherwise Clang's pcm.
|
||||
"is_framework",
|
||||
"output_artifact", # Compiled artifact either swiftmodule or pcm.
|
||||
"input_relative_path",
|
||||
"deps", # A TSet of [SdkCompiledModuleInfo]
|
||||
])
|
||||
30
vendor/cxx/tools/buck/prelude/apple/tools/TARGETS.v2
vendored
Normal file
30
vendor/cxx/tools/buck/prelude/apple/tools/TARGETS.v2
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
prelude = native
|
||||
|
||||
prelude.python_bootstrap_binary(
|
||||
name = "make_modulemap",
|
||||
main = "make_modulemap.py",
|
||||
visibility = ["PUBLIC"],
|
||||
)
|
||||
|
||||
prelude.export_file(
|
||||
name = "swift_exec.sh",
|
||||
src = "swift_exec.sh",
|
||||
)
|
||||
|
||||
prelude.command_alias(
|
||||
name = "swift_exec",
|
||||
exe = ":swift_exec.sh",
|
||||
visibility = ["PUBLIC"],
|
||||
)
|
||||
|
||||
prelude.python_bootstrap_binary(
|
||||
name = "make_vfsoverlay",
|
||||
main = "make_vfsoverlay.py",
|
||||
visibility = ["PUBLIC"],
|
||||
)
|
||||
|
||||
prelude.python_bootstrap_binary(
|
||||
name = "swift_objc_header_postprocess",
|
||||
main = "swift_objc_header_postprocess.py",
|
||||
visibility = ["PUBLIC"],
|
||||
)
|
||||
154
vendor/cxx/tools/buck/prelude/apple/tools/make_modulemap.py
vendored
Normal file
154
vendor/cxx/tools/buck/prelude/apple/tools/make_modulemap.py
vendored
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
#!/usr/bin/env python3
|
||||
# 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.
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
from io import TextIOWrapper
|
||||
from typing import Dict, Iterable, List
|
||||
|
||||
|
||||
class Module:
|
||||
def __init__(self, name: str) -> None:
|
||||
self.name: str = name
|
||||
self.headers: List[str] = []
|
||||
self.submodules: Dict[str, Module] = {}
|
||||
|
||||
def add_header(self, src: str) -> None:
|
||||
self.headers.append(src)
|
||||
|
||||
def get_submodule(self, name: str) -> "Module":
|
||||
if name not in self.submodules:
|
||||
self.submodules[name] = Module(name)
|
||||
|
||||
return self.submodules[name]
|
||||
|
||||
def render(self, f: TextIOWrapper, path_prefix: str, indent: int = 0) -> None:
|
||||
space = " " * indent
|
||||
f.write(f"{space}module {self.name} {{\n")
|
||||
|
||||
submodule_names = set()
|
||||
for submodule_name in sorted(self.submodules.keys()):
|
||||
submodule = self.submodules[submodule_name]
|
||||
|
||||
# remove any extensions for readibility
|
||||
sanitized_name = os.path.splitext(submodule_name)[0]
|
||||
|
||||
# module names can only be ascii or _
|
||||
sanitized_name = re.sub(r"[^A-Za-z0-9_]", "_", sanitized_name)
|
||||
if sanitized_name[0].isdigit():
|
||||
sanitized_name = "_" + sanitized_name
|
||||
|
||||
# avoid any collisions with other files
|
||||
while sanitized_name in submodule_names:
|
||||
sanitized_name += "_"
|
||||
|
||||
submodule_names.add(sanitized_name)
|
||||
submodule.name = sanitized_name
|
||||
submodule.render(f, path_prefix, indent + 4)
|
||||
|
||||
header_space = " " * (indent + 4)
|
||||
for h in sorted(self.headers):
|
||||
f.write(f'{header_space}header "{os.path.join(path_prefix, h)}"\n')
|
||||
|
||||
if self.headers:
|
||||
f.write(f"{header_space}export *\n")
|
||||
|
||||
f.write(f"{space}}}\n")
|
||||
|
||||
|
||||
def _write_single_module(
|
||||
f: TextIOWrapper, name: str, headers: Iterable[str], path_prefix: str
|
||||
) -> None:
|
||||
module = Module(name)
|
||||
for h in headers:
|
||||
module.add_header(h)
|
||||
|
||||
module.render(f, path_prefix)
|
||||
|
||||
|
||||
def _write_submodules(
|
||||
f: TextIOWrapper, name: str, headers: Iterable[str], path_prefix: str
|
||||
) -> None:
|
||||
# Create a tree of nested modules, one for each path component.
|
||||
root_module = Module(name)
|
||||
for h in headers:
|
||||
module = root_module
|
||||
for i, component in enumerate(h.split(os.sep)):
|
||||
if i == 0 and component == name:
|
||||
# The common case is we have a singe header path prefix that matches the module name.
|
||||
# In this case we add the headers directly to the root module.
|
||||
pass
|
||||
else:
|
||||
module = module.get_submodule(component)
|
||||
|
||||
module.add_header(h)
|
||||
|
||||
root_module.render(f, path_prefix)
|
||||
|
||||
|
||||
def _write_swift_header(f: TextIOWrapper, name: str, swift_header_path: str) -> None:
|
||||
f.write(
|
||||
f"""
|
||||
module {name}.Swift {{
|
||||
header "{swift_header_path}"
|
||||
requires objc
|
||||
}}
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--output", required=True, help="The path to write the modulemap to"
|
||||
)
|
||||
parser.add_argument("--name", required=True, help="The name of the module")
|
||||
parser.add_argument(
|
||||
"--swift-header", help="If this is a mixed module extend with this Swift header"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--use-submodules",
|
||||
action="store_true",
|
||||
help="If set produce a modulemap with per-header submodules",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--symlink-tree",
|
||||
required=True,
|
||||
)
|
||||
parser.add_argument(
|
||||
"mappings", nargs="*", default=[], help="A list of import paths"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
output_dir = os.path.dirname(args.output)
|
||||
path_prefix = os.path.relpath(args.symlink_tree, output_dir)
|
||||
|
||||
with open(args.output, "w") as f:
|
||||
if args.use_submodules:
|
||||
# pyre-fixme[6]: For 4th param expected `str` but got `bytes`.
|
||||
_write_submodules(f, args.name, args.mappings, path_prefix)
|
||||
else:
|
||||
# pyre-fixme[6]: For 4th param expected `str` but got `bytes`.
|
||||
_write_single_module(f, args.name, args.mappings, path_prefix)
|
||||
|
||||
if args.swift_header:
|
||||
swift_header_name = os.path.relpath(args.swift_header, output_dir)
|
||||
_write_swift_header(
|
||||
f,
|
||||
args.name,
|
||||
os.path.join(
|
||||
"swift-extended_symlink_tree",
|
||||
args.name,
|
||||
str(swift_header_name),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
95
vendor/cxx/tools/buck/prelude/apple/tools/make_vfsoverlay.py
vendored
Normal file
95
vendor/cxx/tools/buck/prelude/apple/tools/make_vfsoverlay.py
vendored
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
#!/usr/bin/env fbpython
|
||||
# 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.
|
||||
|
||||
import argparse
|
||||
import itertools
|
||||
import json
|
||||
import os
|
||||
from typing import Dict, List, Tuple, TypedDict
|
||||
|
||||
# Example VFS overlay in JSON format
|
||||
# ----------------------------------
|
||||
# {
|
||||
# 'version': 0,
|
||||
# 'roots': [
|
||||
# { 'name': 'OUT_DIR', 'type': 'directory',
|
||||
# 'contents': [
|
||||
# { 'name': 'module.map', 'type': 'file',
|
||||
# 'external-contents': 'INPUT_DIR/actual_module2.map'
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
|
||||
|
||||
class OverlayRoot(TypedDict):
|
||||
name: str
|
||||
type: str
|
||||
contents: List[Dict[str, str]]
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--output", required=True, help="The path to write the VFS overlay to"
|
||||
)
|
||||
parser.add_argument(
|
||||
"mappings", nargs="*", default=[], help="A list of virtual paths to real paths"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
if len(args.mappings) % 2 != 0:
|
||||
parser.error("mappings must be dest-source pairs")
|
||||
|
||||
# Group the mappings by containing directory
|
||||
mappings: Dict[str, List[Tuple[str, str]]] = {}
|
||||
for src, dst in itertools.zip_longest(*([iter(args.mappings)] * 2)):
|
||||
folder, basename = os.path.split(src)
|
||||
mappings.setdefault(folder, []).append((basename, dst))
|
||||
|
||||
with open(args.output, "w") as f:
|
||||
json.dump(
|
||||
{
|
||||
"version": 0,
|
||||
"roots": _get_roots(mappings),
|
||||
},
|
||||
f,
|
||||
sort_keys=True,
|
||||
indent=4,
|
||||
)
|
||||
f.write("\n")
|
||||
f.flush()
|
||||
|
||||
|
||||
def _get_roots(mappings: Dict[str, List[Tuple[str, str]]]) -> List[OverlayRoot]:
|
||||
roots = []
|
||||
for folder, file_maps in mappings.items():
|
||||
contents = []
|
||||
for src, dst in file_maps:
|
||||
contents.append(
|
||||
{
|
||||
"name": src,
|
||||
"type": "file",
|
||||
"external-contents": dst,
|
||||
}
|
||||
)
|
||||
|
||||
roots.append(
|
||||
{
|
||||
"name": folder,
|
||||
"type": "directory",
|
||||
"contents": contents,
|
||||
}
|
||||
)
|
||||
|
||||
return roots
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
26
vendor/cxx/tools/buck/prelude/apple/tools/swift_exec.sh
vendored
Normal file
26
vendor/cxx/tools/buck/prelude/apple/tools/swift_exec.sh
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#!/bin/bash
|
||||
# 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.
|
||||
|
||||
# - Apply a debug prefix map for the current directory
|
||||
# to make debug info relocatable.
|
||||
# - Use $TMPDIR for the module cache location. This
|
||||
# will be set to a unique location for each RE action
|
||||
# which will avoid sharing modules across RE actions.
|
||||
# This is necessary as the inputs to the modules will
|
||||
# be transient and can be removed at any point, causing
|
||||
# module validation errors to fail builds.
|
||||
if [ -n "$INSIDE_RE_WORKER" ]; then
|
||||
MODULE_CACHE_PATH="$TMPDIR/module-cache"
|
||||
else
|
||||
# When building locally we can use a shared module
|
||||
# cache as the inputs should remain at a fixed
|
||||
# location.
|
||||
MODULE_CACHE_PATH="/tmp/buck-module-cache"
|
||||
fi
|
||||
|
||||
exec "$@" -debug-prefix-map "$PWD"=. -module-cache-path "$MODULE_CACHE_PATH"
|
||||
307
vendor/cxx/tools/buck/prelude/apple/tools/swift_objc_header_postprocess.py
vendored
Normal file
307
vendor/cxx/tools/buck/prelude/apple/tools/swift_objc_header_postprocess.py
vendored
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
#!/usr/bin/env fbpython
|
||||
# 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.
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from typing import Dict, Iterable, TextIO
|
||||
|
||||
# Out-of-date? Update with this command:
|
||||
#
|
||||
# xcode-select --print-path | xargs printf '%s/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/' | xargs ls | rg '^([A-Z].+)\.framework$' -r '${1}' | xargs printf ' "%s",\n' && xcode-select --print-path | xargs printf '%s/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/module.modulemap' | xargs cat | rg '^module ([a-zA-Z0-9_]*) .*$' -r '${1}'| xargs printf ' "%s",\n'
|
||||
APPLE_SYSTEM_MODULES = {
|
||||
"ARKit",
|
||||
"AVFAudio",
|
||||
"AVFoundation",
|
||||
"AVKit",
|
||||
"Accelerate",
|
||||
"Accessibility",
|
||||
"Accounts",
|
||||
"AdServices",
|
||||
"AdSupport",
|
||||
"AddressBook",
|
||||
"AddressBookUI",
|
||||
"AppClip",
|
||||
"AppTrackingTransparency",
|
||||
"AssetsLibrary",
|
||||
"AudioToolbox",
|
||||
"AudioUnit",
|
||||
"AuthenticationServices",
|
||||
"AutomaticAssessmentConfiguration",
|
||||
"BackgroundTasks",
|
||||
"BusinessChat",
|
||||
"CFNetwork",
|
||||
"CallKit",
|
||||
"CarPlay",
|
||||
"ClassKit",
|
||||
"ClockKit",
|
||||
"CloudKit",
|
||||
"Combine",
|
||||
"Contacts",
|
||||
"ContactsUI",
|
||||
"CoreAudio",
|
||||
"CoreAudioKit",
|
||||
"CoreAudioTypes",
|
||||
"CoreBluetooth",
|
||||
"CoreData",
|
||||
"CoreFoundation",
|
||||
"CoreGraphics",
|
||||
"CoreHaptics",
|
||||
"CoreImage",
|
||||
"CoreLocation",
|
||||
"CoreLocationUI",
|
||||
"CoreMIDI",
|
||||
"CoreML",
|
||||
"CoreMedia",
|
||||
"CoreMotion",
|
||||
"CoreNFC",
|
||||
"CoreServices",
|
||||
"CoreSpotlight",
|
||||
"CoreTelephony",
|
||||
"CoreText",
|
||||
"CoreVideo",
|
||||
"CryptoKit",
|
||||
"CryptoTokenKit",
|
||||
"DataDetection",
|
||||
"DeveloperToolsSupport",
|
||||
"DeviceActivity",
|
||||
"DeviceCheck",
|
||||
"EventKit",
|
||||
"EventKitUI",
|
||||
"ExposureNotification",
|
||||
"ExternalAccessory",
|
||||
"FamilyControls",
|
||||
"FileProvider",
|
||||
"FileProviderUI",
|
||||
"Foundation",
|
||||
"GLKit",
|
||||
"GSS",
|
||||
"GameController",
|
||||
"GameKit",
|
||||
"GameplayKit",
|
||||
"GroupActivities",
|
||||
"HealthKit",
|
||||
"HealthKitUI",
|
||||
"HomeKit",
|
||||
"IOKit",
|
||||
"IOSurface",
|
||||
"IdentityLookup",
|
||||
"IdentityLookupUI",
|
||||
"ImageCaptureCore",
|
||||
"ImageIO",
|
||||
"Intents",
|
||||
"IntentsUI",
|
||||
"JavaScriptCore",
|
||||
"LinkPresentation",
|
||||
"LocalAuthentication",
|
||||
"ManagedSettings",
|
||||
"ManagedSettingsUI",
|
||||
"MapKit",
|
||||
"MediaAccessibility",
|
||||
"MediaPlayer",
|
||||
"MediaToolbox",
|
||||
"MessageUI",
|
||||
"Messages",
|
||||
"Metal",
|
||||
"MetalKit",
|
||||
"MetalPerformanceShaders",
|
||||
"MetalPerformanceShadersGraph",
|
||||
"MetricKit",
|
||||
"MobileCoreServices",
|
||||
"ModelIO",
|
||||
"MultipeerConnectivity",
|
||||
"MusicKit",
|
||||
"NaturalLanguage",
|
||||
"NearbyInteraction",
|
||||
"Network",
|
||||
"NetworkExtension",
|
||||
"NewsstandKit",
|
||||
"NotificationCenter",
|
||||
"OSLog",
|
||||
"OpenAL",
|
||||
"OpenGLES",
|
||||
"PDFKit",
|
||||
"PHASE",
|
||||
"PassKit",
|
||||
"PencilKit",
|
||||
"Photos",
|
||||
"PhotosUI",
|
||||
"PushKit",
|
||||
"QuartzCore",
|
||||
"QuickLook",
|
||||
"QuickLookThumbnailing",
|
||||
"RealityFoundation",
|
||||
"RealityKit",
|
||||
"ReplayKit",
|
||||
"SafariServices",
|
||||
"SceneKit",
|
||||
"ScreenTime",
|
||||
"Security",
|
||||
"SensorKit",
|
||||
"ShazamKit",
|
||||
"Social",
|
||||
"SoundAnalysis",
|
||||
"Speech",
|
||||
"SpriteKit",
|
||||
"StoreKit",
|
||||
"SwiftUI",
|
||||
"SystemConfiguration",
|
||||
"TabularData",
|
||||
"Twitter",
|
||||
"UIKit",
|
||||
"UniformTypeIdentifiers",
|
||||
"UserNotifications",
|
||||
"UserNotificationsUI",
|
||||
"VideoSubscriberAccount",
|
||||
"VideoToolbox",
|
||||
"Vision",
|
||||
"VisionKit",
|
||||
"WatchConnectivity",
|
||||
"WebKit",
|
||||
"WidgetKit",
|
||||
"AppleTextureEncoder",
|
||||
"Compression",
|
||||
"Darwin",
|
||||
"asl",
|
||||
"dnssd",
|
||||
"os",
|
||||
"os_object",
|
||||
"os_workgroup",
|
||||
"libkern",
|
||||
"notify",
|
||||
"zlib",
|
||||
"SQLite3",
|
||||
}
|
||||
|
||||
APPLE_TEST_FRAMEWORKS = {
|
||||
"XCTest",
|
||||
}
|
||||
|
||||
|
||||
# These modules require specific handling, as they do not have an umbrella
|
||||
# header that matches the module name, as typical Apple frameworks do.
|
||||
APPLE_SYSTEM_MODULE_OVERRIDES = {
|
||||
"Dispatch": ("dispatch", ("dispatch.h",)),
|
||||
"ObjectiveC": ("objc", ("runtime.h",)),
|
||||
}
|
||||
|
||||
|
||||
def write_imports_for_headers(out: TextIO, prefix: str, headers: Iterable[str]) -> None:
|
||||
for header in headers:
|
||||
print(f"#import <{prefix}/{header}>", file=out)
|
||||
|
||||
|
||||
def write_imports_for_modules(
|
||||
out: TextIO,
|
||||
postprocessing_module_name: str,
|
||||
modules: Iterable[str],
|
||||
deps: Dict[str, Iterable[str]],
|
||||
) -> None:
|
||||
# We only include the traditional textual imports when modules are disabled, so
|
||||
# that the behavior with modules enabled is identical to the behavior without
|
||||
# the postprocessing.
|
||||
print("#else", file=out)
|
||||
for module in modules:
|
||||
if headers := deps.get(module):
|
||||
write_imports_for_headers(out, module, headers)
|
||||
elif override := APPLE_SYSTEM_MODULE_OVERRIDES.get(module):
|
||||
write_imports_for_headers(out, override[0], override[1])
|
||||
elif module in APPLE_SYSTEM_MODULES or module in APPLE_TEST_FRAMEWORKS:
|
||||
# When we don't have an explicit override for the module, we use the module's
|
||||
# name as an umbrella header. This is used for typical Apple frameworks like
|
||||
# Foundation and UIKit.
|
||||
write_imports_for_headers(out, module, (f"{module}.h",))
|
||||
else:
|
||||
print(
|
||||
f"""
|
||||
The module "{module}" was imported as a dependency of Swift code in "{postprocessing_module_name}", but could not be mapped to a list of header imports by Buck's Swift header postprocessing. There are two possibilities:
|
||||
|
||||
1. If "{module}" is an internal library, it is likely that the exported_deps of "{postprocessing_module_name}" are incorrect. Try fixing them manually or with "arc fixmydeps". This is the most likely issue.
|
||||
|
||||
2. If "{module}" is a system (Apple) framework, the list of Apple system modules in {os.path.basename(__file__)} is out-of-date. There is a command to fix it in that file. This issue is unlikely.
|
||||
""",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("header")
|
||||
parser.add_argument("deps")
|
||||
parser.add_argument("out")
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.deps) as f:
|
||||
deps = json.load(f)
|
||||
|
||||
# Strips the suffix from the header name, leaving us with just the name
|
||||
# of the module that we are postprocessing the header for. This is used
|
||||
# for error reporting.
|
||||
postprocessing_module_name = os.path.basename(args.header).split("-")[0]
|
||||
|
||||
# The Swift compiler's output looks like this:
|
||||
#
|
||||
# #if __has_feature(modules)
|
||||
# #if __has_warning("-Watimport-in-framework-header")
|
||||
# #pragma clang diagnostic ignored "-Watimport-in-framework-header"
|
||||
# #endif
|
||||
# @import ModuleA;
|
||||
# @import ModuleB;
|
||||
# @import ModuleC;
|
||||
# #endif
|
||||
#
|
||||
# The implementation here balances being somewhat flexible to changes to the compiler's
|
||||
# output, unlikely though they may be, with avoiding adding too much complexity and getting
|
||||
# too close to implementing a full parser for Objective-C un-preprocessed header files.
|
||||
|
||||
with open(args.header) as header, open(args.out, "w") as out:
|
||||
# When this is None, it means that we are still searching for the start of the conditional
|
||||
# @import block in the generated header.
|
||||
modules = None
|
||||
# The Swift compiler emits an additional #if gate inside the conditional @import block, so
|
||||
# we need to track whether we're in a further nested conditional so that we know when the
|
||||
# main conditional block has ended.
|
||||
if_level = 0
|
||||
|
||||
for line in header:
|
||||
line = line.rstrip("\n")
|
||||
# When the modules has not been set, we are still searching for the start of the
|
||||
# modules @import section.
|
||||
if modules is None:
|
||||
if line == "#if __has_feature(modules)":
|
||||
modules = []
|
||||
if_level = 1
|
||||
else:
|
||||
if line.startswith("@import"):
|
||||
# Splitting on:
|
||||
# "@import ": to separate from the @import.
|
||||
# Semicolon and period: to separate the main module name from submodules or EOL.
|
||||
# The module name will then be the first item.
|
||||
modules.append(re.split(r"@import |[;.]", line)[1])
|
||||
elif line.startswith("#if"):
|
||||
# This allows us to handle the Clang diagnostic #if block that the compiler inserts
|
||||
# within the main #if block for modules.
|
||||
if_level += 1
|
||||
elif line.startswith("#endif"):
|
||||
if_level -= 1
|
||||
if if_level == 0:
|
||||
write_imports_for_modules(
|
||||
out,
|
||||
postprocessing_module_name,
|
||||
modules,
|
||||
deps,
|
||||
)
|
||||
modules = None
|
||||
print(line, file=out)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
52
vendor/cxx/tools/buck/prelude/apple/user/apple_resource_bundle.bzl
vendored
Normal file
52
vendor/cxx/tools/buck/prelude/apple/user/apple_resource_bundle.bzl
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# 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//:attributes.bzl", "AppleBundleExtension")
|
||||
load("@prelude//apple:apple_bundle_resources.bzl", "get_apple_bundle_resource_part_list")
|
||||
load("@prelude//apple:apple_bundle_types.bzl", "AppleBundleResourceInfo")
|
||||
load("@prelude//apple:apple_toolchain_types.bzl", "AppleToolchainInfo", "AppleToolsInfo")
|
||||
load("@prelude//user:rule_spec.bzl", "RuleRegistrationSpec")
|
||||
load(":resource_group_map.bzl", "resource_group_map_attr")
|
||||
|
||||
def _get_apple_resources_toolchain_attr():
|
||||
# FIXME: prelude// should be standalone (not refer to fbcode//)
|
||||
return attrs.toolchain_dep(default = "fbcode//buck2/platform/toolchain:apple-resources", providers = [AppleToolchainInfo])
|
||||
|
||||
def _impl(ctx: "context") -> ["provider"]:
|
||||
resource_output = get_apple_bundle_resource_part_list(ctx)
|
||||
return [
|
||||
DefaultInfo(),
|
||||
AppleBundleResourceInfo(
|
||||
resource_output = resource_output,
|
||||
),
|
||||
]
|
||||
|
||||
registration_spec = RuleRegistrationSpec(
|
||||
name = "apple_resource_bundle",
|
||||
impl = _impl,
|
||||
attrs = {
|
||||
"asset_catalogs_compilation_options": attrs.dict(key = attrs.string(), value = attrs.any(), default = {}),
|
||||
"binary": attrs.option(attrs.dep(), default = None),
|
||||
"deps": attrs.list(attrs.dep(), default = []),
|
||||
"extension": attrs.one_of(attrs.enum(AppleBundleExtension), attrs.string()),
|
||||
"ibtool_flags": attrs.option(attrs.list(attrs.string()), default = None),
|
||||
"ibtool_module_flag": attrs.option(attrs.bool(), default = None),
|
||||
"info_plist": attrs.source(),
|
||||
"info_plist_substitutions": attrs.dict(key = attrs.string(), value = attrs.string(), sorted = False, default = {}),
|
||||
"product_name": attrs.option(attrs.string(), default = None),
|
||||
"resource_group": attrs.option(attrs.string(), default = None),
|
||||
"resource_group_map": resource_group_map_attr(),
|
||||
# Only include macOS hosted toolchains, so we compile resources directly on Mac RE
|
||||
"_apple_toolchain": _get_apple_resources_toolchain_attr(),
|
||||
# FIXME: prelude// should be standalone (not refer to fbsource//)
|
||||
"_apple_tools": attrs.exec_dep(default = "fbsource//xplat/buck2/platform/apple:apple-tools", providers = [AppleToolsInfo]),
|
||||
# Because `apple_resource_bundle` is a proxy for `apple_bundle`, we need to get `name`
|
||||
# field of the `apple_bundle`, as it's used as a fallback value in Info.plist.
|
||||
"_bundle_target_name": attrs.string(),
|
||||
"_compile_resources_locally_override": attrs.option(attrs.bool(), default = None),
|
||||
},
|
||||
)
|
||||
51
vendor/cxx/tools/buck/prelude/apple/user/apple_toolchain_override.bzl
vendored
Normal file
51
vendor/cxx/tools/buck/prelude/apple/user/apple_toolchain_override.bzl
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# 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//apple:apple_toolchain_types.bzl", "AppleToolchainInfo")
|
||||
load("@prelude//cxx:cxx_toolchain_types.bzl", "CxxToolchainInfo")
|
||||
load("@prelude//user:rule_spec.bzl", "RuleRegistrationSpec")
|
||||
|
||||
def _impl(ctx: "context") -> ["provider"]:
|
||||
base = ctx.attrs.base[AppleToolchainInfo]
|
||||
cxx_toolchain_override = ctx.attrs.cxx_toolchain[CxxToolchainInfo]
|
||||
return [
|
||||
DefaultInfo(),
|
||||
AppleToolchainInfo(
|
||||
actool = base.actool,
|
||||
ibtool = base.ibtool,
|
||||
dsymutil = base.dsymutil,
|
||||
dwarfdump = base.dwarfdump,
|
||||
lipo = base.lipo,
|
||||
cxx_platform_info = base.cxx_platform_info,
|
||||
cxx_toolchain_info = cxx_toolchain_override if cxx_toolchain_override != None else base.cxx_toolchain_info,
|
||||
codesign = base.codesign,
|
||||
codesign_allocate = base.codesign_allocate,
|
||||
compile_resources_locally = base.compile_resources_locally,
|
||||
libtool = base.libtool,
|
||||
momc = base.momc,
|
||||
min_version = base.min_version,
|
||||
xctest = base.xctest,
|
||||
platform_path = base.platform_path,
|
||||
sdk_name = base.sdk_name,
|
||||
sdk_path = base.sdk_path,
|
||||
sdk_version = base.sdk_version,
|
||||
sdk_build_version = base.sdk_build_version,
|
||||
swift_toolchain_info = base.swift_toolchain_info,
|
||||
watch_kit_stub_binary = base.watch_kit_stub_binary,
|
||||
xcode_version = base.xcode_version,
|
||||
xcode_build_version = base.xcode_build_version,
|
||||
),
|
||||
]
|
||||
|
||||
registration_spec = RuleRegistrationSpec(
|
||||
name = "apple_toolchain_override",
|
||||
impl = _impl,
|
||||
attrs = {
|
||||
"base": attrs.dep(providers = [AppleToolchainInfo]),
|
||||
"cxx_toolchain": attrs.dep(providers = [CxxToolchainInfo]),
|
||||
},
|
||||
)
|
||||
36
vendor/cxx/tools/buck/prelude/apple/user/apple_tools.bzl
vendored
Normal file
36
vendor/cxx/tools/buck/prelude/apple/user/apple_tools.bzl
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# 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//apple:apple_toolchain_types.bzl", "AppleToolsInfo")
|
||||
load("@prelude//user:rule_spec.bzl", "RuleRegistrationSpec")
|
||||
|
||||
def _impl(ctx: "context") -> ["provider"]:
|
||||
return [
|
||||
DefaultInfo(),
|
||||
AppleToolsInfo(
|
||||
assemble_bundle = ctx.attrs.assemble_bundle[RunInfo],
|
||||
info_plist_processor = ctx.attrs.info_plist_processor[RunInfo],
|
||||
make_modulemap = ctx.attrs.make_modulemap[RunInfo],
|
||||
make_vfsoverlay = ctx.attrs.make_vfsoverlay[RunInfo],
|
||||
swift_objc_header_postprocess = ctx.attrs.swift_objc_header_postprocess[RunInfo],
|
||||
),
|
||||
]
|
||||
|
||||
# The `apple_tools` rule exposes a set of supplementary tools
|
||||
# required by the Apple rules _internally_. Such tools are not
|
||||
# toolchain/SDK specific, they're just internal helper tools.
|
||||
registration_spec = RuleRegistrationSpec(
|
||||
name = "apple_tools",
|
||||
impl = _impl,
|
||||
attrs = {
|
||||
"assemble_bundle": attrs.dep(providers = [RunInfo]),
|
||||
"info_plist_processor": attrs.dep(providers = [RunInfo]),
|
||||
"make_modulemap": attrs.dep(providers = [RunInfo]),
|
||||
"make_vfsoverlay": attrs.dep(providers = [RunInfo]),
|
||||
"swift_objc_header_postprocess": attrs.dep(providers = [RunInfo]),
|
||||
},
|
||||
)
|
||||
59
vendor/cxx/tools/buck/prelude/apple/user/apple_watchos_bundle.bzl
vendored
Normal file
59
vendor/cxx/tools/buck/prelude/apple/user/apple_watchos_bundle.bzl
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
# 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//:attributes.bzl", "AppleBundleExtension", "Traversal")
|
||||
load("@prelude//apple:apple_bundle.bzl", "apple_bundle_impl")
|
||||
load("@prelude//apple:apple_rules_impl_utility.bzl", "apple_bundle_extra_attrs")
|
||||
load("@prelude//user:rule_spec.bzl", "RuleRegistrationSpec")
|
||||
load(":watch_transition.bzl", "watch_transition")
|
||||
|
||||
def _apple_bundle_base_attrs():
|
||||
return {
|
||||
# Attributes comes from `attributes.bzl` but since it's autogenerated, we cannot easily abstract
|
||||
"asset_catalogs_compilation_options": attrs.dict(key = attrs.string(), value = attrs.any(), default = {}),
|
||||
"binary": attrs.option(attrs.dep(), default = None),
|
||||
"codesign_flags": attrs.list(attrs.string(), default = []),
|
||||
"codesign_identity": attrs.option(attrs.string(), default = None),
|
||||
"contacts": attrs.list(attrs.string(), default = []),
|
||||
"default_host_platform": attrs.option(attrs.configuration_label(), default = None),
|
||||
"default_platform": attrs.option(attrs.string(), default = None),
|
||||
"deps": attrs.list(attrs.dep(), default = []),
|
||||
"extension": attrs.one_of(attrs.enum(AppleBundleExtension), attrs.string()),
|
||||
"ibtool_flags": attrs.option(attrs.list(attrs.string()), default = None),
|
||||
"ibtool_module_flag": attrs.option(attrs.bool(), default = None),
|
||||
"incremental_bundling_enabled": attrs.option(attrs.bool(), default = None),
|
||||
"info_plist": attrs.source(),
|
||||
"info_plist_substitutions": attrs.dict(key = attrs.string(), value = attrs.string(), sorted = False, default = {}),
|
||||
"labels": attrs.list(attrs.string(), default = []),
|
||||
"licenses": attrs.list(attrs.source(), default = []),
|
||||
"platform_binary": attrs.option(attrs.list(attrs.tuple(attrs.regex(), attrs.dep())), default = None),
|
||||
"product_name": attrs.option(attrs.string(), default = None),
|
||||
"resource_group": attrs.option(attrs.string(), default = None),
|
||||
"resource_group_map": attrs.option(attrs.list(attrs.tuple(attrs.string(), attrs.list(attrs.tuple(attrs.dep(), attrs.enum(Traversal), attrs.option(attrs.string()))))), default = None),
|
||||
"skip_copying_swift_stdlib": attrs.option(attrs.bool(), default = None),
|
||||
"try_skip_code_signing": attrs.option(attrs.bool(), default = None),
|
||||
"within_view": attrs.option(attrs.list(attrs.string())),
|
||||
"xcode_product_type": attrs.option(attrs.string(), default = None),
|
||||
}
|
||||
|
||||
def _apple_watchos_bundle_attrs():
|
||||
attributes = {}
|
||||
attributes.update(_apple_bundle_base_attrs())
|
||||
attributes.update(apple_bundle_extra_attrs())
|
||||
return attributes
|
||||
|
||||
def apple_watchos_bundle_impl(ctx: "context") -> ["provider"]:
|
||||
# This rule is _equivalent_ to `apple_bundle` except it applies
|
||||
# an incoming watchOS transition.
|
||||
return apple_bundle_impl(ctx)
|
||||
|
||||
registration_spec = RuleRegistrationSpec(
|
||||
name = "apple_watchos_bundle",
|
||||
impl = apple_watchos_bundle_impl,
|
||||
attrs = _apple_watchos_bundle_attrs(),
|
||||
cfg = watch_transition,
|
||||
)
|
||||
51
vendor/cxx/tools/buck/prelude/apple/user/resource_group_map.bzl
vendored
Normal file
51
vendor/cxx/tools/buck/prelude/apple/user/resource_group_map.bzl
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# 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//:attributes.bzl", "Traversal")
|
||||
load(
|
||||
"@prelude//apple:resource_groups.bzl",
|
||||
"ResourceGroupInfo",
|
||||
"create_resource_graph",
|
||||
"get_resource_graph_node_map_func",
|
||||
)
|
||||
load(
|
||||
"@prelude//cxx:groups.bzl",
|
||||
"compute_mappings",
|
||||
"parse_groups_definitions",
|
||||
)
|
||||
load("@prelude//user:rule_spec.bzl", "RuleRegistrationSpec")
|
||||
|
||||
def v1_attrs():
|
||||
return attrs.list(attrs.tuple(attrs.string(), attrs.list(attrs.tuple(attrs.dep(), attrs.enum(Traversal), attrs.option(attrs.string())))))
|
||||
|
||||
def resource_group_map_attr():
|
||||
v2_attrs = attrs.dep(providers = [ResourceGroupInfo])
|
||||
return attrs.option(attrs.one_of(v2_attrs, v1_attrs()), default = None)
|
||||
|
||||
def _impl(ctx: "context") -> ["provider"]:
|
||||
resource_groups = parse_groups_definitions(ctx.attrs.map)
|
||||
resource_groups_deps = [mapping.root.node for group in resource_groups for mapping in group.mappings]
|
||||
resource_graph = create_resource_graph(
|
||||
ctx = ctx,
|
||||
labels = [],
|
||||
deps = resource_groups_deps,
|
||||
exported_deps = [],
|
||||
)
|
||||
resource_graph_node_map = get_resource_graph_node_map_func(resource_graph)()
|
||||
mappings = compute_mappings(groups = resource_groups, graph_map = resource_graph_node_map)
|
||||
return [
|
||||
DefaultInfo(),
|
||||
ResourceGroupInfo(groups = resource_groups, groups_hash = hash(str(resource_groups)), mappings = mappings),
|
||||
]
|
||||
|
||||
registration_spec = RuleRegistrationSpec(
|
||||
name = "resource_group_map",
|
||||
impl = _impl,
|
||||
attrs = {
|
||||
"map": v1_attrs(),
|
||||
},
|
||||
)
|
||||
84
vendor/cxx/tools/buck/prelude/apple/user/watch_transition.bzl
vendored
Normal file
84
vendor/cxx/tools/buck/prelude/apple/user/watch_transition.bzl
vendored
Normal file
|
|
@ -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.
|
||||
|
||||
"""
|
||||
Transition from iOS to watchOS. Used for watchOS bundle rule.
|
||||
Transforms both OS and SDK constraints.
|
||||
Only sanity check for source configuration is done.
|
||||
"""
|
||||
|
||||
load("@prelude//utils:utils.bzl", "expect")
|
||||
|
||||
def _os_and_sdk_unrelated_constraints(platform: PlatformInfo.type, refs: struct.type) -> {"target_label": ConstraintValueInfo.type}:
|
||||
return {
|
||||
constraint_setting_label: constraint_setting_value
|
||||
for (constraint_setting_label, constraint_setting_value) in platform.configuration.constraints.items()
|
||||
if constraint_setting_label not in [refs.os[ConstraintSettingInfo].label, refs.sdk[ConstraintSettingInfo].label]
|
||||
}
|
||||
|
||||
def _old_os_constraint_value(platform: PlatformInfo.type, refs: struct.type) -> [None, ConstraintValueInfo.type]:
|
||||
return platform.configuration.constraints.get(refs.os[ConstraintSettingInfo].label)
|
||||
|
||||
def _old_sdk_constraint_value(platform: PlatformInfo.type, refs: struct.type) -> [None, ConstraintValueInfo.type]:
|
||||
return platform.configuration.constraints.get(refs.sdk[ConstraintSettingInfo].label)
|
||||
|
||||
def _impl(platform: PlatformInfo.type, refs: struct.type) -> "PlatformInfo":
|
||||
# This functions operates in the following way:
|
||||
# - Start with all the constraints from the platform and filter out the constraints for OS and SDK.
|
||||
# - If the old OS constraint was iOS or watchOS, set the new constraint to be always watchOS.
|
||||
# - If the old SDK constraint was iOS, replace with the equivalent watchOS constraint.
|
||||
# - Return a new platform with the updated constraints.
|
||||
updated_constraints = _os_and_sdk_unrelated_constraints(platform, refs)
|
||||
|
||||
# Update OS constraint
|
||||
old_os = _old_os_constraint_value(platform, refs)
|
||||
watchos = refs.watchos[ConstraintValueInfo]
|
||||
ios = refs.ios[ConstraintValueInfo]
|
||||
if old_os != None:
|
||||
expect(old_os.label in [watchos.label, ios.label], "If present, OS transitioned non-identically to watchOS should be `iphoneos`, got {}".format(old_os.label))
|
||||
updated_constraints[refs.os[ConstraintSettingInfo].label] = watchos
|
||||
|
||||
# Update SDK constraint
|
||||
old_sdk = _old_sdk_constraint_value(platform, refs)
|
||||
watchos_device_sdk = refs.watchos_device_sdk[ConstraintValueInfo]
|
||||
watchos_simulator_sdk = refs.watchos_simulator_sdk[ConstraintValueInfo]
|
||||
ios_device_sdk = refs.ios_device_sdk[ConstraintValueInfo]
|
||||
ios_simulator_sdk = refs.ios_simulator_sdk[ConstraintValueInfo]
|
||||
is_simulator = True
|
||||
if old_sdk != None:
|
||||
if old_sdk.label == watchos_simulator_sdk.label:
|
||||
pass
|
||||
elif old_sdk.label == watchos_device_sdk.label:
|
||||
is_simulator = False
|
||||
elif old_sdk.label == ios_simulator_sdk.label:
|
||||
pass
|
||||
elif old_sdk.label == ios_device_sdk.label:
|
||||
is_simulator = False
|
||||
else:
|
||||
fail("If present, SDK transitioned non-identically to watchOS should be either `iphoneos` or `iphonesimulator`, got {}".format(old_sdk.label))
|
||||
updated_constraints[refs.sdk[ConstraintSettingInfo].label] = watchos_simulator_sdk if is_simulator else watchos_device_sdk
|
||||
|
||||
new_cfg = ConfigurationInfo(
|
||||
constraints = updated_constraints,
|
||||
values = platform.configuration.values,
|
||||
)
|
||||
return PlatformInfo(
|
||||
label = "watch_transition",
|
||||
configuration = new_cfg,
|
||||
)
|
||||
|
||||
# FIXME: prelude// should be standalone (not refer to ovr_config//)
|
||||
watch_transition = transition(impl = _impl, refs = {
|
||||
"ios": "ovr_config//os/constraints:iphoneos",
|
||||
"ios_device_sdk": "ovr_config//os/sdk/apple/constraints:iphoneos",
|
||||
"ios_simulator_sdk": "ovr_config//os/sdk/apple/constraints:iphonesimulator",
|
||||
"os": "ovr_config//os/constraints:os",
|
||||
"sdk": "ovr_config//os/sdk/apple/constraints:_",
|
||||
"watchos": "ovr_config//os/constraints:watchos",
|
||||
"watchos_device_sdk": "ovr_config//os/sdk/apple/constraints:watchos",
|
||||
"watchos_simulator_sdk": "ovr_config//os/sdk/apple/constraints:watchsimulator",
|
||||
})
|
||||
62
vendor/cxx/tools/buck/prelude/apple/xcode.bzl
vendored
Normal file
62
vendor/cxx/tools/buck/prelude/apple/xcode.bzl
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# 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//apple:apple_sdk.bzl", "get_apple_sdk_name")
|
||||
load("@prelude//apple:apple_target_sdk_version.bzl", "get_min_deployment_version_for_node")
|
||||
load("@prelude//apple:apple_utility.bzl", "has_apple_toolchain")
|
||||
load(
|
||||
"@prelude//cxx:compile.bzl",
|
||||
"CxxSrcWithFlags", # @unused Used as a type
|
||||
)
|
||||
load("@prelude//cxx:xcode.bzl", "cxx_populate_xcode_attributes")
|
||||
load("@prelude//utils:utils.bzl", "expect")
|
||||
|
||||
def apple_populate_xcode_attributes(
|
||||
ctx,
|
||||
srcs: [CxxSrcWithFlags.type],
|
||||
argsfiles_by_ext: {str.type: "artifact"},
|
||||
product_name: str.type) -> {str.type: ""}:
|
||||
data = cxx_populate_xcode_attributes(ctx = ctx, srcs = srcs, argsfiles_by_ext = argsfiles_by_ext, product_name = product_name)
|
||||
|
||||
if has_apple_toolchain(ctx):
|
||||
data["sdk"] = get_apple_sdk_name(ctx)
|
||||
data["deployment_version"] = get_min_deployment_version_for_node(ctx)
|
||||
|
||||
if hasattr(ctx.attrs, "swift_version"):
|
||||
swift_version = ctx.attrs.swift_version
|
||||
if swift_version != None:
|
||||
data["swift_version"] = swift_version
|
||||
|
||||
apple_xcode_data_add_xctoolchain(ctx, data)
|
||||
return data
|
||||
|
||||
def apple_xcode_data_add_xctoolchain(ctx: "context", data: {str.type: ""}):
|
||||
_add_label_for_attr(ctx, "_apple_xctoolchain_bundle_id", "xctoolchain_bundle_id_target", data)
|
||||
_add_output_for_attr(ctx, "_apple_xctoolchain_bundle_id", "xctoolchain_bundle_id", data)
|
||||
_add_label_for_attr(ctx, "_apple_xctoolchain", "xctoolchain_bundle_target", data)
|
||||
|
||||
def _add_label_for_attr(ctx: "context", attr_name: str.type, field_name: str.type, data: {str.type: ""}):
|
||||
xctoolchain_dep = _get_attribute_with_output(ctx, attr_name)
|
||||
if xctoolchain_dep:
|
||||
data[field_name] = xctoolchain_dep.label
|
||||
|
||||
def _add_output_for_attr(ctx: "context", attr_name: str.type, field_name: str.type, data: {str.type: ""}):
|
||||
xctoolchain_dep = _get_attribute_with_output(ctx, attr_name)
|
||||
if xctoolchain_dep:
|
||||
default_info = xctoolchain_dep[DefaultInfo]
|
||||
expect(len(default_info.default_outputs) == 1, "Expected only one output, got {}", len(default_info.default_outputs))
|
||||
data[field_name] = default_info.default_outputs[0]
|
||||
|
||||
def _get_attribute_with_output(ctx: "context", attr_name: str.type) -> ["dependency", None]:
|
||||
if hasattr(ctx.attrs, attr_name):
|
||||
dep = getattr(ctx.attrs, attr_name)
|
||||
default_info = dep[DefaultInfo]
|
||||
if len(default_info.default_outputs) > 0:
|
||||
# When there's no xctoolchain, there will be an empty `DefaultInfo`.
|
||||
# So, an empty `DefaultInfo` basically signifies that there's no xctoolchain.
|
||||
return dep
|
||||
return None
|
||||
9
vendor/cxx/tools/buck/prelude/apple/xcode_postbuild_script.bzl
vendored
Normal file
9
vendor/cxx/tools/buck/prelude/apple/xcode_postbuild_script.bzl
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# 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.
|
||||
|
||||
def xcode_postbuild_script_impl(_ctx: "context") -> ["provider"]:
|
||||
return [DefaultInfo()]
|
||||
9
vendor/cxx/tools/buck/prelude/apple/xcode_prebuild_script.bzl
vendored
Normal file
9
vendor/cxx/tools/buck/prelude/apple/xcode_prebuild_script.bzl
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# 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.
|
||||
|
||||
def xcode_prebuild_script_impl(_ctx: "context") -> ["provider"]:
|
||||
return [DefaultInfo()]
|
||||
Loading…
Add table
Add a link
Reference in a new issue