Skip to content

Commit

Permalink
[rules_ios] Rebase onto upstream 4.8.2, squash patches, and fix / cle…
Browse files Browse the repository at this point in the history
…anup custom patches (#16)

Re-applying #15 

This does a few things:

- Squashes our existing changes since our last divergence point with
main. I only did this because it was easier since we had a lot of
iteration on our interim PRs that isn't strictly necessary or relevant
anymore.
- Removes some patches / patching logic where we had backported
functionality from rules_apple. We do not need to patch rules_apple
right now.
- Rebases us onto upstream version 4.8.2 of rules_ios
- Removes apple_common.new_objc_provider in _cc_headers_symlinks_impl.
In the new rules_ios, that being present causes it to attempt to infer
and build a swift modulemap, which we don't need.
- Removes a change we had made to CPU configuration to support both
cocoapods and podtobuild at the same time. We're back on the upstream
configuration.

At the end, the major changes we have vs upstream are:

- Adding static_framework rule
- Headermap rewriting
- Changing some rules from -I to -idirafter
- Mark a few things as "system" so we don't see their errors in our
builds.

The original commits were:

2e4ed21 (origin/discord, origin/HEAD, discord) [rules_apple] Add support
for xcprivacy manifests in extensions (#14)
86b8d2d [rules_apple] add upstream filesystem patches (#13)
0add154 [rules_ios] Add more configurability to headers_mapping (#11)
a6c59d1 [rules_ios] Add more entitlement errors (#12)
2699bd3 [rules_ios] Expose cc_headers_symlinks, add a helper function
for headers (#10)
c494ff2 [rules_ios] Add objc_public_headers (#9)
7d8db25 [rules_ios] Export as system_includes (#7)
28ed123 [rules_ios] Make modulemaps have '[system]', fix static_library
deps (#6)
4340c91 [rules_ios] Allow rewriting header paths for frameworks and
libraries (#5)
1fc624a [rules_ios] Use -idirafter instead of -I (#4)
01a939d [rules_ios] Re-enable cpp rules (#3)
238256a [transitions] Do not remove cpus from configured target graph
(#2)
429e3f0 [rules_ios] Add static library variant to allow rewriting
headers (#1)
  • Loading branch information
nataliejameson committed Aug 13, 2024
1 parent 4e09120 commit d0307e9
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 18 deletions.
72 changes: 58 additions & 14 deletions rules/framework.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ load("@bazel_skylib//lib:collections.bzl", "collections")
load("@bazel_skylib//lib:partial.bzl", "partial")
load("@bazel_skylib//lib:paths.bzl", "paths")
load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain", "use_cpp_toolchain")
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:features_support.bzl", "features_support")
load("@build_bazel_rules_apple//apple/internal:linking_support.bzl", "linking_support")
Expand Down Expand Up @@ -45,13 +46,38 @@ _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,
infoplists = [],
infoplists_by_build_setting = {},
xcconfig = {},
xcconfig_by_build_setting = {},
headers_mapping = {},
**kwargs):
"""Builds and packages an Apple framework.
Expand All @@ -74,6 +100,18 @@ def apple_framework(
If '//conditions:default' is not set the value in 'xcconfig'
is set as default.
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 @@ -98,11 +136,14 @@ def apple_framework(

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

if headers_mapping:
headers_mapping = _generate_headers_mapping(headers_mapping, kwargs)
library = apple_library(
name = name,
testonly = testonly,
xcconfig = xcconfig,
xcconfig_by_build_setting = xcconfig_by_build_setting,
headers_mapping = headers_mapping,
**kwargs
)

Expand Down Expand Up @@ -157,6 +198,7 @@ def apple_framework(
testonly = testonly,
minimum_os_version = minimum_os_version,
platform_type = platform_type,
headers_mapping = headers_mapping,
**framework_packaging_kwargs
)

Expand Down Expand Up @@ -218,11 +260,11 @@ def _framework_packaging_symlink_headers(ctx, inputs, outputs, headers_mapping):
for (input, output) in zip(inputs, outputs):
ctx.actions.symlink(output = output, target_file = input)

def _framework_packaging_single(ctx, action, inputs, output, manifest = None):
outputs = _framework_packaging_multi(ctx, action, inputs, [output], manifest = manifest)
def _framework_packaging_single(ctx, action, inputs, output, manifest = None, headers_mapping = {}):
outputs = _framework_packaging_multi(ctx, action, inputs, [output], manifest = manifest, headers_mapping = headers_mapping)
return outputs[0] if outputs else None

def _framework_packaging_multi(ctx, action, inputs, outputs, manifest = None):
def _framework_packaging_multi(ctx, action, inputs, outputs, manifest = None, headers_mapping = {}):
if not inputs:
return []
if inputs == [None]:
Expand Down Expand Up @@ -390,7 +432,8 @@ def _get_framework_files(ctx, deps):
if PrivateHeadersInfo in dep:
for hdr in dep[PrivateHeadersInfo].headers.to_list():
private_headers_in.append(hdr)
destination = paths.join(framework_dir, "PrivateHeaders", hdr.basename)
mapped_path = header_paths.get_mapped_path(hdr, headers_mapping)
destination = paths.join(framework_dir, "PrivateHeaders", mapped_path)
private_headers_out.append(destination)

has_header = False
Expand All @@ -400,7 +443,8 @@ def _get_framework_files(ctx, deps):
if not hdr.is_directory and hdr.path.endswith((".h", ".hh", ".hpp")):
has_header = True
headers_in.append(hdr)
destination = paths.join(framework_dir, "Headers", hdr.basename)
mapped_path = header_paths.get_mapped_path(hdr, headers_mapping)
destination = paths.join(framework_dir, "Headers", mapped_path)
headers_out.append(destination)
elif hdr.path.endswith(".modulemap"):
modulemap_in = hdr
Expand Down Expand Up @@ -447,19 +491,19 @@ def _get_framework_files(ctx, deps):
# so inputs that do not depend on compilation
# are available before those that do,
# improving parallelism
binary_out = _framework_packaging_single(ctx, "binary", binaries_in, binary_out, framework_manifest)
headers_out = _framework_packaging_multi(ctx, "header", headers_in, headers_out, framework_manifest)
private_headers_out = _framework_packaging_multi(ctx, "private_header", private_headers_in, private_headers_out, framework_manifest)
binary_out = _framework_packaging_single(ctx, "binary", binaries_in, binary_out, framework_manifest, headers_mapping)
headers_out = _framework_packaging_multi(ctx, "header", headers_in, headers_out, framework_manifest, headers_mapping)
private_headers_out = _framework_packaging_multi(ctx, "private_header", private_headers_in, private_headers_out, framework_manifest, headers_mapping)

# Instead of creating a symlink of the modulemap, we need to copy it to modulemap_out.
# It's a hacky fix to guarantee running the clean action before compiling objc files depending on this framework in non-sandboxed mode.
# Otherwise, stale header files under framework_root will cause compilation failure in non-sandboxed mode.
modulemap_out = _framework_packaging_single(ctx, "modulemap", [modulemap_in], modulemap_out, framework_manifest)
swiftmodule_out = _framework_packaging_single(ctx, "swiftmodule", [swiftmodule_in], swiftmodule_out, framework_manifest)
swiftinterface_out = _framework_packaging_single(ctx, "swiftinterface", [swiftinterface_in], swiftinterface_out, framework_manifest)
swiftdoc_out = _framework_packaging_single(ctx, "swiftdoc", [swiftdoc_in], swiftdoc_out, framework_manifest)
infoplist_out = _framework_packaging_single(ctx, "infoplist", [infoplist_in], infoplist_out, framework_manifest)
symbol_graph_out = _framework_packaging_single(ctx, "symbol_graph", [symbol_graph_in], symbol_graph_out, framework_manifest)
modulemap_out = _framework_packaging_single(ctx, "modulemap", [modulemap_in], modulemap_out, framework_manifest, headers_mapping)
swiftmodule_out = _framework_packaging_single(ctx, "swiftmodule", [swiftmodule_in], swiftmodule_out, framework_manifest, headers_mapping)
swiftinterface_out = _framework_packaging_single(ctx, "swiftinterface", [swiftinterface_in], swiftinterface_out, framework_manifest, headers_mapping)
swiftdoc_out = _framework_packaging_single(ctx, "swiftdoc", [swiftdoc_in], swiftdoc_out, framework_manifest, headers_mapping)
infoplist_out = _framework_packaging_single(ctx, "infoplist", [infoplist_in], infoplist_out, framework_manifest, headers_mapping)
symbol_graph_out = _framework_packaging_single(ctx, "symbol_graph", [symbol_graph_in], symbol_graph_out, framework_manifest, headers_mapping)

outputs = struct(
binary = binary_out,
Expand Down
31 changes: 28 additions & 3 deletions rules/library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ load("//rules/library:resources.bzl", "wrap_resources_in_filegroup")
load("//rules/library:xcconfig.bzl", "copts_by_build_setting_with_defaults")
load("//rules:import_middleman.bzl", "import_middleman")
load("//rules:utils.bzl", "bundle_identifier_for_bundle")
load("//rules:header_paths.bzl", "header_paths")

PrivateHeadersInfo = provider(
doc = "Propagates private headers, so they can be accessed if necessary",
Expand Down Expand Up @@ -490,6 +491,8 @@ def apple_library(
xcconfig_by_build_setting = {},
objc_defines = [],
swift_defines = [],
headers_mapping = {},
objc_public_headers = None,
**kwargs):
"""Create libraries for native source code on Apple platforms.
Expand Down Expand Up @@ -620,13 +623,15 @@ def apple_library(
testonly = kwargs.pop("testonly", False)
features = kwargs.pop("features", [])
extension_safe = kwargs.pop("extension_safe", None)
system_module = kwargs.pop("system_module", True)

# Set extra linkopt for application extension safety
if extension_safe:
linkopts += ["-fapplication-extension"]
objc_copts += ["-fapplication-extension"]
swift_copts += ["-application-extension"]


# Collect the swift_library related kwargs, these are typically only set when provided to allow
# for wider compatibility with rule_swift versions.
swift_kwargs = {arg: kwargs.pop(arg) for arg in _SWIFT_LIBRARY_KWARGS if arg in kwargs}
Expand Down Expand Up @@ -912,7 +917,12 @@ def apple_library(

if len(objc_hdrs) > 0:
public_hmap_name = name + "_public_hmap"
public_hdrs = objc_hdrs

public_hdrs_dests = [
header_paths.get_string_mapped_path(header, headers_mapping)
for header in public_hdrs
]
# Public hmaps are for vendored static libs to export their header only.
# Other dependencies' headermaps will be generated by li_ios_framework
# rules.
Expand All @@ -921,20 +931,28 @@ def apple_library(
namespace = namespace,
hdrs = objc_hdrs,
tags = _MANUAL,
hdr_dests = public_hdrs_dests,
)
private_dep_names.append(public_hmap_name)
additional_objc_copts, additional_swift_copts, additional_cc_copts = _append_headermap_copts(public_hmap_name, "-I", additional_objc_copts, additional_swift_copts, additional_cc_copts)
additional_objc_copts, additional_swift_copts, additional_cc_copts = _append_headermap_copts(public_hmap_name, "-idirafter", additional_objc_copts, additional_swift_copts, additional_cc_copts)

if len(objc_non_exported_hdrs + objc_private_hdrs) > 0:
private_hmap_name = name + "_private_hmap"

private_hdrs = objc_non_exported_hdrs + objc_private_hdrs + objc_hdrs
private_hdrs_dests = [
header_paths.get_string_mapped_path(header, headers_mapping)
for header in private_hdrs
]

headermap(
name = private_hmap_name,
hdrs = objc_non_exported_hdrs + objc_private_hdrs,
hdr_dests = private_hdrs_dests,
tags = _MANUAL,
)
private_dep_names.append(private_hmap_name)
additional_objc_copts, additional_swift_copts, additional_cc_copts = _append_headermap_copts(private_hmap_name, "-I", additional_objc_copts, additional_swift_copts, additional_cc_copts)
additional_objc_copts, additional_swift_copts, additional_cc_copts = _append_headermap_copts(private_hmap_name, "-idirafter", additional_objc_copts, additional_swift_copts, additional_cc_copts)

## END HMAP

Expand All @@ -955,7 +973,7 @@ def apple_library(
additional_swift_copts += ["-swift-version", swift_version]

if has_swift_sources:
additional_swift_copts += ["-Xcc", "-I."]
additional_swift_copts.extend(("-Xcc", "-idirafter."))
if module_map:
# Frameworks find the modulemap file via the framework vfs overlay
if not namespace_is_module_name:
Expand All @@ -977,6 +995,11 @@ def apple_library(
generated_swift_header_name = module_name + "-Swift.h"

if module_map:
# NOTE(nmj): Need to make sure that both the extended and the regular
# modulemap are included as inputs, otherwise swiftc compilation
# will fail.
swiftc_inputs.append(module_map)

extend_modulemap(
name = module_map + ".extended." + name,
destination = "%s.extended.modulemap" % name,
Expand Down Expand Up @@ -1055,6 +1078,7 @@ def apple_library(
name = swift_doublequote_hmap_name,
namespace = namespace,
hdrs = [],
hdr_dests = [],
direct_hdr_providers = [swift_libname],
tags = _MANUAL,
testonly = testonly,
Expand All @@ -1068,6 +1092,7 @@ def apple_library(
name = swift_angle_bracket_hmap_name,
namespace = namespace,
hdrs = [],
hdr_dests = [],
direct_hdr_providers = [swift_libname],
tags = _MANUAL,
testonly = testonly,
Expand Down
1 change: 0 additions & 1 deletion rules/static_library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,6 @@ def _cc_headers_symlinks_impl(ctx):
return [
DefaultInfo(files = output_depset),
CcInfo(compilation_context = compilation_context),
apple_common.new_objc_provider(),
]

cc_headers_symlinks = rule(
Expand Down

0 comments on commit d0307e9

Please sign in to comment.