4

I have two executables that are build from the same source (a client and a server) and they're built with the compile options -D CLIENT=0 -D SERVER=1 for the server and -D CLIENT=1 -D SERVER=0 for the client. If I do something like

if (CLIENT) {
// Client specific code
}

clangd complains that CLIENT is not defined. Is there a way to make clangd aware of those macros? (The code compiles just fine, the errors are from clangd, not the compiler)

Duddino
  • 53
  • 4
  • It cant be reproduced https://godbolt.org/z/b56aPsW6G – 0___________ Jun 08 '21 at 13:07
  • yes, `clang` compiles just fine, the problem is with `clangd`, the language server – Duddino Jun 08 '21 at 13:08
  • Instead of `if (CLIENT)` which might get evaluated at run-time, depending on the optimization settings, I suggest to use `#ifdef CLIENT` or `#if CLIENT` – Bodo Jun 08 '21 at 13:16
  • This is not the best way to use compile time configuration. You better use the preprocessor `#ifdef`/`ifndef` directives to conditionally compile specific code portions. – Eugene Sh. Jun 08 '21 at 13:16
  • I find `if (CLIENT)` easier to read, and i'll use it if I can. It will definitely be optimized by any modern compiler anyways – Duddino Jun 08 '21 at 13:49

3 Answers3

1

Is there a way to make clangd aware of those macros?

From getting started with clangd:

Project setup

To understand source code in your project, clangd needs to know the build flags. (This is just a fact of life in C++, source files are not self-contained.)

By default, clangd will assume that source code is built as clang some_file.cc, and you’ll probably get spurious errors about missing #included files, etc. There are a couple of ways to fix this.

compile_commands.json

compile_commands.json file provides compile commands for all source files in the project. This file is usually generated by the build system, or tools integrated with the build system. Clangd will look for this file in the parent directories of the files you edit. Other tools can also generate this file. See the compile_commands.json specification.

compile_commands.json is typically generated with CMake build system, but more build systems try to generate it.

I would suggest moving your project to CMake, in the process you will learn this tool that will definitely help you in further C-ish development.

compile_flags.txt

If all files in a project use the same build flags, you can put those flags, one flag per line, in compile_flags.txt in your source root.

Clangd will assume the compile command is clang $FLAGS some_file.cc.

Creating this file by hand is a reasonable place to start if your project is quite simple.

If not moving to cmake, create a compile_flags.txt file with the content for example like the following, and clangd should pick this file up:

-DCLIENT=1
-DSERVER=1
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • If you aren't using cmake, you can also use something like [Bear](https://github.com/rizsotto/Bear) to build compile_commands.json. – Hasturkun Jun 08 '21 at 15:22
  • 1
    @Hasturkun: [Compiledb](https://github.com/nickdiego/compiledb) might be a better alternative, as it does not require a project rebuild. – godo Apr 06 '22 at 06:49
1

The Answer above suggest to use compile_flags.txt, but it would be ignored if compile_commands.json is present.

It's suggested to add a project configuration .clangd in the root of your project. And add the compile flags manually.

#.clangd
CompileFlags:
  Add: [-DLAB_PGTBL, -DSOL_PGTBL]
Xander C
  • 11
  • 1
0

How about rather than making clangd aware of them, make the error message suppressed? As it is not always desired to switch the build system, nor is it always welcome to add non-essential files to all codebases.

Few people would object to adding safety checks such as these, providing more clear error messages:

#ifndef CLIENT
#error "CLIENT undeclared. Must be set when building."
#define CLIENT 0
#endif

#ifndef SERVER
#error "SERVER undeclared. Must be set when building."
#define SERVER 0
#endif

With those in place, one can suppress the pp_hash_error in ones clangd.yaml file:

clangd.yaml:

Diagnostics:
  Suppress: pp_hash_error

One could of course instead suppress the undeclared_var_use directly, without needing the safety check in the source code. However one can argue that has a high risk of hiding real errors, while explicit #error calls should rarely be of interest for clangd.

sampi
  • 576
  • 5
  • 15