Building with Bazel

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

Part 1: Learning Bazel

4. Build a Simple App

Lesson Complete

Play Next Lesson
Next
Save for later
About this episode

See forum comments
Cinema mode Mark as Complete Download course materials
Previous episode: 3. Understand Bazel Next episode: 5. Meet the Sample Projects

Episode 4 - Build a Simple App

At this point, you have Bazel installed and you understand some of the various components in Bazel. It’s time to put Bazel to work. For that, we’re going to write a simple joke generator. This is a command line application that when run, will tell a simple knock knock joke. We’re going to write this in Java.

Mind you I’m only going to cover the Bazel aspects. If you are unfamiliar with Java, just follow along. I’ll briefly review the code but that’s not the point of this episode. Rather, we want Bazel to actually build something.

Why Java? It’s supported by Bazel out of the box. But don’t worry. We’ll get to other languages. One of Bazel’s most powerful features is its ability to be extended to support other languages. We’ll be adding support soon enough.

Demo

To get started, create a new folder on your Desktop and call it JokeGenerator. Now I’ll open this folder in Visual Studio Code. Feel free to use another editor. The first thing to do is to create a Workspace.

Create a new file and call it WORKSPACE in all caps. Okay, we’re going to use Java which is packaged with Bazel. You’ll notice that I have a green heart next to my WORKSPACE. This is because I have the Bazel extension installed in Visual Studio Code which gives me syntax highlighting and formatting.

Okay, before we write the Build file, we need to write our console app. We’ll start with the directory structure. Create a new folder called source (src). Next, we’ll create a folder called main. Now in the main folder, we’ll add a folder called resources. This is where our jokes will go.

I’m going to create six text files named one, two, three, four, fix, and six. I’m going to add a knock knock joke. Each joke will only have five lines.

1.txt
Knock, knock.
Who’s there?
Hawaii.
Hawaii who?
I’m good. Hawaii you?

2.txt
Knock, knock.
Who’s there?
Who.
Who who?
I didn’t know you were an owl!

3.txt
Knock, knock.
Who’s there?
Water.
Water who?
Water you doing telling jokes right now? Don’t you have things to do?

4.txt
Knock, knock.
Who’s there?
Hal.
Hal who?
Hal will you know if you don’t open the door?

5.txt
Knock, knock.
Who’s there?
Cow says.
Cow says who?
No, a cow says mooooo!

6.txt
Knock, knock.
Who’s there?
Figs.
Figs who?
Figs the doorbell, it’s not working!

Okay, now to create our KnockKnock joke class. Now, in the main folder, create a folder for java / com / and example. Then create a file called KnockKnock.java.

Okay, first we’re going to declare a package for our file.

package com.example;

Next, we’ll import a series of classes that we’ll be using.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Random;

With that done, let’s define our KnockKnock class.

public class KnockKnock {

}

We’ll set a constant for the number of jokes we’re using. Make sure to adjust to the amount of joke files that you used.

private static final int TOTAL_JOKES = 6;

We’re going to create a method to print out a joke that will throw an exception. We’re not going to deal with any exceptions.

public void printJoke(int jokeNumber) throws IOException {

}

Next we’re going to create a file name based on the joke number.

String fileName = jokeNumber + ".txt";

Then we’ll open the file and prep it for reading.

InputStream resourceStream = KnockKnock.class.getClassLoader().getResourceAsStream(fileName);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(resourceStream, StandardCharsets.UTF_8));

Now we’ll read the file and print it out to the screen, one line at a time per pressing the return or enter key.

String text;
while((text = bufferedReader.readLine()) != null) {
    System.out.println(text);
    System.in.read();
}   

Okay, now let’s create a method to get a random joke.

private int getRandomNumber() {
    Random rand = new Random();
    return rand.nextInt(TOTAL_JOKES - 1) + 1;
}

Here we just get a random number from one to the total joke number. Finally, lets create a main method to actually run our joke generator.

public static void main(String[] args) throws IOException {
    KnockKnock knock = new KnockKnock();
    knock.printJoke(knock.getRandomNumber());
}

Okay, we have our app setup. Now let’s write our build file. Create a new BUILD file in the KnockKnock folder alongside our WORKSPACE folder. This is the same place as our workplace folder.

Okay, we’re going to create a simple target called a java binary. This is the name defined in the rules of the language.

java_binary(

)

Next, we’ll give it the name knock knock.

name = "knock_knock",

Now we need to signify all the source files. For this we use a Bazel function called glob. Glob allows us to find files based on file matching. In this case, we want to get all the java files which is one.

srcs = glob(["src/main/java/com/example/*.java"]),

This build is going to create a jar so we need to designate the class that has the main method. In this case, this is the KnockKnock class.

main_class = "com.example.KnockKnock",

Finally, we need to designate our jokes. For this, we use the resources argument, passing in our list of text files.

resources = glob(["src/main/resources/*.txt"])

And believe it or not - that’s our build file. At this point, it’s time to run the build. For this, I’m going to open my terminal view. Now in my Terminal window, I’m going to call my build target.

I do this by calling bazel build.

bazel build

Now we need to provide the package. We start with two forward slashes followed by the directory structure of the build target.

bazel build //src

After which, provide the target that I want to build. I do this by adding a colon after the package followed by the target name. Since we are currently in the package, we don’t need to specify. Rather, we can just put our target name.

bazel build //:knock_knock

At which point, the build kicks off. In the process, it creates four folders: bazel-bin, bazel-JokeGenerator, bazel-out, and bazel-testlogs. The bazel-bin directory is a symlink to the most written bin directory. The bazel-JokeGenerator is the working directory for the all the actions that took place in your build. The bazel-out directory a symlink to the output path and finally the bazel-testlogs is the results of all your unit tests. For greater detail, see the Bazel Output Directory Layout documentation. ∂

https://bazel.build/docs/output_directories

Now to run our app. Bazel allows us to do this right from the command line. Enter the following command:

bazel run //:knock_knock

And with that, we our knock knock joke printed to the console. As you can see, this was a simple demonstration of Bazel. In the next episode, we’re going to scale it up by compiling a native mobile app for both iOS and Android.