======================================= Experimental Bazel Support in Everest ======================================= .. note:: This feature is currently experimental and subject to change. Introduction ------------ EVerest now offers experimental support for `Bazel `. With Bazel, you can efficiently build, test and deploy software projects of any size. For EVerest developers, Bazel offers a couple advantages: * While developing features, that span multiple modules, Bazel can swiftly rebuild only the necessary parts of the project. * If you have already setup Bazel in your project, EVerest framework can be integrated with it. This tutorial will guide you through the process of setting up and using Bazel in your Everest projects. Getting Started --------------- To install Bazel, it's recommended to use bazelisk, which is a tool that downloads and runs the correct version of Bazel for your project. You can install bazelisk by following the `instructions on the official GitHub repository `. .. note:: Bazelisk provides a `bazel` command, and the rest of this tutorial will refer to it as `bazel`. C/C++ Compilers: At the moment, Bazel will use the default C/C++ compilers on your system. If it is not the desired compiler to build EVerest, you can set the environment variables `CC` and `CXX` to the desired compiler. All other dependencies are fetched by Bazel as needed. Using Bazel Commands -------------------- Once Bazel is configured, you can use various Bazel commands to build, test and run. Most useful commands are: * `bazel build //...` - Build all targets in the project. * `bazel test //...` - Run all tests in the project. Dependency Management --------------------- There are a few different ways of managing dependencies in EVerest. * Dependencies that CMake takes from the system (e.g. boost). These dependencies are configured in the `third_party/bazel/repos.bzl` file. * Dependencies that are described in the `./dependencies.yaml` file. These dependencies are pulled automatically by Bazel with help of `edm` tool. * Rust dependencies are managed by cargo, and are described in the `Cargo.toml` file. Cargo dependencies are automatically picked up by Bazel. Defining C++ EVerest Modules ---------------------------- Let's assume, you have a module named `Example` with a single interface implementation named `example`. This module depends on the `sigslot` library. For a more realistic scenario, the module has two extra files `utils.cpp` and `utils.hpp`. .. code-block:: bash modules/ └── Example ├── BUILD.bazel ├── CMakeLists.txt ├── Example.cpp ├── Example.hpp ├── manifest.yaml ├── utils.cpp ├── utils.hpp └── example/ ├── exampleImpl.cpp └── exampleImpl.hpp The `manifest.yaml` file for the module looks like this: .. code-block:: yaml description: Simple example module written in C++ provides: example: interface: example description: This implements an example interface that uses multiple framework features ... requires: kvs: interface: kvs enable_external_mqtt: true metadata: license: https://opensource.org/licenses/Apache-2.0 authors: - Example Authors To build this module with Bazel, you need to create a `BUILD.bazel` file in the module directory, next to the `manifest.yaml` file. In the `BUILD.bazel`, use predefined macros to define the module: .. code-block:: python load("//modules:module.bzl", "cc_everest_module") cc_everest_module( # Name of the module, must be the same as the directory name. name = "Example", deps = [ # List of libraries, that module depends on. # In CMakeLists.txt these are typically added as `target_link_libraries`. # The should be listed in the `third_party/bazel/repos.bzl` file. # Note that header-only libraries should be added here as well. "@sigslot//:sigslot", ], impls = [ # List of implementations in the module. # This should correspond to the list of keys in the # `provides` section of the manifest.yaml file. "example", ], # List of additional source files of the module. # # Here you only have to list the files that are not autogenerated. # The mandatory module files are added automatically. srcs = [ "utils.cpp", "utils.hpp", ], # Alternatively, you can use `glob` function to list files. # srcs = glob( # [ # "*.cpp", # "*.hpp", # ], # ), ) Defining Rust EVerest Modules ---------------------------- To define a Rust module in EVerest, you need to create a BUILD.bazel file in the module directory. Generic `rust_binary` and `rust_test` are used at the moment. .. code-block:: python load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_test") load("@everest_core_crate_index//:defs.bzl", "all_crate_deps") load("@rules_rust//cargo:defs.bzl", "cargo_build_script") # cargo_build_script describes to Bazel how to run autogeneration of the code. # This should be pretty-much the same for every module cargo_build_script( name = "build_script", srcs = ["build.rs"], edition="2021", build_script_env = { # This is the path relative to the module directory. "EVEREST_CORE_ROOT": "../..", }, data = [ "manifest.yaml", "@everest-core//interfaces", "@everest-core//types", ], deps = all_crate_deps(build = True), ) # The module is described as a rust_binary at the moment. rust_binary( # Name of the module, must be the same as the directory name. name = "RsIskraMeterBinary", # List of source files of the module. # In most cases this glob should be enough. srcs = glob(["src/*.rs"]), # Rust language edition, used in this module. edition="2021", # Bazel makes distinctions between dependencies needed on different # stages of the build. This is the list of proc_macro dependencies. # In most cases this is enough proc_macro_deps = all_crate_deps(proc_macro = True), visibility = ["//visibility:public"], # List of "normal" dependencies. # all_crate_deps will add all the dependencies from the Cargo.toml file. # We need as well to add framework, bridge, and the result of the build_script. # Typically this is enough. deps = all_crate_deps(normal = True) + [ ":build_script", "@everest-framework//everestrs/everestrs:everestrs_sys", "@everest-framework//everestrs/everestrs:everestrs_bridge", ], ) Using EVerest in external Bazel projects ---------------------------------------- TBD