Abseil Compatibility Guidelines
Abseil launched on September, 2017, and the guidelines spelled
out below became effective on November 1, 2017. Any new APIs we release
will have these requirements waived for a period of 30 days, though we will make
a best effort to adhere to these guidelines as we resolve any issues with the
new APIs.
This document details what we expect from well-behaved users, and what
we will offer in exchange. Any usage of Abseil libraries outside of
these technical boundaries may result in breakage when upgrading to
newer versions of Abseil.
Put another way: don’t do things that make Abseil API maintenance
tasks harder, and we promise not to break you if at all possible. If
you misuse Abseil APIs, you’re on your own.
What Users Must (And Must Not) Do
- Do not depend on a compiled representation of Abseil. We do not
promise any ABI compatibility — we intend for Abseil to be
built from source, hopefully from head. The internal layout of our
types may change at any point, without notice. Building Abseil in
the presence of different C++ standard library types may change
Abseil types, especially for pre-adopted types (string_view,
variant, etc) — these will become typedefs and their ABI will
change accordingly.
- Run Tooling / Follow Directions when Updating. We will always
strive to not break API compatibility. If we feel that we must, we
will provide a compiler-based refactoring tool to assist in the
upgrade, along with directions for how to execute the update. Most
often these happen in the form: update to version N (where old and
new APIs co-exist), run tool to convert between old and new APIs. In
the rare instance where tooling cannot be produced, we’ll provide as
much information as we can about what to look for and how to resolve
issues. (Remember: any time we are making a change publicly we’re
also doing the work to update the 250MLoC+ internal Google codebase
— we very rarely do such refactoring that cannot be
automated.)
- Do not rely on dynamic unloading. We consistently use patterns
that may not be friendly to dynamic unloading of shared libraries.
We make no claims that any of this code is usable in a system with
regular unloading of such libraries.
- Not all Abseil libraries are suitable for dynamic loading. Some
libraries have startup/initialization requirements and may not be
suitable for dynamic loading. We will try to be clear about which
libraries are OK for dynamic loading. However we don’t generally
deploy code in this fashion, mistakes are possible, and the normal
argument of “This code is production hardened” does not apply in
such usage.
- You may not open namespace
absl
. You are not allowed to define
additional names in namespace absl
, nor are you allowed to
specialize anything we provide. We expect there may eventually be
templates that are valid extension points provided by Abseil —
there are not currently. (This is similar to the restriction in the
C++ standard — there are very few things you are allowed to do
in namespace std
.)
- You may not depend on the signatures of Abseil APIs. You cannot
take the address of APIs in Abseil (that would prevent us from
adding overloads without breaking you). You cannot use
metaprogramming tricks to depend on those signatures either. (This
is also similar to the restrictions in the C++ standard.)
- You may not forward declare Abseil APIs. This is actually a
sub-point of “do not depend on the signatures of Abseil APIs” as
well as “do not open namespace
absl
”, but can be surprising. Any
refactoring that changes template parameters, default parameters, or
namespaces will be a breaking change in the face of
forward-declarations.
- Avoid unnecessary dependency on Argument-Dependent Lookup (ADL)
when calling Abseil APIs. Some APIs are designed to work via ADL
(e.g.
operator<<
for iostreams, unqualified swap
in generic
code, etc.) For most APIs, however, ADL is not part of the design.
Calling functions from namespace absl
via ADL, unless that is
explicitly intended as part of the design, should be avoided.
This is especially true for any function that accepts a pre-adopted
type like absl::string_view
: when the type changes to utilize the
std
version, its associated namespace will change and ADL will
fail, resulting in build breaks. More generally: just don’t do it,
we may need to shift things around internally, so please don’t
depend on namespace details.
- Do not depend upon internal details. This should go without
saying: if something is in a namespace or filename/path that
includes the word “internal”, you are not allowed to depend upon it.
It’s an implementation detail. You cannot friend it, you cannot
include it, you cannot mention it or refer to it in any way.
- Include What You Use. We may make changes to the internal
#include
graph for Abseil headers - if you use an API, please include the relevant
header file directly.
- Do not make unqualified calls in the global namespace. A call like
f(a);
for a function f
in the global namespace can become ambiguous if/when we add
absl::f
(especially if a
is an Abseil type). We generally do not recommend
you use the global namespace for anything. If you must, please qualify any
call that accepts a type provided by Abseil.
What We Promise
- We will support our code for at least 5 years. We will support language
versions, compilers, platforms, and workarounds as needed for 5 years after
their replacement is available, when possible. If it is technically
infeasible (such as support for MSVC before 2015, which has limited C++11
functionality), those will be noted specifically. After 5 years we will stop
support and may remove workarounds.
ABSL_HAVE_THREAD_LOCAL
is a good
example: the base language feature works on everything except Xcode prior to
Xcode 8 ; once Xcode 8 is out for 5 years, we will drop that workaround
support.
- We will not break API compatibility. If we must, we will ship a tool to
automate the upgrade to a preferred API. We will never break that API in a
single change - we believe in non-atomic refactoring. We will introduce the
new API and the tool, wait some time, and then remove the old.
- We promise to provide good forward-compatibility with the C++ standard.
- We promise at least the basic-exception guarantee. Although Google is
part of the minority of the C++ community that doesn’t use exceptions, we
recognize that it is a minority and believe that code is often better
when it’s exception-safe. We’ve done our best to make things exception-safe.
However, we won’t contort things to support all possible exceptions —
if you have a hash functor or
operator==
that throws, we may just mark it
noexcept
instead.