Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[rules_ios] Add more configurability to headers_mapping #11

Merged
merged 4 commits into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,
)