What’s new in Pigweed: August 2026#

Highlights:

Arch interfaces#

pw_interrupt Bazel backend configuration#

pw_interrupt now supports selecting backend implementations in Bazel via :compatible constraints and the @pigweed//pw_interrupt:backend flag mapped to :impl, laying the groundwork to deprecate the legacy backend multiplexer. CLs: 1

# In platform configuration:
constraint_values = [
    "@pigweed//pw_interrupt_cortex_m:compatible",
]
flags = {
    "@pigweed//pw_interrupt:backend": "@pigweed//pw_interrupt_cortex_m:impl",
}

Async and concurrency#

FutureOrValue container in pw_async2#

The new pw::async2::FutureOrValue container holds either an in-progress future or its resolved result. This simplifies manual state machine polling by preserving values across suspension points without extra boilerplate. CLs: 1, 2

#include "pw_async2/future_or_value.h"

class ConcurrentOperationsTask : public pw::async2::Task {
 private:
  pw::async2::Poll<> DoPend(pw::async2::Context& cx) override {
    // Start operations when empty:
    if (op_a_.empty()) {
      op_a_ = DoWork(1);
    }
    if (op_b_.empty()) {
      op_b_ = DoWork(2);
    }

    // Advance both slots without short-circuiting:
    PW_FOV_TRY_ADVANCE(cx, op_a_, op_b_);

    // Both values are now available across suspension points:
    pw::Status status_a = op_a_.Take();
    pw::Status status_b = op_b_.Take();

    return pw::async2::Ready();
  }

  pw::async2::FutureOrValue<ValueFuture<pw::Status>> op_a_;
  pw::async2::FutureOrValue<ValueFuture<pw::Status>> op_b_;
};

Build systems#

Dedicated sub-workspace for pw workflows launcher#

The ./pw command-line wrapper now builds inside an isolated sub-workspace in pw_build/workflows_launcher. This prevents Bazel from evaluating root development dependencies, eliminating hundreds of megabytes of unnecessary toolchain downloads on fresh checkouts. CLs: 1

Developer tools#

Rust code intelligence in pw_ide and VS Code#

pw_ide and the Pigweed VS Code extension now support generating rust-project.json compilation databases for Rust code intelligence. The release also introduces a dedicated target selection panel with separate tables for C++ and Rust, custom bazel_args support, and dedicated rust_check_args for editor check and lint commands. CLs: 1, 2, 3

Python module scaffolding in pw_module#

pw module create now supports Python via --languages py. Developers can scaffold new Python modules complete with starter templates for BUILD.bazel, BUILD.gn, pyproject.toml, and unit tests. CLs: 1

$ pw module create --languages py pw_my_module

Multi-directory formatting in pw_presubmit#

The pw_presubmit format CLI now accepts multiple -C / --directory arguments, making it possible to format code across multiple directories in a single invocation. CLs: 1

Memory management#

pw_buf module for contiguous memory buffers#

The new pw_buf module introduces pw::Buf and pw::ConstBuf abstractions for contiguous memory buffers. It supports owned and unowned buffer views, zero-copy slicing, truncation, and prefix/suffix byte reclamation. CLs: 1, 2, 3

#include "pw_buf/buf.h"

pw::Buf buf = pw::Buf::Unowned(my_span);
pw::Buf sliced = pw::Slice(std::move(buf), /*offset=*/4, /*length=*/16);
pw::Buf reclaimed = pw::ReclaimPrefix(std::move(sliced), /*count=*/4);

Third-party hardware and software#

On-device Bazel unit testing on STM32F429I-DISC1#

The STM32F429I-DISC1 target platform now supports running on-device unit tests directly with Bazel, including automatic device flashing and RPC test result reporting via a target test server. CLs: 1

# Start the test server:
$ bazelisk run //targets/stm32f429i_disc1/py:unit_test_server

# Run on-device unit tests:
$ bazelisk test //... --config=stm32f429i_freertos

Tokenization#

ELF token database parsing in Rust#

The Rust pw_tokenizer crate now supports parsing ELF token database sections (.pw_tokenizer.entries) directly via Detokenizer::from_elf_section and Detokenizer::from_elf_section_with_prefix. CLs: 1

use pw_tokenizer::Detokenizer;

let detok = Detokenizer::from_elf_section(elf_section_bytes)?;
let result = detok.detokenize(&encoded_bytes);