Skip to content

Commit

Permalink
[rules_ios] Add more configurability to headers_mapping (#11)
Browse files Browse the repository at this point in the history
When this just takes a dictionary, it requires us to do a lot more
boilerplate work to first construct that dictionary. Add a couple of
helpers for the common use cases that are in repo.
  • Loading branch information
nataliejameson authored Aug 25, 2023
1 parent a6c59d1 commit 0add154
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 3 deletions.
43 changes: 40 additions & 3 deletions rules/framework.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ load("//rules:plists.bzl", "process_infoplists")
load("//rules:providers.bzl", "AvoidDepsInfo", "FrameworkInfo")
load("//rules:transition_support.bzl", "transition_support")
load("//rules/internal:objc_provider_utils.bzl", "objc_provider_utils")
load("@bazel_skylib//lib:collections.bzl", "collections")
load("@bazel_skylib//lib:partial.bzl", "partial")
load("@bazel_skylib//lib:paths.bzl", "paths")
load("@bazel_skylib//lib:types.bzl", "types")
load("@build_bazel_rules_apple//apple/internal:apple_product_type.bzl", "apple_product_type")
load("@build_bazel_rules_apple//apple/internal:bundling_support.bzl", "bundling_support")
load("@build_bazel_rules_apple//apple/internal:features_support.bzl", "features_support")
Expand Down Expand Up @@ -41,16 +43,48 @@ _APPLE_FRAMEWORK_PACKAGING_KWARGS = [
"exported_symbols_lists",
]

_HEADER_EXTS = {
"srcs": (".h", ".hh", ".hpp"),
"public_headers": (".inc", ".h", ".hh", ".hpp"),
"private_headers": (".inc", ".h", ".hh", ".hpp"),
}

def _generate_headers_mapping(headers_mapping, kwargs):
if types.is_dict(headers_mapping):
return headers_mapping

to_map = []
for attr in headers_mapping.attrs:
exts = _HEADER_EXTS[attr]
to_map += [h for h in kwargs.get(attr, []) if h.endswith(exts)]

headers = collections.uniq(to_map)
if headers_mapping.op == "strip":
return header_paths.mapped_without_prefix(headers, headers_mapping.pattern)
elif headers_mapping.op == "add":
return {h: headers_mapping.pattern + h for h in headers}
else:
fail("Invalid headers_mapping `{}`".format(headers_mapping))


def apple_framework(name, apple_library = apple_library, headers_mapping = {}, **kwargs):
"""Builds and packages an Apple framework.
Args:
name: The name of the framework.
apple_library: The macro used to package sources into a library.
headers_mapping: A mapping of {str: str}, where the key is a path to a header,
and the value where that header should be placed in Headers,
PrivateHeaders, umbrella headers, hmaps, etc.
headers_mapping: Either a dictionary, or the value from add_prefix / strip_prefix.
If a dictionary, a mapping of {str: str}, where the key is a
path to a header, and the value where that header should be
placed in Headers, PrivateHeaders, umbrella headers, hmaps, etc.
If the result of header_paths.add_prefix, then the attributes
specified will have the prefix appended to the beginning.
If the result of header_paths.strip_prefix, then the
attributes specified will have the prefix reoved from the
beginning.
**kwargs: Arguments passed to the apple_library and apple_framework_packaging rules as appropriate.
"""
framework_packaging_kwargs = {arg: kwargs.pop(arg) for arg in _APPLE_FRAMEWORK_PACKAGING_KWARGS if arg in kwargs}
Expand All @@ -77,6 +111,9 @@ def apple_framework(name, apple_library = apple_library, headers_mapping = {}, *

testonly = kwargs.pop("testonly", False)

if headers_mapping:
headers_mapping = _generate_headers_mapping(headers_mapping, kwargs)

library = apple_library(name = name, testonly = testonly, headers_mapping = headers_mapping, **kwargs)
framework_deps = []

Expand Down
34 changes: 34 additions & 0 deletions rules/header_paths.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,44 @@ def _glob_and_strip_prefix(src_dirs, suffix = ".h"):
ret[file] = file[to_strip:]
return ret

def _strip_prefix(prefix, attrs=("srcs", "private_headers", "public_headers")):
"""
When remapping headers, strip the given prefix from the destination for all headers
in the specified attrs.
Only supported as the headers_mapping attribute in apple_framework
"""
return struct(pattern = prefix, attrs = attrs, op = "strip")

def _add_prefix(prefix, attrs=("srcs", "private_headers", "public_headers")):
"""
When remapping headers, add the given prefix to the destination for all headers
in the specified attrs.
Only supported as the headers_mapping attribute in apple_framework
"""
return struct(pattern = prefix, attrs = attrs, op = "add")

def _identity_mapping(attrs=("srcs", "private_headers", "public_headers")):
"""
Create a mapping that ensures that paths are not changed
Normally apple_framework moves all headers to a Headers/PrivateHeaders directory,
and often we just to make sure the files stay put in those directories with the
full on-filesystem layout.
This replaces doing something like `{h: h for h in HEADERS}`
"""
return struct(pattern = "", attrs = attrs, op = "strip")


header_paths = struct(
stringify_mapping = _stringify_mapping,
get_mapped_path = _get_mapped_path,
get_string_mapped_path = _get_string_mapped_path,
mapped_without_prefix = _mapped_without_prefix,
glob_and_strip_prefix = _glob_and_strip_prefix,
add_prefix = _add_prefix,
strip_prefix = _strip_prefix,
identity_mapping = _identity_mapping,
)

0 comments on commit 0add154

Please sign in to comment.