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