Create relative paths for compiler_commands.json

I am working on a project where the code is currently compiled inside a linux container.
When I instruct cmake to write the file it uses absolute paths.

cmake -S /app/opt/myApp -B /app/opt/myApp -DCMAKE_EXPORT_COMPILE_COMMANDS=YES

Which results in compiler_commands.json containing absolute paths to both the compiler and the other libraries. Once I debug the program outside of the container, my Language Server (clangd) will read the compile_commands.json file. Then return values that can only be resolved within the container.

How can i make the compile_commands.json file use relative paths?

Is there a way to make it write with paths with environment variables like %PATH%, %HOME%,etc?

AFAIK you cannot produce relative path: cf:
https://cmake.org/cmake/help/latest/variable/CMAKE_USE_RELATIVE_PATHS.html

However you can use volume mount in the container that makes the path to be the same in the container as in the host.

and then:

so I bet the container and the host are somehow “compatible” or do you do “remote debugging” from the host to the container ?

In any case making the source tree and the build appear at the same location in the container and on the host should be the simplest path to go (I do that myself for the same reason as yours).

@erk thanks for the contribution here.

That is the same thing i have found. The way we use docker containers is to provide a cross platform solution for running the container. The problem is that if you start to do very specific mounts which are not relative to the container’s path then it is no longer cross platform.

For example to run the container on windows gcc will likely be located within msys, and the Conan Packages that are pulled with the container get installed @ $HOME/.conan/data. So with this combination (docker + conan + cmake) you can buidl cross platform solutions that are just pull and run. Working in any env, but to debug those one must have the same path visible to CLANGD. Then begins the pain. As **CMAKE ** writes the compiler_commands.json it is using absolute paths. So if i just want to write cpp code on my desktop that is running the clangd language server, I cannot do it unless I do something like make a container which contains clangd, gdb, and an entire ide…Which far from elegant.

Someone else have a solution here?

CMake’s build trees are not relocatable in this way. You’ll need different compile_commands.json files for each platform (at least).

This is tough, because I want to have the same project root.
I am assuming there are others out there who setup their builds to target multiple platforms, but share the exact same directory (though a shared folder) . How do I do this? Any modern ide is going to use the compiler_commands (which is great) but I will have different paths for each one.

One a seperate note, the cmake discouse page has come a long way.

The thing is that even for the same directory, it is unlikely that the compilation commands are going to be exactly the same anyways (at least that is certainly true for many projects I’ve worked on). External dependency paths are certainly not going to be the same I imagine (different Linux distros, macOS, Windows, etc.).

Okay, that seems reasonable, because even if i get the dependencies all defined for external libraries, there will be other things that are called out of standard library. I would not say that I have found a solution to this problem completely. It just may be where the tech stands today. There has been so much progress in packaging of cpp binaries for cross platform development (conan) and development of the build config (cmake). However, there is still a bit of a gap when it comes to the compilation_commands.json because Language servers automatically look to the root of the build tree for that file. I guess I could make something that identifies the operating system then dynamically links the correct compiler_commands.json so that clang can find it.

(sudo code inside ProjectDir/cmakelists.txt)
Assume out of source build in some file like ProjectDir/build-thisos

  1. delete compiler_commands.json in root dir
  2. write compiler commands .json in current dir
  3. write softlink (based on os executing) from current build dir to project root dir

Feedback is welcome :slight_smile:

Improvements to compile_commands.json really need to go to the Clang developer list (e.g., adding a separate object/field for “working directory” of the file as a whole or some other variable replacement mechanism to allow for path expansions[1]). That’s where the spec is defined. I really don’t want to have CMake embark on adding things to it that do not have defined semantics within the wider community.

[1]Note that this makes quoting non-trivial to determine because the path can have all kinds of characters that need escaping in different ways depending on where in the command line it appears.

So i actually think i have a cmake based solution which is very simple.
Want to wait to share until completed. Will then add as proposed addition