blob: 3566dc9f3a9c13296e632c778cb05377b9e6f34f [file] [log] [blame] [view]
Kristina Chodorowc1411502015-04-29 16:32:06 +00001---
2layout: documentation
3---
4
Googler3fb27ca2015-04-30 21:38:04 +00005C++ Basics
6==========
7
Kristina Chodorowc1411502015-04-29 16:32:06 +00008Use fully qualified include paths
Googler3fb27ca2015-04-30 21:38:04 +00009---------------------------------
Kristina Chodorowc1411502015-04-29 16:32:06 +000010
11Includes are relative to the root of your workspace. For example, suppose
12you have the following directory structure:
13
14```
15[workspace]/
16 WORKSPACE
17 a/
18 BUILD
19 a.h
20 a.cc
21 b/
22 BUILD
23 b.h
24 b.cc
25 main.cc
26```
27
David Chen62d200c2015-06-19 10:08:58 +000028If `b/main.cc` needs to include b.h then we'd create the following `b/BUILD`
Kristina Chodorowc1411502015-04-29 16:32:06 +000029file:
30
31```python
32cc_library(
33 name = "b",
34 srcs = ["b.cc"],
35 hdrs = ["b.h"],
36)
37
38cc_binary(
39 name = "main",
40 srcs = ["main.cc"],
41 deps = [":b"],
42)
43```
44
David Chen62d200c2015-06-19 10:08:58 +000045`b/main.cc` would have the following include statement:
Kristina Chodorowc1411502015-04-29 16:32:06 +000046
47```cpp
48#include "b/b.h"
49```
50
David Chen62d200c2015-06-19 10:08:58 +000051Note that the full path from the package root is used. If we want `b/main.cc` to
52also depend on `a/a.h`, we'd add the rule to `a/BUILD`:
Kristina Chodorowc1411502015-04-29 16:32:06 +000053
54```python
55cc_library(
56 name = "a",
57 srcs = ["a.cc"],
58 hdrs = ["a.h"],
59 visibility = ["//b:__pkg__"],
60)
61```
62
David Chen62d200c2015-06-19 10:08:58 +000063Then we'd add a dependency to `b/BUILD`:
Kristina Chodorowc1411502015-04-29 16:32:06 +000064
65```python
66cc_binary(
67 name = "main",
68 srcs = ["main.cc"],
69 deps = [
70 ":b",
71 "//a",
72 ],
73)
74```
75
David Chen62d200c2015-06-19 10:08:58 +000076And the following include to `b/main.cc`:
Kristina Chodorowc1411502015-04-29 16:32:06 +000077
78```cpp
79#include "a/a.h"
80```
81
David Chen62d200c2015-06-19 10:08:58 +000082`b/main.cc` will then be able to access symbols from `a/a.h` or `b/b.h`.
Kristina Chodorowc1411502015-04-29 16:32:06 +000083
84Transitive includes
Googler3fb27ca2015-04-30 21:38:04 +000085-------------------
Kristina Chodorowc1411502015-04-29 16:32:06 +000086
87If a file includes a header then the file's rule should depend on that header's
88library. Conversely, only direct dependencies need to be specified as
David Chen62d200c2015-06-19 10:08:58 +000089dependencies. For example, suppose `sandwich.h` includes `bread.h` and
90`bread.h` includes `flour.h`. `sandwich.h` doesn't include `flour.h` (who wants
Kristina Chodorowc1411502015-04-29 16:32:06 +000091flour in their sandwich?), so the BUILD file would look like:
92
93```python
94cc_library(
95 name = "sandwich",
96 srcs = ["sandwich.cc"],
97 hdrs = ["sandwich.h"],
98 deps = [":bread"],
99)
100
101cc_library(
102 name = "bread",
103 srcs = ["bread.cc"],
104 hdrs = ["bread.h"],
105 deps = [":flour"],
106)
107
108cc_library(
109 name = "flour",
110 srcs = ["flour.cc"],
111 hdrs = ["flour.h"],
112)
113```
114
David Chen3f16b562015-07-23 15:04:50 +0000115This expresses that the `sandwich` library depends on the `bread` library,
116which depends on the `flour` library.
Kristina Chodorowc1411502015-04-29 16:32:06 +0000117
118Adding include paths
Googler3fb27ca2015-04-30 21:38:04 +0000119--------------------
Kristina Chodorowc1411502015-04-29 16:32:06 +0000120
121Sometimes you cannot (or do not want to) base include paths at the workspace
122root. Existing libaries might already have a include directory that doesn't
123match its path in your workspace. For example, suppose you have the following
124directory structure:
125
126```
127[workspace]/
128 WORKSPACE
129 third_party/
130 some_lib/
131 include/
132 some_lib.h
133 BUILD
134 some_lib.cc
135```
136
David Chen62d200c2015-06-19 10:08:58 +0000137Bazel will expect `some_lib.h` to be included as
138`third_party/some_lib/include/some_lib.h`, but suppose `some_lib.cc` includes
Kristina Chodorowc1411502015-04-29 16:32:06 +0000139`"include/some_lib.h"`. To make that include path valid,
David Chen62d200c2015-06-19 10:08:58 +0000140`third_party/some_lib/BUILD` will need to specify that the `some_lib/`
Kristina Chodorowc1411502015-04-29 16:32:06 +0000141directory is an include directory:
142
143```python
144cc_library(
145 name = "some_lib",
146 srcs = ["some_lib.cc"],
147 hdrs = ["some_lib.h"],
Kristina Chodorowc97ee9c2015-10-08 14:58:34 +0000148 copts = ["-Ithird_party/some_lib"],
Kristina Chodorowc1411502015-04-29 16:32:06 +0000149)
150```
151
152This is especially useful for external dependencies, as their header files
David Chen62d200c2015-06-19 10:08:58 +0000153must otherwise be included with an `external/[repository-name]/` prefix.
Kristina Chodorowc1411502015-04-29 16:32:06 +0000154
155Including external libraries: an example
Googler3fb27ca2015-04-30 21:38:04 +0000156----------------------------------------
Kristina Chodorowc1411502015-04-29 16:32:06 +0000157
158Suppose you are using [Google Test](https://code.google.com/p/googletest/). You
David Chen62d200c2015-06-19 10:08:58 +0000159can use one of the `new_` repository functions in the `WORKSPACE` file to
Kristina Chodorow1b99f1b2015-05-08 13:34:43 +0000160download Google Test and make it available in your repository:
Kristina Chodorowc1411502015-04-29 16:32:06 +0000161
162```python
163new_http_archive(
Kristina Chodorow0f85e102015-05-22 14:03:02 +0000164 name = "gtest",
Kristina Chodorowc1411502015-04-29 16:32:06 +0000165 url = "https://googletest.googlecode.com/files/gtest-1.7.0.zip",
166 sha256 = "247ca18dd83f53deb1328be17e4b1be31514cedfc1e3424f672bf11fd7e0d60d",
167 build_file = "gtest.BUILD",
168)
Kristina Chodorowc1411502015-04-29 16:32:06 +0000169```
170
David Chen62d200c2015-06-19 10:08:58 +0000171Then create `gtest.BUILD`, a BUILD file to use to compile Google Test.
Kristina Chodorow1b99f1b2015-05-08 13:34:43 +0000172Google Test has several "special" requirements that make its `cc_library` rule
Kristina Chodorowc1411502015-04-29 16:32:06 +0000173more complicated:
174
David Chen62d200c2015-06-19 10:08:58 +0000175* `gtest-1.7.0/src/gtest-all.cc` `#include`s all of the other files in
176 `gtest-1.7.0/src/`, so we need to exclude it from the compile or we'll get
Kristina Chodorow4f806b52015-05-18 15:35:17 +0000177 link errors for duplicate symbols.
David Chen62d200c2015-06-19 10:08:58 +0000178* It uses header files that relative to the `gtest-1.7.0/include/` directory
Kristina Chodorowc97ee9c2015-10-08 14:58:34 +0000179 (`"gtest/gtest.h"`), so we must add that directory the include paths.
180* It uses "private" header files in `src/`, so we add that to the include pahs,
181 too, so it can `#include "src/gtest-internal-inl.h"`.
Kristina Chodorowc1411502015-04-29 16:32:06 +0000182* It needs to link in pthread, so we add that as a `linkopt`.
183
184The final rule looks like this:
185
186```python
187cc_library(
188 name = "main",
189 srcs = glob(
Kristina Chodorow4f806b52015-05-18 15:35:17 +0000190 ["gtest-1.7.0/src/*.cc"],
191 exclude = ["gtest-1.7.0/src/gtest-all.cc"]
Kristina Chodorowc1411502015-04-29 16:32:06 +0000192 ),
Kristina Chodorow4f806b52015-05-18 15:35:17 +0000193 hdrs = glob(["gtest-1.7.0/include/**/*.h"]),
Kristina Chodorowc97ee9c2015-10-08 14:58:34 +0000194 copts = [
195 "-Iexternal/gtest/gtest-1.7.0",
196 "-Iexternal/gtest/gtest-1.7.0/include"
Kristina Chodorowc1411502015-04-29 16:32:06 +0000197 ],
198 linkopts = ["-pthread"],
199 visibility = ["//visibility:public"],
200)
201```
202
Kristina Chodorow443db5c2015-09-28 14:22:34 +0000203This is somewhat messy: everything is prefixed with gtest-1.7.0 as a byproduct
204of the archive's structure. You can make `new_http_archive` strip this prefix by
205adding the `strip_prefix` attribute:
206
207```python
208new_http_archive(
209 name = "gtest",
210 url = "https://googletest.googlecode.com/files/gtest-1.7.0.zip",
211 sha256 = "247ca18dd83f53deb1328be17e4b1be31514cedfc1e3424f672bf11fd7e0d60d",
212 build_file = "gtest.BUILD",
213 strip_prefix = "gtest-1.7.0",
214)
215```
216
217Then `gtest.BUILD` would look like this:
218
219```python
220cc_library(
221 name = "main",
222 srcs = glob(
223 ["src/*.cc"],
224 exclude = ["src/gtest-all.cc"]
225 ),
226 hdrs = glob(["include/**/*.h"]),
Kristina Chodorowc97ee9c2015-10-08 14:58:34 +0000227 copts = [
228 "-Iexternal/gtest",
229 "-Iexternal/gtest/include"
Kristina Chodorow443db5c2015-09-28 14:22:34 +0000230 ],
231 linkopts = ["-pthread"],
232 visibility = ["//visibility:public"],
233)
234```
235
Kristina Chodorowc1411502015-04-29 16:32:06 +0000236Now `cc_` rules can depend on `//external:gtest/main`.
237
238For example, we could create a test such as:
239
240```cpp
241#include "gtest/gtest.h"
242
243TEST(FactorialTest, Negative) {
244 EXPECT_EQ(1, 1);
245}
246```
247
248Then create a BUILD file for your tests:
249
250```python
251cc_test(
252 name = "my_test",
253 srcs = ["my_test.cc"],
Kristina Chodorowc97ee9c2015-10-08 14:58:34 +0000254 copts = ["-Iexternal/gtest"],
Kristina Chodorow0f85e102015-05-22 14:03:02 +0000255 deps = ["@gtest//:main"],
Kristina Chodorowc1411502015-04-29 16:32:06 +0000256)
257```
258
259You can then use `bazel test` to run the test.
Kristina Chodorow0efd26f2015-05-29 14:11:41 +0000260
261
262Adding dependencies on precompiled libraries
263--------------------------------------------
264
265If you want to use a library that you only have a compiled version of (e.g.,
266headers and a .so) wrap it in a `cc_library` rule:
267
268```python
269cc_library(
270 name = "mylib",
271 srcs = ["mylib.so"],
272 hdrs = ["mylib.h"],
273)
274```
275
276Then other C++ targets in your workspace can depend on this rule.