BEBE is a flexible tool for generating and managing high-performance C++ build environments. It uses Jinja2 templates to dynamically generate Dockerfiles based on JSON configurations, allowing for easy management of different compiler versions and toolchains.
- Dynamic Dockerfile Generation: Uses Jinja2 templates to build tailored Docker images.
- Multiprocess Builds: Supports building Clang, GCC, and more from source.
- Configuration Inheritance: Share common settings across multiple environments using base configurations.
- CI/CD Optimization: Integrated with Docker Buildx and Container Registry caching for lightning-fast incremental builds.
- CLI Tool: A unified
bebecommand for all build and management tasks.
- Python 3.12+
- Docker or Podman
- (Optional) Docker Buildx for advanced caching
-
Clone the repository:
git clone https://github.com/twon/bebe.git cd bebe -
Set up the virtual environment and install BeBe:
python3 -m venv .venv source .venv/bin/activate # On Windows: .venv\Scripts\activate pip install .
BEBE supports configuration inheritance to reduce duplication. You can define a base configuration (e.g., configs/base.json) with common settings and inherit from it in specific environment configs.
Example configs/ubuntu.clang19.json:
{
"inherits": "base.json",
"compiler": {
"family": "clang",
"version": "release/19.x"
}
}Configurations marked as "abstract": true will be ignored by CI discovery but can be used as bases for other configs.
The bebe command is the main entry point for all operations.
Discover all buildable (non-abstract) configurations:
bebe list --directory configsRender and print the Dockerfile for a specific configuration without building it:
bebe generate --config configs/ubuntu.clang19.jsonThis is useful for manual inspection or running external linters like Hadolint.
bebe build --config configs/ubuntu.clang19.jsonTo enable advanced caching in CI:
bebe build --config configs/ubuntu.clang19.json \
--cache-from type=registry,ref=ghcr.io/twon/bebe/cache:ubuntu.clang19 \
--cache-to type=registry,ref=ghcr.io/twon/bebe/cache:ubuntu.clang19,mode=maxLaunch a shell inside the built environment:
bebe shell --config configs/ubuntu.clang19.jsonBeBe provides a native GitHub Action to simplify and automate your CI pipelines.
This pattern uses two jobs: one to resolve the correct image tag for your configuration, and another to run your build inside that image. This is the recommended way to use BeBe for a seamless CI environment experience.
jobs:
env:
runs-on: ubuntu-latest
outputs:
image: ${{ steps.resolve.outputs.image }}
steps:
- uses: Twon/Bebe@main
id: resolve
with:
config: ubuntu.gcc14.json # Choose your environment
build:
needs: env
runs-on: ubuntu-latest
container:
image: ${{ needs.env.outputs.image }}
steps:
- uses: actions/checkout@v4
- run: gcc --version
- run: cmake --versionIf you only need to run a quick script, you can use the run input to execute it directly inside the container without switching the whole job's environment:
- uses: Twon/Bebe@main
with:
config: ubuntu.gcc14.json
run: |
gcc --version
cmake --versionBEBE is designed to be CI-native. We use Docker Buildx with the Container Registry Cache Backend (type=registry).
In our build workflow, we use the following flags to ensure that expensive build steps (like compiling LLVM from source) are cached across different runs:
--cache-from "type=registry,ref=...": Reuses build layers cached in previous CI runs from the registry.--cache-to "type=registry,ref=...,mode=max": Exports all build layers back to the registry.
This caching methodology ensures that only the parts of the environment that have changed are rebuilt, saving hours of CI time.
BEBE uses a sophisticated multi-stage build process designed for maximum cache efficiency and minimal final image size:
build_base: A heavy stage containing all tools needed to compile other software (e.g.,build-essential,cmake,ninja-build,git,wget). This stage is only used for building and is discarded in the final image.tools_build_stage: Independent of the compiler, this stage builds all additional tools (CMake, Ninja, LCOV, etc.) from source. Because it's independent, these builds are cached and shared across all compiler images that use the same tool versions.compiler_stage: Dedicated stage for building the specific compiler (GCC, Clang) requested in the configuration from source.runtime_base: A minimal version of the OS containing only the bare essentials needed at runtime.bebe_final: The final production image that inherits fromruntime_baseand copies only the completed binaries fromcompiler_stageandtools_build_stage.
This "Split-Stage" approach ensures that even if you're building 10 different versions of GCC, you only build your "Bleeding Edge" tools once, and your final image remains as lean as possible.
We are actively working on expanding the BeBe ecosystem. Key upcoming features include:
- VS Code / Dev Container Integration: Seamless integration to allow developers to switch between toolsets while keeping their project source on the host, mapping it into the optimized build container for high-performance development.
© 2026 BeBe Contributors. Released under the MIT License.
