actions
Actions
Actions in Bazel are the discrete steps that the build system executes to transform source code and other inputs into the desired outputs. They are the practical realization of the instructions defined in
BUILDfiles through rules, and they form the backbone of Bazel's build and test processes.
In Bazel, actions are fundamental units of work that the build system performs to build software. They are the concrete steps taken to transform inputs (like source files) into outputs (like executables, libraries, or other artifacts).
Definition and Role
- What Are Actions? In Bazel, an action represents a specific task or command that needs to be executed during the build process. It's** a command-line invocation** that processes inputs and produces outputs.
- Role in Build Process: Actions are the actual workhorses of the Bazel build system. They are generated based on the rules defined in
BUILDfiles and are executed to build the targets.
Types of Actions
- Compilation: This involves compiling source code into binary code. For instance, compiling
.javafiles into.classfiles for Java, or.ccfiles into object files for C++. - Linking: Combining compiled object files into a single executable or library.
- Code Generation: Generating code from templates or other inputs, such as generating Java files from Protocol Buffers (.proto) definitions.
- Testing: Running tests and generating test reports.
How Actions Work
- Generated by Rules: Each rule in a
BUILDfile translates into one or more actions. For example, acc_binaryrule will generate actions for compiling each C++ source file and then linking these into an executable. - Inputs and Outputs: Each action specifies its inputs (like source files, headers, tools) and outputs (like object files, libraries, executables). Bazel uses this information to manage dependencies and determine which actions need to be rerun when files change.
- Commands and Tools: Actions define the exact command-line commands that need to be executed. This can include standard build tools like compilers or custom scripts.
Dependency Graph and Incremental Builds
- Dependency Tracking: Bazel tracks the dependencies between actions. This forms a directed acyclic graph (DAG) where each action depends on the outputs of previous actions.
- Incremental Builds: By understanding which inputs affect which actions, Bazel can perform incremental builds, only re-running actions whose inputs have changed.
Sandboxing and Reproducibility
- Sandboxing: To ensure builds are reproducible and to minimize side effects, Bazel can execute actions in a sandboxed environment. This restricts actions to only access their declared inputs and outputs, preventing unintended interactions with the rest of the system.
- Reproducibility: Actions in Bazel are designed to be deterministic. Given the same inputs, an action should always produce the same outputs, regardless of the environment in which it's run. This is key to Bazel's promise of reproducible builds.
Challenges and Best Practices
- Complexity: Defining custom actions can be complex and requires a good understanding of the underlying build process.
- Optimization: When creating custom actions, it's important to consider their efficiency and impact on the overall build time. Minimizing unnecessary work and optimizing the use of resources are key considerations.