1# WebRTC iOS development 2 3## Development Environment 4 5In case you need to build the framework manually 6(for instance if you need to support bitcode) or you want to try out the demo application 7AppRTCMobile, follow the instructions illustrated bellow. 8 9A macOS machine is required for iOS development. While it's possible to 10develop purely from the command line with text editors, it's easiest to use 11Xcode. Both methods will be illustrated here. 12 13_NOTICE:_ You will need to install [Chromium depot_tools][webrtc-prerequisite-sw]. 14 15## Getting the Code 16 17Create a working directory, enter it, and run: 18 19``` 20$ fetch --nohooks webrtc_ios 21$ gclient sync 22``` 23 24This will fetch a regular WebRTC checkout with the iOS-specific parts 25added. Notice the size is quite large: about 6GB. The same checkout can be used 26for both Mac and iOS development, since GN allows you to generate your 27[Ninja][ninja] project files in different directories for each build config. 28 29You may want to disable Spotlight indexing for the checkout to speed up 30file operations. 31 32Note that the git repository root is in `src`. 33 34From here you can check out a new local branch with: 35 36``` 37$ git new-branch <branch name> 38``` 39 40See [Development][webrtc-development] for generic instructions on how 41to update the code in your checkout. 42 43 44## Generating project files 45 46[GN][gn] is used to generate [Ninja][ninja] project files. In order to configure 47[GN][gn] to generate build files for iOS certain variables need to be set. 48Those variables can be edited for the various build configurations as needed. 49 50The variables you should care about are the following: 51 52* `target_os`: 53 - To build for iOS this should be set as `target_os="ios"` in your `gn args`. 54 The default is whatever OS you are running the script on, so this can be 55 omitted when generating build files for macOS. 56* `target_cpu`: 57 - For builds targeting iOS devices, this should be set to either `"arm"` or 58 `"arm64"`, depending on the architecture of the device. For builds to run in 59 the simulator, this should be set to `"x64"`. 60* `is_debug`: 61 - Debug builds are the default. When building for release, specify `false`. 62 63The component build is the default for Debug builds, which are also enabled by 64default unless `is_debug=false` is specified. 65 66The [GN][gn] command for generating build files is `gn gen <output folder>`. 67 68After you've generated your build files once, subsequent invocations of `gn gen` 69with the same output folder will use the same arguments as first supplied. 70To edit these at any time use `gn args <output folder>`. This will open up 71a file in `$EDITOR` where you can edit the arguments. When you've made 72changes and save the file, `gn` will regenerate your project files for you 73with the new arguments. 74 75### Examples 76 77``` 78$ # debug build for 64-bit iOS 79$ gn gen out/ios_64 --args='target_os="ios" target_cpu="arm64"' 80 81$ # debug build for simulator 82$ gn gen out/ios_sim --args='target_os="ios" target_cpu="x64"' 83``` 84 85## Compiling with ninja 86 87To compile, just run ninja on the appropriate target. For example: 88 89``` 90$ ninja -C out/ios_64 AppRTCMobile 91``` 92 93Replace `AppRTCMobile` in the command above with the target you 94are interested in. 95 96To see a list of available targets, run `gn ls out/<output folder>`. 97 98## Using Xcode 99 100Xcode is the default and preferred IDE to develop for the iOS platform. 101 102*Generating an Xcode project* 103 104To have GN generate Xcode project files, pass the argument `--ide=xcode` 105when running `gn gen`. This will result in a file named `all.xcworkspace` 106placed in your specified output directory. 107 108Example: 109 110``` 111$ gn gen out/ios --args='target_os="ios" target_cpu="arm64"' --ide=xcode 112$ open -a Xcode.app out/ios/all.xcworkspace 113``` 114 115*Compile and run with Xcode* 116 117Compiling with Xcode is not supported! What we do instead is compile using a 118script that runs ninja from Xcode. This is done with a custom _run script_ 119action in the build phases of the generated project. This script will simply 120call ninja as you would when building from the command line. 121 122This gives us access to the usual deployment/debugging workflow iOS developers 123are used to in Xcode, without sacrificing the build speed of Ninja. 124 125## Running the tests 126 127There are several test targets in WebRTC. To run the tests, you must deploy the 128`.app` bundle to a device (see next section) and run them from there. 129To run a specific test or collection of tests, normally with gtest one would pass 130the `--gtest_filter` argument to the test binary when running. To do this when 131running the tests from Xcode, from the targets menu, select the test bundle 132and press _edit scheme..._ at the bottom of the target dropdown menu. From there 133click _Run_ in the sidebar and add `--gtest_filter` to the _Arguments passed on 134Launch_ list. 135 136If deploying to a device via the command line using [`ios-deploy`][ios-deploy], 137use the `-a` flag to pass arguments to the executable on launch. 138 139## Deploying to Device 140 141It's easiest to deploy to a device using Xcode. Other command line tools exist 142as well, e.g. [`ios-deploy`][ios-deploy]. 143 144**NOTICE:** To deploy to an iOS device you must have a valid signing identity 145set up. You can verify this by running: 146 147``` 148$ xcrun security find-identity -v -p codesigning 149``` 150 151If you don't have a valid signing identity, you can still build for ARM, 152but you won't be able to deploy your code to an iOS device. To do this, 153add the flag `ios_enable_code_signing=false` to the `gn gen` args when you 154generate the build files. 155 156## Using WebRTC in your app 157 158To build WebRTC for use in a native iOS app, it's easiest to build 159`WebRTC.framework`. This can be done with ninja as follows, replacing `ios` 160with the actual location of your generated build files. 161 162``` 163ninja -C out/ios framework_objc 164``` 165 166This should result in a `.framework` bundle being generated in `out/ios`. 167This bundle can now be directly included in another app. 168 169If you need a FAT `.framework`, that is, a binary that contains code for 170multiple architectures, and will work both on device and in the simulator, 171a script is available [here][framework-script] 172 173To build the framework with bitcode support, pass the `--bitcode` flag to the script like so 174 175``` 176$ python build_ios_libs.py --bitcode 177``` 178The resulting framework can be found in out_ios_libs/. 179 180Please note that you can not ship the FAT framework binary with your app 181if you intend to distribute it through the app store. 182To solve this either remove "x86-64" from the list of architectures in 183the [build script][framework-script] or split the binary and recreate it without x86-64. 184For instructions on how to do this see [here][strip-arch]. 185 186 187[cocoapods]: https://cocoapods.org/pods/GoogleWebRTC 188[webrtc-prerequisite-sw]: https://webrtc.googlesource.com/src/+/refs/heads/master/docs/native-code/development/prerequisite-sw/index.md 189[webrtc-development]: https://webrtc.googlesource.com/src/+/refs/heads/master/docs/native-code/development/index.md 190[framework-script]: https://chromium.googlesource.com/external/webrtc/+/master/tools_webrtc/ios/build_ios_libs.py 191[ninja]: https://ninja-build.org/ 192[gn]: https://gn.googlesource.com/gn/+/master/README.md 193[ios-deploy]: https://github.com/phonegap/ios-deploy 194[strip-arch]: http://ikennd.ac/blog/2015/02/stripping-unwanted-architectures-from-dynamic-libraries-in-xcode/ 195