Meet the Starlark language that you’ll use to write your workspaces and build files. This episode will give you an overview of it.
Episode 7 - Learn Starlark
When we write our workspaces and build files, we code in language called
Starlark which is a custom variant of Python. Now for all you Python developers out there, hold your high fives. Starlark is a variant of Python - that is, a limited version of the language.
This was specifically designed for Bazel. It was meant to be deterministic and designed to run in parallel such as on cores are entirely different machines. Because of this, some of your favorite features of the language may have been culled.
For instance, with Starlark, classes have been pulled from the language. You can’t use the import statement. Instead, you use a custom load function. Most built in functions and most methods aren’t supported. There are a bunch of other limitations as well.
If you are interested in what Starlark can do, then you should check out the Starlark specification. This gives a comprehensive breakdown at what language features are available to you from the type system to various built in methods and functions.
This may beg the question as to what you can do with Starlark and the answer is a lot. If you look at the build api, you’ll see that Bazel comes with a lot of functions, objects and types ready to use out of the box. By viewing the build api documentation, you’ll see all the various things that Bazel exposes to our scripts.
Okay, for those of you who don’t know python, we’ll write a little code to comfortable but you’ll need to
To get started, let’s return to our JokeGenerator project. It’s all in a monorepo so we need to move our Workspace file to the root of our monorepo.
Now we’ll make some alterations to the workspace to you comfortable working in Starlark.
First off, let’s create a comment. In Starlark, and well python, we use the pound symbol.
# Create a variable
Of course, this is also useful to comment out code while writing your build scripts. Next we’ll define a variable. Here we’ll create a simple name.
build_name = "JokeGenerator"
Now we’ll print it out to the console.
# print to the console print(build_name)
Save the file and switch over to the command line. Navigate to the monorepo root. To fire off the build, we have to call the JokeGenerator’s build target.
bazel build //JokeGenerator:knock_knock
You’ll notice that we get a debug statement printed out during the build sequence. And lo and behold, there is a variable printed out.
We do get if statements, but we can’t use them in the top-level of a script. For example, if we were to check for the build name, we’d need to wrap it into the function.
Let’s add the following to print out whether jokes are allowed:
if build_name == "JokeGenerator": print("Jokes Allowed") else: print("No Jokes Allowed")
Now if we save and build:
bazel build //JokeGenerator:knock_knock
And we get an error. Welcome to Starlark. In such a feature, we need to define our own rules file. A rules file is just a text file with a bzl extension. When we import rules for other languages, we import bzl files.
In such ways, we keep our logic out of our build definitions. Create a new file called, functions.bzl.
Now lets define a method to get the current joke policy.
def get_joke_policy(name): if name == "JokeGenerator": return "Jokes Allowed" else: return "No Jokes Allowed"
Save and return back to the workspace. We need to load our new rule. We use the load method. Add the following:
Here we are declaring that we are loading the functions rules and then we using the get_joke_policy function. Now, before we can run this build, we need to provide an empty Build file along with our custom rules.
Create a new Build file. Now we can just call the function.
Save the file. Now run the build. You’ll see we get our joke policy printed out to the console along with the build running to completion.
We will be using a load a lot through this course as well as some other modules so play around get comfortable.