blob: 16c8d692be4f62a716736f32cba63308f6604146 [file]
.. _module-pw_ide-bazel-usage:
=================
Code intelligence
=================
.. pigweed-module-subpage::
:name: pw_ide
The Pigweed Visual Studio Code extension bridges the build system and ``clangd``
to provide the smoothest possible C++ embedded development system. For
background on the tools and approaches Pigweed uses, check out the
:ref:`design docs<module-pw_ide-contributing-design-cpp>`. For Rust code
intelligence, see :ref:`module-pw_ide-bazel-rust`. This doc is a
user guide to the way those concepts are applied in Visual Studio Code.
----------------
Target discovery
----------------
Pigweed IDE will discover build targets for Bazel, GN and CMake builds
automatically, as well as any other targets described by compilation databases
produced by other means.
In general, the process of discovering and processing build targets is triggered
by running the :ref:`Refresh Compile Commands<module-pw_ide-bazel-commands-refresh-compile-commands>`
command. See below for build system-specific details.
.. tab-set::
.. tab-item:: Bazel
Pigweed IDE generates ``clangd``-compatible compilation databases for
your project's build targets defined by ``pw_compile_commands_generator``
targets in your ``BUILD.bazel`` file.
.. tip::
For instructions on configuring and using Rust code intelligence with
``rust-analyzer``, see :ref:`module-pw_ide-bazel-rust`.
**Fixed Compile Command Generation**
To ensure a consistent set of compilation databases, you can use the
``pw_compile_commands_generator`` rule in your top-level ``BUILD.bazel``
file. This provides a declarative way to define and group build targets
for which to generate compile commands. ``pw_compile_commands_generator``
targets must be run via ``bazel run`` to generate updated compile commands
databases.
.. note::
Each instance of ``pw_compile_commands_generator`` is intended to
represent a unique target platform or build configuration.
This method provides wide code intelligence coverage by analyzing all
targets specified in the generator target. It ensures that code
intelligence is available for all configured platforms without needing to
build them first.
Example configuration:
.. code-block:: bazel
load(
"@pigweed//pw_ide/bazel/compile_commands:pw_compile_commands_generator.bzl",
"pw_compile_commands_generator",
)
# Creates a set of compile command databases that merges
# all of the databases produced by its deps.
pw_compile_commands_generator(
name = "update_compile_commands",
deps = [
":update_host_compile_commands",
":update_rp2040_compile_commands",
],
)
pw_compile_commands_generator(
name = "update_host_compile_commands",
display_name = "Host C++",
platform = "@bazel_tools//tools:host_platform",
target_patterns = [
"//...",
],
)
pw_compile_commands_generator(
name = "update_rp2040_compile_commands",
display_name = "RP2040",
platform = "//targets/rp2040",
target_patterns = [
"//...",
],
)
**Generator Rule Arguments**
The ``pw_compile_commands_generator`` rule supports the following main
arguments:
* ``target_patterns``: List of Bazel target patterns for C/C++ compilation
database generation (used by ``clangd``).
* ``platform``: The Bazel target platform to evaluate when collecting
C/C++ target patterns.
* ``config``: Optional Bazel build configuration name to use for
compilation and platform inference.
* ``bazel_args``: Optional list of extra Bazel command-line arguments
(such as custom flags or build configs) used when building platforms or
evaluating target patterns.
* ``display_name``: Optional human-readable label shown in the Pigweed
Visual Studio Code target selection panel.
* ``symlink_prefix``: Custom symlink prefix if your Bazel workspace uses
the ``--symlink_prefix`` flag.
**Custom Symlink Prefixes**
By default, Bazel creates symlinks like ``bazel-out`` and ``external`` in
your workspace root to point to the build output and external
dependencies. ``pw_ide`` utilizes these symlinks to generate **relative
paths** (e.g., ``bazel-out/...``) in the resulting compilation databases.
Relative paths ensure that the compilation database remains portable and
correct across different machines and build environments.
If you use Bazel's ``--symlink_prefix`` flag (e.g., to support multiple
concurrent builds in the same workspace), Bazel will create these
symlinks with a custom name (e.g. ``out/out`` instead of ``bazel-out``).
If ``pw_ide`` is unaware of this prefix, it may fail to find the
necessary symlinks and fall back to using absolute paths, which are
not portable and can cause issues with code intelligence tools.
You can inform ``pw_ide`` of your custom prefix using the
``symlink_prefix`` attribute:
.. code-block:: bazel
pw_compile_commands_generator(
name = "update_custom_prefix_commands",
symlink_prefix = "out/", # Match your Bazel --symlink_prefix
target_patterns = [
"//...",
],
)
Example usage:
.. code-block:: console
$ bazel run //:update_compile_commands
.. tab-item:: GN
GN :ref:`can be configured<module-pw_ide-contributing-design-cpp-gn>` to generate a
compilation database whenever ``gn gen`` is run. Pigweed IDE will find
that file when :ref:`Refresh Compile Commands<module-pw_ide-bazel-commands-refresh-compile-commands>`
is run and make those targets available for code analysis.
Right now, this is a manual process; if the compilation databases need to
be updated, you have to run ``gn gen`` and then
:ref:`Refresh Compile Commands<module-pw_ide-bazel-commands-refresh-compile-commands>`.
.. tab-item:: CMake
CMake :ref:`can be configured<module-pw_ide-contributing-design-cpp-cmake>` to generate
compilation databases during its build. Pigweed IDE will find those files
when :ref:`Refresh Compile Commands<module-pw_ide-bazel-commands-refresh-compile-commands>`
is run and make those targets available for code analysis.
If you have a CMake build watcher running, then the compilation databases
will update automatically in response to your code changes without the
need to run :ref:`Refresh Compile Commands<module-pw_ide-bazel-commands-refresh-compile-commands>`.
The only time you would need to manually run that command is if build
targets were added or removed from the build.
-------------------------------------------------
Selecting a target platform for code intelligence
-------------------------------------------------
Pigweed IDE allows you to inspect, generate, and switch C/C++ code
intelligence targets (used by ``clangd``) directly from the Visual Studio
Code interface. For Rust targets, see
:ref:`module-pw_ide-bazel-rust`.
Target selection panel
======================
The recommended way to manage compile commands is through the **Pigweed**
extension panel in Visual Studio Code (accessible from the Activity Bar icon).
Under **Select or generate compile commands**, locate the **C++ Targets**
table (for Rust targets, see
:ref:`module-pw_ide-bazel-rust`). Each target row
displays:
* **Target**: The display name of the target platform (configured via
``display_name`` in your generator target).
* **Last generated at**: The timestamp when compile commands were last generated
for this target (e.g., ``1 month ago`` or ``Never``).
* **Action**: A button to **Generate** (if never generated) or **Regenerate**
the compile commands for that target.
Clicking **Generate** or **Regenerate** triggers generation of the compilation
database for that target and automatically selects it as the active target for
code intelligence.
Selecting a C++ target configures ``clangd`` with the generated
``compile_commands.json`` for that platform. Note that C++ and Rust target
platforms are selected and managed independently. See
:ref:`module-pw_ide-bazel-rust` for Rust
target selection details.
Once compile commands are generated and selected, step **2. Enjoy code
intelligence** updates to confirm that code intelligence is active.
Status bar and command palette
==============================
The currently-selected target platform is also displayed in the Visual
Studio Code status bar:
.. figure:: https://www.gstatic.com/pigweed/vsc-status-bar-target.png
:alt: Visual Studio Code screenshot showing the target status bar item
You can click the status bar item to select a new target platform from a dropdown
list at the top of the screen.
.. figure:: https://www.gstatic.com/pigweed/vsc-dropdown-select-target.png
:alt: Visual Studio Code screenshot showing the target selector
No automatic process is perfect, and if an error occurs during the refresh
process, that will be indicated with this icon in the status bar:
.. figure:: https://www.gstatic.com/pigweed/vsc-status-bar-fault.png
:alt: Visual Studio Code screenshot showing the target status bar item in an
error state
You can click the status bar item to trigger a retry, or you can
:ref:`open the output panel<module-pw_ide-bazel-commands-open-output-panel>`
to get more details about the error.
.. note::
* You can always trigger a manual compilation database refresh by running
:ref:`Pigweed: Refresh Compile Commands<module-pw_ide-bazel-commands-refresh-compile-commands>`.
* If you don't want to use the automatic refresh process, you can
:ref:`disable it<module-pw_ide-bazel-configuration-disable-compile-commands-file-watcher>`.
----------------------------------
Inactive and orphaned source files
----------------------------------
As discussed in the :ref:`design docs<module-pw_ide-contributing-design-cpp>`, some source
files will be compiled in several different targets, possibly with different
compiler and linker options. Likewise, some files may not be compiled as part
of a particular selected target, perhaps because the file is not relevant to
the target (for example, hardware support implementations for a host simulator
target). Finally, some source files may not be compiled by *any* defined target
group, either because those files have not yet been brought into the build
graph, or because none of the defined target platforms contain a target that builds
that source file.
We need to care about this because ``clangd`` tries to be helpful in a way that
is very counterproductive in Pigweed projects: If it encounters a file but
cannot find a corresponding compile command in the compilation database, it
will *infer* a compile command for that file from other similar files that *are*
in the compilation database.
Since the compilation databases that Pigweed generates are specifically
engineered to only include compile commands pertinent to the selected target
group, the *inferred* code intelligence ``clangd`` provides for other files
is invalid. So the Pigweed extension provides mechanisms to exclude those files
from ``clangd`` and prevent misleading code intelligence information.
.. glossary::
Active source file
A source file that is built in the currently-selected target platform
Inactive source file
A source file that is *not* built in the currently-selected target platform
Orphaned source file
A source file that is not built by *any* defined target platforms
Disabling ``clangd`` for inactive and orphaned files
====================================================
By default, Pigweed will disable ``clangd`` for inactive and orphaned files to
prevent inaccurate and distracting information from appearing in the editor.
You can see that ``clangd`` is disabled for those files when you see this icon
in the status bar:
.. figure:: https://www.gstatic.com/pigweed/vsc-inactive-clangd-disabled.png
:alt: Visual Studio Code screenshot showing code intelligence disabled for
inactive files
You can click the icon to *enable* ``clangd`` for all files, regardless of
whether they are in the current target's build graph or not. That state will be
indicated with this icon:
.. figure:: https://www.gstatic.com/pigweed/vsc-inactive-clangd-enabled.png
:alt: Visual Studio Code screenshot showing code intelligence enabled for
inactive files
You can click it again to toggle it back to the default state.
File status indicators
======================
The Visual Studio Code explorer (file tree) displays an indicator next to
inactive and orphaned files to help you understand which files will not have
code intelligence. These indicators will change as you change targets and as
you change the build graph.
.. figure:: https://www.gstatic.com/pigweed/vsc-inactive-file-indicators.png
:alt: Visual Studio Code screenshot file indicators for inactive and
orphaned files
:figwidth: 250
Inactive files are indicated like this:
.. figure:: https://www.gstatic.com/pigweed/vsc-inactive-file-indicators-inactive.png
:alt: Visual Studio Code screenshot file indicators for inactive files
:figwidth: 250
Orphaned files are indicated like this:
.. figure:: https://www.gstatic.com/pigweed/vsc-inactive-file-indicators-orphaned.png
:alt: Visual Studio Code screenshot file indicators for orphaned files
:figwidth: 250
Note that the colors may vary depending on your Visual Studio Code theme.
.. tip::
By default, file status indicators will be shown even if ``clangd`` is
enabled for all files. You can change this behavior with
:ref:`this setting<module-pw_ide-bazel-configuration-hide-inactive-file-indicators>`.