One more way to build CocoaPods with Bazel. It generates Bazel's BUILD
files for pods using awesome rules_ios.
Core idea, Podspec parser, Starlark compiler are forked from PodToBUILD
iOS | macOS | watchOS | tvOS | |
---|---|---|---|---|
static library | ✅ | ✅ | ❓ | ❓ |
dynamic (use_framework! ) |
✅ | 🔜 | ❓ | ❓ |
vendored static libs | ✅ | ❓ | ❓ | ❓ |
vendored frameworks | ✅ | ❓ | ❓ | ❓ |
vendored xcframeworks | ✅ | ❓ | ❓ | ❓ |
bundles and resources | ✅ | ❓ | ❓ | ❓ |
rules_xcodeproj | ✅ | ❓ | ❓ | ❓ |
tests specs | Beta | ❓ | ❓ | ❓ |
app specs | Beta | ❓ | ❓ | ❓ |
- Autodetect vendored frameworks and libs architectures and ignore unsupported
- Local pods with custom paths, private pods (resolved by CocoaPods)
- Test and app specs 🚀
Don't forget to setup rules_ios
and rules_apple
first.
Add BazelPods
to your MODULE.bazel
bazel_dep(name = "bazelpods", version = "<version>")
Add BazelPods
to your WORKSPACE
http_archive(
name = "bazelpods",
sha256 = "<sha256>",
url = "https://github.com/sergeykhliustin/BazelPods/releases/download/<version>/release.tar.gz"
)
load("@bazelpods//:repositories.bzl", "bazelpods_dependencies")
bazelpods_dependencies()
Add post_install
action to your Podfile
and run pod install
post_install do |installer|
puts "Generating Pods.json"
development_pods = installer.sandbox.development_pods
mapped_pods = installer.analysis_result.specifications.reduce({}) { |result, spec|
result[spec.name] = {
name: spec.name,
podspec: "#{spec.defined_in_file.to_s}",
development_path: development_pods[spec.name]
}
result
}
File.open('Pods/Pods.json', 'w') { |file|
file.write(JSON.pretty_generate(mapped_pods))
}
end
Run BazelPods
bazel run @bazelpods//:bazelpods -- --src $PWD
See full list of command line options below
Now you can add first level dependencies to your app as //Pods/<pod_name>
Note: if you have multiplatform setup (--platform
with more than 1 option), use //Pods/<pod_name>:<pod_name>_<platform>
Enjoy :)
You can specify patches to use in order you want. Also you can use same patch several times.
bundle_deduplicate
checks if final bundle will contain bundles with same name and avoids them.
For example, GoogleMaps containsGoogleMaps.bundle
inresources
and vendoredGoogleMaps.xcframework
also contains same bundle.arm64_to_sim
patches legacy frameworks and libraries to support arm64 simulator. Read more arm64-to-sim. By default will run only on arm64 host machine. Usearm64_to_sim_forced
to override.user_options
applies options from--user-options
. If not specified but--user-options
not empty will be applied in the end.missing_sdks
scans all sources forimport
,@import
and#import
to find missing sdk frameworks and adds them to final configuration.
Generate
OVERVIEW: Generates BUILD files for pods
USAGE: bazelpods generate [<options>] --src <src>
OPTIONS:
--src <src> Sources root where Pods directory located (or renamed by podsRoot)
--platforms <platforms> Space separated platforms.
Valid values are: ios, osx, tvos, watchos. (default: ios)
--min-ios <min-ios> Minimum iOS version (default: 13.0)
--patches <patches> Patches. It will be applied in the order listed here.
Available options: bundle_deduplicate, arm64_to_sim, arm64_to_sim_forced, missing_sdks, user_options.
user_options requires --user-options configured.
If 'user_options' not specified, but --user_options exist, user_options patch are applied automatically. (values: bundle_deduplicate, arm64_to_sim, arm64_to_sim_forced, missing_sdks, user_options)
--user-options <user-options>
User extra options.
Supported fields: 'sdk_frameworks', 'sdk_dylibs', 'weak_sdk_frameworks', 'vendored_libraries', 'vendored_frameworks', 'vendored_xcframeworks', 'testonly', 'link_dynamic', 'data', 'objc_defines', 'runner', 'test_host', 'timeout',
'objc_copts', 'swift_copts', 'cc_copts', 'linkopts'.
Supported operators: '+=' (append), '-=' (delete), ':=' (replace).
Example:
'SomePod.sdk_dylibs += something,something'
'SomePod.testonly := true'
Platform specific:
'SomePod.platform_ios.sdk_dylibs += something,something'
For test specs:
'SomePod/UnitTests.runner := //:SomeTestsRunner'
'SomePod/UnitTests.test_host := //:SomeTestHostApp'
'SomePod/UnitTests.timeout := eternal'
--deps-prefix <deps-prefix>
Dependencies prefix (default: //Pods)
--pods-root <pods-root> Pods root relative to workspace. Used for headers search paths (default: Pods)
-f, --frameworks Packaging pods in dynamic frameworks if possible (same as `use_frameworks!`)
--no-concurrency Disable concurrency.
--log-level <log-level> Log level (debug|info|warning|error|none) (values: debug, info, warning, error, none; default: info)
--use-bundler Option to use `bundle exec` for `pod` calls
--tests-timeout <tests-timeout>
(Optional) Default timeout for test targets (short|moderate|long|eternal) (values: short, moderate, long, eternal)
--pods-json <pods-json> Pods.json (default: Pods/Pods.json)
--print-output Print BUILD files contents to terminal output
--dry-run Dry run. Files will not be written
-d, --diff Print diff between previous and new generated BUILD files
-a, --add-podspec Will add podspec.json to the pod directory. Just for debugging purposes.
--color <color> Logs color (auto|yes|no) (default: auto)
-h, --help Show help information.
Compile
OVERVIEW: Compiles podspec.json to BUILD file
USAGE: bazelpods compile [<options>] --src <src> --podspec <podspec>
OPTIONS:
--src <src> Sources root where Pods directory located (or renamed by podsRoot)
--platforms <platforms> Space separated platforms.
Valid values are: ios, osx, tvos, watchos. (default: ios)
--min-ios <min-ios> Minimum iOS version (default: 13.0)
--patches <patches> Patches. It will be applied in the order listed here.
Available options: bundle_deduplicate, arm64_to_sim, arm64_to_sim_forced, missing_sdks, user_options.
user_options requires --user-options configured.
If 'user_options' not specified, but --user_options exist, user_options patch are applied automatically. (values: bundle_deduplicate, arm64_to_sim, arm64_to_sim_forced, missing_sdks, user_options)
--user-options <user-options>
User extra options.
Supported fields: 'sdk_frameworks', 'sdk_dylibs', 'weak_sdk_frameworks', 'vendored_libraries', 'vendored_frameworks', 'vendored_xcframeworks', 'testonly', 'link_dynamic', 'data', 'objc_defines', 'runner', 'test_host', 'timeout',
'objc_copts', 'swift_copts', 'cc_copts', 'linkopts'.
Supported operators: '+=' (append), '-=' (delete), ':=' (replace).
Example:
'SomePod.sdk_dylibs += something,something'
'SomePod.testonly := true'
Platform specific:
'SomePod.platform_ios.sdk_dylibs += something,something'
For test specs:
'SomePod/UnitTests.runner := //:SomeTestsRunner'
'SomePod/UnitTests.test_host := //:SomeTestHostApp'
'SomePod/UnitTests.timeout := eternal'
--deps-prefix <deps-prefix>
Dependencies prefix (default: //Pods)
--pods-root <pods-root> Pods root relative to workspace. Used for headers search paths (default: Pods)
-f, --frameworks Packaging pods in dynamic frameworks if possible (same as `use_frameworks!`)
--no-concurrency Disable concurrency.
--log-level <log-level> Log level (debug|info|warning|error|none) (values: debug, info, warning, error, none; default: info)
--use-bundler Option to use `bundle exec` for `pod` calls
--tests-timeout <tests-timeout>
(Optional) Default timeout for test targets (short|moderate|long|eternal) (values: short, moderate, long, eternal)
--podspec <podspec> podspec.json
--subspecs <subspecs> Subspecs list
-h, --help Show help information.
arm64sim. Parses all pods same way like generate
and replaces frameworks and libraries with patched if required.
OVERVIEW: Converts existing frameworks and static libs to arm64 simulator
USAGE: bazelpods arm64sim [<options>] --src <src>
OPTIONS:
--src <src> Sources root where Pods directory located (or renamed by podsRoot)
--platforms <platforms> Space separated platforms.
Valid values are: ios, osx, tvos, watchos. (default: ios)
--min-ios <min-ios> Minimum iOS version (default: 13.0)
--patches <patches> Patches. It will be applied in the order listed here.
Available options: bundle_deduplicate, arm64_to_sim, arm64_to_sim_forced, missing_sdks, user_options.
user_options requires --user-options configured.
If 'user_options' not specified, but --user_options exist, user_options patch are applied automatically.
--user-options <user-options>
User extra options.
Supported fields: 'sdk_frameworks', 'sdk_dylibs', 'weak_sdk_frameworks', 'vendored_libraries', 'vendored_frameworks', 'vendored_xcframeworks', 'testonly', 'link_dynamic'.
Supported operators: '+=' (append), '-=' (delete), ':=' (replace).
Example:
'SomePod.sdk_dylibs += something,something'
'SomePod.testonly := true'
Platform specific:
'SomePod.platform_ios.sdk_dylibs += something,something'
--deps-prefix <deps-prefix>
Dependencies prefix (default: //Pods)
--pods-root <pods-root> Pods root relative to workspace. Used for headers search paths (default: Pods)
-f, --frameworks Packaging pods in dynamic frameworks if possible (same as `use_frameworks!`)
--no-concurrency Disable concurrency.
--log-level <log-level> Log level (debug|info|warning|error|none) (default: info)
--pods-json <pods-json> Pods.json (default: Pods/Pods.json)
--subspecs <subspecs> Subspecs list
--force By default it will run only on arm64 host. Use this option to override.
-h, --help Show help information.
There are two existing wonderful alternatives to this project: cocoapods-bazel and PodToBUILD.
cocoapods-bazel
generates BUILD files based on targets from Pods.xcodeproj
.
As a result of this, we will have some aggregated targets needed for Xcode but redundant for Bazel.
These targets cause issues with resources and module name resolving.
For example, currently, it's not working out of the box for a custom Firebase setup.
PodToBUILD
's main idea is to generate BUILD files directly from .podspec info and it's great!
Unfortunately, out of the box, it cannot resolve the whole dependency tree with private pods as Cocoapods do.
We can solve it by letting Cocoapods do its work and vendorise pods after. (something like this)
Another problem is "mixed code" (Swift + Objective-C). It's still in development
, so you cannot resolve it with reasonable effort.
Meanwhile, rules_ios
already supports it.
BazelPods
uses best of all worlds.
Let Cocoapods download, resolve and setup everything for us. After that, BazelPods will generate BUILD
files from .podspecs with only needed subspecs with rules from rules_ios
. Written in Swift, so it will do it really fast.
make xcodeproj
Just contribute and report your issues