blob: 4e7c49e2e5cd45ed76324c5c342dba8bb9298629 [file] [log] [blame] [view]
Yun Peng1f63afa2016-06-24 18:01:03 +00001---
dzc22b85a22017-05-31 20:37:50 +02002layout: documentation
Googlere7634412017-06-07 14:52:50 -04003title: Build Tutorial - C++
Yun Peng1f63afa2016-06-24 18:01:03 +00004---
dzc22b85a22017-05-31 20:37:50 +02005
ahumesky71c14412017-12-08 11:55:53 -08006Introduction to Bazel: Building a C++ Project
Googlere7634412017-06-07 14:52:50 -04007==========
dzc22b85a22017-05-31 20:37:50 +02008
Googlere7634412017-06-07 14:52:50 -04009In this tutorial, you'll learn the basics of building C++ applications with
10Bazel. You will set up your workspace and build a simple C++ project that
11illustrates key Bazel concepts, such as targets and `BUILD` files. After
12completing this tutorial, take a look at
Yves Junqueira83d0d902018-01-03 05:22:53 -080013[Common C++ Build Use Cases](../cpp-use-cases.md) for information on more advanced
Googlere7634412017-06-07 14:52:50 -040014concepts such as writing and running C++ tests.
dzc22b85a22017-05-31 20:37:50 +020015
Googlere7634412017-06-07 14:52:50 -040016Estimated completion time: 30 minutes.
dzc22b85a22017-05-31 20:37:50 +020017
Googlere7634412017-06-07 14:52:50 -040018## What you'll learn
dzc22b85a22017-05-31 20:37:50 +020019
Googlere7634412017-06-07 14:52:50 -040020In this tutorial you'll learn how to:
dzc22b85a22017-05-31 20:37:50 +020021
Googlere7634412017-06-07 14:52:50 -040022* Build a target
23* Visualize the project's dependencies
24* Split the project into multiple targets and packages
25* Control target visibility across packages
26* Reference targets through labels
dzc22b85a22017-05-31 20:37:50 +020027
Googler6c315782017-08-04 20:03:30 +020028## Contents
29
30* [Before you begin](#before-you-begin)
31 * [Install Bazel](#install-bazel)
32 * [Get the sample project](#get-the-sample-project)
33* [Build with Bazel](#build-with-bazel)
34 * [Set up the workspace](#set-up-the-workspace)
35 * [Understand the BUILD file](#understand-the-build-file)
36 * [Build the project](#build-the-project)
37 * [Review the dependency graph](#review-the-dependency-graph)
38* [Refine your Bazel build](#refine-your-bazel-build)
39 * [Specify multiple build targets](#specify-multiple-build-targets)
40 * [Use multiple packages](#use-multiple-packages)
41* [Use labels to reference targets](#use-labels-to-reference-targets)
42* [Further reading](#further-reading)
43
Googlere7634412017-06-07 14:52:50 -040044## Before you begin
dzc22b85a22017-05-31 20:37:50 +020045
dzc205125b2017-06-26 11:01:47 +020046To prepare for the tutorial, first [Install Bazel](../install.md) if
Googlere7634412017-06-07 14:52:50 -040047you don't have it installed already. Then, retrieve the sample project from
48Bazel's GitHub repository:
dzc22b85a22017-05-31 20:37:50 +020049
Googlere7634412017-06-07 14:52:50 -040050```
51git clone https://github.com/bazelbuild/examples/
52```
dzc22b85a22017-05-31 20:37:50 +020053
Googlere7634412017-06-07 14:52:50 -040054The sample project for this tutorial is in the `examples/cpp-tutorial` directory
55and is structured as follows:
dzc22b85a22017-05-31 20:37:50 +020056
dzc22b85a22017-05-31 20:37:50 +020057
Googlere7634412017-06-07 14:52:50 -040058```
59examples
60└── cpp-tutorial
61 ├──stage1
62 │ └── main
63 │   ├── BUILD
64 │   ├── hello-world.cc
65 │ └── WORKSPACE
66 ├──stage2
67 │ ├── main
68 │  │ ├── BUILD
69 │  │ ├── hello-world.cc
70 │  │   ├── hello-greet.cc
71 │  │   ├── hello-greet.h
72 │ └── WORKSPACE
73 └──stage3
74 ├── main
75   │ ├── BUILD
76   │ ├── hello-world.cc
77   │   ├── hello-greet.cc
78   │   └── hello-greet.h
79 ├── lib
80 │ ├── BUILD
81 │ ├── hello-time.cc
82 │ └── hello-time.h
83 └── WORKSPACE
84```
dzc22b85a22017-05-31 20:37:50 +020085
Googlere7634412017-06-07 14:52:50 -040086As you can see, there are three sets of files, each set representing a stage in
87this tutorial. In the first stage, you will build a single target residing in a
88single package. In the second stage, you will split your project into multiple
89targets but keep it in a single package. In the third and final stage, you will
90split your project into multiple packages and build it with multiple targets.
dzc22b85a22017-05-31 20:37:50 +020091
Googlere7634412017-06-07 14:52:50 -040092## Build with Bazel
dzc22b85a22017-05-31 20:37:50 +020093
Googlere7634412017-06-07 14:52:50 -040094### Set up the workspace
dzc22b85a22017-05-31 20:37:50 +020095
Googlere7634412017-06-07 14:52:50 -040096Before you can build a project, you need to set up its workspace. A workspace is
97a directory that holds your project's source files and Bazel's build outputs. It
98also contains files that Bazel recognizes as special:
dzc22b85a22017-05-31 20:37:50 +020099
Googlere7634412017-06-07 14:52:50 -0400100* The `WORKSPACE` file, which identifies the directory and its contents as a
101 Bazel workspace and lives at the root of the project's directory structure,
dzc22b85a22017-05-31 20:37:50 +0200102
Googlere7634412017-06-07 14:52:50 -0400103* One or more `BUILD` files, which tell Bazel how to build different parts of
104 the project. (A directory within the workspace that contains a `BUILD` file
105 is a *package*. You will learn about packages later in this tutorial.)
dzc22b85a22017-05-31 20:37:50 +0200106
Googlere7634412017-06-07 14:52:50 -0400107To designate a directory as a Bazel workspace, create an empty file named
108`WORKSPACE` in that directory.
dzc22b85a22017-05-31 20:37:50 +0200109
Googlere7634412017-06-07 14:52:50 -0400110When Bazel builds the project, all inputs and dependencies must be in the same
111workspace. Files residing in different workspaces are independent of one
112another unless linked, which is beyond the scope of this tutorial.
dzc22b85a22017-05-31 20:37:50 +0200113
Googlere7634412017-06-07 14:52:50 -0400114### Understand the BUILD file
dzc22b85a22017-05-31 20:37:50 +0200115
Googlere7634412017-06-07 14:52:50 -0400116A `BUILD` file contains several different types of instructions for Bazel.
117The most important type is the *build rule*, which tells Bazel how to build the
118desired outputs, such as executable binaries or libraries. Each instance
119of a build rule in the `BUILD` file is called a *target* and points to a
120specific set of source files and dependencies. A target can also point to other
121targets.
dzc22b85a22017-05-31 20:37:50 +0200122
Googlere7634412017-06-07 14:52:50 -0400123Take a look at the `BUILD` file in the `cpp-tutorial/stage1/main` directory:
dzc22b85a22017-05-31 20:37:50 +0200124
Googlere7634412017-06-07 14:52:50 -0400125```
126cc_binary(
127 name = "hello-world",
128 srcs = ["hello-world.cc"],
129)
130```
dzc22b85a22017-05-31 20:37:50 +0200131
Googlere7634412017-06-07 14:52:50 -0400132In our example, the `hello-world` target instantiates Bazel's built-in
Yi Cheng9e18b0a2017-08-09 10:34:27 +0200133[`cc_binary` rule](../be/c-cpp.html#cc_binary). The rule tells Bazel to build
Googlere7634412017-06-07 14:52:50 -0400134a self-contained executable binary from the `hello-world.cc` source file with no
135dependencies.
dzc22b85a22017-05-31 20:37:50 +0200136
Googlere7634412017-06-07 14:52:50 -0400137The attributes in the target explicitly state its dependencies and options.
138While the `name` attribute is mandatory, many are optional. For example, in the
Googlerc89a8ac2017-09-19 23:31:41 +0200139`hello-world` target, `name` is self-explanatory, and `srcs` specifies the
Googlere7634412017-06-07 14:52:50 -0400140source file(s) from which Bazel builds the target.
dzc22b85a22017-05-31 20:37:50 +0200141
Googlere7634412017-06-07 14:52:50 -0400142### Build the project
143
144Let's build your sample project. Change into the `cpp-tutorial/stage1` directory
145and run the following command:
146
147```
148bazel build //main:hello-world
149```
150
151Notice the target label - the `//main:` part is the location of our `BUILD`
152file relative to the root of the workspace, and `hello-world` is what we named
153that target in the `BUILD` file. (You will learn about target labels in more
154detail at the end of this tutorial.)
155
156Bazel produces output similar to the following:
157
158```
159INFO: Found 1 target...
160Target //main:hello-world up-to-date:
161 bazel-bin/main/hello-world
162INFO: Elapsed time: 2.267s, Critical Path: 0.25s
163```
164
165Congratulations, you just built your first Bazel target! Bazel places build
166outputs in the `bazel-bin` directory at the root of the workspace. Browse
167through its contents to get an idea for Bazel's output structure.
168
169Now test your freshly built binary:
170
dzc51dcd282017-06-14 22:52:27 +0200171```sh
Googlere7634412017-06-07 14:52:50 -0400172bazel-bin/main/hello-world
173```
174
175### Review the dependency graph
176
177A successful build has all of its dependencies explicitly stated in the `BUILD`
178file. Bazel uses those statements to create the project's dependency graph,
179which enables accurate incremental builds.
180
181Let's visualize our sample project's dependencies. First, generate a text
182representation of the dependency graph (run the command at the workspace root):
183
184```
185bazel query --nohost_deps --noimplicit_deps 'deps(//main:hello-world)' \
186 --output graph
187```
188
189The above command tells Bazel to look for all dependencies for the target
190`//main:hello-world` (excluding host and implicit dependencies) and format the
191output as a graph.
192
193Then, paste the text into [GraphViz](http://www.webgraphviz.com/).
194
Alexd21d5d62017-08-16 13:45:29 +0200195As you can see, the first stage of the sample project has a single target
Googlere7634412017-06-07 14:52:50 -0400196that builds a single source file with no additional dependencies:
197
198![Dependency graph for 'hello-world'](/assets/cpp-tutorial-stage1.png)
199
200Now that you have set up your workspace, built your project, and examined its
201dependencies, let's add some complexity.
202
203## Refine your Bazel build
204
205While a single target is sufficient for small projects, you may want to split
206larger projects into multiple targets and packages to allow for fast incremental
207builds (that is, only rebuild what's changed) and to speed up your builds by
208building multiple parts of a project at once.
209
210### Specify multiple build targets
211
212Let's split our sample project build into two targets. Take a look at the
213`BUILD` file in the `cpp-tutorial/stage2/main` directory:
214
215```
dzc22b85a22017-05-31 20:37:50 +0200216cc_library(
217 name = "hello-greet",
218 srcs = ["hello-greet.cc"],
219 hdrs = ["hello-greet.h"],
dzc22b85a22017-05-31 20:37:50 +0200220)
221
222cc_binary(
223 name = "hello-world",
224 srcs = ["hello-world.cc"],
225 deps = [
Googlere7634412017-06-07 14:52:50 -0400226 ":hello-greet",
dzc22b85a22017-05-31 20:37:50 +0200227 ],
228)
Googlere7634412017-06-07 14:52:50 -0400229```
dzc22b85a22017-05-31 20:37:50 +0200230
Googlere7634412017-06-07 14:52:50 -0400231With this `BUILD` file, Bazel first builds the `hello-greet` library
Yi Cheng9e18b0a2017-08-09 10:34:27 +0200232(using Bazel's built-in [`cc_library` rule](../be/c-cpp.html#cc_library),
Googlere7634412017-06-07 14:52:50 -0400233then the `hello-world` binary. The `deps` attribute in the `hello-world` target
234tells Bazel that the `hello-greet` library is required to build the `hello-world`
235binary.
dzc22b85a22017-05-31 20:37:50 +0200236
Googlere7634412017-06-07 14:52:50 -0400237Let's build this new version of our project. Change into the
238`cpp-tutorial/stage2` directory and run the following command:
dzc22b85a22017-05-31 20:37:50 +0200239
Googlere7634412017-06-07 14:52:50 -0400240```
241bazel build //main:hello-world
242```
dzc22b85a22017-05-31 20:37:50 +0200243
Googlere7634412017-06-07 14:52:50 -0400244Bazel produces output similar to the following:
dzc22b85a22017-05-31 20:37:50 +0200245
Googlere7634412017-06-07 14:52:50 -0400246```
dzc22b85a22017-05-31 20:37:50 +0200247INFO: Found 1 target...
248Target //main:hello-world up-to-date:
249 bazel-bin/main/hello-world
Googlere7634412017-06-07 14:52:50 -0400250INFO: Elapsed time: 2.399s, Critical Path: 0.30s
251```
dzc22b85a22017-05-31 20:37:50 +0200252
Googlere7634412017-06-07 14:52:50 -0400253Now test your freshly built binary:
dzc22b85a22017-05-31 20:37:50 +0200254
Googlere7634412017-06-07 14:52:50 -0400255```
256bazel-bin/main/hello-world
257```
dzc22b85a22017-05-31 20:37:50 +0200258
Googlere7634412017-06-07 14:52:50 -0400259If you now modify `hello-greet.cc` and rebuild the project, Bazel will
260only recompile that file.
dzc22b85a22017-05-31 20:37:50 +0200261
Googlere7634412017-06-07 14:52:50 -0400262Looking at the dependency graph, you can see that `hello-world` depends on the
263same inputs as it did before, but the structure of the build is different:
dzc22b85a22017-05-31 20:37:50 +0200264
Googlere7634412017-06-07 14:52:50 -0400265![Dependency graph for 'hello-world'](/assets/cpp-tutorial-stage2.png)
dzc22b85a22017-05-31 20:37:50 +0200266
Googlere7634412017-06-07 14:52:50 -0400267You've now built the project with two targets. The `hello-world` target builds
268one source file and depends on one other target (`//main:hello-greet`), which
269builds two additional source files.
dzc22b85a22017-05-31 20:37:50 +0200270
Googlere7634412017-06-07 14:52:50 -0400271### Use multiple packages
dzc22b85a22017-05-31 20:37:50 +0200272
Googlere7634412017-06-07 14:52:50 -0400273Lets now split the project into multiple packages. Take a look at the contents
274of the `cpp-tutorial/stage3` directory:
dzc22b85a22017-05-31 20:37:50 +0200275
Googlere7634412017-06-07 14:52:50 -0400276```
277└──stage3
278 ├── main
279   │ ├── BUILD
280   │ ├── hello-world.cc
281   │   ├── hello-greet.cc
282   │   └── hello-greet.h
283 ├── lib
284 │ ├── BUILD
285 │ ├── hello-time.cc
286 │ └── hello-time.h
287 └── WORKSPACE
288```
289Notice that we now have two sub-directories, and each contains a `BUILD` file.
290Therefore, to Bazel, the workspace now contains two packages, `lib` and `main`.
291
292Take a look at the `lib/BUILD` file:
dzc22b85a22017-05-31 20:37:50 +0200293
294```python
295cc_library(
Googlere7634412017-06-07 14:52:50 -0400296 name = "hello-time",
297 srcs = ["hello-time.cc"],
298 hdrs = ["hello-time.h"],
299 visibility = ["//main:__pkg__"],
dzc22b85a22017-05-31 20:37:50 +0200300)
301```
302
Googlere7634412017-06-07 14:52:50 -0400303And at the `main/BUILD` file:
dzc22b85a22017-05-31 20:37:50 +0200304
305```python
306cc_library(
Googlere7634412017-06-07 14:52:50 -0400307 name = "hello-greet",
308 srcs = ["hello-greet.cc"],
309 hdrs = ["hello-greet.h"],
dzc22b85a22017-05-31 20:37:50 +0200310)
dzc22b85a22017-05-31 20:37:50 +0200311
Googlere7634412017-06-07 14:52:50 -0400312cc_binary(
313 name = "hello-world",
314 srcs = ["hello-world.cc"],
dzc22b85a22017-05-31 20:37:50 +0200315 deps = [
Googlere7634412017-06-07 14:52:50 -0400316 ":hello-greet",
317 "//lib:hello-time",
dzc22b85a22017-05-31 20:37:50 +0200318 ],
319)
320```
321
Googlere7634412017-06-07 14:52:50 -0400322As you can see, the `hello-world` target in the `main` package depends on the
323`hello-time` target in the `lib` package (hence the target label
324`//lib:hello-time`) - Bazel knows this through the `deps` attribute. Take a look
325at the dependency graph:
dzc22b85a22017-05-31 20:37:50 +0200326
Googlere7634412017-06-07 14:52:50 -0400327![Dependency graph for 'hello-world'](/assets/cpp-tutorial-stage3.png)
dzc22b85a22017-05-31 20:37:50 +0200328
Googlere7634412017-06-07 14:52:50 -0400329Notice that for the build to succeed, we make the `//lib:hello-time` target in
330`lib/BUILD` explicitly visible to targets in `main/BUILD` using the `visibility`
331attribute. This is because by default targets are only visible to other targets
332in the same `BUILD` file. (Bazel uses target visibility to prevent issues such
333as libraries containing implementation details leaking into public APIs.)
dzc22b85a22017-05-31 20:37:50 +0200334
Googlere7634412017-06-07 14:52:50 -0400335Let's build this final version of our project. Change into the
336`cpp-tutorial/stage3` directory and run the following command:
dzc22b85a22017-05-31 20:37:50 +0200337
Googlere7634412017-06-07 14:52:50 -0400338```
339bazel build //main:hello-world
dzc22b85a22017-05-31 20:37:50 +0200340```
341
Googlere7634412017-06-07 14:52:50 -0400342Bazel produces output similar to the following:
343
344```
345INFO: Found 1 target...
346Target //main:hello-world up-to-date:
347 bazel-bin/main/hello-world
348INFO: Elapsed time: 0.167s, Critical Path: 0.00s
349```
350
351Now test the freshly built binary:
352
353```
354bazel-bin/main/hello-world
355```
356
357You've now built the project as two packages with three targets and understand
358the dependencies between them.
359
360## Use labels to reference targets
361
362In `BUILD` files and at the command line, Bazel uses *labels* to reference
363targets - for example, `//main:hello-world` or `//lib:hello-time`. Their syntax
364is:
365
366```
367//path/to/package:target-name
368```
369
370If the target is a rule target, then `path/to/package` is the path to the
371directory containing the `BUILD` file, and `target-name` is what you named the
372target in the `BUILD` file (the `name` attribute). If the target is a file
373target, then `path/to/package` is the path to the root of the package, and
374`target-name` is the name of the target file, including its full path.
375
376When referencing targets within the same package, you can skip the package path
377and just use `//:target-name`. When referencing targets within the same `BUILD`
378file, you can even skip the `//` workspace root identifier and just use
379`:target-name`.
380
381
382## Further reading
383
384Congratulations! You now know the basics of building a C++ project with Bazel.
Googler44f3a3f2017-12-11 08:40:40 -0800385Next, read up on the most common [C++ build use cases](../cpp-use-cases.md).
386Then, check out the following:
Googlere7634412017-06-07 14:52:50 -0400387
dzc205125b2017-06-26 11:01:47 +0200388* [External Dependencies](../external.html) to learn more about working with
389 local and remote repositories.
Googlere7634412017-06-07 14:52:50 -0400390
dzc205125b2017-06-26 11:01:47 +0200391* The [Build Encyclopedia](../be/overview.html) to learn more about Bazel.
Googlere7634412017-06-07 14:52:50 -0400392
dzc205125b2017-06-26 11:01:47 +0200393* The [Java build tutorial](java.md) to get started with
Googlere7634412017-06-07 14:52:50 -0400394 building Java applications with Bazel.
395
dzc205125b2017-06-26 11:01:47 +0200396* The [mobile application tutorial](app.md) to get started with
Googlere7634412017-06-07 14:52:50 -0400397 building mobile applications for Android and iOS with Bazel.
398
399Happy building!