1# Checking out and building Chromium for iOS 2 3There are instructions for other platforms linked from the 4[get the code](../get_the_code.md) page. 5 6## Instructions for Google Employees 7 8Are you a Google employee? See 9[go/building-chrome](https://goto.google.com/building-chrome) instead. 10 11[TOC] 12 13## System requirements 14 15* A 64-bit Mac running 10.12.6 or later. 16* [Xcode](https://developer.apple.com/xcode) 11.4+. 17* The current version of the JDK (required for the Closure compiler). 18 19## Install `depot_tools` 20 21Clone the `depot_tools` repository: 22 23```shell 24$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git 25``` 26 27Add `depot_tools` to the end of your PATH (you will probably want to put this 28in your `~/.bashrc` or `~/.zshrc`). Assuming you cloned `depot_tools` to 29`/path/to/depot_tools`: 30 31```shell 32$ export PATH="$PATH:/path/to/depot_tools" 33``` 34 35## Get the code 36 37Create a `chromium` directory for the checkout and change to it (you can call 38this whatever you like and put it wherever you like, as 39long as the full path has no spaces): 40 41```shell 42$ mkdir chromium && cd chromium 43``` 44 45Run the `fetch` tool from `depot_tools` to check out the code and its 46dependencies. 47 48```shell 49$ fetch ios 50``` 51 52If you don't want the full repo history, you can save a lot of time by 53adding the `--no-history` flag to `fetch`. 54 55Expect the command to take 30 minutes on even a fast connection, and many 56hours on slower ones. 57 58When `fetch` completes, it will have created a hidden `.gclient` file and a 59directory called `src` in the working directory. The remaining instructions 60assume you have switched to the `src` directory: 61 62```shell 63$ cd src 64``` 65 66*Optional*: You can also [install API 67keys](https://www.chromium.org/developers/how-tos/api-keys) if you want your 68build to talk to some Google services, but this is not necessary for most 69development and testing purposes. 70 71## Setting up the build 72 73Since the iOS build is a bit more complicated than a desktop build, we provide 74`ios/build/tools/setup-gn.py`, which will create four appropriately configured 75build directories under `out` for Release and Debug device and simulator 76builds, and generates an appropriate Xcode project (`out/build/all.xcodeproj`) 77as well. 78 79More information about [developing with Xcode](xcode_tips.md). *Xcode project 80is an artifact, any changes made in the project itself will be ignored.* 81 82You can customize the build by editing the file `$HOME/.setup-gn` (create it if 83it does not exist). Look at `src/ios/build/tools/setup-gn.config` for 84available configuration options. 85 86From this point, you can either build from Xcode or from the command line using 87`autoninja`. `setup-gn.py` creates sub-directories named 88`out/${configuration}-${platform}`, so for a `Debug` build for simulator use: 89 90```shell 91$ autoninja -C out/Debug-iphonesimulator gn_all 92``` 93 94(`autoninja` is a wrapper that automatically provides optimal values for the 95arguments passed to `ninja`.) 96 97Note: The `setup-gn.py` script needs to run every time one of the `BUILD.gn` 98files is updated (either by you or after rebasing). If you forget to run it, 99the list of targets and files in the Xcode solution may be stale. You can run 100the script directly or use either `gclient sync` or `gclient runhooks` which 101will run `setup-gn.py` for you as part of the update hooks. 102 103You can add a custom hook to `.gclient` file to configure `setup-gn.py` to 104be run as part of `gclient runhooks`. In that case, your `.gclient` file 105would look like this: 106 107``` 108solutions = [ 109 { 110 "name" : "src", 111 "url" : "https://chromium.googlesource.com/chromium/src.git", 112 "deps_file" : "DEPS", 113 "managed" : False, 114 "custom_deps" : {}, 115 "custom_vars" : {}, 116 "custom_hooks": [{ 117 "name": "setup_gn", 118 "pattern": ".", 119 "action": [ 120 "python", 121 "src/ios/build/tools/setup-gn.py", 122 ] 123 }], 124 "safesync_url": "", 125 }, 126] 127target_os = ["ios"] 128target_os_only = True 129``` 130 131You can also follow the manual instructions on the 132[Mac page](../mac_build_instructions.md), but make sure you set the 133GN arg `target_os="ios"`. 134 135## Building for device 136 137To be able to build and run Chromium and the tests for devices, you need to 138have an Apple developer account (a free one will work) and the appropriate 139provisioning profiles, then configure the build to use them. 140 141### Code signing identity 142 143Please refer to the Apple documentation on how to get a code signing identity 144and certificates. You can check that you have a code signing identity correctly 145installed by running the following command. 146 147```shell 148$ xcrun security find-identity -v -p codesigning 149 1) 0123456789ABCDEF0123456789ABCDEF01234567 "iPhone Developer: someone@example.com (XXXXXXXXXX)" 150 1 valid identities found 151``` 152 153If the command output says you have zero valid identities, then you do not 154have a code signing identity installed and need to get one from Apple. If 155you have more than one identity, the build system may select the wrong one 156automatically, and you can use the `ios_code_signing_identity` gn variable 157to control which one to use by setting it to the identity hash, e.g. to 158`"0123456789ABCDEF0123456789ABCDEF01234567"`. 159 160### Mobile provisioning profiles 161 162Once you have the code signing identity, you need to decide on a prefix 163for the application bundle identifier. This is controlled by the gn variable 164`ios_app_bundle_id_prefix` and usually corresponds to a reversed domain name 165(the default value is `"org.chromium"`). 166 167You then need to request provisioning profiles from Apple for your devices 168for the following bundle identifiers to build and run Chromium with these 169application extensions: 170 171- `${prefix}.chrome.ios.herebedragons` 172- `${prefix}.chrome.ios.herebedragons.ShareExtension` 173- `${prefix}.chrome.ios.herebedragons.TodayExtension` 174- `${prefix}.chrome.ios.herebedragons.SearchTodayExtension` 175 176All these certificates need to have the "App Groups" 177(`com.apple.security.application-groups`) capability enabled for 178the following groups: 179 180- `group.${prefix}.chrome` 181- `group.${prefix}.common` 182 183The `group.${prefix}.chrome` is only shared by Chromium and its extensions 184to share files and configurations while the `group.${prefix}.common` is shared 185with Chromium and other applications from the same organisation and can be used 186to send commands to Chromium. 187 188### Mobile provisioning profiles for tests 189 190In addition to that, you need a different provisioning profile for each 191test application. Those provisioning profile will have a bundle identifier 192matching the following pattern `${prefix}.gtest.${test-suite-name}` where 193`${test-suite-name}` is the name of the test suite with underscores changed 194to dashes (e.g. `base_unittests` app will use `${prefix}.gest.base-unittests` 195as bundle identifier). 196 197To be able to run the EarlGrey tests on a device, you'll need two provisioning 198profiles for EarlGrey and OCHamcrest frameworks: 199 200- `${prefix}.test.OCHamcrest` 201- `${prefix}.test.EarlGrey` 202 203In addition to that, then you'll need one additional provisioning profile for 204the XCTest module too. It must match the pattern: 205`${prefix}.gtest.${test-suite-name}-module`. 206 207### Other applications 208 209Other applications like `ios_web_shell` usually will require mobile provisioning 210profiles with bundle identifiers that may usually match the following pattern 211`${prefix}.${application-name}` and may require specific capabilities. 212 213Generally, if the mobile provisioning profile is missing then the code signing 214step will fail and will print the bundle identifier of the bundle that could not 215be signed on the command line, e.g.: 216 217```shell 218$ autoninja -C out/Debug-iphoneos ios_web_shell 219ninja: Entering directory `out/Debug-iphoneos' 220FAILED: ios_web_shell.app/ios_web_shell ios_web_shell.app/_CodeSignature/CodeResources ios_web_shell.app/embedded.mobileprovision 221python ../../build/config/ios/codesign.py code-sign-bundle -t=iphoneos -i=0123456789ABCDEF0123456789ABCDEF01234567 -e=../../build/config/ios/entitlements.plist -b=obj/ios/web/shell/ios_web_shell ios_web_shell.app 222Error: no mobile provisioning profile found for "org.chromium.ios-web-shell". 223ninja: build stopped: subcommand failed. 224``` 225 226Here, the build is failing because there are no mobile provisioning profiles 227installed that could sign the `ios_web_shell.app` bundle with the identity 228`0123456789ABCDEF0123456789ABCDEF01234567`. To fix the build, you'll need to 229request such a mobile provisioning profile from Apple. 230 231You can inspect the file passed via the `-e` flag to the `codesign.py` script 232to check which capabilites are required for the mobile provisioning profile 233(e.g. `src/build/config/ios/entitlements.plist` for the above build error, 234remember that the paths are relative to the build directory, not to the source 235directory). 236 237If the required capabilities are not enabled on the mobile provisioning profile, 238then it will be impossible to install the application on a device (Xcode will 239display an error stating that "The application was signed with invalid 240entitlements"). 241 242## Running apps from the command line 243 244Any target that is built and runs on the bots (see [below](#Troubleshooting)) 245should run successfully in a local build. To run in the simulator from the 246command line, you can use `iossim`. For example, to run a debug build of 247`Chromium`: 248 249```shell 250$ out/Debug-iphonesimulator/iossim out/Debug-iphonesimulator/Chromium.app 251``` 252 253With Xcode 9, `iossim` no longer automatically launches the Simulator. This must now 254be done manually from within Xcode (`Xcode > Open Developer Tool > Simulator`), and 255also must be done *after* running `iossim`. 256 257### Passing arguments 258 259Arguments needed to be passed to the test application through `iossim`, such as 260`--gtest_filter=SomeTest.FooBar` should be passed through the `-c` flag: 261 262```shell 263$ out/Debug-iphonesimulator/iossim \ 264 -c "--gtest_filter=SomeTest.FooBar --gtest_repeat=3" \ 265 out/Debug-iphonesimulator/base_unittests.app 266``` 267 268### Running EarlGrey tests 269 270EarlGrey tests are run differently than other test targets, as there is an 271XCTest bundle that is injected into the target application. Therefore you must 272also pass in the test bundle: 273 274```shell 275$ out/Debug-iphonesimulator/iossim \ 276 out/Debug-iphonesimulator/ios_chrome_ui_egtests.app \ 277 out/Debug-iphonesimulator/ios_chrome_ui_egtests.app/PlugIns/ios_chrome_ui_egtests_module.xctest 278``` 279 280### Running on specific simulator 281 282By default, `iossim` will pick an arbitrary simulator to run the tests. If 283you want to run them on a specific simulator, you can use `-d` to pick the 284simulated device and `-s` to select the iOS version. 285 286For example, to run the tests on a simulated iPhone 6s running iOS 10.0, 287you would invoke `iossim` like this. 288 289```shell 290$ out/Debug-iphonesimulator/iossim -d 'iPhone 6s' -s '10.0' \ 291 out/Debug-iphonesimulator/base_unittests.app 292``` 293 294Please note that by default only a subset of simulator devices are installed 295with Xcode. You may have to install additional simulators in Xcode (or even 296an older version of Xcode) to be able to run on a specific configuration. 297 298Go to "Preferences > Components" tab in Xcode to install other simulator images 299(this is the location the setting is in Xcode 9.2; it may be different in other 300version of the tool). 301 302## Update your checkout 303 304To update an existing checkout, you can run 305 306```shell 307$ git rebase-update 308$ gclient sync 309``` 310 311The first command updates the primary Chromium source repository and rebases 312any of your local branches on top of tip-of-tree (aka the Git branch 313`origin/master`). If you don't want to use this script, you can also just use 314`git pull` or other common Git commands to update the repo. 315 316The second command syncs dependencies to the appropriate versions and re-runs 317hooks as needed. 318 319## Tips, tricks, and troubleshooting 320 321Remember that the XCode project you interact with while working on Chromium is a 322build artifact, generated from the `BUILD.gn` files. Do not use it to add new 323files; instead see the procedures for [working with 324files](working_with_files.md). 325 326If you have problems building, join us in `#chromium` on `irc.freenode.net` and 327ask there. As mentioned above, be sure that the 328[waterfall](https://build.chromium.org/buildbot/waterfall/) is green and the tree 329is open before checking out. This will increase your chances of success. 330 331### Debugging 332 333To help with deterministic builds, and to work with Goma, the path to source 334files in debugging symbols are relative to source directory. To allow Xcode 335to find the source files, you need to ensure to have an `~/.lldbinit-Xcode` 336file with the following lines into it (substitute {SRC} for your actual path 337to the root of Chromium's sources): 338 339``` 340script sys.path[:0] = ['{SRC}/tools/lldb'] 341script import lldbinit 342``` 343 344This will also allow you to see the content of some of Chromium types in the 345debugger like `base::string16`, ... If you want to use `lldb` directly, name 346the file `~/.lldbinit` instead of `~/.lldbinit-Xcode`. 347 348### Improving performance of `git status` 349 350#### Increase the vnode cache size 351 352`git status` is used frequently to determine the status of your checkout. Due 353to the large number of files in Chromium's checkout, `git status` performance 354can be quite variable. Increasing the system's vnode cache appears to help. 355By default, this command: 356 357```shell 358$ sysctl -a | egrep kern\..*vnodes 359``` 360 361Outputs `kern.maxvnodes: 263168` (263168 is 257 * 1024). To increase this 362setting: 363 364```shell 365$ sudo sysctl kern.maxvnodes=$((512*1024)) 366``` 367 368Higher values may be appropriate if you routinely move between different 369Chromium checkouts. This setting will reset on reboot, the startup setting can 370be set in `/etc/sysctl.conf`: 371 372```shell 373$ echo kern.maxvnodes=$((512*1024)) | sudo tee -a /etc/sysctl.conf 374``` 375 376Or edit the file directly. 377 378#### Configure git to use an untracked cache 379 380If `git --version` reports 2.8 or higher, try running 381 382```shell 383$ git update-index --test-untracked-cache 384``` 385 386If the output ends with `OK`, then the following may also improve performance of 387`git status`: 388 389```shell 390$ git config core.untrackedCache true 391``` 392 393If `git --version` reports 2.6 or higher, but below 2.8, you can instead run 394 395```shell 396$ git update-index --untracked-cache 397``` 398 399### Xcode license agreement 400 401If you're getting the error 402 403> Agreeing to the Xcode/iOS license requires admin privileges, please re-run as 404> root via sudo. 405 406the Xcode license hasn't been accepted yet which (contrary to the message) any 407user can do by running: 408 409```shell 410$ xcodebuild -license 411``` 412 413Only accepting for all users of the machine requires root: 414 415```shell 416$ sudo xcodebuild -license 417``` 418