Search code examples
c++cvisual-studio-codeclangdheader-only

How to make clangd to enable header-only library implementation


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?


Solution

  • 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.