Exploring Bazel: How I Built a High-Performance Java Calculator

ยท

7 min read

Exploring Bazel: How I Built a High-Performance Java Calculator

Bazel

What is Bazel? ๐Ÿค”

Bazel is an open-source build and test tool developed by Google. It's designed to build, test, and package software efficiently across different programming languages and platforms. ๐ŸŒ๐Ÿ’ป Bazel provides a uniform and reproducible way to manage dependencies and build artifacts, making it an ideal choice for DevOps teams seeking performance and scalability.

Highlights

  • ๐Ÿš€ Bazel is a blazing-fast build tool used by major companies for its speed and reproducibility.

  • ๐Ÿ› ๏ธ Define inputs and outputs to model code dependencies and rebuild only when necessary.

  • ๐Ÿ“ฆ Create packages and build files to specify targets and commands for building code.

  • ๐Ÿ’ก Use macros to simplify complex build steps and reuse code across projects.

  • ๐ŸŒ Explore advanced features like testing, dependency graph generation, and integration with CI/CD pipelines.

Why Bazel? ๐Ÿค”

๐Ÿ”ธ Fast Builds: Bazel's incremental build system ensures only the necessary parts of your project are rebuilt, saving valuable time.

๐Ÿ”ธ Cross-Language Support: It supports multiple programming languages, making it versatile for heterogeneous codebases.

๐Ÿ”ธ Scalability: Bazel scales effortlessly, making it ideal for large and complex projects.

๐Ÿ”ธ Reproducibility: Achieve consistent builds across different environments, ensuring that what works locally works in production.

BAZEL Vs MAVEN Vs Gradle

Aspect

Bazel

Maven

Gradle

Language Support

Multiple languages (Java, C++, Python, etc.)

Primarily Java-centric

Supports various languages (Java, Kotlin, Groovy, etc.)

Performance

Faster, thanks to incremental builds

Slower for larger projects

Slower for large projects

Reproducibility

Strong, with hermetic builds

Less control over dependencies

Limited control over dependencies

Scalability

Scales effortlessly

N/A

Suitable for medium-sized projects

Language Support:

Bazel Example:

py_binary(
    name = "my_python_app",
    srcs = ["main.py"],
)
cc_binary(
    name = "my_cpp_app",
    srcs = ["main.cpp"],
)

Maven Example (Java):

xmlCopy code<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>my-java-app</artifactId>
    <version>1.0</version>
</project>

Gradle Example (Kotlin):

Gradle Example (Kotlin):

plugins {
    id("org.jetbrains.kotlin.jvm") version "1.5.20"
}

repositories {
    mavenCentral()
}

dependencies {
    implementation(kotlin("stdlib"))
}

Installation of Bazel in Ubuntu.

Step - 1:

Go to the Official website https://bazel.build/ click on install bazel

Follow the documentation to install bazel

Bazel Example:

sudo apt install apt-transport-https curl gnupg -y
curl -fsSL https://bazel.build/bazel-release.pub.gpg | gpg --dearmor >bazel-archive-keyring.gpg
sudo mv bazel-archive-keyring.gpg /usr/share/keyrings
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/bazel-archive-keyring.gpg] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list
sudo apt update && sudo apt install bazel -y
sudo apt update && sudo apt full-upgrade
bazel --version

Installation of Bazel in Windows.

First open Windows power shell or Command Prompt as administrative user and follow below commands.

Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
choco install bazelisk
bazel --version

Build application in Ubuntu os

After installation bazel in ubuntu os, now we try to build java sample application using bazel

First install java in your ubuntu os using following command:
sudo apt install openjdk-11-jdk

These are bazel commands for executions, run, build...

bazel build <target>

Build the specified target(s) and their dependencies.

bazel build //path/to:target

bazel test <target>

Build and run tests for the specified target(s).

bazel test //path/to:target

bazel run <target>

Build and run the specified target.

bazel run //path/to:target

bazel clean

Delete build output files and directories.

bazel clean

bazel query <query>

Query the build graph to find targets.

bazel query 'deps(//path/to:target)'

bazel info <key>

Display information about the build configuration.

bazel info execution_root

bazel fetch <target>

Fetch external dependencies for a target.

bazel fetch @maven//:com_google_guava_guava

bazel version

Display Bazel version information.

bazel version

bazel help <command>

Display help information for a specific command.

bazel help build

For example, if you have a Java target in the path //src/main/java/com/example:HelloWorld, you would use the following commands:

To build: bazel build //src/main/java/com/example:HelloWorld To test: bazel test //src/main/java/com/example:HelloWorld To run: bazel run //src/main/java/com/example:HelloWorld

Now we build one simple java calculator application with Bazel tool in Ubuntu os

After Installation of Bazel and java in Ubuntu, then create below folder structure

Make sure your project directory structure looks like this:

  1.   java_calculator/
      โ”œโ”€โ”€ WORKSPACE
      โ”œโ”€โ”€ BUILD
      โ””โ”€โ”€ Calculator.java
    

    In "BUILD.bazel" file write your actions like this

    Update the BUILD file content as follows:

     java_binary(
         name = "calculator",
         srcs = ["Calculator.java"],
         main_class = "Calculator",
     )
    
    • java_binary: This is a Bazel build rule. In this context, it represents a Java binary target. It tells Bazel that you want to create a binary executable from Java source code.

    • name = "calculator": This attribute sets the name of the build target. The target is named "calculator." You will use this name to refer to the target elsewhere in your Bazel configuration or when running Bazel commands.

    • srcs = ["Calculator.java"]: This attribute specifies the source files needed to build the Java binary. In this case, there is a single source file named "Calculator.java." Bazel will compile this Java source file to create the binary executable.

    • main_class = "Calculator": This attribute specifies the main class of your Java application. When you run the binary executable, Bazel will look for the main method in the "Calculator" class and execute it. This attribute is essential because it determines the entry point of your Java program.

Here we use "BUILD" file in BAZEL are

๐ŸŽฏ Purpose of a BUILD File in Bazel:

๐Ÿ—๏ธ Define Targets: BUILD files allow you to define build targets, which are individual components or artifacts that Bazel can build.

๐Ÿ“ Specify Build Instructions: You can specify how these targets should be built, including compilation, testing, and packaging.

๐Ÿงฉ Manage Dependencies: BUILD files help you manage dependencies between different components of your project.

๐Ÿงฑ Structure Your Project: They are crucial for structuring your project and organizing it into manageable pieces.

๐Ÿš€ Build Automation: Bazel uses these files to automate the build process and ensure consistency.

๐Ÿ•ต๏ธ Declarative: They provide a declarative way to describe your project's build requirements, making it clear and easy to understand.

  1. You can name the target anything you like (e.g., "calculator"). Make sure to create a Java source file Calculator.java in the same directory:

     javaCopy code// Calculator.java
     public class Calculator {
         public static void main(String[] args) {
             if (args.length != 3) {
                 System.out.println("Usage: Calculator <num1> <operator> <num2>");
                 return;
             }
             double num1 = Double.parseDouble(args[0]);
             String operator = args[1];
             double num2 = Double.parseDouble(args[2]);
             double result = 0.0;
             switch (operator) {
                 case "+":
                     result = num1 + num2;
                     break;
                 case "-":
                     result = num1 - num2;
                     break;
                 case "*":
                     result = num1 * num2;
                     break;
                 case "/":
                     if (num2 != 0) {
                         result = num1 / num2;
                     } else {
                         System.out.println("Error: Division by zero.");
                         return;
                     }
                     break;
                 default:
                     System.out.println("Error: Invalid operator.");
                     return;
             }
             System.out.println("Result: " + result);
         }
     }
    

    And also create "WORKSPACE.bazel" file for

    ๐Ÿ“ฆ Dependency Management: The WORKSPACE file specifies external dependencies (libraries, frameworks, etc.) your project needs to build and run.

    ๐Ÿ”— Repository Rules: It uses rules (like Git, HTTP, Maven) to fetch and manage external code.

    ๐Ÿ› ๏ธ Toolchains Configuration: You set up toolchains for different languages/platforms (e.g., Java JDK version).

    ๐Ÿญ Workspace Setup: Ensures a consistent environment with all required dependencies for building your project.

    โš™๏ธ Workspace-wide Settings: You define project-wide settings (code formatting, testing) for everyone.

    ๐ŸŒ Third-Party Code Integration: Structured way to declare and manage third-party dependencies.

    The WORKSPACE file streamlines your project's setup, management, and collaboration with external code and resources.

    Here we created a "WORKSPACE" file but we did not insert anything in that file because there is no external dependencies or specific toolchain configurations in the WORKSPACE file. This is perfectly fine and is not always necessary.

    Finally, this is java_calculator dir structure as mentioned picture.

    Then, you build your application following bazel command

    1. Build your Java calculator application:

       cd java_calculator
       sudo bazel build :calculator_deploy.jar
      

      Finally java application is build with bazel tool, After this it will create some bazel files.

      If you want to output for this java_calculator follow this commands

      Run the JAR file: Finally, try running the JAR file with the java -jar command:

       sudo java -jar bazel-bin/calculator_deploy.jar 5 + 3
       sudo java -jar bazel-bin/calculator_deploy.jar 5 / 3
       sudo java -jar bazel-bin/calculator_deploy.jar 5 - 3
      

      Finally we build java simple calculator application using Bazel. You guys try this in Windows

Hope you like my blog...!

If you like the content follow me on LinkedIn: https://www.linkedin.com/in/ashok-sana

Follow my Whatsapp & telegram community: https://chat.whatsapp.com/BzX1aruZIH645l29LxvgO3

https://t.me/ExplorewithAshok

Happy learning......!

Did you find this article valuable?

Support Ashoksana by becoming a sponsor. Any amount is appreciated!

ย