[Note] What is Bazel???

## Introduction
Currently I am working on some project using Tensorflow API in C++. Before starting, I thought this was not going to be so tough. Yet, as soon as began, It turned out that tons of thousands of warnings/errors awaited. Basically most of them were related with a build tool provided by Google. So for the sake of efficiency, why not start learning Bazel, which is the build tool we are using now.

[Official Document](https://docs.bazel.build/versions/master/tutorial/cpp.html)
So in order to enhance my understanding, in this post, I would like to walk you through this tutorial.

Git Repo for this tutorial!
https://github.com/Rowing0914/Bazel_Tutorial

* Estimated completion time: 30 minutes.

## What you will learn
At the end of this post, you will be able to 
1. Build a target
2. Visualize the project's dependencies
3. Split the project into multiple targets and packages
4. Control target visibility across packages
5. Reference targets through labels

## Contents
- Before you begin
    - Install Bazel
    - Get the sample project
- Build with Bazel
    - Set up the workspace
    - Understand the BUILD file
    - Build the project
    - Review the dependency graph
- Refine your Bazel build
    - Specify multiple build targets
    - Use multiple packages
- Further reading

## Before you begin
**Install Bazel**
In case, you have not obtained the bazel itself yet, please try the command below.

```bash
$ git clone https://github.com/bazelbuild/examples/
```
And the directory architecture is set like below.
![Screen Shot 2018-03-31 at 13.10.36.png](https://qiita-image-store.s3.amazonaws.com/0/240801/129ac953-582a-4bb7-3f4e-db2f20adbb73.png)

**Get the sample project**
As you can see, this tutorial is split into **3** stages.

1. building a single target residing in a single package. 
2. splitting your project into multiple targets but keep it in a single package. 
3. splitting your project into multiple packages and build it with multiple targets.

## Build with Bazel
**Set up the workspace**
Before you can build a project, you need to set up its workspace. A workspace is a directory that holds your project's source files and Bazel's build outputs. It also contains files that Bazel recognizes as special:
- <font color="red">**WORKSPACE**</font> file, which defines the directory and its contents as Bazel workspaces, and serves as the root of the projects structures.
- <font color="red">**BUILD**</font> files under some directory, which tell Bazel how to build different parts of the project.(we are going to elaborate this later)

All in all, to designate the project as Bazel-ish, we need to put the blank file named <font color="red">**WORKSPACE**</font> in that directory.
* <font color="gray">Bear in mind that once Bazel builds the project, all inputs and dependencies must be in the same workspace. Files residing in different workspaces are independent of one another unless linked, which is beyond the scope of this tutorial.</font>

**Understand the BUILD file**
Take a look at the <font color="red">**BUILD**</font> file in the `cpp-tutorial/stage1/main` directory.
`BUILD` file is containing several rules telling Bazel how to build the projects. And each rule is called a __target__.

```bash

cc_binary(
    name = "hello-world",
    srcs = ["hello-world.cc"],
)
```
In this script, the rule(target) of name is hello-world target, and srcs specifies the source file(s) from which Bazel builds the target.
The rule tells Bazel to build a self-contained executable binary from the hello-world.cc source file with no dependencies.

**Build the project**

```bash
$ bazel build //main:hello-world
```
Notice: `//main` means the location of our `BUILD` file indicating the root directory of the project, and `hello-world` is the name of target defined before!

OMG..... I got stuck with this error

`Problem with java installation: couldn't find/access rt.jar in /Library/Java/JavaVirtualMachines/jdk-9.0.4.jdk/Contents/Home`

But I could solve the problem by following command.
`$ brew upgrade bazel`

Anyway, once Bazel builds the project, you would receive this output
![Screen Shot 2018-03-31 at 15.08.03.png](https://qiita-image-store.s3.amazonaws.com/0/240801/76ab9226-66cd-1aa9-9105-954808c219ac.png)
Congrats!! You have just finished building your Bazel project!
Now bazel places the outputs of building on the directory under the bazel-bin.
So if you execute this command on your terminal, your first programmed builded by Bazel says "Hello World".
`bazel-bin/main/hello-world`

**Review the dependency graph**
So far, You have made your own workspace and prepared the BUILD file, then run the bazel to build the project. I guess you want more, but before diving into deeper, let us take a time to consider the output of this build a bit.
A successful build has all dependencies explicitly stated in BUILD file. Bazel follows those statements to create the project dependency graph.
Let's visualise our sample project dependencies.

```bash
$ bazel query --nohost_deps --noimplicit_deps 'deps(//main:hello-world)' \
  --output graph
```
While you get these output, no need to read it, instead, go to this page and paste them in the text area!
[GraphViz](http://www.webgraphviz.com/)

As you can see, the project composes a single target that builds a single source file.
![Screen Shot 2018-03-31 at 15.19.19.png](https://qiita-image-store.s3.amazonaws.com/0/240801/ff28eef3-def0-a449-6c19-f7b35d93bb3f.png)

## Refine your Bazel build
Even though sometime a single target should be fine, mostly you may want to have a larger project than what we have done so far.

So let's move on to the second stage!
**Specify multiple build targets**
Browse through the content in `BUILD` of `cpp-tutorial/stage2/main`.

```bash
cc_library(
    name = "hello-greet",
    srcs = ["hello-greet.cc"],
    hdrs = ["hello-greet.h"],
)

cc_binary(
    name = "hello-world",
    srcs = ["hello-world.cc"],
    deps = [
        ":hello-greet",
    ],
)
```

With this file, bazel firstly works on `hello-greet` then move on to `hello-world`. You might wonder about `deps` attribute though, it tells bazel that `hello-greet` library is required to build the `hello-world binary`.

Let's build the second project!

```bash
$ bazel build //main:hello-world
```

Output should be like this,
![Screen Shot 2018-03-31 at 15.35.52.png](https://qiita-image-store.s3.amazonaws.com/0/240801/2074c402-28d1-a3d2-3005-bd22eb1af15c.png)
Congrats again! Let's test our fresh programme.

```bash
$ bazel-bin/main/hello-world
```
Output should be, `Hello World`.

Same?? yes, because if you look at the hello-world.cc, it gives string variable to hello-greet.cc which returns `hello + string`.

If you now modify hello-greet.cc and rebuild the project, Bazel will only recompile that file.
So why not try?

I put one more element to be returned.
hello-greet.cc

```c++
#include "hello-greet.h"
#include <string>

std::string get_greet(const std::string& who) {
  return "Hello " + who + "from Japan!";
}
```

And let's build the project again!
![Screen Shot 2018-03-31 at 15.42.51.png](https://qiita-image-store.s3.amazonaws.com/0/240801/91b7b3ba-7f53-7795-66c8-4be7ff044699.png)
This time, bazel detects the point modified and the file, then builds only it! That is why the build time faster than before!!
And let's see how the dependency graph is! Run the command and paste the output on Graphviz

```bash
bazel query --nohost_deps --noimplicit_deps 'deps(//main:hello-world)' \
  --output graph
```
![Screen Shot 2018-03-31 at 15.45.30.png](https://qiita-image-store.s3.amazonaws.com/0/240801/d74d9744-6239-f9a1-3f4c-57a9024bd5b5.png)
You've now built the project with two targets. The hello-world target builds one source file and depends on one other target (//main:hello-greet), which builds two additional source files.

## Use multiple packages
We have experienced building methods for a single and multi targets. Now it is the time to go more practical.
This time, we are going to go through the case where the packages are split into 2.
![Screen Shot 2018-03-31 at 15.49.04.png](https://qiita-image-store.s3.amazonaws.com/0/240801/ddffbae4-b2c4-653c-1dde-5498fa3ce2c9.png)
Notice now we have 2 sub-directories containing `BUILD` respectively.

`lib/BUILD`

```bash
cc_library(
    name = "hello-time",
    srcs = ["hello-time.cc"],
    hdrs = ["hello-time.h"],
    visibility = ["//main:__pkg__"],
)
```

`main/BUILD`

```bash
cc_library(
    name = "hello-greet",
    srcs = ["hello-greet.cc"],
    hdrs = ["hello-greet.h"],
)

cc_binary(
    name = "hello-world",
    srcs = ["hello-world.cc"],
    deps = [
        ":hello-greet",
        "//lib:hello-time",
    ],
)
```

There is a new keyword here, `visibility` in `lib/BUILD` file. we make the `//lib:hello-time` target in `lib/BUILD` explicitly visible to targets in `main/BUILD` using the `visibility` attribute. This is because <font color="red">by default targets are only visible to other targets in the same `BUILD` file.</font>

Before building, let me explains the dependency graph first since I believe that the clear picture on your mind enhances the understanding.
![Screen Shot 2018-03-31 at 15.56.00.png](https://qiita-image-store.s3.amazonaws.com/0/240801/9b50ffbe-18f9-8e47-2db7-d220214620ba.png)

As you can see, the `hello-world` target in the main package depends on the `hello-time` target in the `lib` package (hence the target label `//lib:hello-time`) - Bazel knows this through the deps attribute. Take a look at the dependency graph.

Now let's build the final project.

```bash
$ bazel build //main:hello-world
```

And feel free to try visualising the dependencies!
However, I would like to off the track a bit and tweak `lib/BUILD` a bit.

```bash
cc_library(
    name = "hello-time",
    srcs = ["hello-time.cc"],
    hdrs = ["hello-time.h"],
)
```
Now I have removed the visibility keyword, and let's see what will happen.
*sorry the error log was too long, so the image gets shrunk.
![Screen Shot 2018-03-31 at 16.04.50.png](https://qiita-image-store.s3.amazonaws.com/0/240801/8706e350-fd5f-4729-c343-5f1016f13dd0.png)
As you can see, it is saying that 

```bash
Target '//lib:hello-time' is not visible from target '//main:hello-world'
```
This is exactly what I wanted! So without visibility defined in BUILD file of its dependent directories, Bazel is not able to build.


## Tips
What is .bazelrc?
check this part
.bazelrc, the Bazel configuration file, the --bazelrc=file option, and the --config=value option

from this link:
https://docs.bazel.build/versions/master/user-manual.html

Common Error
Unexpected error reading .blazerc file '/Users/norio.kosaka/Desktop/tensorflow/.tf_configure.bazelrc'

Solution: as it describes here, just remove .bazelrc!!
https://github.com/bazelbuild/bazel/issues/3053

## Further Readings
https://docs.bazel.build/versions/master/external.html
https://docs.bazel.build/versions/master/be/overview.html
https://docs.bazel.build/versions/master/tutorial/java.html

Thank you for your patience!!