diff options
author | Yun Peng <pcloudy@google.com> | 2016-06-24 18:01:03 +0000 |
---|---|---|
committer | Dmitry Lomov <dslomov@google.com> | 2016-06-27 11:39:16 +0000 |
commit | 1f63afaca0655b0948708ed38a129e4177633639 (patch) | |
tree | 711c068afeb232d4e727858e064b795feea35362 | |
parent | dbc9c7c26023cbde329fb63d56f95db45b976bba (diff) |
- Move Java-specific content to Java landing page
- Turn C++ Basic into a C++ language landing page
- Reorganized tutorial menu
--
MOS_MIGRATED_REVID=125796335
-rw-r--r-- | site/_layouts/documentation.html | 25 | ||||
-rw-r--r-- | site/docs/cpp.md | 277 | ||||
-rw-r--r-- | site/docs/tutorial/app.md (renamed from site/docs/tutorial/index.md) | 4 | ||||
-rw-r--r-- | site/docs/tutorial/cpp.md | 360 | ||||
-rw-r--r-- | site/docs/tutorial/java.md | 245 |
5 files changed, 624 insertions, 287 deletions
diff --git a/site/_layouts/documentation.html b/site/_layouts/documentation.html index f265b784e5..40277fd862 100644 --- a/site/_layouts/documentation.html +++ b/site/_layouts/documentation.html @@ -34,13 +34,23 @@ nav: docs Tutorial <span class="caret"></span> </a> <ul class="collapse sidebar-nav sidebar-submenu" id="tutorial-menu"> - <li><a href="/docs/tutorial/index.html">Introduction</a></li> - <li><a href="/docs/tutorial/environment.html">Set Up Your Environment</a></li> - <li><a href="/docs/tutorial/workspace.html">Set Up a Workspace</a></li> - <li><a href="/docs/tutorial/android-app.html">Build an Android App</a></li> - <li><a href="/docs/tutorial/ios-app.html">Build an iOS App</a></li> - <li><a href="/docs/tutorial/backend-server.html">Build the Backend Server</a></li> - <li><a href="/docs/tutorial/review.html">Review</a></li> + <li><a href="/docs/tutorial/java.html">Build Java</a></li> + <li><a href="/docs/tutorial/cpp.html">Build C++</a></li> + <li> + <a class="sidebar-nav-heading" href="#app-menu" + data-toggle="collapse" aria-expanded="false" aria-controls="app-menu"> + Build Mobile Application + </a> + <ul class="collapse sidebar-nav sidebar-submenu" id="app-menu"> + <li><a href="/docs/tutorial/app.html">Introduction</a></li> + <li><a href="/docs/tutorial/environment.html">Set Up Your Environment</a></li> + <li><a href="/docs/tutorial/workspace.html">Set Up a Workspace</a></li> + <li><a href="/docs/tutorial/android-app.html">Build an Android App</a></li> + <li><a href="/docs/tutorial/ios-app.html">Build an iOS App</a></li> + <li><a href="/docs/tutorial/backend-server.html">Build the Backend Server</a></li> + <li><a href="/docs/tutorial/review.html">Review</a></li> + </ul> + </li> </ul> </li> <li><a href="/docs/support.html">Get Support</a></li> @@ -53,7 +63,6 @@ nav: docs <li><a href="/docs/query.html">Query Language</a></li> <li><a href="/docs/query-how-to.html">Query How-To</a></li> <li><a href="/docs/mobile-install.html">mobile-install (Android)</a></li> - <li><a href="/docs/cpp.html">C++ Basics</a></li> <li><a href="/docs/external.html">External Dependencies</a></li> <li><a href="/docs/command-line-reference.html">Command-line Reference</a></li> <li><a href="/docs/output_directories.html">Output Directories</a></li> diff --git a/site/docs/cpp.md b/site/docs/cpp.md deleted file mode 100644 index 8ae8595a11..0000000000 --- a/site/docs/cpp.md +++ /dev/null @@ -1,277 +0,0 @@ ---- -layout: documentation -title: C++ Basics ---- - -C++ Basics -========== - -Use fully qualified include paths ---------------------------------- - -Includes are relative to the root of your workspace. For example, suppose -you have the following directory structure: - -``` -[workspace]/ - WORKSPACE - a/ - BUILD - a.h - a.cc - b/ - BUILD - b.h - b.cc - main.cc -``` - -If `b/main.cc` needs to include b.h then we'd create the following `b/BUILD` -file: - -```python -cc_library( - name = "b", - srcs = ["b.cc"], - hdrs = ["b.h"], -) - -cc_binary( - name = "main", - srcs = ["main.cc"], - deps = [":b"], -) -``` - -`b/main.cc` would have the following include statement: - -```cpp -#include "b/b.h" -``` - -Note that the full path from the package root is used. If we want `b/main.cc` to -also depend on `a/a.h`, we'd add the rule to `a/BUILD`: - -```python -cc_library( - name = "a", - srcs = ["a.cc"], - hdrs = ["a.h"], - visibility = ["//b:__pkg__"], -) -``` - -Then we'd add a dependency to `b/BUILD`: - -```python -cc_binary( - name = "main", - srcs = ["main.cc"], - deps = [ - ":b", - "//a", - ], -) -``` - -And the following include to `b/main.cc`: - -```cpp -#include "a/a.h" -``` - -`b/main.cc` will then be able to access symbols from `a/a.h` or `b/b.h`. - -Transitive includes -------------------- - -If a file includes a header then the file's rule should depend on that header's -library. Conversely, only direct dependencies need to be specified as -dependencies. For example, suppose `sandwich.h` includes `bread.h` and -`bread.h` includes `flour.h`. `sandwich.h` doesn't include `flour.h` (who wants -flour in their sandwich?), so the BUILD file would look like: - -```python -cc_library( - name = "sandwich", - srcs = ["sandwich.cc"], - hdrs = ["sandwich.h"], - deps = [":bread"], -) - -cc_library( - name = "bread", - srcs = ["bread.cc"], - hdrs = ["bread.h"], - deps = [":flour"], -) - -cc_library( - name = "flour", - srcs = ["flour.cc"], - hdrs = ["flour.h"], -) -``` - -This expresses that the `sandwich` library depends on the `bread` library, -which depends on the `flour` library. - -Adding include paths --------------------- - -Sometimes you cannot (or do not want to) base include paths at the workspace -root. Existing libaries might already have a include directory that doesn't -match its path in your workspace. For example, suppose you have the following -directory structure: - -``` -[workspace]/ - WORKSPACE - third_party/ - some_lib/ - include/ - some_lib.h - BUILD - some_lib.cc -``` - -Bazel will expect `some_lib.h` to be included as -`third_party/some_lib/include/some_lib.h`, but suppose `some_lib.cc` includes -`"include/some_lib.h"`. To make that include path valid, -`third_party/some_lib/BUILD` will need to specify that the `some_lib/` -directory is an include directory: - -```python -cc_library( - name = "some_lib", - srcs = ["some_lib.cc"], - hdrs = ["some_lib.h"], - copts = ["-Ithird_party/some_lib"], -) -``` - -This is especially useful for external dependencies, as their header files -must otherwise be included with an `external/[repository-name]/` prefix. - -Including external libraries: an example ----------------------------------------- - -Suppose you are using [Google Test](https://code.google.com/p/googletest/). You -can use one of the `new_` repository functions in the `WORKSPACE` file to -download Google Test and make it available in your repository: - -```python -new_http_archive( - name = "gtest", - url = "https://googletest.googlecode.com/files/gtest-1.7.0.zip", - sha256 = "247ca18dd83f53deb1328be17e4b1be31514cedfc1e3424f672bf11fd7e0d60d", - build_file = "gtest.BUILD", -) -``` - -Then create `gtest.BUILD`, a BUILD file to use to compile Google Test. -Google Test has several "special" requirements that make its `cc_library` rule -more complicated: - -* `gtest-1.7.0/src/gtest-all.cc` `#include`s all of the other files in - `gtest-1.7.0/src/`, so we need to exclude it from the compile or we'll get - link errors for duplicate symbols. -* It uses header files that relative to the `gtest-1.7.0/include/` directory - (`"gtest/gtest.h"`), so we must add that directory the include paths. -* It needs to link in pthread, so we add that as a `linkopt`. - -The final rule looks like this: - -```python -cc_library( - name = "main", - srcs = glob( - ["gtest-1.7.0/src/*.cc"], - exclude = ["gtest-1.7.0/src/gtest-all.cc"] - ), - hdrs = glob([ - "gtest-1.7.0/include/**/*.h", - "gtest-1.7.0/src/*.h" - ]), - copts = [ - "-Iexternal/gtest/gtest-1.7.0/include" - ], - linkopts = ["-pthread"], - visibility = ["//visibility:public"], -) -``` - -This is somewhat messy: everything is prefixed with gtest-1.7.0 as a byproduct -of the archive's structure. You can make `new_http_archive` strip this prefix by -adding the `strip_prefix` attribute: - -```python -new_http_archive( - name = "gtest", - url = "https://googletest.googlecode.com/files/gtest-1.7.0.zip", - sha256 = "247ca18dd83f53deb1328be17e4b1be31514cedfc1e3424f672bf11fd7e0d60d", - build_file = "gtest.BUILD", - strip_prefix = "gtest-1.7.0", -) -``` - -Then `gtest.BUILD` would look like this: - -```python -cc_library( - name = "main", - srcs = glob( - ["src/*.cc"], - exclude = ["src/gtest-all.cc"] - ), - hdrs = glob([ - "include/**/*.h", - "src/*.h" - ]), - copts = ["-Iexternal/gtest/include"], - linkopts = ["-pthread"], - visibility = ["//visibility:public"], -) -``` - -Now `cc_` rules can depend on `//external:gtest/main`. - -For example, we could create a test such as: - -```cpp -#include "gtest/gtest.h" - -TEST(FactorialTest, Negative) { - EXPECT_EQ(1, 1); -} -``` - -Then create a BUILD file for your tests: - -```python -cc_test( - name = "my_test", - srcs = ["my_test.cc"], - copts = ["-Iexternal/gtest/include"], - deps = ["@gtest//:main"], -) -``` - -You can then use `bazel test` to run the test. - - -Adding dependencies on precompiled libraries --------------------------------------------- - -If you want to use a library that you only have a compiled version of (e.g., -headers and a .so) wrap it in a `cc_library` rule: - -```python -cc_library( - name = "mylib", - srcs = ["mylib.so"], - hdrs = ["mylib.h"], -) -``` - -Then other C++ targets in your workspace can depend on this rule. diff --git a/site/docs/tutorial/index.md b/site/docs/tutorial/app.md index c7e5d24873..fdc33c5f83 100644 --- a/site/docs/tutorial/index.md +++ b/site/docs/tutorial/app.md @@ -1,9 +1,9 @@ --- layout: documentation -title: Tutorial - Introduction +title: Build Mobile Application --- -# Tutorial - Introduction +# Build Mobile Application You can use Bazel to build a variety of software outputs, including Linux and Mac OS X applications written in Java, C++ and Objective-C. You can diff --git a/site/docs/tutorial/cpp.md b/site/docs/tutorial/cpp.md new file mode 100644 index 0000000000..cea0a1c513 --- /dev/null +++ b/site/docs/tutorial/cpp.md @@ -0,0 +1,360 @@ +--- +layout: documentation +title: Build C++ +--- + +Build C++ +========= + +You can use Bazel to build your C++ application, in this tutorial you'll learn how to: + +* Build your first C++ target +* Using external libraries +* Writing and running C++ test +* Using precompiled libraries + +## Setup your workspace + +Suppose that you have an existing project in a directory, say, +`~/gitroot/my-project/`. Create an empty file at +`~/gitroot/my-project/WORKSPACE` to show Bazel where your project's root is. +We are going to create a small hello world project with the following directory structure: +{% highlight bash %} +└── my-project + ├── lib + │ ├── BUILD + │ ├── hello-greet.cc + │ └── hello-greet.h + ├── main + │ ├── BUILD + │ ├── hello-time.cc + │ ├── hello-time.h + │ └── hello-world.cc + └── WORKSPACE +{% endhighlight %} + +## Creating source files + +Using the following commands to create the necessary source files: +{% highlight bash %} +$ # If you're not already there, move to your workspace directory. +$ cd ~/gitroot/my-project +$ mkdir ./main +$ cat > main/hello-world.cc <<'EOF' +#include "lib/hello-greet.h" +#include "main/hello-time.h" +#include <iostream> +#include <string> + +int main(int argc, char** argv) { + std::string who = "world"; + if (argc > 1) { + who = argv[1]; + } + std::cout << get_greet(who) <<std::endl; + print_localtime(); + return 0; +} +EOF +$ cat > main/hello-time.h <<'EOF' +#ifndef MAIN_HELLO_TIME_H_ +#define MAIN_HELLO_TIME_H_ + +void print_localtime(); + +#endif +EOF +$ cat > main/hello-time.cc <<'EOF' +#include "main/hello-time.h" +#include <ctime> +#include <iostream> + +void print_localtime() { + std::time_t result = std::time(nullptr); + std::cout << std::asctime(std::localtime(&result)); +} +EOF +$ mkdir ./lib +$ cat > lib/hello-greet.h <<'EOF' +#ifndef LIB_HELLO_GREET_H_ +#define LIB_HELLO_GREET_H_ + +#include <string> + +std::string get_greet(const std::string &thing); + +#endif +EOF +$ cat > lib/hello-greet.cc <<'EOF' +#include "lib/hello-greet.h" +#include <string> + +std::string get_greet(const std::string& who) { + return "Hello " + who; +} +EOF +{% endhighlight %} + +## Adding BUILD files + +As you can see from the source code, `main/hello-world.cc` needs to include both `lib/hello-greet.h` and `main/hello-time.h`. +First we create `lib/BUILD` for hello-greet.cc: + +{% highlight python %} +cc_library( + name = "hello-greet", + srcs = ["hello-greet.cc"], + hdrs = ["hello-greet.h"], + visibility = ["//main:__pkg__"], +) +{% endhighlight %} + +Note that `visibility = ["//main:__pkg__"]` indicates `hello-greet` is visible from `main/BUILD`. +Then we'd create following `main/BUILD` file: + +{% highlight python %} +cc_library( + name = "hello-time", + srcs = ["hello-time.cc"], + hdrs = ["hello-time.h"], +) + +cc_binary( + name = "hello-world", + srcs = ["hello-world.cc"], + deps = [ + ":hello-time", + "//lib:hello-greet", + ], +) +{% endhighlight %} + +Note when depending on a target in the same package, we can just use `:hello-time`, +when the target is in other package, a full path from root should be used, like `//lib:hello-greet`. + +Now you are ready to build your hello world C++ binary: + +{% highlight bash %} +$ bazel build main:hello-world +INFO: Found 1 target... +Target //main:hello-world up-to-date: + bazel-bin/main/hello-world +INFO: Elapsed time: 2.869s, Critical Path: 1.00s +$ ./bazel-bin/main/hello-world +Hello world +Thu Jun 23 18:51:46 2016 +$ ./bazel-bin/main/hello-world Bazel +Hello Bazel +Thu Jun 23 18:52:10 2016 +{% endhighlight %} + +Congratulations, you've just built your first Bazel target! + +## Transitive includes + +If a file includes a header then the file's rule should depend on that header's +library. Conversely, only direct dependencies need to be specified as +dependencies. For example, suppose `sandwich.h` includes `bread.h` and +`bread.h` includes `flour.h`. `sandwich.h` doesn't include `flour.h` (who wants +flour in their sandwich?), so the BUILD file would look like: + +```python +cc_library( + name = "sandwich", + srcs = ["sandwich.cc"], + hdrs = ["sandwich.h"], + deps = [":bread"], +) + +cc_library( + name = "bread", + srcs = ["bread.cc"], + hdrs = ["bread.h"], + deps = [":flour"], +) + +cc_library( + name = "flour", + srcs = ["flour.cc"], + hdrs = ["flour.h"], +) +``` + +This expresses that the `sandwich` library depends on the `bread` library, +which depends on the `flour` library. + +## Adding include paths + +Sometimes you cannot (or do not want to) base include paths at the workspace +root. Existing libaries might already have a include directory that doesn't +match its path in your workspace. For example, suppose you have the following +directory structure: + +``` +└── my-project + ├── third_party + │ └── some_lib + │ ├── BUILD + │ ├── include + │ │ └── some_lib.h + │ └── some_lib.cc + └── WORKSPACE +``` + +Bazel will expect `some_lib.h` to be included as +`third_party/some_lib/include/some_lib.h`, but suppose `some_lib.cc` includes +`"include/some_lib.h"`. To make that include path valid, +`third_party/some_lib/BUILD` will need to specify that the `some_lib/` +directory is an include directory: + +```python +cc_library( + name = "some_lib", + srcs = ["some_lib.cc"], + hdrs = ["some_lib.h"], + copts = ["-Ithird_party/some_lib"], +) +``` + +This is especially useful for external dependencies, as their header files +must otherwise be included with an `external/[repository-name]/` prefix. + +## Including external libraries + +Suppose you are using [Google Test](https://code.google.com/p/googletest/). You +can use one of the `new_` repository functions in the `WORKSPACE` file to +download Google Test and make it available in your repository: + +```python +new_http_archive( + name = "gtest", + url = "https://googletest.googlecode.com/files/gtest-1.7.0.zip", + sha256 = "247ca18dd83f53deb1328be17e4b1be31514cedfc1e3424f672bf11fd7e0d60d", + build_file = "gtest.BUILD", +) +``` + +Then create `gtest.BUILD`, a BUILD file to use to compile Google Test. +Google Test has several "special" requirements that make its `cc_library` rule +more complicated: + +* `gtest-1.7.0/src/gtest-all.cc` `#include`s all of the other files in + `gtest-1.7.0/src/`, so we need to exclude it from the compile or we'll get + link errors for duplicate symbols. +* It uses header files that relative to the `gtest-1.7.0/include/` directory + (`"gtest/gtest.h"`), so we must add that directory the include paths. +* It needs to link in pthread, so we add that as a `linkopt`. + +The final rule looks like this: + +```python +cc_library( + name = "main", + srcs = glob( + ["gtest-1.7.0/src/*.cc"], + exclude = ["gtest-1.7.0/src/gtest-all.cc"] + ), + hdrs = glob([ + "gtest-1.7.0/include/**/*.h", + "gtest-1.7.0/src/*.h" + ]), + copts = [ + "-Iexternal/gtest/gtest-1.7.0/include" + ], + linkopts = ["-pthread"], + visibility = ["//visibility:public"], +) +``` + +This is somewhat messy: everything is prefixed with gtest-1.7.0 as a byproduct +of the archive's structure. You can make `new_http_archive` strip this prefix by +adding the `strip_prefix` attribute: + +```python +new_http_archive( + name = "gtest", + url = "https://googletest.googlecode.com/files/gtest-1.7.0.zip", + sha256 = "247ca18dd83f53deb1328be17e4b1be31514cedfc1e3424f672bf11fd7e0d60d", + build_file = "gtest.BUILD", + strip_prefix = "gtest-1.7.0", +) +``` + +Then `gtest.BUILD` would look like this: + +```python +cc_library( + name = "main", + srcs = glob( + ["src/*.cc"], + exclude = ["src/gtest-all.cc"] + ), + hdrs = glob([ + "include/**/*.h", + "src/*.h" + ]), + copts = ["-Iexternal/gtest/include"], + linkopts = ["-pthread"], + visibility = ["//visibility:public"], +) +``` + +Now `cc_` rules can depend on `//external:gtest/main`. + +## Writing and running C++ test + +For example, we could create a test `./test/hello-test.cc` such as: + +```cpp +#include "gtest/gtest.h" +#include "lib/hello-greet.h" + +TEST(FactorialTest, Negative) { + EXPECT_EQ(get_greet("Bazel"), "Hello Bazel"); +} +``` + +Then create `./test/BUILD` file for your tests: + +```python +cc_test( + name = "hello-test", + srcs = ["hello-test.cc"], + copts = ["-Iexternal/gtest/include"], + deps = [ + "@gtest//:main", + "//lib:hello-greet", + ], +) +``` + +Note in order to make `hello-greet` visible to `hello-test`, we have to add `"//test:__pkg__",` to `visibility` attribute in `./lib/BUILD`. + +Now You can then use `bazel test` to run the test. + +{% highlight bash %} +$ bazel test test:hello-test +INFO: Found 1 test target... +Target //test:hello-test up-to-date: + bazel-bin/test/hello-test +INFO: Elapsed time: 4.497s, Critical Path: 2.53s +//test:hello-test PASSED in 0.3s + +Executed 1 out of 1 tests: 1 test passes. +{% endhighlight %} + + +## Adding dependencies on precompiled libraries + +If you want to use a library that you only have a compiled version of (e.g., +headers and a .so) wrap it in a `cc_library` rule: + +```python +cc_library( + name = "mylib", + srcs = ["mylib.so"], + hdrs = ["mylib.h"], +) +``` + +Then other C++ targets in your workspace can depend on this rule. diff --git a/site/docs/tutorial/java.md b/site/docs/tutorial/java.md new file mode 100644 index 0000000000..1d2008b310 --- /dev/null +++ b/site/docs/tutorial/java.md @@ -0,0 +1,245 @@ +--- +layout: documentation +title: Build Java +--- + +Build Java +========== + +You can use Bazel to build your Java application, in this tutorial you'll learn how to: + +* Build your first Java target +* Adding dependencies to your target +* Using multiple packages +* Deploying your target + +## Setup your workspace + +Suppose that you have an existing project in a directory, say, +`~/gitroot/my-project/`. Create an empty file at +`~/gitroot/my-project/WORKSPACE` to show Bazel where your project's root is. + +## Creating Your Own Build File + +Use the following commands to make a small Java project for this example: + +{% highlight bash %} +$ # If you're not already there, move to your workspace directory. +$ cd ~/gitroot/my-project +$ mkdir -p src/main/java/com/example +$ cat > src/main/java/com/example/ProjectRunner.java <<'EOF' +package com.example; + +public class ProjectRunner { + public static void main(String args[]) { + Greeting.sayHi(); + } +} +EOF +$ cat > src/main/java/com/example/Greeting.java <<'EOF' +package com.example; + +public class Greeting { + public static void sayHi() { + System.out.println("Hi!"); + } +} +EOF +{% endhighlight %} + +Bazel figures out what to build by looking for files named `BUILD` in your +workspace, so we'll create a `BUILD` file in the `~/gitroot/my-project` +directory. Add the following lines to this BUILD file: + +{% highlight python %} +# ~/gitroot/my-project/BUILD +java_binary( + name = "my-runner", + srcs = glob(["**/*.java"]), + main_class = "com.example.ProjectRunner", +) +{% endhighlight %} + +`java_binary` is the type of thing this rule will build. +`glob(["**/*.java"])` is a handy shorthand for "recursively include every file +that ends with .java" (see the +[build encyclopedia](be/functions.html#glob) for more information about +globbing). `com.example.ProjectRunner` specifies the class that contains the +main method. + +Now you are ready to build your Java binary: + +{% highlight bash %} +$ cd ~/gitroot/my-project +$ bazel build //:my-runner +INFO: Found 1 target... +Target //:my-runner up-to-date: + bazel-bin/my-runner.jar + bazel-bin/my-runner +INFO: Elapsed time: 1.021s, Critical Path: 0.83s +$ bazel-bin/my-runner +Hi! +{% endhighlight %} + +Congratulations, you've just built your first Bazel target! + +## Adding Dependencies + +Creating one rule to build your entire project may be sufficient for small +projects, but as projects get larger it's important to break up the build into +self-contained libraries that can be assembled into a final product. This way +the entire world doesn't need to be rebuilt on small changes and Bazel can +parallelize more of the build steps. + +To break up a project, create separate rules for each subcomponent and then +make them depend on each other. For the example above, add the following rules +to the `BUILD` file: + +{% highlight python %} +java_binary( + name = "my-other-runner", + srcs = ["src/main/java/com/example/ProjectRunner.java"], + main_class = "com.example.ProjectRunner", + deps = [":greeter"], +) + +java_library( + name = "greeter", + srcs = ["src/main/java/com/example/Greeting.java"], +) +{% endhighlight %} + +This builds the same files as before, but in a different way: now Bazel will +build the `greeter` library first and then build `my-other-runner`. Try building +and running `//:my-other-runner`: + +{% highlight bash %} +$ bazel run //:my-other-runner +INFO: Found 1 target... +Target //:my-other-runner up-to-date: + bazel-bin/my-other-runner.jar + bazel-bin/my-other-runner +INFO: Elapsed time: 2.454s, Critical Path: 1.58s + +INFO: Running command line: bazel-bin/my-other-runner +Hi! +{% endhighlight %} + +Now if you edit `ProjectRunner.java` and rebuild `my-other-runner`, +`Greeting.java` will not need to be recompiled. + +## Using Multiple Packages + +For larger projects, you will often be dealing with several directories. You +can refer to targets defined in other BUILD files using the syntax +`//path/to/directory:target-name`. For example, suppose +`src/main/java/com/example/` has a `cmdline/` subdirectory with the following +file: + +{% highlight bash %} +$ mkdir -p src/main/java/com/example/cmdline +$ cat > src/main/java/com/example/cmdline/Runner.java <<'EOF' +package com.example.cmdline; + +import com.example.Greeting; + +public class Runner { + public static void main(String args[]) { + Greeting.sayHi(); + } +} +EOF +{% endhighlight %} + +`Runner.java` depends on `com.example.Greeting`, so we could add a `BUILD` file +at `src/main/java/com/example/cmdline/BUILD` that contained the following rule: + +{% highlight python %} +# ~/gitroot/my-project/src/main/java/com/example/cmdline/BUILD +java_binary( + name = "runner", + srcs = ["Runner.java"], + main_class = "com.example.cmdline.Runner", + deps = ["//:greeter"] +) +{% endhighlight %} + +However, by default, build rules are _private_. This means that they can only be +referred to by rules in the same BUILD file. This prevents libraries that are +implementation details from leaking into public APIs, but it also means that you +must explicitly allow `runner` to depend on `//:greeter`. As is, if we +build `runner` we'll get a permissions error: + +{% highlight bash %} +$ bazel build //src/main/java/com/example/cmdline:runner +ERROR: /home/user/gitroot/my-project/src/main/java/com/example/cmdline/BUILD:2:1: + Target '//:greeter' is not visible from target '//src/main/java/com/example/cmdline:runner'. + Check the visibility declaration of the former target if you think the dependency is legitimate. +ERROR: Analysis of target '//src/main/java/com/example/cmdline:runner' failed; build aborted. +INFO: Elapsed time: 0.091s +{% endhighlight %} + +You can make a rule visibile to rules in other BUILD files by adding a +`visibility = level` attribute. Change the `greeter` rule in +`~/gitroot/my-project/BUILD` to be visible to our new rule: + +{% highlight python %} +java_library( + name = "greeter", + srcs = ["src/main/java/com/example/Greeting.java"], + visibility = ["//src/main/java/com/example/cmdline:__pkg__"], +) +{% endhighlight %} + +This makes `//:greeter` visible to any rule in the +`//src/main/java/com/example/cmdline` package. Now we can build and +run the `runner` binary: + +{% highlight bash %} +$ bazel run //src/main/java/com/example/cmdline:runner +INFO: Found 1 target... +Target //src/main/java/com/example/cmdline:runner up-to-date: + bazel-bin/src/main/java/com/example/cmdline/runner.jar + bazel-bin/src/main/java/com/example/cmdline/runner +INFO: Elapsed time: 1.576s, Critical Path: 0.81s + +INFO: Running command line: bazel-bin/src/main/java/com/example/cmdline/runner +Hi! +{% endhighlight %} + +See the [build encyclopedia](be/common-definitions.html#common.visibility) for more +visibility options. + +## Deploying + +If you look at the contents of +_bazel-bin/src/main/java/com/example/cmdline/runner.jar_, you can see that it +only contains `Runner.class`, not its dependencies (`Greeting.class`): + +{% highlight bash %} +$ jar tf bazel-bin/src/main/java/com/example/cmdline/runner.jar +META-INF/ +META-INF/MANIFEST.MF +com/ +com/example/ +com/example/cmdline/ +com/example/cmdline/Runner.class +{% endhighlight %} + +This works for running locally (the `runner` script Bazel generates adds the +greeter jar to the classpath) but will not work if we want to copy `runner.jar` +to another machine and use it as a standalone binary. To build a self-contained +jar that can be deployed, build `runner_deploy.jar` (or, more generally, +`<target-name>_deploy.jar`): + +{% highlight bash %} +$ bazel build //src/main/java/com/example/cmdline:runner_deploy.jar +INFO: Found 1 target... +Target //src/main/java/com/example/cmdline:runner_deploy.jar up-to-date: + bazel-bin/src/main/java/com/example/cmdline/runner_deploy.jar +INFO: Elapsed time: 1.700s, Critical Path: 0.23s +{% endhighlight %} + +`runner_deploy.jar` will contain all of its dependencies. + + |