vscode-cmake-tools icon indicating copy to clipboard operation
vscode-cmake-tools copied to clipboard

Setting "cmake.exportCompileCommandsFile": true does not work with CMake Presets

Open globberwops opened this issue 3 years ago • 15 comments

Brief Issue Summary

Setting "cmake.exportCompileCommandsFile": true does not work with CMake Presets.

Expected:

  1. Set "cmake.exportCompileCommandsFile": true
  2. -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=ON is added to the CMake configure call even when on the presets path

Platform and Versions

  • Operating System: Ubuntu
  • CMake Version: 3.20.2
  • VSCode Version: 1.55.0
  • CMake Tools Extension Version: 1.7.1
  • Compiler/Toolchain: GCC 9.3.0

globberwops avatar May 05 '21 19:05 globberwops

Thank you for opening this report. You can specify this in the preset as well. I just verified that it works. "cacheVariables": { "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" }

@xisui-MSFT, I don't see any reason why presets wouldn't pick up from regular settings but I am not sure, please confirm if this behavior is by design or we should fix something in CMake Tools. Is the user supposed to define the above when wanting compile_commands.json or the usual setting we had should have effect even with presets on?

andreeis avatar May 05 '21 19:05 andreeis

This is by design. All settings in settings.json that can be achieved via presets are ignored when using presets.

xisui-MSFT avatar May 05 '21 19:05 xisui-MSFT

@andreeis Thanks for your reply.

@xisui-MSFT The reason I would like to see this picked up from the settings is, that I want to be able to set this globally in my user settings. Otherwise I would have to write an awful amount of cmake user presets, just to get the compile commands exported.

globberwops avatar May 05 '21 19:05 globberwops

You can write a base preset like:

{
    "name": "base",
    "cacheVariables": {
        "CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
    },
    "hidden": true
}

And then in all presets you need this:

{
    "name": "name",
    "inherits": [
        "base",
        ...
    ],
    ...
}

xisui-MSFT avatar May 05 '21 19:05 xisui-MSFT

Also, each entry in cacheVariables is inherited independently. So you can write more cache vars in your base preset, and then overwrite any entry you need independently.

xisui-MSFT avatar May 05 '21 19:05 xisui-MSFT

@xisui-MSFT While this would be possible, it would still need a complete rewrite of all presets as far as I understand.

Suppose this is my CMakePresets.json:

{
    "version": 2,
    "cmakeMinimumRequired": {
        "major": 3,
        "minor": 20,
        "patch": 0
    },
    "configurePresets": [
        {
            "name": "preset_a",
            "generator": "Ninja Multi-Config",
            "binaryDir": "${sourceDir}/build"
        },
        {
            "name": "preset_b",
            "inherits": "preset_a",
            "cacheVariables": {
                "CACHE_VARIABLE_B": "ON"
            }
        },
        {
            "name": "preset_c",
            "inherits": "preset_a",
            "cacheVariables": {
                "CACHE_VARIABLE_C": "ON"
            }
        }
    ],
    "buildPresets": [
        {
            "name": "preset_a_release",
            "configurePreset": "preset_a",
            "configuration": "Release"
        },
        {
            "name": "preset_a_debug",
            "configurePreset": "preset_a",
            "configuration": "Debug"
        },
        {
            "name": "preset_b_release",
            "configurePreset": "preset_b",
            "configuration": "Release"
        },
        {
            "name": "preset_b_debug",
            "configurePreset": "preset_b",
            "configuration": "Debug"
        },
        {
            "name": "preset_c_release",
            "configurePreset": "preset_c",
            "configuration": "Release"
        },
        {
            "name": "preset_c_debug",
            "configurePreset": "preset_c",
            "configuration": "Debug"
        }
    ],
    "testPresets": [
        {
            "name": "preset_a_debug_testing",
            "configurePreset": "preset_a"
        },
        {
            "name": "preset_b_debug_testing",
            "configurePreset": "preset_b"
        },
        {
            "name": "preset_c_debug_testing",
            "configurePreset": "preset_c"
        }
    ]
}

My CMakeUserPresets.json would look something like this:

{
    "version": 2,
    "cmakeMinimumRequired": {
        "major": 3,
        "minor": 20,
        "patch": 0
    },
    "configurePresets": [
        {
            "name": "base",
            "cacheVariables": {
                "CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
            },
            "hidden": true
        },
        {
            "name": "preset_a_export",
            "inherits": [
                "base",
                "preset_a"
            ]
        },
        {
            "name": "preset_b_export",
            "inherits": [
                "base",
                "preset_b"
            ]
        },
        {
            "name": "preset_c_export",
            "inherits": [
                "base",
                "preset_c"
            ]
        }
    ],
    "buildPresets": [
        {
            "name": "preset_a_export_release",
            "configurePreset": "preset_a_export",
            "configuration": "Release"
        },
        {
            "name": "preset_a_export_debug",
            "configurePreset": "preset_a_export",
            "configuration": "Debug"
        },
        {
            "name": "preset_b_export_release",
            "configurePreset": "preset_b_export",
            "configuration": "Release"
        },
        {
            "name": "preset_b_export_debug",
            "configurePreset": "preset_b_export",
            "configuration": "Debug"
        },
        {
            "name": "preset_c_export_release",
            "configurePreset": "preset_c_export",
            "configuration": "Release"
        },
        {
            "name": "preset_c_export_debug",
            "configurePreset": "preset_c_export",
            "configuration": "Debug"
        }
    ],
    "testPresets": [
        {
            "name": "preset_a_export_debug_testing",
            "configurePreset": "preset_a_export"
        },
        {
            "name": "preset_b_export_debug_testing",
            "configurePreset": "preset_b_export"
        },
        {
            "name": "preset_c_export_debug_testing",
            "configurePreset": "preset_c_export"
        }
    ]
}

Which in extension brings me to https://github.com/microsoft/vscode-cmake-tools/issues/1836

Sorry for the wall of text.

globberwops avatar May 05 '21 23:05 globberwops

As this setting relates more to the IDE and configures IDE features (eg compile commands being available to the IDE) I would think this should be controlled by the IDE's cmake.exportCompileCommandsFile setting. The setting would not be required for out-of IDE builds and as such should not be in the configurePresets. It also would avoid having to edit existing project's build settings just to get an IDE feature working.

hwmaier avatar Jul 27 '21 00:07 hwmaier

I like to add that

    "cmake.configureEnvironment": {
        "CMAKE_EXPORT_COMPILE_COMMANDS": "ON",  
    },

does not work either for presets.

hwmaier avatar Oct 26 '21 00:10 hwmaier

@hwmaier, the same as many other settings that for now, by design, are not automatically inherited from a global settings scope (the one used for variants/kits), "cmake.configureEnvironment" would not be seen by the presets, but presets do have an "environment" keyword that you can define. Let us know if that doesn't work for you.

andreeis avatar Oct 26 '21 06:10 andreeis

Ok, so this is by design. I can understand this as you want Cmake yield the same result regardless if launched from VS Code or command line. I think for users familiar with the variant/kit system transitioning to the preset system this is something with must be expressed very clearly in the documentation.

And yes, setting CMAKE_EXPORT_COMPILE_COMMANDS in the preset environment works, this is what we are presently doing:

    "configurePresets": [
        {
...
            "environment": {
                "CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
            },

But I still think that exportCompileCommandsFile is a setting not for cmake itself but for the IDE controlling it so I believe cmake.exportCompileCommandsFile should flow through as it does not affect the build but allows VS Code to parse it and offer compile command for single C files.

hwmaier avatar Oct 26 '21 06:10 hwmaier

This issue is now marked as 'stale-old' due to there being no activity on it for the past 720 days. Unless the 'stale-old' label is removed or the issue is commented on, this will be remain open for at least 14 days and then it may be closed. If you would like to make this issue exempt from getting stale, please add the 'stale-exempt' label.

github-actions[bot] avatar Oct 19 '23 16:10 github-actions[bot]

I had the same issue last week. I am sad that the provided solution was not that intuitive... Using clangd or intellisense is an IDE related setting. Thus, I would expect those kind of settings that are not "build" related but rather "tooling" related, to pass through. On the other hand, I understand the hassle. Can we at least remove the "cmake.exportCompileCommandsFile" option if a cmake preset is detected? It is the default way to do cmake nowadays and it took me two days to understand what was going on. I think that @globberwops @mpusz and @bobbrow who reported this in the past will agree with the conditional removal of this setting

Jason5480 avatar Oct 21 '23 20:10 Jason5480

@Jason5480 From what I understand, extension settings can't be defined under a when clause, however, we could at the very least make a description change to cmake.exportCopmileCommandsFile setting to make sure that it's clear when it will and when it won't be used.

I'm not sure when we'll get to this, but since it's a simple request, I'll mark it as stale-exempt so that it doesn't get marked as stale again.

gcampbell-msft avatar Oct 24 '23 13:10 gcampbell-msft

@Jason5480 From what I understand, extension settings can't be defined under a when clause, however, we could at the very least make a description change to cmake.exportCopmileCommandsFile setting to make sure that it's clear when it will and when it won't be used.

I'm not sure when we'll get to this, but since it's a simple request, I'll mark it as stale-exempt so that it doesn't get marked as stale again.

Thank you very much @gcampbell-msft ! A detailed description and a warning sign and that will highlight the fact that this setting don't work if CMake is used with presets, would be very useful for ppl who want to use clangd and export compile_comands.json file! If there are any questions on how I use that setting inside a devcontainer you can check the public repo of the glaze json serialize library. Thank you again for your time

Jason5480 avatar Oct 25 '23 14:10 Jason5480

@Jason5480 Additionally, you should be able to do this strictly through cmake, and therefore CMakePresets.json: https://cmake.org/cmake/help/latest/variable/CMAKE_EXPORT_COMPILE_COMMANDS.html

gcampbell-msft avatar Apr 24 '24 13:04 gcampbell-msft