# rules_apple handles the bundling step Bazel does not do for you

> rules_apple is a Bazel rule set that links and bundles Objective-C and Swift code into .app and .ipa artifacts for Apple platforms. It is deliberately narrow, and its two hard constraints are the Xcode version and the Bazel version you are on.

**bazelbuild/rules_apple** — Bazel rules to build apps for Apple platforms.

- Repository: https://github.com/bazelbuild/rules_apple
- Stars: 595 · Forks: 339
- Language: Starlark
- License: Apache-2.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/bazelbuild-rules-apple

## Only the linking and bundling step belongs here

rules_apple contains Bazel rules for bundling applications for Apple platforms, and the division of labour is stated plainly. These rules handle the linking and bundling of applications and extensions, which is the formation of an .app with an executable and its resources, archived into an .ipa. Compilation is not part of the job. Objective-C compilation is still done by the objc_library rule that ships with Bazel itself, and Swift compilation is done by swift_library from rules_swift. A team that arrives at this repository expecting a full Apple toolchain will find a narrower thing than they assumed, and the documentation points mixed language frameworks at rules_swift's mixed_language_library instead. If your problem is producing a signed, installable artefact from code that already compiles under Bazel, you are in the right place.

## A minimal iOS application in a few Starlark calls

The quick setup instruction is short. You copy the latest MODULE.bazel snippet from the releases page into your own module, and the repository ships a MODULE.bazel of its own along with a .bazelversion file that pins the Bazel release the project expects. The example below is the minimal iOS application, and it is the whole shape of the API: a swift_library for the sources, then an ios_application that takes a bundle identifier, a device family list, a minimum OS version and the library as a dependency.

```python
load("@rules_apple//apple:ios.bzl", "ios_application")
load("@rules_swift//swift:swift.bzl", "swift_library")

swift_library(
    name = "MyLibrary",
    srcs = glob(["**/*.swift"]),
)

ios_application(
    name = "App",
    bundle_id = "com.example.app",
    families = ["iphone"],
    minimum_os_version = "26.0",
    deps = [":MyLibrary"],
)
```

Two details in that snippet are worth reading twice. The iOS rule is loaded from the apple namespace of the rules_apple module, while the Swift rule comes from rules_swift, which makes the dependency between the two projects explicit in the build file. The family list and the minimum OS version are ordinary attributes on the application rule, so a project that also targets watchOS or tvOS adds sibling rules rather than reconfiguring one.

## The examples directory covers every platform family

The examples directory is more informative than the short README, because it shows the same API applied to each target the project supports. Alongside examples/BUILD there are directories for examples/ios, examples/macos, examples/tvos, examples/visionos, examples/watchos, a multi_platform directory, and a resources directory for bundled assets. The presence of watchOS, tvOS and visionOS entries says more about the scope of the rule set than any single rule definition. The rest of the repository follows a conventional Bazel shape: an apple/ directory with the rule implementations, a doc/ directory holding the reference documentation that the README links to, a test/ directory, a tools/ directory,.bazelci/ for continuous integration configuration and.bcr/ for the Bazel Central Registry entry that makes the rules installable by version.

## Xcode support is a moving line the maintainers try to raise

The README is candid about the dependency on the host toolchain. rules_apple is heavily tied to Xcode and to the tools that Xcode ships, and the project says it can change functionality depending on the current Xcode. The stated policy is to reduce the maintenance cost of supporting older versions and to remove support for them, while doing so conservatively and remaining open to supporting more versions if there is a need. The support table records Xcode 27.x, 26.x and 16.x, and every row currently shows the minimum supported rules version as unknown with the final supported version as current. That table is a live signal rather than a settled matrix, and it tells you that a rules_apple upgrade is usually an Xcode upgrade in the same week.

## Bazel version support decides which branch you need

The second constraint is Bazel itself. The project notes that rules_apple and rules_swift are often affected by changes in Bazel, which means you generally need to update these rules as you update Bazel. The support table is therefore the practical decision input. Bazel 10.x, 9.x, 8.x and 7.x all require rules version 2 or later. Older lines are closed: Bazel 6.x is supported up to rules version 3.13.0, 5.x up to 1.x, 4.x up to 0.32.0 and 3.x up to 0.21.2. The last two rows of the table also name the branch that keeps working: a bazel/7.x branch for the 7.x line and a bazel/5.x branch for the 5.x line, while the 6.x, 4.x and 3.x lines have no branch at all. Teams still on an old Bazel are not left with a current release, they are left with a frozen one. The project also says it follows semver as closely as it can since the 1.0.0 release, which is a useful signal for a dependency you will pin in a MODULE.bazel.

## What this repository will not do for you

There are boundaries worth stating plainly. rules_apple does not compile Swift or Objective-C, so a team without rules_swift and a working Apple toolchain cannot use it at all, and the host has to be a machine with Xcode installed. It is also not the tool for a mixed language framework, which the documentation routes to rules_swift instead. The reference documentation lives in the doc/ directory rather than in the README, which means the details of signing, entitlements and archive options have to be read rule by rule. The README does not document a rollback procedure for a bad upgrade, and with a table that lists final supported versions as low as 0.21.2, teams on legacy Bazel lines are expected to read the release notes before moving rather than after.

## Apache-2.0 and a release pace measured in days

The licence is Apache-2.0, which is the usual choice for a Bazel rule set that ships inside other people's builds. The release record is short and recent: 5.3.1 on 2026-10-17, 5.3.0 on 2026-10-09 and 5.2.0 on 2026-09-24, and the last push was on 2026-10-22, so the repository is moving quickly. The repository also carries the usual governance files, with CODEOWNERS, a MAINTENANCE.md, a.pre-commit-config.yaml and a.bazelrc. A MAINTENANCE.md is a helpful sign here, because a rule set whose behaviour depends on a host toolchain needs a written policy about who decides when to drop support, and this one is unusually candid about the cost of carrying old Xcode versions.

## Conclusion

rules_apple is the right choice for a team already on Bazel that needs reproducible .app and .ipa output from Swift or Objective-C sources and accepts a toolchain tied to a specific Xcode. It is the wrong choice for a project that wants Bazel to compile Apple code, because compilation still comes from objc_library and rules_swift, and it is the wrong choice for a mixed language framework, where rules_swift's mixed_language_library is the documented path. Before upgrading, check the Bazel version table for your release line and read the release notes, because the rules version you need may sit on a maintenance branch rather than main.

## FAQ

### What does rules_apple do in a Bazel build?

It handles the linking and bundling of applications and extensions for Apple platforms, producing an .app with an executable and resources and archiving it into an .ipa. Compilation stays with Bazel's objc_library rule and with swift_library from rules_swift.

### How do I add rules_apple to my project?

The quick setup is to copy the latest MODULE.bazel snippet from the repository releases page into your own module file. The repository itself ships a MODULE.bazel and a .bazelversion that pins the expected Bazel release.

### Which Xcode and Bazel versions does rules_apple support?

The README records Xcode 27.x, 26.x and 16.x, with the minimum supported rules version still listed as unknown for each. On the Bazel side, versions 2.* and later cover Bazel 7.x through 10.x, and older lines are frozen at the versions listed in the table, with bazel/7.x and bazel/5.x branches still maintained.

## Sources

- [bazelbuild/rules_apple on GitHub](https://github.com/bazelbuild/rules_apple)
- [Issues](https://github.com/bazelbuild/rules_apple/issues)
- [License: Apache-2.0](https://github.com/bazelbuild/rules_apple/blob/main/LICENSE)
- [README](https://github.com/bazelbuild/rules_apple/blob/main/README.md)
- [Releases](https://github.com/bazelbuild/rules_apple/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/bazelbuild-rules-apple
