Skip to main content
Glama
apple_asset_catalog.bzl7.09 kB
# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under both the MIT license found in the # LICENSE-MIT file in the root directory of this source tree and the Apache # License, Version 2.0 found in the LICENSE-APACHE file in the root directory # of this source tree. load("@prelude//apple:apple_toolchain_types.bzl", "AppleToolchainInfo") load( "@prelude//ide_integrations/xcode:data.bzl", "XCODE_DATA_SUB_TARGET", "XcodeDataInfoKeys", "generate_xcode_data", ) 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: AnalysisContext) -> list[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, ) xcode_data_default_info, xcode_data_info = generate_xcode_data(ctx, "apple_asset_catalog", None, _xcode_populate_attributes) return [DefaultInfo( sub_targets = { XCODE_DATA_SUB_TARGET: xcode_data_default_info, }, ), graph, xcode_data_info] def compile_apple_asset_catalog(ctx: AnalysisContext, specs: list[AppleAssetCatalogSpec]) -> [AppleAssetCatalogResult, 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", dir = True) 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, prefer_remote = processing_options.prefer_remote, 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: AnalysisContext, xs: list[AppleAssetCatalogSpec]) -> AppleAssetCatalogSpec: 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: AnalysisContext, xs: list[typing.Any], attr_name: str) -> [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: AnalysisContext) -> str: return ctx.label.package + ":" + ctx.label.name def _get_actool_command(ctx: AnalysisContext, info: AppleAssetCatalogSpec, catalog_output: OutputArtifact, plist_output: OutputArtifact, compilation_options: AppleAssetCatalogsCompilationOptions) -> cmd_args: external_name = get_apple_sdk_name(ctx) sdk_metadata = get_apple_sdk_metadata_for_sdk_name(external_name) target_device = sdk_metadata.target_device_flags actool_platform = sdk_metadata.actool_platform_override if not actool_platform: actool_platform = external_name actool = ctx.attrs._apple_toolchain[AppleToolchainInfo].actool actool_command = cmd_args([ actool, "--platform", actool_platform, "--minimum-deployment-target", get_bundle_min_target_version(ctx, ctx.attrs.binary), "--compile", '"$TMPDIR"', "--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("set -euo pipefail"), cmd_args('export TMPDIR="$(mktemp -d)"'), cmd_args(actool_command, delimiter = " "), cmd_args(catalog_output, format = 'mkdir -p {} && cp -r "$TMPDIR"/ {}'), ], allow_args = True, ) command = cmd_args(["/bin/sh", wrapper_script], hidden = [actool_command, catalog_output]) return command def _xcode_populate_attributes(ctx) -> dict[str, typing.Any]: data = {XcodeDataInfoKeys.EXTRA_XCODE_FILES: ctx.attrs.dirs} return data

Latest Blog Posts

MCP directory API

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

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

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