Abseil C++ Library

repository·master·Indexed 12 days ago

https://github.com/abseil/abseil-cpp

An open-source collection of C++17 compliant libraries designed to augment the C++ standard library. It provides high-performance containers, synchronization primitives, and error-handling abstractions used within Google's codebase. Supports build systems including Bazel and CMake, and provides modules for strings, time, hashing, and more.

Tokens
3.6K
Snippets
8
Records
13
Agent score
94%

What's inside Abseil

  1. Overview of Abseil C++ library components

    master

    Abseil is a collection of C++17 compliant libraries designed to augment the C++ standard library. The components are organized into several modules:

    • base: Low-level initialization and foundational code. Code in base has no dependencies other than the C++ standard library.
    • algorithm: Additions to <algorithm> and container-based algorithms.
    • cleanup: Provides absl::Cleanup for executing callbacks on scope exit.
    • container: STL-style containers, including the high-performance "Swiss table" containers.
    • crc: Cyclic redundancy checks (CRC) for error detection.
    • debugging: Leak checks, stacktrace, and symbolization utilities.
    • flags: Command line flag handling for libraries and binaries.
    • hash: Hashing framework and default hash functors.
    • log: LOG and CHECK macros for logging to disk, stderr, or extensible destinations.
    • memory: Memory management utilities augmenting <memory>.
    • meta: Type checks similar to <type_traits>.
    • numeric: 128-bit integer types and C++20 bitwise math functions.
    • profiling: Profiling utilities (currently a private dependency of other Abseil libraries).
    • random: Pseudorandom value generation.
    • status: Error handling via absl::Status and absl::StatusOr<T>.
    • strings: String manipulation routines and utilities.
    • synchronization: Concurrency primitives like absl::Mutex and other synchronization abstractions.
    • time: Absolute time points, durations, and time zone formatting/parsing.
    • types: Non-container utility types.
    • utility: General helper code.
  2. Abseil release and update strategy

    master

    Abseil follows a "live-at-head" philosophy, meaning it is recommended to update to the latest commit from the master branch as frequently as possible.

    For projects that cannot follow this approach, Abseil provides Long Term Support (LTS) Releases where severe bug fixes are backported. Detailed information on release management can be found in the Abseil release management documentation.

  3. Understand Abseil hash table randomization

    master

    Abseil hash tables use a random seed to prevent dependencies on iteration order (Hyrum's Law).

    Key considerations:

    • Not for security: The hash function prioritizes speed and is not cryptographically secure. It is not a primary defense against hash-flooding attacks; for attacker-controlled data, use containers with non-$O(n)$ worst-case behavior.
    • ODR Risk: If Abseil is linked incorrectly (e.g., static Abseil in multiple DSOs), multiple seeds may exist. This causes different calls to return different values, making elements inaccessible and causing crashes.
    • No disable flag: There is no option to disable hash randomization, as this would encourage code that depends on implementation details.
  4. Avoid ABI mismatches and ODR violations

    master

    Abseil provides API compatibility but does not guarantee ABI compatibility. To prevent crashes, strange runtime behaviors, or linker errors caused by One Definition Rule (ODR) violations, follow these rules:

    1. Build from source: Avoid using pre-compiled versions of Abseil (e.g., from Linux package managers or vcpkg) unless you can guarantee the exact same compile options were used to build them.
    2. Global compile options: Ensure all compile options that affect ABI (e.g., -std=, -O2, -fexceptions, -DNDEBUG) are applied globally to the entire build, not just to specific targets.
    3. Avoid mixed-mode compilation: In Bazel, do not use copts on a cc_library to set the C++ standard, as this only affects that target and creates a mismatch with Abseil dependencies.
    4. Single version of Abseil: Ensure your project and all its transitive dependencies use the same version of Abseil to avoid the 'diamond dependency' problem.
    # DON'T DO THIS in a Bazel BUILD file:
    cc_library(
        name = "my_library",
        srcs = ["my_library.cc"],
        copts = ["-std=c++17"],  # This creates a mixed-mode compile!
        deps = ["@com_google_absl//absl/strings"],
    )
  5. Run Abseil tests with CMake

    master

    To run Abseil's internal tests, you must enable testing and provide a Google Test dependency.

    Method 1: Automatic Google Test Download

    Use -DABSL_BUILD_TESTING=ON and -DABSL_USE_GOOGLETEST_HEAD=ON. This automatically downloads the latest Google Test source during configuration.

    Method 2: Manual Google Test Integration

    Integrate Google Test into your project manually using standard CMake methods, then enable Abseil testing.

    Example Workflow (Automatic):

    cd path/to/abseil-cpp
    mkdir build && cd build
    cmake -DABSL_BUILD_TESTING=ON -DABSL_USE_GOOGLETEST_HEAD=ON ..
    make -j
    ctest
    cd path/to/abseil-cpp
    mkdir build
    cd build
    cmake -DABSL_BUILD_TESTING=ON -DABSL_USE_GOOGLETEST_HEAD=ON ..
    make -j
    ctest
  6. Use LLVM Sanitizers (MSan) with Abseil

    master

    To use LLVM Sanitizers (like MemorySanitizer) with Abseil, you must avoid ODR violations caused by instrumentation mismatches. All code, including the C++ standard library, must be built with the same sanitizer configuration.

    Specifically, MemorySanitizer (MSan) requires an instrumented libc++.

    MSan Recipe

    1. Build instrumented libc++ from the LLVM source tree using CMake and Ninja.
    2. Install the components (libcxx, libcxxabi, libunwind) to a local directory.
    3. Build your project using Bazel, passing the appropriate environment variables to point to the instrumented library and enable the sanitizer.
    # 1. Configure instrumented libc++ from LLVM source tree
    cmake -G Ninja -S runtimes -B build_msan \
      -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind" \
      -DCMAKE_BUILD_TYPE=Release \
      -DCMAKE_INSTALL_PREFIX="${HOME}/llvm-msan" \
      -DCMAKE_C_COMPILER=clang \
      -DCMAKE_CXX_COMPILER=clang++ \
      -DLLVM_USE_SANITIZER=MemoryWithOrigins \
      -DLLVM_TARGETS_TO_BUILD="host"
    
    # 2. Build and install
    ninja -C build_msan install-cxx install-cxxabi install-unwind
    
    # 3. Build/test your code with Bazel
    bazel test --repo_env=CC=clang \
      --repo_env=BAZEL_CXXOPTS=nostdinc++ \
      --repo_env=BAZEL_LINKOPTS="-L${HOME}/llvm-msan/lib:-lc++:-lc++abi:-lgcc_s:-lm:-Wl,-rpath=${HOME}/llvm-msan/lib" \
      --repo_env=CPLUS_INCLUDE_PATH="${HOME}/llvm-msan/include/c++/v1" \
      --copt=-fsanitize=memory \
      --linkopt=-fsanitize=memory \
      --linkopt=-fsanitize-link-c++-runtime ...
  7. Incorporate Abseil into a CMake project

    master

    For API/ABI compatibility, it is strongly recommended to build Abseil as an embedded dependency or in a subdirectory of your project.

    Steps:

    1. Download Abseil: Copy the source into a subdirectory or add it as a git submodule.
    2. Include via CMake: Use add_subdirectory() to include the Abseil directory.
    3. Link Targets: Use target_link_libraries() to link the specific absl:: targets your application requires.

    C++ Standard Requirements:

    Abseil supports C++17 and C++20.

    • For Applications: Set CMAKE_CXX_STANDARD (e.g., to 17) at the top-level project.
    • For Libraries: Do not set CMAKE_CXX_STANDARD globally. Instead, set it only if the library is the top-level project. Use target_compile_features(your_lib PUBLIC cxx_std_17) to enforce requirements for consumers and ensure CMAKE_CXX_STANDARD is at least 17 to maintain ABI compatibility.
    cmake_minimum_required(VERSION 3.16)
    project(my_app_project)
    
    # Abseil supports C++17 and C++20
    set(CMAKE_CXX_STANDARD 17)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    
    add_subdirectory(abseil-cpp)
    
    add_executable(my_exe source.cpp)
    target_link_libraries(my_exe absl::base absl::synchronization absl::strings)
  8. Update Abseil to the latest commit (Live at Head)

    master

    Abseil recommends 'living at head' by updating to the latest commit in the master branch as often as possible. This ensures you receive bug fixes quickly and can address incremental changes to the API or behavior.

    If you use Bazel with Bzlmod, you can track the latest commit by using a git_override in your MODULE.bazel file.

    # In your MODULE.bazel file
    bazel_dep(name = "abseil-cpp", version = "20260107.1")
    
    git_override(
        module_name = "abseil-cpp",
        remote = "https://github.com/abseil/abseil-cpp.git",
        # Replace the following line with the latest commit.
        commit = "6ec9964c325db0610a376b3cb81de073ea6ada90",
    )
  9. Traditional CMake build and install for large projects

    master

    For large-scale projects, you can build and install Google Test and Abseil separately.

    1. Build and Install Google Test: Set CMAKE_INSTALL_PREFIX to your desired installation directory.

    2. Build and Install Abseil:

      • Set CMAKE_PREFIX_PATH to the Google Test installation directory.
      • Set CMAKE_INSTALL_PREFIX for the Abseil installation.
      • Enable ABSL_ENABLE_INSTALL=ON.
      • Enable ABSL_USE_EXTERNAL_GOOGLETEST=ON and ABSL_FIND_GOOGLETEST=ON to use the pre-installed Google Test.
    # 1. Build and install Google Test
    cmake -S /source/googletest -B /build/googletest -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/installation/dir -DBUILD_GMOCK=ON
    cmake --build /build/googletest --target install
    
    # 2. Build and install Abseil
    cmake -S /source/abseil-cpp -B /build/abseil-cpp -DCMAKE_PREFIX_PATH=/installation/dir -DCMAKE_INSTALL_PREFIX=/installation/dir -DABSL_ENABLE_INSTALL=ON -DABSL_USE_EXTERNAL_GOOGLETEST=ON -DABSL_FIND_GOOGLETEST=ON
    cmake --build /temporary/build/abseil-cpp
    
    # 3. Run tests
    ctest --test-dir /temporary/build/abseil-cpp
    
    # 4. Install
    cmake --build /temporary/build/abseil-cpp --target install
  10. Set the C++ dialect for building Abseil

    master

    To avoid ABI (Application Binary Interface) mismatches and One Definition Rule (ODR) violations, you must set the C++ dialect consistently at the global level for your entire project. Do not apply dialect flags (like -std=c++17) to individual targets; instead, apply them to the entire build.

    Using Bazel

    You can set the dialect using one of these methods:

    • Command line: Pass --cxxopt=-std=c++17 to the bazel build command.
    • Environment variable: Set BAZEL_CXXOPTS=-std=c++17.
    • Configuration file: Add build --cxxopt=-std=c++17 to your .bazelrc file.

    Using CMake

    • For applications: Add set(CMAKE_CXX_STANDARD 17) to your top-level CMakeLists.txt.
    • For libraries: Leave CMAKE_CXX_STANDARD unset and configure the minimum required standard for each target using target_compile_features to ensure compatibility with clients.
    # Bazel command line example
    bazel build --cxxopt=-std=c++17 ...
    
    # Environment variable example
    BAZEL_CXXOPTS=-std=c++17 bazel build ...
  11. Configure Abseil CMake build options

    master

    The following CMake flags control the build behavior of Abseil:

    Installation

    • -DABSL_ENABLE_INSTALL=ON: Enables standard CMake installation.

    Google Test Configuration

    To enable testing, -DABSL_BUILD_TESTING=ON must be set.

    Option A: Let Abseil manage Google Test (Default behavior: -DABSL_USE_EXTERNAL_GOOGLETEST=OFF)

    • -DABSL_USE_GOOGLETEST_HEAD=ON: Download and build the latest Google Test source.
    • -DABSL_GOOGLETEST_DOWNLOAD_URL=<URL>: Download a specific Google Test version (ZIP archive).
    • -DABSL_LOCAL_GOOGLETEST_DIR=<path>: Use Google Test from a specific local directory.

    Option B: Use an existing Google Test installation

    • -DABSL_USE_EXTERNAL_GOOGLETEST=ON: Use Google Test included elsewhere in your project.
    • -DABSL_FIND_GOOGLETEST=ON: Use standard CMake find_package(CTest) to locate the installed Google Test.