xref: /aosp_15_r20/external/pigweed/pw_ide/design/cpp.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_ide-design-cpp:
2*61c4878aSAndroid Build Coastguard Worker
3*61c4878aSAndroid Build Coastguard Worker=======================
4*61c4878aSAndroid Build Coastguard WorkerC/C++ code intelligence
5*61c4878aSAndroid Build Coastguard Worker=======================
6*61c4878aSAndroid Build Coastguard Worker.. pigweed-module-subpage::
7*61c4878aSAndroid Build Coastguard Worker   :name: pw_ide
8*61c4878aSAndroid Build Coastguard Worker
9*61c4878aSAndroid Build Coastguard WorkerPigweed projects have a few characteristics that make it challenging for some
10*61c4878aSAndroid Build Coastguard WorkerIDEs and language servers to support C/C++ code intelligence out of the box:
11*61c4878aSAndroid Build Coastguard Worker
12*61c4878aSAndroid Build Coastguard Worker* Pigweed projects generally don't use the default host toolchain.
13*61c4878aSAndroid Build Coastguard Worker
14*61c4878aSAndroid Build Coastguard Worker* Pigweed projects usually use multiple toolchains for separate targets.
15*61c4878aSAndroid Build Coastguard Worker
16*61c4878aSAndroid Build Coastguard Worker* Pigweed projects rely on the build system to define the relationship between
17*61c4878aSAndroid Build Coastguard Worker  :ref:`facades and backends<docs-module-structure-facades>` for each target.
18*61c4878aSAndroid Build Coastguard Worker
19*61c4878aSAndroid Build Coastguard WorkerThese challenges are common to embedded projects in general.
20*61c4878aSAndroid Build Coastguard Worker
21*61c4878aSAndroid Build Coastguard WorkerWe've found that the best solution is to use the
22*61c4878aSAndroid Build Coastguard Worker`clangd <https://clangd.llvm.org/>`_ language server or alternative language
23*61c4878aSAndroid Build Coastguard Workerservers that use the same
24*61c4878aSAndroid Build Coastguard Worker`compilation database format <https://clang.llvm.org/docs/JSONCompilationDatabase.html>`_
25*61c4878aSAndroid Build Coastguard Workerand comply with the language server protocol. Usually, your build system
26*61c4878aSAndroid Build Coastguard Workergenerates the compilation database, and we supplement that with Pigweed
27*61c4878aSAndroid Build Coastguard Workertools to produce target-specific compilation databases that work well with
28*61c4878aSAndroid Build Coastguard Workerlanguage servers.
29*61c4878aSAndroid Build Coastguard Worker
30*61c4878aSAndroid Build Coastguard Worker-------------------------------------------
31*61c4878aSAndroid Build Coastguard WorkerSupporting ``clangd`` for embedded projects
32*61c4878aSAndroid Build Coastguard Worker-------------------------------------------
33*61c4878aSAndroid Build Coastguard WorkerThere are three main challenges that often prevent ``clangd`` from working
34*61c4878aSAndroid Build Coastguard Workerout-of-the-box with embedded projects:
35*61c4878aSAndroid Build Coastguard Worker
36*61c4878aSAndroid Build Coastguard Worker#. Embedded projects cross-compile using alternative toolchains, rather than
37*61c4878aSAndroid Build Coastguard Worker   using the system toolchain. ``clangd`` doesn't know about those toolchains
38*61c4878aSAndroid Build Coastguard Worker   by default.
39*61c4878aSAndroid Build Coastguard Worker
40*61c4878aSAndroid Build Coastguard Worker#. Embedded projects (particularly Pigweed projects) often have *multiple*
41*61c4878aSAndroid Build Coastguard Worker   targets that use *multiple* toolchains. Most build systems that generate
42*61c4878aSAndroid Build Coastguard Worker   compilation databases put all compile commands in a single database, meaning
43*61c4878aSAndroid Build Coastguard Worker   a single file can have multiple, conflicting compile commands. ``clangd``
44*61c4878aSAndroid Build Coastguard Worker   will typically use the first one it finds, which may not be the one you want.
45*61c4878aSAndroid Build Coastguard Worker
46*61c4878aSAndroid Build Coastguard Worker#. Pigweed projects have build steps that use languages other than C/C++. These
47*61c4878aSAndroid Build Coastguard Worker   steps are not relevant to ``clangd`` but some build systems will include them
48*61c4878aSAndroid Build Coastguard Worker   in the compilation database anyway.
49*61c4878aSAndroid Build Coastguard Worker
50*61c4878aSAndroid Build Coastguard WorkerTo deal with these challenges, ``pw_ide`` processes the compilation database(s)
51*61c4878aSAndroid Build Coastguard Workeryou provide, yielding one or more compilation databases that are valid,
52*61c4878aSAndroid Build Coastguard Workerconsistent, and specific to a particular target and toolchain combination.
53*61c4878aSAndroid Build Coastguard WorkerThis enables code intelligence and navigation features that accurately reflect
54*61c4878aSAndroid Build Coastguard Workera specific build.
55*61c4878aSAndroid Build Coastguard Worker
56*61c4878aSAndroid Build Coastguard WorkerAfter processing a compilation database, ``pw_ide`` knows what targets are
57*61c4878aSAndroid Build Coastguard Workeravailable and provides tools for selecting which target the language server
58*61c4878aSAndroid Build Coastguard Workershould use.  Then ``clangd``'s configuration is changed to use the compilation
59*61c4878aSAndroid Build Coastguard Workerdatabase associated with that target.
60*61c4878aSAndroid Build Coastguard Worker
61*61c4878aSAndroid Build Coastguard Worker----------------------
62*61c4878aSAndroid Build Coastguard WorkerImplementation details
63*61c4878aSAndroid Build Coastguard Worker----------------------
64*61c4878aSAndroid Build Coastguard Worker.. tab-set::
65*61c4878aSAndroid Build Coastguard Worker
66*61c4878aSAndroid Build Coastguard Worker   .. tab-item:: Bazel
67*61c4878aSAndroid Build Coastguard Worker
68*61c4878aSAndroid Build Coastguard Worker      Bazel doesn't have native support for generating compile commands, so it's
69*61c4878aSAndroid Build Coastguard Worker      common to rely on outside tools. In the
70*61c4878aSAndroid Build Coastguard Worker      :ref:`Pigweed Visual Studio Code extension<module-pw_ide-guide-vscode>`,
71*61c4878aSAndroid Build Coastguard Worker      we use the `Bazel Compile Commands Extractor <https://github.com/hedronvision/bazel-compile-commands-extractor>`_.
72*61c4878aSAndroid Build Coastguard Worker
73*61c4878aSAndroid Build Coastguard Worker   .. tab-item:: GN
74*61c4878aSAndroid Build Coastguard Worker
75*61c4878aSAndroid Build Coastguard Worker      Invoking GN with the ``--export-compile-commands`` flag (e.g.
76*61c4878aSAndroid Build Coastguard Worker      ``gn gen out --export-compile-commands``) will output a compilation
77*61c4878aSAndroid Build Coastguard Worker      database in the ``out`` directory along with all of the other GN build
78*61c4878aSAndroid Build Coastguard Worker      outputs (in other words, it produces the same output as ``gn gen out``
79*61c4878aSAndroid Build Coastguard Worker      but *additionally* produces the compilation database). You can remove the
80*61c4878aSAndroid Build Coastguard Worker      need to explicitly provide the flag by adding this to your ``.gn`` file:
81*61c4878aSAndroid Build Coastguard Worker      ``export_compile_commands = [ ":*" ]``.
82*61c4878aSAndroid Build Coastguard Worker
83*61c4878aSAndroid Build Coastguard Worker      The database that GN produces will have all compile commands for all
84*61c4878aSAndroid Build Coastguard Worker      targets, which is a problem for the reasons described above. It will also
85*61c4878aSAndroid Build Coastguard Worker      include invocations of certain Pigweed Python scripts that are not valid
86*61c4878aSAndroid Build Coastguard Worker      C/C++ compile commands and cause ``clangd`` to fault. So these files need
87*61c4878aSAndroid Build Coastguard Worker      to be processed to:
88*61c4878aSAndroid Build Coastguard Worker
89*61c4878aSAndroid Build Coastguard Worker      * Filter out invalid compile commands
90*61c4878aSAndroid Build Coastguard Worker
91*61c4878aSAndroid Build Coastguard Worker      * Separate compile commands into separate databases for each target
92*61c4878aSAndroid Build Coastguard Worker
93*61c4878aSAndroid Build Coastguard Worker      * Resolve relative paths so ``clangd`` can find tools in the Pigweed
94*61c4878aSAndroid Build Coastguard Worker        environment
95*61c4878aSAndroid Build Coastguard Worker
96*61c4878aSAndroid Build Coastguard Worker      The :ref:`pw_ide CLI<module-pw_ide-guide-cli>` does all of this when you
97*61c4878aSAndroid Build Coastguard Worker      run the ``sync`` command.
98*61c4878aSAndroid Build Coastguard Worker
99*61c4878aSAndroid Build Coastguard Worker   .. tab-item:: CMake
100*61c4878aSAndroid Build Coastguard Worker
101*61c4878aSAndroid Build Coastguard Worker      Enabling the ``CMAKE_EXPORT_COMPILE_COMMANDS`` option ensures that
102*61c4878aSAndroid Build Coastguard Worker      compilation databases are produced along with the rest of the CMake build.
103*61c4878aSAndroid Build Coastguard Worker      This can be done either in your project's ``CMakeLists.txt`` (i.e.
104*61c4878aSAndroid Build Coastguard Worker      ``set(CMAKE_EXPORT_COMPILE_COMMANDS ON)``), or by setting the flag when
105*61c4878aSAndroid Build Coastguard Worker      invoking CMake (i.e. ``-DCMAKE_EXPORT_COMPILE_COMMANDS=ON``).
106*61c4878aSAndroid Build Coastguard Worker
107*61c4878aSAndroid Build Coastguard Worker      CMake will generate separate ``compile_commands.json`` files that are
108*61c4878aSAndroid Build Coastguard Worker      specific to each target in the target's build output directory. These
109*61c4878aSAndroid Build Coastguard Worker      files are *already* in the format we need them to be in, so the only
110*61c4878aSAndroid Build Coastguard Worker      thing Pigweed needs to provide is a mechanism for discovering those
111*61c4878aSAndroid Build Coastguard Worker      targets and pointing ``clangd`` at the appropriate file.
112*61c4878aSAndroid Build Coastguard Worker
113*61c4878aSAndroid Build Coastguard Worker.. _module-pw_ide-design-cpp-target-groups:
114*61c4878aSAndroid Build Coastguard Worker
115*61c4878aSAndroid Build Coastguard Worker-------------
116*61c4878aSAndroid Build Coastguard WorkerTarget groups
117*61c4878aSAndroid Build Coastguard Worker-------------
118*61c4878aSAndroid Build Coastguard WorkerRunning code intelligence on the compilation database of a single target is the
119*61c4878aSAndroid Build Coastguard Workermost *consistent* approach, but it's not always the most *useful*. For example,
120*61c4878aSAndroid Build Coastguard Workerapplication code and test code are usually built in separate targets, but it's
121*61c4878aSAndroid Build Coastguard Workera nuisance to switch code intelligence targets as you move back and forth
122*61c4878aSAndroid Build Coastguard Workerbetween application code and test code.
123*61c4878aSAndroid Build Coastguard Worker
124*61c4878aSAndroid Build Coastguard WorkerWe address this through the use of "target groups", which in which a compilation
125*61c4878aSAndroid Build Coastguard Workerdatabase is build by intentionally combining the compile commands from several
126*61c4878aSAndroid Build Coastguard Workerrelated targets. Continuing the previous example, you might have a target
127*61c4878aSAndroid Build Coastguard Workergroup that contains both the application code and test code to eliminate the
128*61c4878aSAndroid Build Coastguard Workernuisance of repeatedly switching between those targets. The compile commands
129*61c4878aSAndroid Build Coastguard Workerfor the application code would be higher in the list than those for test code,
130*61c4878aSAndroid Build Coastguard Workerso in a conflict (e.g., a test that uses a different backend from the
131*61c4878aSAndroid Build Coastguard Workerapplication code), you will get code intelligence for the application code. This
132*61c4878aSAndroid Build Coastguard Workeris usually an acceptable trade-off.
133