Skip to content

Commit

Permalink
[rules_ios] Add static library variant to allow rewriting headers (#1)
Browse files Browse the repository at this point in the history
Add an `apple_static_library` that lets us map source files to arbitrary
relative include paths by creating a link tree, and adding that link
tree to the deps of a main library.

This also uses apple_library instead of apple_framework as the framework
is frankly unnecessary for what we're trying to build for third party
deps.

Test Plan: Ported fmt locally to use this, and ran `clyde ios build`

Tasks:

https://app.asana.com/0/1203960884932166/1204190072048691 
https://app.asana.com/0/1203960884932166/1204190072362093
  • Loading branch information
nataliejameson authored Mar 28, 2023
1 parent 22c619b commit 429e3f0
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 1 deletion.
2 changes: 1 addition & 1 deletion rules/library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -1018,7 +1018,7 @@ def apple_library(name, library_tools = {}, export_private_headers = True, names
_append_headermap_copts(swift_angle_bracket_hmap_name, "-I", additional_objc_copts, additional_swift_copts, additional_cc_copts)

# Note: this line is intentionally disabled
if cpp_sources:
if cpp_sources and False:
additional_cc_copts.append("-I.")
native.objc_library(
name = cpp_libname,
Expand Down
179 changes: 179 additions & 0 deletions rules/static_library.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
load("@bazel_skylib//lib:paths.bzl", "paths")
load("//rules:library.bzl", "apple_library")

def apple_static_library(
name,
apple_library = apple_library,
public_headers = [],
public_headers_to_name = {},
visibility = [],
testonly = False,
**kwargs):

"""
A thin wrapper around `apple_library` that exposes a single target to depend on
and allows additionally exposing renamed headers.
public_headers_to_name is a dictionary that maps input files to their output
location within the link tree. This link tree then is added as a dep to the
final library. This allows us to effectively "move" headers and #include them
at whatever path we want.
Every other attribute is passed through to applie_library/objc_library as is
from **kwargs.
Examples:
In the case below, we declare "include/fmt/chorno.h" as a public header,
but we remap it so that '#include <fmt/chrono.h>' works.
```
apple_static_library(
name = "Texture",
srcs = glob([
"Source/**/*.h",
"Source/**/*.mm",
"Source/TextKit/*.h",
]),
module_name = "AsyncDisplayKit",
platforms = {"ios": "9.0"},
public_headers = [
"Source/ASBlockTypes.h",
"Source/ASButtonNode+Private.h",
"Source/ASButtonNode+Yoga.h",
"Source/ASButtonNode.h",
"Source/ASCellNode.h",
"Source/ASCollectionNode+Beta.h",
"Source/ASCollectionNode.h",
"Source/ASCollections.h",
"Source/ASCollectionView.h",
"Source/ASCollectionViewLayoutFacilitatorProtocol.h",
"Source/ASCollectionViewProtocols.h",
"Source/ASConfiguration.h",
"Source/ASConfigurationDelegate.h",
"Source/ASConfigurationInternal.h",
"Source/ASContextTransitioning.h",
"Source/ASControlNode+Subclasses.h",
"Source/ASControlNode.h",
"Source/ASDisplayNode+Beta.h",
"Source/ASDisplayNode+Convenience.h",
"Source/ASDisplayNode+InterfaceState.h",
"Source/ASDisplayNode+LayoutSpec.h",
"Source/ASDisplayNode+Subclasses.h",
"Source/ASDisplayNode+Yoga.h",
...
"Source/Details/ASAbstractLayoutController.h",
"Source/Details/ASBasicImageDownloader.h",
"Source/Details/ASBatchContext.h",
...
"Source/Debug/AsyncDisplayKit+Tips.h",
"Source/TextKit/ASTextNodeTypes.h",
"Source/TextKit/ASTextKitComponents.h",
],
public_headers_to_name = {
"Source/ASBlockTypes.h": "Texture/AsyncDisplayKit/ASBlockTypes.h",
"Source/ASButtonNode+Private.h": "Texture/AsyncDisplayKit/ASButtonNode+Private.h",
"Source/ASButtonNode+Yoga.h": "Texture/AsyncDisplayKit/ASButtonNode+Yoga.h",
...
"Source/Details/ASAbstractLayoutController.h": "Texture/AsyncDisplayKit/ASAbstractLayoutController.h",
"Source/Details/ASBasicImageDownloader.h": "Texture/AsyncDisplayKit/ASBasicImageDownloader.h",
"Source/Details/ASBatchContext.h": "Texture/AsyncDisplayKit/ASBatchContext.h",
...
"Source/Debug/AsyncDisplayKit+Tips.h": "Texture/AsyncDisplayKit/AsyncDisplayKit+Tips.h",
"Source/TextKit/ASTextNodeTypes.h": "Texture/AsyncDisplayKit/ASTextNodeTypes.h",
"Source/TextKit/ASTextKitComponents.h": "Texture/AsyncDisplayKit/ASTextKitComponents.h",
},
sdk_dylibs = ["c++"],
sdk_frameworks = [
"AVFoundation",
"AssetsLibrary",
"CoreLocation",
"CoreMedia",
"MapKit",
"Photos",
],
visibility = ["//visibility:public"],
xcconfig = {
"CLANG_CXX_LANGUAGE_STANDARD": "c++11",
"CLANG_CXX_LIBRARY": "libc++",
"GCC_PREPROCESSOR_DEFINITIONS": [
"AS_USE_ASSETS_LIBRARY=1",
"AS_USE_MAPKIT=1",
"AS_USE_PHOTOS=1",
"AS_USE_VIDEO=1",
],
},
deps = ["@PINRemoteImage"],
)
```
"""

public_headers = public_headers

library = apple_library(
name = name,
public_headers = public_headers,
visibility=visibility,
testonly=testonly,
**kwargs
)

platforms = library.platforms if library.platforms else {}

extra_deps = []

# TODO(nmj): We'll likely need to add a way to set up a private headers link tree
# that others can include as a dependency too. This is just a thing
# that some Pods do.
if public_headers_to_name:
public_headers_symlinks_name = "{}_public_headers_symlinks".format(name)
_headers_symlinks(
name = public_headers_symlinks_name,
hdrs = public_headers_to_name,
visibility = visibility,
)
extra_deps.append(public_headers_symlinks_name)

native.objc_library(
name = name,
deps = library.deps + extra_deps,
data = [library.data] if library.data else [],
linkopts = library.linkopts,
testonly = kwargs.get("testonly", False),
visibility = visibility,
)

def _headers_symlinks_impl(ctx):
if not ctx.attr.hdrs:
return []

outputs = []
public_headers_dir = None
for hdr, sub_path in ctx.attr.hdrs.items():
output = ctx.actions.declare_file(paths.join(ctx.attr.name, sub_path))
outputs.append(output)
if public_headers_dir == None:
public_headers_dir = output.path[:-(len(sub_path) + 1)]
ctx.actions.symlink(output = output, target_file = hdr.files.to_list()[0])

output_depset = depset(outputs)
return [
DefaultInfo(files = output_depset),
CcInfo(compilation_context = cc_common.create_compilation_context(
headers = output_depset,
includes = depset([
public_headers_dir,
]),
)),
apple_common.new_objc_provider(),
]

_headers_symlinks = rule(
implementation = _headers_symlinks_impl,
doc = "Rule that actually creates symlink trees for header remapping",
attrs = {
"hdrs": attr.label_keyed_string_dict(
allow_files = True,
doc = "Mapping of source file paths to relative path where the file should life in the link tree"
),
},
)

0 comments on commit 429e3f0

Please sign in to comment.