2

There is a way of distributing C/C++ libraries as a one header-only file. Library is in one library.h file: header declarations together with implementation hidden under #ifdef LIBRARY_IMPL. You need to create some .c/.cpp file that does #define LIBRARY_IMPL; #include "library.h" which creates compilation unit with implementation.

I have a project which uses such libraries extensively. Project build system creates compile_commands.json which is then used by clangd to provide project paths, data structures and hints to VSCode (with llvm-vs-code-extensions.vscode-clangd).

The issue I have is when opening the library.h file for editing, the symbol LIBRARY_IMPL is not defined, thus the #ifdef LIBRARY_IMPL section is treated as comment - without syntax highlighting, type checking etc.

Is there a way to tell clangd or the extension to treat the file as it was during compilation of the library.c wrapper file, not stand-alone .h file?

smokku
  • 1,256
  • 13
  • 22
  • 1
    the `c_cpp_properties.json` has a `defines` property – rioV8 Jul 28 '23 at 08:33
  • Another way for **[header only](https://en.wikipedia.org/wiki/Header-only) C++ libraries** is with `template` and `inline`; **for an example** see [this header only HTTP library](https://github.com/yhirose/cpp-httplib) – Basile Starynkevitch Jul 28 '23 at 08:38
  • Clangd has a project-wide config file where you can specify common compiler flags, maybe you can define your macro there. – HolyBlackCat Jul 28 '23 at 08:47
  • @BasileStarynkevitch What does `make` have to do with anything? You'll still need to generate the same `compiler_commands.json` regardless of build system choice. Regarding `inline`: this is way slower that only having the implementation in a single TU. – HolyBlackCat Jul 28 '23 at 08:49
  • 1
    Don’t call this arrangement “header-only”; that term has a specific meaning here. You could call it something like “implementation conditionally included in the header”. – Davis Herring Jul 28 '23 at 12:34

2 Answers2

1

A simple way would be to create a .clangd file in your project's root directory, containing:

CompileFlags:
  Add: [-DLIBRARY_IMPL]

This instructs clangd to add the flag -DLIBRARY_IMPL (which has the effect of defining the macro LIBRARY_IMPL) to any compile command used when opening a file in your project.

Note, for this to be effective, library.h needs to be located in the directory tree of your project (because the .clangd file will only apply to files in that directory tree).

If library.h is located outside the project directory, an alternative approach would be to create a user config file containing the same thing, but this time you probably want to make it conditional on the file's path:

If:
  PathMatch: /path/to/library/library.h

CompileFlags:
  Add: [-DLIBRARY_IMPL]

You can read more about clangd config files at https://clangd.llvm.org/config.html.

HighCommander4
  • 50,428
  • 24
  • 122
  • 194
-2

You can use the defines field of the c_cpp_properties.json file to set #defines in a way that clangd can see. Here is the full schema reference. The relevant portion is

"configurations": [
  {
    ...
    "defines": ["FOO", "BAR=100"],
    ...
  },
]

This is where you would put your LIBRARY_IMPL. Your c_cpp_properties.json file should be in the top level directory of your project folder.

Steampunkery
  • 3,839
  • 2
  • 19
  • 28
  • `c_cpp_properties.json` is for configuring [Microsoft's C++ plugin](https://github.com/microsoft/vscode-cpptools), not clangd. Clangd is usually configured using `compile_commands.json`, see https://clangd.llvm.org/installation#project-setup for details. You can also use a [clangd config file](https://clangd.llvm.org/config.html) to customize the configuration in cases where the `compile_commands.json` generated by the build is not suitable by itself. – HighCommander4 Jul 29 '23 at 01:19