Building with Bazel

Jul 8 2022 · Starlark, Bazel 5.1, Visual Studo Code 1.66

Part 1: Learning Bazel

13. Write an Android Build File

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 12. Write an iOS Build File Next episode: 14. Incorporate a BazelRC File
Transcript: 13. Write an Android Build File

Episode 13 - Write an Android Build File

In the last episode, we built an iOS app but that app was relatively simple being that it didn’t include any dependencies. We’ll now write the same app in Kotlin.

Open up the starter project. In the android src file, create an empty BUILD file. Open it in your editor.

Now we’re going to load our rules. Add the following:

load("@rules_jvm_external//:defs.bzl", "artifact")
load("@rules_android//android:rules.bzl", "android_binary")
load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_android_library")

Now we are going to declare a variables for the manifest. You’ll see why soon enough

MANIFEST = "main/AndroidManifest.xml"

Okay we’ll first create a library target. This will be a type of kt_android_library. That is, a kotlin library file.

kt_android_library(

)

We’ll give it the name kotlin_sources and pass in the kotlin files.

name = "kotlin_sources",
srcs = glob(["main/java/com/fleepgeek/bullseyesample/*.kt"]),

Next, we’ll pass in a package name and a manifest.

custom_package = "com.fleepgeek.bullseyesample",
manifest = MANIFEST,

Finally, we need to make sure that we include all of our android resource files.

resource_files = glob(["main/res/**"]),

Okay, now the fun part. We’re going to include all the dependencies that we need to build the project. Add the following:

deps = [
    artifact("androidx.core:core-ktx"),
    artifact("androidx.appcompat:appcompat"),
    artifact("com.google.android.material:material"),
    artifact("androidx.constraintlayout:constraintlayout"),
    artifact("androidx.core:core"),
    artifact("junit:junit:4.13.2"),
    artifact("androidx.test.ext:junit:1.1.3"),
    artifact("androidx.test.espresso:espresso-core:3.4.0"),
    artifact("androidx.lifecycle:lifecycle-runtime"),
    artifact("androidx.lifecycle:lifecycle-viewmodel"),
    artifact("androidx.lifecycle:lifecycle-common"),
    artifact("androidx.databinding:viewbinding"),
],

Okay, that’s our first target. Now for our second target. This is for our android binary.

android_binary(
    name = "yourfirstandroidapp",
    manifest = MANIFEST,
    deps = [":kotlin_sources"],
)

Notice that we are passing in the manifest. The manifest is required for both the android_binary and the kt_android_library. This is why we stored the manifest in a variable.

Now we can try to build the app. The key word being try. Build the following:

bazel build //Bullseye-Android/app/src:yourfirstapp

After this runs for some time, the build fails. We can get more information by passing in the –verbose_failures flag.

bazel build //Bullseye-Android/app/src:yourfirstapp --verbose_failures

We’re running in a DEX issue. We need to pass in some flags to help with the DEX parsing. Add the following:

bazel build //Bullseye-Android/app/src:yourfirstapp
--define=android_dexmerger_tool=d8_dexmerger --nouse_workers_with_dexbuilder 

Now the build runs but we’ll have to pass in those flags. Thankfully, there’s a way to do this without adding the flags to the command line and you’ll learn about it in the next episode.