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