• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Abseil FAQ
2
3## Is Abseil the right home for my utility library?
4
5Most often the answer to the question is "no." As both the [About
6Abseil](https://abseil.io/about/) page and our [contributing
7guidelines](https://github.com/abseil/abseil-cpp/blob/master/CONTRIBUTING.md#contribution-guidelines)
8explain, Abseil contains a variety of core C++ library code that is widely used
9at [Google](https://www.google.com/). As such, Abseil's primary purpose is to be
10used as a dependency by Google's open source C++ projects. While we do hope that
11Abseil is also useful to the C++ community at large, this added constraint also
12means that we are unlikely to accept a contribution of utility code that isn't
13already widely used by Google.
14
15## How to I set the C++ dialect used to build Abseil?
16
17The short answer is that whatever mechanism you choose, you need to make sure
18that you set this option consistently at the global level for your entire
19project. If, for example, you want to set the C++ dialect to C++17, with
20[Bazel](https://bazel/build/) as the build system and `gcc` or `clang` as the
21compiler, there several ways to do this:
22* Pass `--cxxopt=-std=c++17` on the command line (for example, `bazel build
23  --cxxopt=-std=c++17 ...`)
24* Set the environment variable `BAZEL_CXXOPTS` (for example,
25  `BAZEL_CXXOPTS=-std=c++17`)
26* Add `build --cxxopt=-std=c++17` to your [`.bazelrc`
27  file](https://docs.bazel.build/versions/master/guide.html#bazelrc)
28
29If you are using CMake as the build system, you'll need to add a line like
30`set(CMAKE_CXX_STANDARD 17)` to your top level `CMakeLists.txt` file. See the
31[CMake build
32instructions](https://github.com/abseil/abseil-cpp/blob/master/CMake/README.md)
33for more information.
34
35For a longer answer to this question and to understand why some other approaches
36don't work, see the answer to ["What is ABI and why don't you recommend using a
37pre-compiled version of
38Abseil?"](#what-is-abi-and-why-dont-you-recommend-using-a-pre-compiled-version-of-abseil)
39
40## What is ABI and why don't you recommend using a pre-compiled version of Abseil?
41
42For the purposes of this discussion, you can think of
43[ABI](https://en.wikipedia.org/wiki/Application_binary_interface) as the
44compiled representation of the interfaces in code. This is in contrast to
45[API](https://en.wikipedia.org/wiki/Application_programming_interface), which
46you can think of as the interfaces as defined by the code itself. [Abseil has a
47strong promise of API compatibility, but does not make any promise of ABI
48compatibility](https://abseil.io/about/compatibility). Let's take a look at what
49this means in practice.
50
51You might be tempted to do something like this in a
52[Bazel](https://bazel.build/) `BUILD` file:
53
54```
55# DON'T DO THIS!!!
56cc_library(
57    name = "my_library",
58    srcs = ["my_library.cc"],
59    copts = ["-std=c++17"],  # May create a mixed-mode compile!
60    deps = ["@com_google_absl//absl/strings"],
61)
62```
63
64Applying `-std=c++17` to an individual target in your `BUILD` file is going to
65compile that specific target in C++17 mode, but it isn't going to ensure the
66Abseil library is built in C++17 mode, since the Abseil library itself is a
67different build target. If your code includes an Abseil header, then your
68program may contain conflicting definitions of the same
69class/function/variable/enum, etc. As a rule, all compile options that affect
70the ABI of a program need to be applied to the entire build on a global basis.
71
72C++ has something called the [One Definition
73Rule](https://en.wikipedia.org/wiki/One_Definition_Rule) (ODR). C++ doesn't
74allow multiple definitions of the same class/function/variable/enum, etc. ODR
75violations sometimes result in linker errors, but linkers do not always catch
76violations. Uncaught ODR violations can result in strange runtime behaviors or
77crashes that can be hard to debug.
78
79If you build the Abseil library and your code using different compile options
80that affect ABI, there is a good chance you will run afoul of the One Definition
81Rule. Examples of GCC compile options that affect ABI include (but aren't
82limited to) language dialect (e.g. `-std=`), optimization level (e.g. `-O2`),
83code generation flags (e.g. `-fexceptions`), and preprocessor defines
84(e.g. `-DNDEBUG`).
85
86If you use a pre-compiled version of Abseil, (for example, from your Linux
87distribution package manager or from something like
88[vcpkg](https://github.com/microsoft/vcpkg)) you have to be very careful to
89ensure ABI compatibility across the components of your program. The only way you
90can be sure your program is going to be correct regarding ABI is to ensure
91you've used the exact same compile options as were used to build the
92pre-compiled library. This does not mean that Abseil cannot work as part of a
93Linux distribution since a knowledgeable binary packager will have ensured that
94all packages have been built with consistent compile options. This is one of the
95reasons we warn against - though do not outright reject - using Abseil as a
96pre-compiled library.
97
98Another possible way that you might afoul of ABI issues is if you accidentally
99include two versions of Abseil in your program. Multiple versions of Abseil can
100end up within the same binary if your program uses the Abseil library and
101another library also transitively depends on Abseil (resulting in what is
102sometimes called the diamond dependency problem). In cases such as this you must
103structure your build so that all libraries use the same version of Abseil.
104[Abseil's strong promise of API compatibility between
105releases](https://abseil.io/about/compatibility) means the latest "HEAD" release
106of Abseil is almost certainly the right choice if you are doing as we recommend
107and building all of your code from source.
108
109For these reasons we recommend you avoid pre-compiled code and build the Abseil
110library yourself in a consistent manner with the rest of your code.
111
112## What is "live at head" and how do I do it?
113
114From Abseil's point-of-view, "live at head" means that every Abseil source
115release (which happens on an almost daily basis) is either API compatible with
116the previous release, or comes with an automated tool that you can run over code
117to make it compatible. In practice, the need to use an automated tool is
118extremely rare. This means that upgrading from one source release to another
119should be a routine practice that can and should be performed often.
120
121We recommend you update to the [latest commit in the `master` branch of
122Abseil](https://github.com/abseil/abseil-cpp/commits/master) as often as
123possible. Not only will you pick up bug fixes more quickly, but if you have good
124automated testing, you will catch and be able to fix any [Hyrum's
125Law](https://www.hyrumslaw.com/) dependency problems on an incremental basis
126instead of being overwhelmed by them and having difficulty isolating them if you
127wait longer between updates.
128
129If you are using the [Bazel](https://bazel.build/) build system and its
130[external dependencies](https://docs.bazel.build/versions/master/external.html)
131feature, updating the
132[`http_archive`](https://docs.bazel.build/versions/master/repo/http.html#http_archive)
133rule in your
134[`WORKSPACE`](https://docs.bazel.build/versions/master/be/workspace.html) for
135`com_google_abseil` to point to the [latest commit in the `master` branch of
136Abseil](https://github.com/abseil/abseil-cpp/commits/master) is all you need to
137do. For example, on February 11, 2020, the latest commit to the master branch
138was `98eb410c93ad059f9bba1bf43f5bb916fc92a5ea`. To update to this commit, you
139would add the following snippet to your `WORKSPACE` file:
140
141```
142http_archive(
143  name = "com_google_absl",
144  urls = ["https://github.com/abseil/abseil-cpp/archive/98eb410c93ad059f9bba1bf43f5bb916fc92a5ea.zip"],  # 2020-02-11T18:50:53Z
145  strip_prefix = "abseil-cpp-98eb410c93ad059f9bba1bf43f5bb916fc92a5ea",
146  sha256 = "aabf6c57e3834f8dc3873a927f37eaf69975d4b28117fc7427dfb1c661542a87",
147)
148```
149
150To get the `sha256` of this URL, run `curl -sL --output -
151https://github.com/abseil/abseil-cpp/archive/98eb410c93ad059f9bba1bf43f5bb916fc92a5ea.zip
152| sha256sum -`.
153
154You can commit the updated `WORKSPACE` file to your source control every time
155you update, and if you have good automated testing, you might even consider
156automating this.
157
158One thing we don't recommend is using GitHub's `master.zip` files (for example
159[https://github.com/abseil/abseil-cpp/archive/master.zip](https://github.com/abseil/abseil-cpp/archive/master.zip)),
160which are always the latest commit in the `master` branch, to implement live at
161head. Since these `master.zip` URLs are not versioned, you will lose build
162reproducibility. In addition, some build systems, including Bazel, will simply
163cache this file, which means you won't actually be updating to the latest
164release until your cache is cleared or invalidated.
165