Projects#
pw_ide: Code editor and IDE support for Pigweed projects
There are broadly two types of Pigweed projects that Pigweed’s IDE tooling supports:
Bootstrap projects, in which a development environment is populated by sourcing binary dependencies from CIPD, and is accessed by setting environment variables via
bootstrap
andactivate
shell scripts. Usually, the build system is GN or CMake.Bazel projects, in which Bazel is the build system, Bazel manages development environment dependencies, and the
bazel
(orbazelisk
) command is the entry point into all tooling
Other project configurations are possible, but these are the two that our IDE tooling recognizes and supports.
Project structure#
For both project types, we look for the presence of a pigweed.json
file to
indicate the root of the project directory.
Bootstrap projects#
This project structure has the following properties:
Development tools and dependences are located in an
environment
directory.
Note
The location and name of the environment
can be actually customized when
running bootstrap.sh
, and multiple independent environments are
supported.
Access to the development environment is provided through mutations to the shell environment; the
$PATH
is modified to point to locations inenvironment
, and Pigweed-specific environment variables are used to configure the development environment.A
bootstrap.sh
script creates theenvironment
directory, populates it with development tools and dependencies, and modifies the environment of the shell in which the script was run to provide access to the development environment.As a side effect of the bootstrap process, an
actions.json
file is created in theenvironment
directory that describes the mutations to the shell environment required to provide access to the development environment.Pigweed commands are made available via an executable called
pw
.
Assuming the environment has already been bootstrapped, exposing the development environment to an IDE or other developer tooling requires:
Finding the
environment
directory, or potentially multipleenvironment
directories. We do this by looking for directories with anactions.json
file.Executing commands within a shell environment modified per the
actions.json
file. How this is done depends on the language and runtime of the IDE. An example in JavaScript:
// Assuming `actionsJson` is a parsed `actions.json` file, and `activateEnv`
// is a function that applies the mutations described in `actionsJson` to
// a shell environment.
const activatedEnv = activateEnv(process.env, actionsJson);
child_process.exec("clang", activatedEnv);
If the environment has not been bootstrapped yet, we just need to run
bootstrap.sh
. It’s not necessary to capture the mutated shell environment
that results from running the script, since we have access to it through the
steps described above.
Bazel projects#
This project structure has the following properties:
Development tools and dependences are managed by Bazel. There are multiple mechanisms for this, including WORKSPACE and bzlmod. Regardless of the mechanism used, Bazel manages the tools and dependencies, and their location on disk.
The Bazel environment is created and updated by running a Bazel build command.
Access to tools and commands in the development environment is provided by Bazel itself. In other words, the
bazel
executable is the entry point to all project operations.
So all that’s required to expose the development environment to an IDE is to
execute bazel run
commands.
Managing Bazel environments#
It’s important to use the version of Bazel specified by the project, and to use a single Bazel environment and build directory regardless of the tools the developer is using. For example, a developer should be able to edit code in their IDE and run Bazel commands from a separate terminal and be sure that all of those actions will execute within the same environment.
We ensure that behavior by using bazelisk
instead of plain bazel
.
It wraps bazel
and ensures that your project uses the exact version of Bazel
specified in the project’s .bazelversion
file.
A developer can have multiple installations of bazelisk
from different
sources, and invocations of any of those executables on the same project will
all run in the same Bazel environment. So we can actually bundle bazelisk
with the IDE, ensuring that it’s available to IDE functionality, without
worrying about it conflicting with the developer’s use of bazelisk
in the
terminal or in other tools.