An easy way to integrate
CocoaPods.org into Bazel.
PodToBUILD integrates Pod dependencies end to end with an easy to use
In the root directory, clone
git clone https://github.com/pinterest/PodToBUILD.git Vendor/rules_pods
That's it. Now you're ready to add Pods.
Repositories are initialized in the
Pods.WORKSPACE file with the macro,
Create the file
Pod repositories are described using the
new_pod_repository( name = "PINOperation", url = "https://github.com/pinterest/PINOperation/archive/1.0.3.zip", )
PINOperation and the associated
PINOperation, is available for use within Bazel. The package and target name
are combined to form the label
bin/update_pods.py loads the Pod into
This notion is similar to
# SRC_ROOT is the root workspace directory ./Vendor/rules_pods/bin/update_pods.py --src_root $PWD
Pods.WORKSPACE is changed,
bin/update_pods.py should be
ran to ensure all dependencies are updated.
PodToBUILD puts stabilty and predictablity at the core of managing
dependencies. Loading files in
external has implications on Tulsi, Xcode,
network bandwidth, and build times.
This macro is the main point of integration for pod dependencies.
Each pod is integrated as a repository and each repository is self contained.
By declaring a
Pods.WORKSPACE, the dependency is
automatically availble within all Bazel targets.
In Bazel a label is a build target identifier. Pod labels are all formed using the same logic.
The first part of the label is the package name, followed by the name of the
The top level target is determined by the root subspec.
For example, in
PINCache, the root target's label is
Subspecs targets have the same name as the subspec. For example, the label of the
Dependencies on Pods
Transitive dependencies must be declared in the
Dependencies between targets are resolved through an idiomatic naming convention.
PINCache depends on
the dependency on
//Vendor/PINOperation:PINOperation is generated. The
needs to declare both
Local dependencies in
new_pod_repository are supported in addition to remote
Instead of using a
url that points to the remote repository, use a
points to the local repository.
For example, if we wanted to depend on a local version of
new_pod_repository( name = "PINOperation", url = "/Path/To/PINOperation", )
bin/update_pods.py, the local files are sym-linked into the pod
This can aid in local development of Pod dependencies, and was originally designed for such a use case.
Resolving issues with dependencies
Many dependencies will work with
new_pod_repository without any special
considerations: just add the
Some dependencies may not. The
install_script attribute is a way to resolve
issues with such dependencies.
For example, in
PINRemoteImage source files are in folders that have spaces in
the name. This is not supported in Bazel. Please see the Known
incompatibilities section for more info.
Customizing rule attributes
It may be desirable or required to change the way that a target is built. The compiler supports customizing attributes of generated targets.
For example, to add a custom
PINOperation we could turn on pedantic
warnings just for
new_pod_repository( name = "PINOperation", url = "https://github.com/pinterest/PINOperation/archive/1.0.3.zip", user_options = ["PINOperation.copts += -pedantic"], )
objc_library, the following fields are supported:
Acknowledgements Plist and Settings.bundle
Acknowledgments metadata from a Pod is supported.
A target containing acknowledgment metadata for a given target is automatically
generated. Acknowledgment targets have the label of the form
Merge all of the dependencies into
load("@rules_pods//BazelExtensions:extensions.bzl", "acknowledgments_plist") # Example `Settings`.bundle target objc_bundle_library( name = "Settings", resources = ["Root.plist", "acknowledgements"], visibility = ['//visibility:public'], ) ALL_POD_DEPS = ["//Vendor/PINOperation:PINOperation", "//Vendor/PINCache:PINCache"] acknowledgments_plist( name = "acknowledgements", deps = [d + "_acknowledgement" for d in ALL_POD_DEPS], merger = "//Vendor/rules_pods/BazelExtensions:acknowledgement_merger" )
new_pod_repository Attribute reference
name: the name of this repo
url: the url of this repo
podspec_url: the podspec url. By default, we will look in the root of the
repository, and read a .podspec file. This requires having CocoaPods installed
on build nodes. If a JSON podspec is provided here, then it is not required to
strip_prefix: a directory prefix to strip from the extracted files. Many
archives contain a top-level directory that contains all of the useful files in
For most sources, this is typically not needed.
user_options: an array of key value operators that act on code
Supported operators: PlusEquals ( += ). Add an item to an array
objc_library. Supported fields:
Example usage: add a custom define to the target, Texture's
user_options = [ "Texture.copts += -DTEXTURE_DEBUG " ]
install_script: a script used for installation.
__INIT_REPO__ indicates at which point the BUILD file is
generated, if any.
repo_tools may be provided as a label. The names provided in
substituted out for the respective tools.
note that the script is ran directly after the repository has been fetched.
repo_tools: a mapping of executables in Bazel to command names. If we are
running something like "mv" or "sed" these binaries are already on path, so
there is no need to add an entry for them.
inhibit_warnings: whether compiler warnings should be inhibited.
trace: dump out useful debug info for a given repo.
generate_module_map: whether a module map should be generated.
enable_modules: set generated rules
header_visibility: DEPRECATED: This is replaced by headermaps: https://github.com/Bazelbuild/Bazel/pull/3712
Incompatible file paths
Apple File systems support different characters than Linux ones do. Bazel uses
the least common denominator, the Linux convention. For now, use an
install_script to resolve differences.
Some code, like Texture, uses
__has_include to conditionally include code.
In Bazel, if that include is not explicitly added, then this feature will not
work. In this case, use a
user_option to add dependencies available on the
Incompatible Target Names
Some targets may contain characters that are not valid Bazel targets.
The target should be renamed to a compatible name. The easiest way to achieve
this is to declare the dependency with a valid name. All references should be
replaced in the podspec file before the
BUILD file is generated.
SPUserResizableView+Pion exbibits this issue.
new_pod_repository( name = "SPUserResizableView_Pion", url = "https://github.com/keleixu/SPUserResizableView/archive/b263fc4e8101c6c5ac352806fb5c31aa69e32025.zip", user_options = ["SPUserResizableView_Pion.sdk_frameworks += UIKit, CoreGraphics, Foundation"], inhibit_warnings = True, install_script = """ /usr/bin/sed -i "" 's,SPUserResizableView+Pion,SPUserResizableView_Pion,g' 'SPUserResizableView+Pion.podspec' mv 'SPUserResizableView+Pion.podspec' 'SPUserResizableView_Pion.podspec' __INIT_REPO__ """, generate_module_map = False )
Now, in Bazel, the target is accessible via
This should eventually be handled by default.