aboutsummaryrefslogtreecommitdiffhomepage
path: root/site/docs/tutorial/ios-app.md
blob: ff6a5b19645f59929fa031133b401f133ab950c8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
---
layout: documentation
title: Tutorial - Build an iOS App
---

# Tutorial - Build an iOS App

Like the [Android app](android-app.md) you built in the previous step, the iOS
app is a simple mobile app that communicates with the [backend server](backend-server.md).

If you're following the steps in this tutorial on macOS, you can go ahead
and build the sample iOS app as described below. If you are on Linux, skip ahead
to the [next step](backend-server.md).

Here, you'll do the following:

*   Review the source files for the app
*   Create a `BUILD` file
*   Build the app for the simulator
*   Find the build outputs
*   Run/Debug the app on the simulator
*   Build the app for a device
*   Install the app on a device

## Update the WORKSPACE file

To build applications for Apple devices, Bazel needs to pull the latest
[Apple build rules](https://github.com/bazelbuild/rules_apple) from its GitHub
repository. To enable this, add the following to your `WORKSPACE` file:

```
git_repository(
    name = "build_bazel_rules_apple",
    remote = "https://github.com/bazelbuild/rules_apple.git",
    tag = "0.0.1",
)
```

## Review the source files

Let's take a look at the source files for the app. These are located in
`$WORKSPACE/ios-app/UrlGet`. Again, you're just looking at these files now to
become familiar with the structure of the app. You don't have to edit any of the
source files to complete this tutorial.

## Create a BUILD file

At a command-line prompt, open your new `BUILD` file for editing:

```bash
vi $WORKSPACE/ios-app/BUILD
```

## Add the rule load statement

To build iOS targets, Bazel needs to load build rules from its GitHub repository
whenever the build runs. To make these rules available to your project, add the
following load statement to the beginning of your `BUILD` file:

```
load("@build_bazel_rules_apple//apple:ios.bzl", "ios_application")
```

## Add an objc_library rule

Bazel provides several build rules that you can use to build an app for the
iOS platform. For this tutorial, you'll first use the
[`objc_library`](../be/objective-c.html#objc_library) rule to tell Bazel
how to build a static library from the app source code and Xib files. Then
you'll use the [`ios_application`](https://github.com/bazelbuild/rules_apple)
rule to tell it how to build the application binary and the `.ipa` bundle.

**NOTE:** This tutorial presents a minimal use case of the Objective-C rules in
Bazel. For example, you have to use the `ios_application` rule to build
multi-architecture iOS apps.

Add the following to your `BUILD` file:

```python
objc_library(
    name = "UrlGetClasses",
    srcs = [
         "UrlGet/AppDelegate.m",
         "UrlGet/UrlGetViewController.m",
         "UrlGet/main.m",
    ],
    hdrs = glob(["UrlGet/*.h"]),
    xibs = ["UrlGet/UrlGetViewController.xib"],
)
```

Note the name of the rule, `UrlGetClasses`.

## Add an ios_application rule

The [`ios_application`](../be/objective-c.html#ios_application) rule builds
the application binary and creates the `.ipa` bundle file.

Add the following to your `BUILD` file:

```python
ios_application(
    name = "ios-app",
    bundle_id = "Google.UrlGet",
    families = [
        "iphone",
        "ipad",
    ],
    infoplists = [":UrlGet/UrlGet-Info.plist"],
    visibility = ["//visibility:public"],
    deps = [":UrlGetClasses"],
)
```

Note how the `deps` attribute references the output of the `UrlGetClasses` rule
you added to the `BUILD` file above.

Now, save and close the file. You can compare your `BUILD` file to the
[completed example](https://github.com/bazelbuild/examples/blob/master/tutorial/ios-app/BUILD)
in the `master` branch of the GitHub repo.

## Build the app for the simulator

Make sure that your current working directory is inside your Bazel workspace:

```bash
cd $WORKSPACE
```

Now, enter the following to build the sample app:

```bash
bazel build //ios-app:ios-app
```

Bazel launches and builds the sample app. During the build process, its
output will appear similar to the following:

```bash
INFO: Found 1 target...
Target //ios-app:ios-app up-to-date:
  bazel-bin/ios-app/ios-app.ipa
INFO: Elapsed time: 0.565s, Critical Path: 0.44s
```



## Find the build outputs

The `.ipa` file and other outputs are located in the
`$WORKSPACE/bazel-bin/ios-app` directory.

## Run/Debug the app on the simulator

You can now run the app from Xcode using the iOS Simulator. First, [generate an Xcode project using Tulsi](http://tulsi.bazel.io/).
Then, open the project in Xcode, choose an iOS Simulator as the runtime scheme,
and click **Run**.

**Note:** If you modify any project files in Xcode (for example, if you add or
remove a file, or add or change a dependency), you must rebuild the app using
Bazel, re-generate the Xcode project in Tulsi, and then re-open the project in
Xcode.

## Build the app for a device

To build your app so that it installs and launches on an iOS device, Bazel needs
the appropriate provisioning profile for that device model. Do the following:

1. Go to your [Apple Developer Account](https://developer.apple.com/account) and
   download the appropriate provisioning profile for your device. See
   [Apple's documentation](https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/MaintainingProfiles/MaintainingProfiles.html)
   for more information.

2. Move your profile into `$WORKSPACE`.

3. (Optional) Add your profile to your `.gitignore` file.

4. Add the following line to the `ios_application` target in your `BUILD` file:

   ```python
   provisioning_profile = "<your_profile_name>.mobileprovision",
   ```

   **NOTE:** Ensure the profile is correct so that the app can be installed on
   a device.

Now build the app for your device:

```bash
bazel build //ios-app:ios-app --ios_multi_cpus=armv7,arm64
```

This builds the app as a fat binary. To build for a specific device
architecture, designate it in the build options.

To build for a specific Xcode version, use the `--xcode_version` option. To
build for a specific SDK version, use the `--ios_sdk_version` option. The
`--xcode_version` option is sufficient in most scenarios.

To specify a minimum required iOS version, add the `minimum_os_version`
parameter to the `ios_application` build rule in your `BUILD` file.

You can also use [Tulsi](http://tulsi.bazel.io/docs/gettingstarted.html) to
build your app using a GUI rather than the command line.

## Install the app on a device

The easiest way to install the app on the device is to launch Xcode and use the
`Windows > Devices` command. Select your plugged-in device from the list on the
left, then add the app by clicking on the "plus" sign under installed apps and
selecting the `.ipa` that you built.

If your app fails to install on your device, ensure that you are specifying the
correct provisioning profile in your `BUILD` file (step 4 in the previous
section).

If your app fails to launch, make sure that your device is part of your
provisioning profile. The `View Device Logs` button on the `Devices` screen in
Xcode may provide other information as to what has gone wrong.

## What's next

The next step is to build a [backend server](backend-server.md) for the two
mobile apps you built in this tutorial.