Building with Bazel
Part 1: Learning Bazel Write an iOS Build File
— iOS & Swift, Android & Kotlin

Lesson Complete

Play Next Lesson

Write an iOS Build File

Understand how Build files work in Bazel and then write a custom build file to compile an iOS app.


Episode 12 - Write a Build File

Now comes the fun part. We’re going to write our build file for both our iOS and Android app. We’ll start with the iOS app first. We’re going to break down our app into several target different targets. One target will encapsulate the iOS app itself whereas the other target will encompass all the swift code.

The iOS application target will depend on the swift library. Each of these targets contain three different types of attributes. The srcs attributes are files consumed by the rules and outputs source files. The deps attribute is a list of separate compiled modules that produce headers files, symbols, libraries and data. Finally, the data attribute is for the data files needed for the target such as the xcassets file.

You can also designate the visibility of a target using the visibility attribute. That is, you can set the target as public which means that anyone can access. You can also set it as private which means only targets in the package can use that target. You can also set visibility according to specific packages and sub-packages as well as as a package group. For more information see the visibility documentation. With that all said, let’s build ourselves a build file.


To get started, create a BUILD file in the bullseye directory. Remember, a build file is just a text file. We’re going to import the iOS rules and the swift rules. For iOS, we’ll import the ios_application and swift_library rule.

load("@build_bazel_rules_apple//apple:ios.bzl", "ios_application", "ios_unit_test")
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")

We’ll start with the swift library. First, we’ll give the name sources.

    name = "sources",

Next we’ll get all the sources files. For this, we use a glob function. Remember, the glob function returns files that match certain patterns. In this case, we’ll get all the swift files.

srcs = glob(["Bullseye/Sources/*.swift"]),

Finally, we’ll set the visibility to private.

visibility = ["//visibility:private"],

Okay, we created a swift library. Now its time to create an iOS application that will depend on the swift library. First, we’ll create the iOS application.



We’ll give it the name youfirstiosapp.

name = "youfirstiosapp",

Next, we’ll pass pass in our swift library target to the deps.

deps = [":sources"],

Then we’ll pass in the bundle it.

bundle_id = "com.example.bullseye",

After which, we define the device families which is the iPhone and the iPad.

families = [

Then we pass in the info.plist.

infoplists = ["Bullseye/App/Info.plist"],

After which, we’ll add all the assets in our assets catalog.

resources = glob(["Bullseye/App/Assets.xcassets/**"]),

We’ll add the minimum os version which is 14.

minimum_os_version = "14.0",

Finally, we add the visibility which is public.

visibility = ["//visibility:public"],

And that’s it - we’ve define ourself two build targets. One for the swift library and the other for the iOS application.

Now in terminal we build our iOS app.

bazel build //bullseye:youfirstiosapp

And with that, we have a compiled app. Now to run it. We can actually do that with the following command:

bazel run //bullseye:youfirstiosapp

Now we get the simulator with out app running. Well done.