Bazel iOS Hello World (Objective-C, Mac M1 / M2)

Deep Learning Make Easy
3 min readJun 25, 2023

--

A quick tutorial of building a hello world on iOS by Bazel. All files are hosted at https://github.com/deeplearningmakeeasy/bazelioshelloworld

Prerequisite: MacOS 12.4, Xcode 13.4.1, Bazel 5.2.0

  1. Create a directory called HelloAppIOS anywhere you like. In my case I created it under my user directory and inside the BazelTutorial directory. e.g. /Users/deeplearningmakeeasy/BazelTutorial/HelloAppIOS
  2. Go to the HelloAppIOS directory.
cd /Users/deeplearningmakeeasy/BazelTutorial/HelloAppIOS

3. Create WORKSPACE file.

touch WORKSPACE

4. Create a directory called myapp.

mkdir myapp

5. Use XCode to create an ios app called BazelHelloworldObjC. Copy the directory BazelHelloworldObjC and BazelHelloworldObjC.xcodeproj into myapp

6. Open the project by BazelHelloWorldObjC.xcodeproj. Just put a UILabel on Main.storyboard as below.

7. Add Bundle version and Bundle version string (short) properties on Info.plist as below.

8. Edit the WORKSPACE file.

# Load http_archive from http.bzl
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# Download apple rules, always check and download the latest version. Here is 1.0.1
http_archive(
name = "build_bazel_rules_apple",
sha256 = "36072d4f3614d309d6a703da0dfe48684ec4c65a89611aeb9590b45af7a3e592",
url = "https://github.com/bazelbuild/rules_apple/releases/download/1.0.1/rules_apple.1.0.1.tar.gz",
)
# Load apple rule
load(
"@build_bazel_rules_apple//apple:repositories.bzl",
"apple_rules_dependencies",
)
# Apple rule required to call this function
apple_rules_dependencies()

9. Create a file called BUILD in myapp directory and edit it as follow.

# load ios application rule
load("@build_bazel_rules_apple//apple:ios.bzl", "ios_application")
# load build in objc_library rule
load("@rules_cc//cc:defs.bzl", "objc_library")
objc_library(
name = "BazelHelloworldObjC_classes",
srcs = [
"BazelHelloworldObjC/AppDelegate.m",
"BazelHelloworldObjC/SceneDelegate.m",
"BazelHelloworldObjC/ViewController.m",
"BazelHelloworldObjC/main.m",

],
hdrs = glob(["BazelHelloworldObjC/*.h"]),
data = [
"BazelHelloworldObjC/Base.lproj/Main.storyboard",
"BazelHelloworldObjC/Base.lproj/LaunchScreen.storyboard",
],
)
# Use ios application rule
ios_application(
name = "BazelHelloworldObjCApp",
bundle_id = "<com.domain.appBundleID>",
families = [
"iphone",
"ipad",
],
minimum_os_version = "13.0",
infoplists = [":BazelHelloworldObjC/Info.plist"],
#Must have launch_storyboard, otherwise UI goes funny
launch_storyboard = "BazelHelloworldObjC/Base.lproj/LaunchScreen.storyboard",
provisioning_profile = "<Your App Provisioning Profile>.mobileprovision",
visibility = ["//visibility:public"],
deps = [":BazelHelloworldObjC_classes"],
)

10. Visit apple developer page, create an app provisioning profile, download and save it to the myapp directory. IMPORTANT: In the BUILD file, you must rename the code <Your App Provisioning Profile> to match your provisioning profile name. And rename <com.domain.appBundleID> to your app bundle id.

11. Build an ipa file for run at real iphone device (Fat binary that contains armv7 and arm64 architectures ). Execute the below command in terminal, under the directory of HelloAppIOS.

bazel build //myapp:BazelHelloworldObjCApp --ios_multi_cpus=armv7,arm64

12. Retrieve the generated ipa file. The file path is showed after the project built. e.g. bazel-out/applebin_ios-ios_armv7-fastbuild-ST-c80203c02312/bin/myapp/BazelHelloworldObjCApp.ipa

13. Connect your iPhone and Open XCode -> Window -> Devices and Simulators in XCode. Select Devices tab, Drag the BazelHelloworldObjCApp.ipa into the INSTALLED APPS column. And run it on your iPhone.

14. You done it.

--

--