pw_watch#

Embedded development file system watcher

Stable

  • Automatically trigger build actions when source files change

Background#

In the web development space, file system watchers like nodemon and watchman are prevalent. These watchers trigger actions when files change (such as reloading a web server), making development much faster. In the embedded space, file system watchers are less prevalent but no less useful!

Our solution#

pw_watch is similar to file system watchers found in web development tooling but is focused around embedded development use cases. After changing source code, pw_watch can instantly compile, flash, and run tests.

``pw watch`` running in fullscreen mode and displaying errors

pw watch running in fullscreen mode and displaying errors.#

Combined with the GN-based build which expresses the full dependency tree, only the exact tests affected by source changes are run.

The demo below shows pw_watch building for a STMicroelectronics STM32F429I-DISC1 development board, flashing the board with the affected test, and verifying the test runs as expected. Once this is set up, you can attach multiple devices to run tests in a distributed manner to reduce the time it takes to run tests.

pw_watch running on-device tests

Get started#

GN#

cd ~/pigweed
source activate.sh
pw watch

The simplest way to get started with pw_watch is to launch it from a shell using the Pigweed environment as pw watch. By default, pw_watch watches for repository changes and triggers the default Ninja build target at //out. To override this behavior, provide the -C argument to pw watch.

See How-to guide for more examples and CLI reference for detailed CLI usage information.

Bazel#

The Bazel build provides a //:watch entrypoint to pw_watch, which executes commands with bazelisk. Arguments are forwarded directly to bazel / bazelisk, so any bazel subcommands may be used.

# Runs bazelisk build //... when files change.
bazelisk run //:watch build //...

# Runs an executable when files change.
bazelisk run //:watch -- run //important:script -a --value 52

# Builds //..., then runs the //foo:bar test.
bazelisk run //:watch build //... , test //foo:bar

Important

bazelisk run interprets arguments that start with -. Pass -- before any other arguments to separate arguments to Bazel from command arguments.

bazelisk run //:watch -- <commands to run>

//:watch is an alias of //pw_watch/py:bazel. External projects may run this tool directly as @pigweed//:watch, or create their own //:watch alias.

Custom commands#

pw_watch.run executes arbitrary commands when watched files change.

One or more commands to run are provided on the command line. These are executed in order when changes are detected.

Examples:

# Run `bazelisk --symlink_prefix=/ build //...`
run.py --prefix bazelisk --symlink_prefix=/ --pw-watch-commands build //...

Multiple commands may be specified, separated by ,:

# Run `cowsay` then `cowthink` when watched files change.
run.py cowsay "Hey, how are you?" , cowthink Not in moood to talk

The Bazel build’s //:watch watch entrypoint invokes //pw_watch/py:run with bazelisk as the command prefix.