Giter Club home page Giter Club logo

podtobuild's Introduction

An easy way to integrate CocoaPods.org into Bazel.

PodToBUILD integrates Pod dependencies end to end with an easy to use macro.

Quickstart Instructions:

In the root directory, clone rules_pods into Vendor/rules_pods.

mkdir -p Vendor/rules_pods
# TODO: Add actual URL to V1 release
curl http//:github.com/Pinterest/rules_pods/releases/archive/0.1.zip

Adding Pods

That's it. Now you're ready to add Pods.

Repositories are initialized in the Pods.WORKSPACE file with the macro, new_pod_repository.

Create the file Pods.WORKSPACE:

Pod repositories are described using the new_pod_repository macro.

new_pod_repository(
  name = "PINOperation",
  url = "https://github.com/pinterest/PINOperation/archive/1.0.3.zip",
)

The package PINOperation and the associated objc_library target, PINOperation, is available for use within Bazel. The package and target name are combined to form the label //Vendor/PINOperation:PINOperation.

Installation

The script bin/update_pods.py loads the Pod into Vendor/__POD_NAME__. This notion is similar to pod install.

# SRC_ROOT is the root workspace directory
./Vendor/rules_pods/bin/update_pods.py --src_root $PWD

Anytime 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.

new_pod_repository

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 new_pod_repository in Pods.WORKSPACE, the dependency is automatically availble within all Bazel targets.

Naming Convention

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 target: //Vendor/__PACKAGE__:__TARGET__

The top level target is determined by the root subspec.

For example, in PINCache, the root target's label is //Vendor/PINCache:PINCache.

Subspecs targets have the same name as the subspec. For example, the label of the subpsec Core in PINCache is //Vendor/PINCache:Core

Dependencies on Pods

Transitive dependencies must be declared in the Pods.WORKSPACE.

Dependencies between targets are resolved through an idiomatic naming convention.

For example, PINCache depends on PINOperation. In PINCache's BUILD file, the dependency on //Vendor/PINOperation:PINOperation is generated. The WORKSPACE needs to declare both PINOperation and PINCache.

Local Dependencies

Local dependencies in new_pod_repository are supported in addition to remote ones.

Instead of using a url that points to the remote repository, use a url that points to the local repository.

For example, if we wanted to depend on a local version of PINOperation:

new_pod_repository(
  name = "PINOperation",
  url = "/Path/To/PINOperation",
)

Upon running bin/update_pods.py, the local files are sym-linked into the pod directory.

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 name, and url.

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 copt to PINOperation we could turn on pedantic warnings just for PINOperation//:PINOperation

new_pod_repository(
  name = "PINOperation",
  url = "https://github.com/pinterest/PINOperation/archive/1.0.3.zip",
  user_options = ["PINOperation.copts += -pedantic"],
)

On objc_library, the following fields are supported: copts, deps, sdkFrameworks

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 //Vendor/__PACKAGE__:$__POD_NAME___acknowledgment

Merge all of the dependencies into Settings.bundle

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 run CocoaPods.

owner: the owner of this dependency #TODO:OSS remove owner

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 archive.

For most sources, this is typically not needed.

user_options: an array of key value operators that act on code generated targets.

Supported operators: PlusEquals ( += ). Add an item to an array

Implemented for: objc_library. Supported fields: copts, deps, sdkFrameworks

Example usage: add a custom define to the target, Texture's copts field

user_options = [ "Texture.copts += -DTEXTURE_DEBUG " ]

install_script: a script used for installation.

The placeholder __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 repo_tools are 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 enable_modules parameter

header_visibility: DEPRECATED: This is replaced by headermaps: bazelbuild/bazel#3712

Known Complications

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.

__has_include directive

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 system.

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.

For example 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 SPUserResizableView_Pion instead of SPUserResizableView_Pion.

This should eventually be handled by default.

podtobuild's People

Contributors

jerrymarino avatar rahul-malik avatar

Watchers

RS avatar James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.