Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/MobileNativeFoundation/rules_xcodeproj/llms.txt

Use this file to discover all available pages before exploring further.

Focused Projects let you limit the Xcode project to a subset of your Bazel dependency graph, keeping the project fast and navigable even in large monorepos. Instead of materializing every transitive dependency as a full Xcode target, you declare exactly which targets should appear in Xcode — everything else remains a Bazel-only dependency that is built automatically when needed.

The focused_targets attribute

The focused_targets attribute accepts a list of target labels as strings. When it is set, only those targets and their transitive dependencies will be included in the generated Xcode project. All other targets that would normally appear are treated as if they were unfocused — Bazel builds them behind the scenes, but Xcode never shows them. Labels must match transitive dependencies of the targets listed in top_level_targets. If a label is not reachable from a top-level target it is silently ignored.
BUILD
load("@rules_xcodeproj//xcodeproj:top_level_target.bzl", "top_level_target")
load("@rules_xcodeproj//xcodeproj:xcodeproj.bzl", "xcodeproj")

xcodeproj(
    name = "xcodeproj",
    project_name = "App",
    top_level_targets = [
        top_level_target(":App", target_environments = ["device", "simulator"]),
        ":Tests",
    ],
    focused_targets = [
        ":App",
        ":Lib",
        ":Tests",
    ],
)
In this example the Xcode project will contain Xcode targets for :App, :Lib, and :Tests. Any other transitive dependencies (third-party libraries, generated code targets, etc.) are built by Bazel without appearing as editable Xcode targets.
Unfocused targets are automatically built by Bazel when Xcode needs them — you don’t lose build correctness. rules_xcodeproj wires up the necessary build phases so that unfocused dependencies are compiled by Bazel before the focused Xcode targets that depend on them are built.

The unfocused_targets attribute

unfocused_targets works in the opposite direction: you list the targets you want to exclude from Xcode. Any label present in unfocused_targets is excluded from the generated project even if it would otherwise appear. Crucially, unfocused_targets overrides focused_targets — if the same label appears in both lists, it will be excluded.
BUILD
load("@rules_xcodeproj//xcodeproj:top_level_target.bzl", "top_level_target")
load("@rules_xcodeproj//xcodeproj:xcodeproj.bzl", "xcodeproj")

xcodeproj(
    name = "xcodeproj",
    project_name = "App",
    top_level_targets = [
        top_level_target(":App", target_environments = ["device", "simulator"]),
        ":Tests",
    ],
    focused_targets = [
        ":App",
        ":Lib",
        ":Tests",
    ],
    # Explicitly exclude :Lib even though it is listed in focused_targets above.
    unfocused_targets = [
        ":Lib",
    ],
)

Visibility considerations

Internal targets generated by rules_xcodeproj live in the @rules_xcodeproj_generated repository. If you reference these targets in focused_targets or unfocused_targets, make sure their visibility allows access from "@rules_xcodeproj//xcodeproj:generated". Failing to set the correct visibility may produce an analysis error during project generation.

When to use focused projects

Focused projects are most valuable in these situations:

Large Monorepos

When your Bazel graph contains hundreds or thousands of targets, loading all of them into Xcode slows down project generation, indexing, and navigation. Focused projects let each developer (or team) work with just the slice they care about.

Slow Index Builds

Xcode’s Index Build runs in the background to power code completion and jump-to-definition. The more targets are focused, the smaller the index build surface area, and the faster per-file indexing becomes.

CI Machines

On CI you typically only need to build and test a specific set of targets. Using focused_targets on a CI-specific xcodeproj target keeps project generation fast and avoids materializing unnecessary build artifacts.

Migration to Bazel

When incrementally migrating a large Xcode project to Bazel, focused projects let you expose only the already-migrated targets in Xcode while Bazel builds the rest, giving you a gradual transition path.

Generating multiple focused projects

You can declare multiple xcodeproj targets in the same BUILD file, each with a different focused_targets list. This lets different teams or workflows share the same Bazel workspace while each generating a tailored Xcode project:
BUILD
load("@rules_xcodeproj//xcodeproj:top_level_target.bzl", "top_level_target")
load("@rules_xcodeproj//xcodeproj:xcodeproj.bzl", "xcodeproj")

# Full project — used by CI and for full-repo searches
xcodeproj(
    name = "xcodeproj",
    project_name = "App",
    top_level_targets = [
        top_level_target(":App", target_environments = ["device", "simulator"]),
        ":Tests",
    ],
)

# Focused project — used by the Networking team
xcodeproj(
    name = "xcodeproj_networking",
    project_name = "App",
    top_level_targets = [
        top_level_target(":App", target_environments = ["device", "simulator"]),
        ":Tests",
    ],
    focused_targets = [
        ":App",
        "//Networking:NetworkingLib",
        "//Networking:NetworkingTests",
    ],
)
Run bazel run //:xcodeproj_networking to generate the networking-focused project.

Build docs developers (and LLMs) love