blob: 98f3ffcac403ae15b4682a0c98e03710fb6ef23d [file] [log] [blame] [view]
David Chenc4af8282016-01-20 11:06:35 +00001---
dzc22b85a22017-05-31 20:37:50 +02002layout: documentation
Googler3d70c312017-08-09 00:23:38 +02003title: Build Tutorial - iOS
daroberts223aebd2021-02-18 17:53:30 -08004category: getting-started
David Chenc4af8282016-01-20 11:06:35 +00005---
dzc22b85a22017-05-31 20:37:50 +02006
Googler22230e42020-12-02 15:18:28 -08007# Bazel Tutorial: Build an iOS App
dzc22b85a22017-05-31 20:37:50 +02008
Googler22230e42020-12-02 15:18:28 -08009This tutorial covers how to build a simple iOS app using Bazel.
10
11## What you'll learn
12
13In this tutorial, you learn how to:
14
15* Set up the environment by installing Bazel and Xcode, and downloading the
16 sample project
17* Set up a Bazel [workspace](workspace.md) that contained the source code
18 for the app and a `WORKSPACE` file that identifies the top level of the
19 workspace directory
20* Update the `WORKSPACE` file to contain references to the required
21 external dependencies
22* Create a `BUILD` file
23* Run Bazel to build the app for the simulator and an iOS device
24* Run the app in the simulator and on an iOS device
dzc22b85a22017-05-31 20:37:50 +020025
Googler3d70c312017-08-09 00:23:38 +020026## Set up your environment
dzc22b85a22017-05-31 20:37:50 +020027
Googler3d70c312017-08-09 00:23:38 +020028To get started, install Bazel and Xcode, and get the sample project.
dzc22b85a22017-05-31 20:37:50 +020029
Googler3d70c312017-08-09 00:23:38 +020030### Install Bazel
31
32Follow the [installation instructions](../install.md) to install Bazel and
33its dependencies.
34
35### Install Xcode
36
Dave MacLachlandc2c7352017-11-17 08:50:48 -080037Download and install [Xcode](https://developer.apple.com/xcode/downloads/).
38Xcode contains the compilers, SDKs, and other tools required by Bazel to build
39Apple applications.
Googler3d70c312017-08-09 00:23:38 +020040
41### Get the sample project
42
43You also need to get the sample project for the tutorial from GitHub. The GitHub
aiuto9afd33d2021-07-12 11:33:09 -070044repo has two branches: `source-only` and `main`. The `source-only` branch
Googler3d70c312017-08-09 00:23:38 +020045contains the source files for the project only. You'll use the files in this
aiuto9afd33d2021-07-12 11:33:09 -070046branch in this tutorial. The `main` branch contains both the source files
Googler3d70c312017-08-09 00:23:38 +020047and completed Bazel `WORKSPACE` and `BUILD` files. You can use the files in this
48branch to check your work when you've completed the tutorial steps.
49
50Enter the following at the command line to get the files in the `source-only`
51branch:
52
53```bash
54cd $HOME
55git clone -b source-only https://github.com/bazelbuild/examples
56```
57
58The `git clone` command creates a directory named `$HOME/examples/`. This
59directory contains several sample projects for Bazel. The project files for this
60tutorial are in `$HOME/examples/tutorial/ios-app`.
61
62## Set up a workspace
63
64A [workspace](../build-ref.html#workspaces) is a directory that contains the
65source files for one or more software projects, as well as a `WORKSPACE` file
66and `BUILD` files that contain the instructions that Bazel uses to build
67the software. The workspace may also contain symbolic links to output
68directories.
69
70A workspace directory can be located anywhere on your filesystem and is denoted
71by the presence of the `WORKSPACE` file at its root. In this tutorial, your
72workspace directory is `$HOME/examples/tutorial/`, which contains the sample
73project files you cloned from the GitHub repo in the previous step.
74
Dave MacLachlandc2c7352017-11-17 08:50:48 -080075Note that Bazel itself doesn't impose any requirements for organizing source
76files in your workspace. The sample source files in this tutorial are organized
77according to conventions for the target platform.
Googler3d70c312017-08-09 00:23:38 +020078
79For your convenience, set the `$WORKSPACE` environment variable now to refer to
80your workspace directory. At the command line, enter:
81
82```bash
83export WORKSPACE=$HOME/examples/tutorial
84```
85
86### Create a WORKSPACE file
87
88Every workspace must have a text file named `WORKSPACE` located in the top-level
89workspace directory. This file may be empty or it may contain references
90to [external dependencies](../external.html) required to build the
91software.
92
93For now, you'll create an empty `WORKSPACE` file, which simply serves to
94identify the workspace directory. In later steps, you'll update the file to add
95external dependency information.
96
97Enter the following at the command line:
98
99```bash
100touch $WORKSPACE/WORKSPACE
Dave MacLachlandc2c7352017-11-17 08:50:48 -0800101open -a Xcode $WORKSPACE/WORKSPACE
Googler3d70c312017-08-09 00:23:38 +0200102```
103
Dave MacLachlandc2c7352017-11-17 08:50:48 -0800104This creates and opens the empty `WORKSPACE` file.
Googler3d70c312017-08-09 00:23:38 +0200105
106### Update the WORKSPACE file
dzc22b85a22017-05-31 20:37:50 +0200107
Googlerb343cda2017-06-07 14:45:17 -0400108To build applications for Apple devices, Bazel needs to pull the latest
109[Apple build rules](https://github.com/bazelbuild/rules_apple) from its GitHub
Sergio Campama2705e8c2018-03-01 09:07:52 -0800110repository. To enable this, add the following [`git_repository`](../be/workspace.html#git_repository)
111rules to your `WORKSPACE` file:
Googlerb343cda2017-06-07 14:45:17 -0400112
vladmos4e9208a2020-03-11 12:16:42 -0700113```python
Yuta Saitoc3ff2132019-09-03 10:45:43 -0700114load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
vladmos4e9208a2020-03-11 12:16:42 -0700115
Sergio Campama2705e8c2018-03-01 09:07:52 -0800116git_repository(
Googlerb343cda2017-06-07 14:45:17 -0400117 name = "build_bazel_rules_apple",
Sergio Campama2705e8c2018-03-01 09:07:52 -0800118 remote = "https://github.com/bazelbuild/rules_apple.git",
Shin Yamamoto257d0932019-12-05 16:31:00 -0800119 tag = "0.19.0",
Sergio Campama2705e8c2018-03-01 09:07:52 -0800120)
vladmos4e9208a2020-03-11 12:16:42 -0700121
Sergio Campama2705e8c2018-03-01 09:07:52 -0800122git_repository(
Shin Yamamoto257d0932019-12-05 16:31:00 -0800123 name = "build_bazel_rules_swift",
124 remote = "https://github.com/bazelbuild/rules_swift.git",
vladmos4e9208a2020-03-11 12:16:42 -0700125 tag = "0.13.0",
Shin Yamamoto257d0932019-12-05 16:31:00 -0800126)
127
128git_repository(
129 name = "build_bazel_apple_support",
130 remote = "https://github.com/bazelbuild/apple_support.git",
vladmos4e9208a2020-03-11 12:16:42 -0700131 tag = "0.7.2",
Shin Yamamoto257d0932019-12-05 16:31:00 -0800132)
133
134git_repository(
Sergio Campama2705e8c2018-03-01 09:07:52 -0800135 name = "bazel_skylib",
136 remote = "https://github.com/bazelbuild/bazel-skylib.git",
Shin Yamamoto257d0932019-12-05 16:31:00 -0800137 tag = "0.9.0",
Googlerb343cda2017-06-07 14:45:17 -0400138)
139```
dzc22b85a22017-05-31 20:37:50 +0200140
Dave MacLachlandc2c7352017-11-17 08:50:48 -0800141**NOTE:** "Always use the [latest version of the build_apple rules](https://github.com/bazelbuild/rules_apple/releases)
Sergio Campama2705e8c2018-03-01 09:07:52 -0800142in the `tag` attribute. Make sure to check the latest dependencies required in
143`rules_apple`'s [project](https://github.com/bazelbuild/rules_apple)."
Dave MacLachlandc2c7352017-11-17 08:50:48 -0800144
145**NOTE:** You **must** set the value of the `name` attribute in the
Sergio Campama2705e8c2018-03-01 09:07:52 -0800146`git_repository` rule to `build_bazel_rules_apple` or the build will fail.
Dave MacLachlandc2c7352017-11-17 08:50:48 -0800147
dzc22b85a22017-05-31 20:37:50 +0200148## Review the source files
149
Googler3d70c312017-08-09 00:23:38 +0200150Take a look at the source files for the app located in
dzc22b85a22017-05-31 20:37:50 +0200151`$WORKSPACE/ios-app/UrlGet`. Again, you're just looking at these files now to
152become familiar with the structure of the app. You don't have to edit any of the
153source files to complete this tutorial.
154
155## Create a BUILD file
156
Dave MacLachlandc2c7352017-11-17 08:50:48 -0800157At a command-line prompt, open a new `BUILD` file for editing:
dzc22b85a22017-05-31 20:37:50 +0200158
159```bash
Dave MacLachlandc2c7352017-11-17 08:50:48 -0800160touch $WORKSPACE/ios-app/BUILD
161open -a Xcode $WORKSPACE/ios-app/BUILD
dzc22b85a22017-05-31 20:37:50 +0200162```
163
Googler3d70c312017-08-09 00:23:38 +0200164### Add the rule load statement
Googlerb343cda2017-06-07 14:45:17 -0400165
166To build iOS targets, Bazel needs to load build rules from its GitHub repository
167whenever the build runs. To make these rules available to your project, add the
168following load statement to the beginning of your `BUILD` file:
169
170```
171load("@build_bazel_rules_apple//apple:ios.bzl", "ios_application")
172```
173
Googlerec7ecd72021-03-19 16:20:52 -0700174You only need to load the `ios_application` rule because the `objc_library`
175rule is built into the Bazel package.
Dave MacLachlandc2c7352017-11-17 08:50:48 -0800176
Googler3d70c312017-08-09 00:23:38 +0200177### Add an objc_library rule
dzc22b85a22017-05-31 20:37:50 +0200178
179Bazel provides several build rules that you can use to build an app for the
180iOS platform. For this tutorial, you'll first use the
dzc205125b2017-06-26 11:01:47 +0200181[`objc_library`](../be/objective-c.html#objc_library) rule to tell Bazel
Googlerb343cda2017-06-07 14:45:17 -0400182how to build a static library from the app source code and Xib files. Then
Googler916f7032019-04-24 16:24:12 -0700183you'll use the
184[`ios_application`](https://github.com/bazelbuild/rules_apple/tree/master/doc)
Googlerb343cda2017-06-07 14:45:17 -0400185rule to tell it how to build the application binary and the `.ipa` bundle.
186
187**NOTE:** This tutorial presents a minimal use case of the Objective-C rules in
188Bazel. For example, you have to use the `ios_application` rule to build
189multi-architecture iOS apps.
dzc22b85a22017-05-31 20:37:50 +0200190
191Add the following to your `BUILD` file:
192
193```python
194objc_library(
195 name = "UrlGetClasses",
196 srcs = [
Googlerb343cda2017-06-07 14:45:17 -0400197 "UrlGet/AppDelegate.m",
198 "UrlGet/UrlGetViewController.m",
199 "UrlGet/main.m",
dzc22b85a22017-05-31 20:37:50 +0200200 ],
201 hdrs = glob(["UrlGet/*.h"]),
Shin Yamamoto257d0932019-12-05 16:31:00 -0800202 data = ["UrlGet/UrlGetViewController.xib"],
dzc22b85a22017-05-31 20:37:50 +0200203)
204```
205
206Note the name of the rule, `UrlGetClasses`.
207
Googler3d70c312017-08-09 00:23:38 +0200208### Add an ios_application rule
dzc22b85a22017-05-31 20:37:50 +0200209
Googler916f7032019-04-24 16:24:12 -0700210The
211[`ios_application`](https://github.com/bazelbuild/rules_apple/tree/master/doc)
212rule builds the application binary and creates the `.ipa` bundle file.
dzc22b85a22017-05-31 20:37:50 +0200213
214Add the following to your `BUILD` file:
215
216```python
217ios_application(
218 name = "ios-app",
Googlerb343cda2017-06-07 14:45:17 -0400219 bundle_id = "Google.UrlGet",
220 families = [
221 "iphone",
222 "ipad",
223 ],
Zain Asgar74f86dc2017-11-28 07:57:45 -0800224 minimum_os_version = "9.0",
Googlerb343cda2017-06-07 14:45:17 -0400225 infoplists = [":UrlGet/UrlGet-Info.plist"],
226 visibility = ["//visibility:public"],
227 deps = [":UrlGetClasses"],
dzc22b85a22017-05-31 20:37:50 +0200228)
229```
230
Dave MacLachlandc2c7352017-11-17 08:50:48 -0800231**NOTE:** Please update the `minimum_os_version` attribute to the minimum
232version of iOS that you plan to support.
233
Googlerb343cda2017-06-07 14:45:17 -0400234Note how the `deps` attribute references the output of the `UrlGetClasses` rule
235you added to the `BUILD` file above.
236
dzc22b85a22017-05-31 20:37:50 +0200237Now, save and close the file. You can compare your `BUILD` file to the
aiuto9afd33d2021-07-12 11:33:09 -0700238[completed example](https://github.com/bazelbuild/examples/blob/main/tutorial/ios-app/BUILD)
239in the `main` branch of the `GitHub repo.
dzc22b85a22017-05-31 20:37:50 +0200240
Googler3d70c312017-08-09 00:23:38 +0200241## Build and deploy the app
242
243You are now ready to build your app and deploy it to a simulator and onto an
244iOS device.
245
246**NOTE:** The app launches standalone but requires a backend server in order to
247produce output. See the README file in the sample project directory to find out
248how to build the backend server.
249
Googler22230e42020-12-02 15:18:28 -0800250The built app is located in the `$WORKSPACE/bazel-bin` directory.
251
252Completed `WORKSPACE` and `BUILD` files for this tutorial are located in the
aiuto9afd33d2021-07-12 11:33:09 -0700253[main branch](https://github.com/bazelbuild/examples/tree/HEAD/tutorial)
Googler22230e42020-12-02 15:18:28 -0800254of the GitHub repo. You can compare your work to the completed files for
255additional help or troubleshooting.
256
Googler3d70c312017-08-09 00:23:38 +0200257### Build the app for the simulator
dzc22b85a22017-05-31 20:37:50 +0200258
259Make sure that your current working directory is inside your Bazel workspace:
260
261```bash
262cd $WORKSPACE
263```
264
265Now, enter the following to build the sample app:
266
267```bash
268bazel build //ios-app:ios-app
269```
270
Googlerb343cda2017-06-07 14:45:17 -0400271Bazel launches and builds the sample app. During the build process, its
dzc22b85a22017-05-31 20:37:50 +0200272output will appear similar to the following:
273
274```bash
275INFO: Found 1 target...
276Target //ios-app:ios-app up-to-date:
277 bazel-bin/ios-app/ios-app.ipa
Googlerb343cda2017-06-07 14:45:17 -0400278INFO: Elapsed time: 0.565s, Critical Path: 0.44s
dzc22b85a22017-05-31 20:37:50 +0200279```
280
Googler3d70c312017-08-09 00:23:38 +0200281### Find the build outputs
dzc22b85a22017-05-31 20:37:50 +0200282
283The `.ipa` file and other outputs are located in the
284`$WORKSPACE/bazel-bin/ios-app` directory.
285
Googler3d70c312017-08-09 00:23:38 +0200286### Run and debug the app in the simulator
dzc22b85a22017-05-31 20:37:50 +0200287
philwo9cd168a2021-06-08 13:22:14 -0700288You can now run the app from Xcode using the iOS Simulator. First, [generate an Xcode project using Tulsi](http://tulsi.bazel.build/).
Dave MacLachlandc2c7352017-11-17 08:50:48 -0800289
Googlerb343cda2017-06-07 14:45:17 -0400290Then, open the project in Xcode, choose an iOS Simulator as the runtime scheme,
291and click **Run**.
dzc22b85a22017-05-31 20:37:50 +0200292
Googlerb343cda2017-06-07 14:45:17 -0400293**Note:** If you modify any project files in Xcode (for example, if you add or
294remove a file, or add or change a dependency), you must rebuild the app using
295Bazel, re-generate the Xcode project in Tulsi, and then re-open the project in
296Xcode.
dzc22b85a22017-05-31 20:37:50 +0200297
Googler3d70c312017-08-09 00:23:38 +0200298### Build the app for a device
dzc22b85a22017-05-31 20:37:50 +0200299
Googlerb343cda2017-06-07 14:45:17 -0400300To build your app so that it installs and launches on an iOS device, Bazel needs
301the appropriate provisioning profile for that device model. Do the following:
dzc22b85a22017-05-31 20:37:50 +0200302
Googlerb343cda2017-06-07 14:45:17 -04003031. Go to your [Apple Developer Account](https://developer.apple.com/account) and
304 download the appropriate provisioning profile for your device. See
305 [Apple's documentation](https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/MaintainingProfiles/MaintainingProfiles.html)
306 for more information.
dzc22b85a22017-05-31 20:37:50 +0200307
Googlerb343cda2017-06-07 14:45:17 -04003082. Move your profile into `$WORKSPACE`.
dzc22b85a22017-05-31 20:37:50 +0200309
Googlerb343cda2017-06-07 14:45:17 -04003103. (Optional) Add your profile to your `.gitignore` file.
311
3124. Add the following line to the `ios_application` target in your `BUILD` file:
313
314 ```python
315 provisioning_profile = "<your_profile_name>.mobileprovision",
316 ```
317
318 **NOTE:** Ensure the profile is correct so that the app can be installed on
319 a device.
320
321Now build the app for your device:
dzc22b85a22017-05-31 20:37:50 +0200322
323```bash
324bazel build //ios-app:ios-app --ios_multi_cpus=armv7,arm64
325```
326
Googlerb343cda2017-06-07 14:45:17 -0400327This builds the app as a fat binary. To build for a specific device
328architecture, designate it in the build options.
dzc22b85a22017-05-31 20:37:50 +0200329
Googlerb343cda2017-06-07 14:45:17 -0400330To build for a specific Xcode version, use the `--xcode_version` option. To
331build for a specific SDK version, use the `--ios_sdk_version` option. The
332`--xcode_version` option is sufficient in most scenarios.
dzc22b85a22017-05-31 20:37:50 +0200333
Googlerb343cda2017-06-07 14:45:17 -0400334To specify a minimum required iOS version, add the `minimum_os_version`
335parameter to the `ios_application` build rule in your `BUILD` file.
336
philwo9cd168a2021-06-08 13:22:14 -0700337You can also use [Tulsi](http://tulsi.bazel.build/docs/gettingstarted.html) to
Googlerb343cda2017-06-07 14:45:17 -0400338build your app using a GUI rather than the command line.
dzc22b85a22017-05-31 20:37:50 +0200339
Googler3d70c312017-08-09 00:23:38 +0200340### Install the app on a device
dzc22b85a22017-05-31 20:37:50 +0200341
342The easiest way to install the app on the device is to launch Xcode and use the
Googlerb343cda2017-06-07 14:45:17 -0400343`Windows > Devices` command. Select your plugged-in device from the list on the
Googler3d70c312017-08-09 00:23:38 +0200344left, then add the app by clicking the **Add** (plus sign) button under
345"Installed Apps" and selecting the `.ipa` file that you built.
dzc22b85a22017-05-31 20:37:50 +0200346
Googlerb343cda2017-06-07 14:45:17 -0400347If your app fails to install on your device, ensure that you are specifying the
348correct provisioning profile in your `BUILD` file (step 4 in the previous
349section).
350
351If your app fails to launch, make sure that your device is part of your
dzc22b85a22017-05-31 20:37:50 +0200352provisioning profile. The `View Device Logs` button on the `Devices` screen in
353Xcode may provide other information as to what has gone wrong.
354
Googler22230e42020-12-02 15:18:28 -0800355## Further reading
dzc22b85a22017-05-31 20:37:50 +0200356
Googler22230e42020-12-02 15:18:28 -0800357For more details, see
aiuto9afd33d2021-07-12 11:33:09 -0700358[main branch](https://github.com/bazelbuild/examples/tree/HEAD/tutorial)
Googler22230e42020-12-02 15:18:28 -0800359of the GitHub repo.
360