{"id":16465055,"url":"https://github.com/morfly/bazel-tutorial","last_synced_at":"2026-03-05T01:01:34.481Z","repository":{"id":113072251,"uuid":"372499701","full_name":"Morfly/bazel-tutorial","owner":"Morfly","description":null,"archived":false,"fork":false,"pushed_at":"2021-06-16T18:34:05.000Z","size":157,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-27T15:45:08.436Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Starlark","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Morfly.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-05-31T12:30:57.000Z","updated_at":"2021-06-16T18:34:07.000Z","dependencies_parsed_at":null,"dependency_job_id":"d15a7da5-0896-4221-8fd6-ee0ab53f83cf","html_url":"https://github.com/Morfly/bazel-tutorial","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Morfly/bazel-tutorial","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Morfly%2Fbazel-tutorial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Morfly%2Fbazel-tutorial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Morfly%2Fbazel-tutorial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Morfly%2Fbazel-tutorial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Morfly","download_url":"https://codeload.github.com/Morfly/bazel-tutorial/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Morfly%2Fbazel-tutorial/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30104218,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-05T00:38:46.881Z","status":"ssl_error","status_checked_at":"2026-03-05T00:38:45.829Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T11:32:00.650Z","updated_at":"2026-03-05T01:01:34.461Z","avatar_url":"https://github.com/Morfly.png","language":"Starlark","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Bazel Fundamentals Workshop - Building Simple Android Application\n\nIn this workshop you will be developing a simple Bazel Android application to get familiar with the Bazel build tool basics.\n\nThe application will consist of the main Android module, Kotlin library and additional Android library. By the end of this workshop you will have an understanding about how to build and run Kotlin Android applications and unit tests for them using Bazel.\n\nIn order to follow the tutorial, open `/start` folder and consider it as a **root** directory of your future Bazel project.\n\nYou can also check you progress with the completed application in `/completed` directory.\n\nFor any information about Bazel build tool please refer to the [official page](https://www.bazel.build/).\n\n## Table of contents\n- [Pre-requisites](#pre-requisites)\n- [Environment setup](#environment-setup)\n    - [Bazelisk](#bazelisk)\n    - [Android Studio / IntelliJ IDEA plugin (Optional)](#android-studio-intellij-idea-plugin-optional)\n    - [Visual Studio Code plugin (Optional)](#visual-studio-code-plugin-optional)\n    - [Buildifier (Optional)](#buildifier-optional)\n- [Creating Bazel Android app](#creating-bazel-android-app)\n    - [Step `1`. Create Bazel `WORKSPACE`](#step-1-create-bazel-workspace)\n    - [Step `2`. Create `BUILD` target](#step-2-create-build-target)\n    - [Step `3`. Launch the app](#step-3-launch-the-app)\n    - [Step `4`. Add Kotlin library](#step-4-add-kotlin-library)\n    - [Step `5`. Add external dependency](#step-5-add-external-dependency)\n    - [Step `6`. Run tests](#step-6-run-tests)\n- [Complete by yourself](#complete-by-yourself)\n    - [Step `7`. Add Android library](#step-7-add-android-library)\n- [Conclusion](#conclusion)\n- [Further learning](#further-learning)\n- [Useful references](#useful-references)\n\n## Pre-requisites\nIn order to proceed with this workshop you need to have:\n- Installed [Android Studio](https://developer.android.com/studio) or standalone Android SDK.\n- Your favourite IDE or Text Editor. (It is preferred to use [Android Studio](https://developer.android.com/studio), [IntelliJ IDEA Community](https://www.jetbrains.com/idea/download/other.html) or [Visual Studio Code](https://code.visualstudio.com/)).\n\u003e **Note:** As of now IntelliJ IDEA version 2020.2 do not support Bazel plugin, so it is prefered to use 2020.1.4 for this workshop.\n- Installed JDK 8. \n\u003e **Note:** If you decided to use IntelliJ IDEA or Android Studio you can use bundled JDK.\n- Minimal experience with Java, Kotlin and Android development.\n\u003e **Note:** Do not worry if you don't have much experience with any of the above technologies. You still will be able to understand Bazel basics and follow the workshop steps as we will not get into platform/language details too much. Just make sure all the required software is installed before starting. \n- Installed [Homebrew](https://brew.sh/).\n- Motivation to use Bazel as a build tool for your project.\n\n\u003cbr\u003e\n\n## Environment setup\nIn order to get your machine ready to work with Bazel, follow the instructions below:\n\n### Bazelisk\n[Official page](https://github.com/bazelbuild/bazelisk)\n\n_Bazelisk is a wrapper for Bazel written in Go. It automatically picks a good version of Bazel given your current working directory, downloads it from the official server (if required) and then transparently passes through all command-line arguments to the real Bazel binary. You can call it just like you would call Bazel._\n\nIf you don't have [Homebrew](https://brew.sh/) on your Mac/Linux machine install it:\n```bash\n/bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)\"\n```\n\nInstall bazelisk with Homebrew:\n```bash\n$ brew install bazelisk\n```\nVerify that Bazel is installed on your machine:\n```bash\n$ bazel --version\n```\n\n\u003e**Note:** Check other installation options on the [official documentation page](https://docs.bazel.build/versions/master/install.html).\n\n### \u003ca id=\"android-studio-intellij-idea-plugin-optional\"\u003e\u003c/a\u003e Android Studio / IntelliJ IDEA plugin (Optional)\n\n[Official page](https://plugins.jetbrains.com/plugin/9185-bazel)\n\nTo have full IDE experience with code completion and other good stuff you can use the official Bazel plugin for Android Studio / IntelliJ IDEA.\n\n\u003cbr\u003e\n\nTo install plugin select...\n\n`Android Studio -\u003e Preferences -\u003e Plugins -\u003e Marketplace` \n\n... and search for `Bazel` plugin developed by Google.\n\n\u003cbr\u003e\n\nAfter you installed the plugin open...\n\n`Android Studio -\u003e Preferences -\u003e Bazel Settings`\n\n... and make sure `Bazel binary location` is set as `/usr/local/bin/bazelisk`\n\n\u003cbr\u003e\n\nNow you are ready to import your Bazel project. To do this select...\n\n`File -\u003e Inport Bazel Project...`\n\n... set the **root** directory of your project and follow further instructions.\n\n\u003e **Note:** Root directory of you project must contain the `WORKSPACE` file which will be described below. \n\n\u003cbr\u003e\n\nAfter the project is imported you can find the `Bazel` menu option in the app menu bar. \n\n![App menu bar](img1.png)\n\nTo sync the project files select...\n\n\n`Bazel -\u003e Sync -\u003e Sync Project with BUILD files`\n\n\n#### Troubleshooting:\n**Issue:** \n\n_Bazel plugin does not recognize java/kotlin source sets and fails to sync java/kotlin files considering their package to be wrong._ \n\n_E.g. it expects `src/main/kotlin/com/morfly/bazel` package instead of `com/morfly/bazel`._ \n\n**Solution:**\n- Make sure `BUILD` file is placed in the same package as your java/kotlin source code. If BUILD file is located in another location you should explicitly set the `custom_package` attribute.\n- Make sure, java/kotlin files has corect `package` set.\n- If it is an Android module make sure `AndroidManifest.xml` has correct `package` attrubute set. \n- If all the above does not solve the issue, uninstall Bazel plugin and install it again. After restarting the IDE it should work correct. \n\n\n### \u003ca id=\"visual-studio-code-plugin-optional\"\u003e\u003c/a\u003e Visual Studio Code plugin (Optional)\n\n[Official page](https://marketplace.visualstudio.com/items?itemName=BazelBuild.vscode-bazel)\n\nInstall official plugin from the Visual Studio Marketplace to enable Bazel VS Code support such as code highlighting and completion. \n\n\n### \u003ca id=\"buildifier-optional\"\u003e\u003c/a\u003e Buildifier (Optional)\n[Official page](https://github.com/bazelbuild/buildtools/blob/master/buildifier/README.md)\n\n_Buildifier is a tool for formatting bazel BUILD and .bzl files with a standard convention._\n\n```bash\n$ brew install buildifier\n```\n\n_In order to make buildifier automatically find all Starlark files (i.e. BUILD, WORKSPACE, .bzl, or .sky) in a directory recursively:_\n```bash\n$ buildifier -r {your_local_path}/bazel-tutorial/start\n```\n\n\u003cbr\u003e\n\n## Creating Bazel Android app\nNow when you machine is ready to work let's build an Android Bazel app.\n\nRefer to the following repository structure to locate files required for this workshop:\n```\nbazel-tutorial\n|\n└── start  \u003c- working directory for this workshop\n|\n└── competed\n```\n\nOpen `{your_local_path}/bazel-tutorial/start` project with your favorite IDE / Text Editor.\n\nTo check your progress use `completed` project directory which contains the resulting source code for this workshop.\n\n### \u003ca id=\"step-1-create-bazel-workspace\"\u003e\u003c/a\u003e Step 1. Create Bazel `WORKSPACE`\n_A workspace is a directory on your filesystem that contains the source files for the software you want to build, as well as symbolic links to directories that contain the build outputs. Each workspace directory has a text file named WORKSPACE which may be empty, or may contain references to external dependencies required to build the outputs._\n\n_Directories containing a file called WORKSPACE are considered the root of a workspace. Therefore, Bazel ignores any directory trees in a workspace rooted at a subdirectory containing a WORKSPACE file (as they form another workspace)._\n\n\u003cbr\u003e\n\nCreate a `WORPSPACE` file in the **root** project directory:\n\n`{your_local_path}/bazel-tutorial/start/WORKSPACE`\n\n\u003e **Note:** It is possible to name the file as `WORKSPACE.bazel` as well. Bazel will consider these two options equally.\n\nOpen terminal at the **root** project directory and type:\n\n```bash\n$ bazel info workspace\n```\nIf everything was done right you will see the the path to your project **root** directory as an output.\n\nIn order to include Android SDK to your project add this code to your `WORKSPACE` file:\n```python\n# WORKSPACE\n\nandroid_sdk_repository(\n    name = \"androidsdk\"\n)\n```\nBy default Bazel will use `$ANDROID_HOME` to access Android SDK. \nCheck if you `ANDROID_HOME` is set on your machine:\n```bash\n$ echo $ANDROID_HOME\n```\nIf for some reason you want to explicitly specify path to Android SDK you can set it in the `WORKSPACE` file.\n\nUsually Android SDK is stored at the following location: `/Users/{username}/Library/Android/sdk`\n\n```python\n# WORKSPACE\n\nandroid_sdk_repository(\n    name = \"androidsdk\",\n    path = \"Users/illidan.stormrage/Library/Android/sdk\", # new code\n)\n```\n\nIt is also possible to set specific version of Android SDK to be used in your project:\n\n```python\n# WORKSPACE\n\nandroid_sdk_repository(\n    name = \"androidsdk\",\n    path = \"Users/bruce.wayne/Library/Android/sdk`\",\n    api_level = 29,                # new code\n    build_tools_version = \"29.0.3\" # new code\n)\n```\n\n#### Results\nHere is our progress so far:\n```\nstart\n└── WORKSPACE  \u003c-- created\n```\n\n### \u003ca id=\"step-2-create-build-target\"\u003e\u003c/a\u003e Step 2. Create `BUILD` target\nNow, when the initial project workspace setup is done, we can define buildable targets. To do this we need to use `BUILD.bazel` files.\n\n_BUILD files tell Bazel how to build different parts of the project. (A directory within the workspace that contains a BUILD file is a package.)_\n\nOpen `src/app/java/com/morfly/bazel` directory of the project. As you can see it contains Java Android source code including `AndroidManifest.xml` and `res` directory.\n\nIn order to build and run this code we need to create a `BUILD.bazel` file and create a target which in turn is an instance of Bazel rule:\n\nCreate a build file at the following location: `src/app/java/com/morfly/bazel/BUILD.bazel` and create a target by using `android_library` rule as shown below:\n\n```python\n# src/app/java/com/morfly/bazel/BUILD.bazel\n\nandroid_library(\n    name = \"main_screen\",\n    srcs = glob([\n        \"MainActivity.java\",\n        \"Utils.java\"\n    ]),\n    manifest = \"AndroidManifest.xml\",\n    resource_files = glob([\n        \"res/**\"\n    ]),\n)\n```\n\nAs you can see, we have specified source files which should be included to the target, manifest file and resource files which include layout, strings, colors, etc.\n\nAlso, note that every target should have a name. Other targets will be able to depend on this one by refering to its name `:main_screen`.\n\n\u003e **Note:** Bazel equally considers `BUILD` and `BUILD.bazel` files. However, it is better to use latter in case of migration from Gradle project as Gradle generates `build` directories that can conflict with Bazel `BUILD` files.\n\nWe have created an Android library target but we are not ready to build the project yet.\n\nIn order to generate `.apk` file it is required to use `android_binary` rule.\n\nCreate another build file at the following location: `src/app/BUILD.bazel` and create a target by using `android_binary` rule:\n```python\n# src/app/BUILD.bazel\n\nandroid_binary(\n    name = \"app\",\n    manifest = \"AndroidManifest.xml\",\n    deps = [\n        \"//src/app/java/com/morfly/bazel:main_screen\",\n    ],\n)\n```\nAs you can see, we are referencing previously created `:main_screen` target.\n\nSuch reference format is called **label** in Bazel, where: \n- `//` specifies that we are referencing the target from **root** of the workspace.\n- `src/app/java/com/morfly/bazel` specifies the package name. (_Please, note that Bazel package and java package are not related to each other. They are different concepts._)\n- `:main_screen` specifies the target name.\n\n\u003e **Note:** It is possible to use shorter labels in some specific cases. Plese refer to the [official documentation page](https://docs.bazel.build/versions/master/build-ref.html#labels) to learn more.\n\nNow we are ready to build the project. To do this use the following command:\n\n```bash\n$ bazel build //src/app:app\n```\nOr, since `:app` target has the same name as its directory, we can use the shortened label: \n```bash\n$ bazel build //src/app\n```\nIf you run the command above you will see the following error:\n\n```\nERROR: {your_local_path}/bazel-tutorial/completed/src/app/BUILD.bazel:1:15: \nin android_binary rule //src/app:app: target '//src/app/java/com/morfly/bazel:main_screen' \nis not visible from target '//src/app:app'. \nCheck the visibility declaration of the former target if you think the dependency is legitimate\nERROR: Analysis of target '//src/app:app' failed; build aborted: Analysis of target '//src/app:app' failed\nINFO: Elapsed time: 0.138s\nINFO: 0 processes.\nFAILED: Build did NOT complete successfully (1 packages loaded, 7 targets configured)\n```\n\nTo resolve this issue we need to get familiar with the _visibility_ concept.\n\n_Visibility controls whether a target can be used (depended on) by targets in other packages. This helps other people distinguish between your library’s public API and its implementation details, and is an important tool to help enforce structure as your workspace grows._\n\nPlease, refer the [official documentation page](https://docs.bazel.build/versions/master/visibility.html) to learn more.\n\nIn order to make `:main_screen` target available for the `:app` add the following line at the beginning of `src/app/java/com/morfly/bazel/BUILD.bazel` file:\n\n```python\n# src/app/java/com/morfly/bazel/BUILD.bazel\n\npackage(default_visibility = [\"//src:__subpackages__\"]) # new code                                                  \n\nandroid_library(\n    name = \"main_screen\",\n    ...\n)\n```\nBy this we are telling that **any** package under `//src` may access `:main_screen` target.\n\nRun the build again:\n\n```bash\n$ bazel build //src/app\n```\n\nNow the build should succeed.\n\n\u003e **Note:** All the code in Bazel build files such as `WORKSPACE`, `*.bazel`, `*.bzl` is written in Starlark language which is a simplified version of Python 3. So, don't be confused when you see more Bazel code in further sections. It is just plain old Python.\n\n#### Results\nHere is out progress so far:\n```\nstart\n│\n└── src/app\n    └── BUILD.bazel  \u003c-- added :main_screen target (android_library rule)\n    │\n    └── java/com/morfly/bazel\n        └── BUILD.bazel  \u003c-- added :app target (android_binary rule)\n```\n\n### \u003ca id=\"step-3-launch-the-app\"\u003e\u003c/a\u003e Step 3. Launch the app\nTo install the app on the mobile phone or emulator use this command:\n```bash\n$ bazel mobile-install //src/app --start_app\n```\n\u003e**Note:** By default Bazel will not run the installed application.\nTo do this use `--start_app` parameter.\n\n\u003e **Note:** Make sure that you have launched Android emulator prior to performing the command above.\n\nRefer to the [official documentation page](https://docs.bazel.build/versions/master/mobile-install.html) to learn more.\n### \u003ca id=\"step-4-add-kotlin-library\"\u003e\u003c/a\u003e Step 4. Add Kotlin library\nSo far we have used only java in this workshop. \nTo be able to use kotlin in our project we need make it available for us.\n\nTo do this, add the following code to the end of `WORKSPACE` file:\n\n```python\n# WORKSPACE\n\n...\n\n# new code v\nload(\"@bazel_tools//tools/build_defs/repo:http.bzl\", \"http_archive\")\n\nrules_kotlin_version = \"legacy-1.3.0\"\n\nrules_kotlin_sha = \"4fd769fb0db5d3c6240df8a9500515775101964eebdf85a3f9f0511130885fde\"\n\nhttp_archive(\n    name = \"io_bazel_rules_kotlin\",\n    sha256 = rules_kotlin_sha,\n    strip_prefix = \"rules_kotlin-%s\" % rules_kotlin_version,\n    type = \"zip\",\n    urls = [\"https://github.com/bazelbuild/rules_kotlin/archive/%s.zip\" % rules_kotlin_version],\n)\n\nload(\"@io_bazel_rules_kotlin//kotlin:kotlin.bzl\", \"kotlin_repositories\", \"kt_register_toolchains\")\n\nkotlin_repositories()\n\nkt_register_toolchains()\n# new code ^\n```\n\nNow we are able to create Kotlin targets. In this workshop we will create a kotlin library which will be added as a dependency to the `:main_screen` target.\n\nTo create a Kotlin target we need to use `kt_jvm_library` rule.\n\nCreate a `BUILD` file at the following location: `src/jvmlib/kotlin/com/morfly/bazel/BUILD.bazel` and paste there the following code:\n```python\n# src/jvmlib/kotlіn/com/morfly/bazel/BUILD.bazel\n\nload(\"@io_bazel_rules_kotlin//kotlin:kotlin.bzl\", \"kt_jvm_library\")\n\npackage(default_visibility = [\"//src:__subpackages__\"])\n\nkt_jvm_library(\n    name = \"kotlin_library\",\n    srcs = glob([\n        \"*.kt\"\n    ]),\n)\n```\nNote that in order to use `kt_jvm_library` rule we need to `load` it to the build file.\nYou can consider `load` as an import statement where:\n- `@io_bazel_rules_kotlin` refers to another (external) workspace `io_bazel_rules_kotlin`.\n- `//kotlin` stands for a package name.\n- `kotlin.bzl` stands for a file where our rule is defined.\n- `kt_jvm_library` is a specific rule that we want to import.\n\u003e **Note:** `.bzl` are extension files where it is possible to define custom macros and rules in Bazel. Extensions are out of scope of the current workshop, so please refer to the [official documentation page](https://docs.bazel.build/versions/master/skylark/concepts.html) for more information.\n\nIn order to be able to use code from `:kotlin_library` in `:main_screen` we need to add former one as a dependency to latter one.\nTo do this open the `BUILD` file where `:main_screen` is defined and add the following line to `deps` attribute:\n```python\n# src/app/com/morfly/bazel/BUILD.bazel\n\nandroid_library(\n    name = \"main_screen\",\n    ...\n    deps = [\n        \"//src/jvmlib/kotlin/com/morfly/bazel:kotlin_library\",    # new code\n    ]\n)\n```\n\nOpen `src/app/java/com/morfly/bazel/MainActivity.java` file and uncommend the following code:\n```java\n// src/app/java/com/morfly/bazel/MainActivity.java\n\npublic class MainActivity extends Activity {\n\n    @Override\n    public void onCreate(Bundle savedInstanceState) {\n        ...\n\n        // updated code, lines 20-24\n        Library library = new KotlinLibrary();\n\n        activateVersionButton.setOnClickListener(v -\u003e\n                libraryVersionTextView.setText(Utils.formattedLibraryDescription(library))\n        );\n        // updated code ^\n    }\n}\n```\n\u003e **Note:** Do not forget about imports.\n\nOpen src/app/java/com/morfly/bazel/Utils.java file and uncomment `formattedLibraryDescription` function:\n```java\npublic class Utils {\n\n    // updated code, lines 6-8\n    public static String formattedLibraryDescription(Library library) {\n        return \"About library:\\n\" + library.getAbout();\n    }\n    // updated code ^\n}\n```\n\nNow you can build and run the app.\n\n#### Results\nHere is out progress so far:\n\n```\nstart\n└── WORKSPACE  \u003c-- added Kotlin language\n│\n└── src\n    │\n    └── app/java/com/morfly/bazel\n    │   └── BUILD.bazel  \u003c-- updated :main_screen target\n    │\n    └── jvmlib/kotlіn/com/morfly/bazel\n        └── BUILD.bazel  \u003c-- added :kotlіn_library target (kt_jvm_library rule)\n```\n\n### \u003ca id=\"step-5-add-external-dependency\"\u003e\u003c/a\u003e Step 5. Add external dependency\nAndroid, Java and Kotlin communities have reach set tools and libraries which can be extremely helpful during the development.\n\nIn this workshop we will use [ConstraintLayout](https://developer.android.com/reference/androidx/constraintlayout/widget/ConstraintLayout) to refactor our UI code in `:main_screen` target.\n\nJust like in Gradle, it is possible to add external dependencies to Bazel projects. To add such dependency to our project paste this code at the end of WORKSPACE file:\n\n```python\n# WORKSPACE\n\n...\n\n# new code v\nload(\"@bazel_tools//tools/build_defs/repo:http.bzl\", \"http_archive\")\n\nRULES_JVM_EXTERNAL_TAG = \"3.3\"\nRULES_JVM_EXTERNAL_SHA = \"d85951a92c0908c80bd8551002d66cb23c3434409c814179c0ff026b53544dab\"\n\nhttp_archive(\n    name = \"rules_jvm_external\",\n    strip_prefix = \"rules_jvm_external-%s\" % RULES_JVM_EXTERNAL_TAG,\n    sha256 = RULES_JVM_EXTERNAL_SHA,\n    url = \"https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip\" % RULES_JVM_EXTERNAL_TAG,\n)\n\nload(\"@rules_jvm_external//:defs.bzl\", \"maven_install\")\n\nmaven_install(\n    artifacts = [\n       \"androidx.constraintlayout:constraintlayout:2.0.0\",\n    ],\n    repositories = [\n        \"https://jcenter.bintray.com/\",\n        \"https://maven.google.com\",\n        \"https://repo1.maven.org/maven2\",\n    ],\n)\n# new code ^\n```\nSo, what is happening in the code above?\n- First, we need to add `rules_jvm_external` to our project.\n- `@rules_jvm_external//:defs.bzl` extension contains the rule `maven_install` which will help us to fetch external maven packages to our project.\n- Finally, we specify artifacts which should be added to our project using `maven_install` rule.\n \nNow, when external dependency became available in our project we need to specify which targets should use them. To do this, we need to update `:main_screen` target definition:\n\n```python\n# src/app/com/morfly/bazel/BUILD.bazel\n\nandroid_library(\n    name = \"main_screen\",\n    ...\n    deps = [\n        \"//src/jvmlib/kotlin/com/morfly/bazel:kotlin_library\",\n        \"@maven//:androidx_constraintlayout_constraintlayout\", # new code\n    ]\n)\n```\n\nNow, we can use `ConstraintLayout` in our code. Follow the steps below:\n1. Open `src/app/com/morfly/bazel/res/layout/activity_main_v2.txt` and **rename** it to `activity_main_v2.xml`.\n1. Use `activity_main_v2.xml` in `MainActivity.java`:\n```java\n// src/app/java/com/morfly/bazel/MainActivity.java\n\npublic class MainActivity extends Activity {\n\n    @Override\n    public void onCreate(Bundle savedInstanceState) {\n        ...\n\n        setContentView(R.layout.activity_main_v2); // updated code, line 15\n\n        ...\n    }\n}\n``` \n\nBuild and run the `:app` target.\n\n#### Results\nHere is out progress so far:\n\n```\nstart\n└── WORKSPACE  \u003c-- added ConstraintLayout dependency\n│\n└── src/app/java/com/morfly/bazel\n    └── BUILD.bazel  \u003c-- updated :main_screen target\n```\n\n### \u003ca id=\"step-6-run-tests\"\u003e\u003c/a\u003e Step 6. Run tests\nNow, when we learned how to build and run our Bazel app, we need to figure out how to test our code.\n\n\u003e **Note:** In this workshop we will consider only unit-tests. If you want to learn more about Android instrumentation tests refer to the [official documentation page](https://docs.bazel.build/versions/master/android-instrumentation-test.html#:~:text=For%20hermeticity%20and%20reproducibility%2C%20Bazel,without%20passing%20states%20between%20them.).\n\nIn order to write unit-tests for our mobile app we will be using JUnit 4.\nIf you remember previous steps, we need to add JUnit 4 artifact to our project. In order to do this open your `WORKSPACE` file and update `maven_install` section:\n```python\n# WORKSPACE\n\n...\n\nmaven_install(\n    artifacts = [\n        \"androidx.constraintlayout:constraintlayout:2.0.0\",\n        \"junit:junit:4.12\",    # new code\n    ],\n    repositories = [\n        ...\n    ],\n)\n\n```\nNow we can use JUnit to writing our unit-tests.\n\nOut unit-test code is located in `src/javatests/com/morfly/bazel/UtilsTest.java` file.\n\nTo actually run those tests we need to create a target using `java_test` rule. To do this create file \"//src/app/javatests/com/morfly/bazel/BUILD.bazel and paste there the following code:\n```python\n# src/app/tavatests/com/morfly/bazel/BUILD.bazel \n\njava_test(\n    name = \"main_unit_tests\",\n    test_class = \"com.morfly.bazel.UtilsTest\",\n    srcs = [\n        \"UtilsTest.java\"\n    ],\n    deps = [\n        \"//src/app/java/com/morfly/bazel:main_screen\",\n        \"//src/jvmlib/kotlin/com/morfly/bazel:kotlin_library\",\n    ]\n)\n```\nAs you can see, we have created `:main_unit_tests` target, specified `test_class` and `srcs` attributes and added `:main_screen` and `:kotlin_library` targets as dependencies to our test target.\n\n\nTo run our unit-tests use the following command:\n```bash\n$ bazel test //src/app/javatests/com/morfly/bazel:main_unit_tests --test_output=all\n```\n\n\u003e**Note:** By default Bazel will not output test results to console. Logs can be found in the `bazel-testlogs/test.log` file. In order to print test results to console use `--test_output=all` parameter.\n\n#### Results\nHere is out progress so far:\n\n```\nstart\n└── WORKSPACE  \u003c-- added JUnit dependency\n│\n└── src/app/tavatests/com/morfly/bazel\n    └── BUILD.bazel  \u003c-- added :main_unit_tests target (java_test rule)\n```\n\n\u003cbr\u003e\n\n## Complete by yourself\n\nDuring this workshop you have discovered how to build, run and test Android Bazel applications. \n\nNow try to practice and implement new functionallity by yourself.\n### \u003ca id=\"step-7-add-android-library\"\u003e\u003c/a\u003e Step 7. Add Android library\n\nWe need to add Android library to the project and show information about it on the main screen instead of Kotlin library which we have already integrated.\n\n**TODO:**\n1. Open `src/androidlib/kotlin/com/morfly/bazel` directory.\n1. Create `//src/androidlib/kotlin/com/morfly/bazel:android-library` target which includes `AndroidLibrary.kt` source file.\n\u003e **Hint:** You can use a `kt_android_library` rule imported from `@bazel_tools//tools/build_defs/repo:http.bzl`.\n3. Created `:android-library` target should also depend on `:kotlin-library`.\n1. Add `:android-library` target as a dependency to the `:main_screen`.\n1. Modify `MainActivity.java` file:\n```java\n// src/app/java/com/morfly/bazel/MainActivity.java\n\npublic class MainActivity extends Activity {\n\n    @Override\n    public void onCreate(Bundle savedInstanceState) {\n        ...\n\n        Button showVersionButton = ...;\n        TextView libraryVersionTextView = ...;\n\n        Library library = new AndroidLibrary(this); // updated code, line 20\n\n        activateVersionButton.setOnClickListener(v -\u003e ... );\n    }\n}\n```\n\u003e**Note:** Do not forget about imports.\n\n6. Build and run `:app` target.\n1. Press the `About library` button. You should see: `com.morfly.bazel: Android library. Version 0.1.0` message on your emulator/device screen.\n\n\u003cbr\u003e\n\n## Conclusion\n\nIn this workshop we have have done the following:\n- Developed Bazel Android multimodule application with using Java and Kotlin languages.\n- Got familiar with Bazel build specifics by using `WORKSPACE` and `BUILD.bazel` files.\n- Included 3rd-party dependency to our Bazel project.\n- Discovered how to run unit-tests with Bazel.\n\nHere is the Bazel file structure that we have built:\n```\nstart\n└── WORKSPACE\n│\n└── src\n    │\n    └── app\n    │   └── BUILD.bazel  \u003c-- :app\n    │   │\n    │   └── java/com/morfly/bazel\n    │   │   └── BUILD.bazel  \u003c-- :main_screen\n    │   │\n    │   └── javatests/com/morfly/bazel\n    │       └── BUILD.bazel  \u003c-- :main_unit_tests\n    │\n    └── jvmlib/kotlіn/com/morfly/bazel\n    │   └── BUILD.bazel  \u003c-- :kotlіn_library\n    │\n    └── androidlib/kotlіn/com/morfly/bazel\n        └── BUILD.bazel  \u003c-- :android_library\n```\n\nCongratulations! At this point you can start building your own Bazel applications. Of course, there are more advanced topics related to Bazel which will allow you to go beyond basic use cases, so feel free to check out [further learning](#further-learning) and [useful references](#refs) sections for hits about what to learn next. \n\nThank you for going through this workshop and have a great learning!\n\nYour feedback and contribution is most welcome here!\n\n\u003cbr\u003e\n\n## Further learning\n- Bazel extensions:\n    - Starlark language and `.bzl` files.\n    - Macros.\n    - Rules.\n- Queries.\n- Android instrumentation tests.\n\n\u003cbr\u003e\n\n## Useful References\n- [Official Bazel documentation:](https://docs.bazel.build/versions/3.5.0/bazel-overview.html)\n    - [Java tutorial](https://docs.bazel.build/versions/master/tutorial/java.html).\n    - [Android tutorial](https://docs.bazel.build/versions/master/tutorial/android-app.html).\n    - [Creating a macro](https://docs.bazel.build/versions/master/skylark/tutorial-creating-a-macro.html).\n    - [Rules tutorial](https://docs.bazel.build/versions/master/skylark/rules-tutorial.html).\n- [Official examples Git repository](https://github.com/bazelbuild/examples).\n- BazelCon conference:\n    - Half-day Bazel bootcamp: [part 1](https://www.youtube.com/watch?v=BGOEq5FdNUQ) and [part 2](https://www.youtube.com/watch?v=1KbfkOWO-DY).\n    - [2017 playlist](https://conf.bazel.build/2017/session-videos).\n    - [2018 playlist](https://conf.bazel.build/2018/session-videos).\n    - [2019 playlist](https://www.youtube.com/playlist?list=PLxNYxgaZ8Rsf-7g43Z8LyXct9ax6egdSj).\n    - [2020 playlist](https://opensourcelive.withgoogle.com/events/bazelcon2020)\n- [Benjamin Mushko, 2020, _Getting Started with Bazel_, O'Relly](https://get.oreilly.com/ind_getting-started-with-bazel.html).\n- Series of articles [_Writing Bazel rules_](https://jayconrod.com/posts/106/writing-bazel-rules--simple-binary-rule) on _jayconrod.com_.\n- [Building Android Apps with Bazel](https://codelabs.developers.google.com/codelabs/bazel-android-intro/index.html#0) official codelab.\n\n\u003cbr\u003e\n\n---\n_Author: Pavlo Stavytskyi_\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmorfly%2Fbazel-tutorial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmorfly%2Fbazel-tutorial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmorfly%2Fbazel-tutorial/lists"}