microsoft / vscode-cpptools

Official repository for the Microsoft C/C++ extension for VS Code.
Other
5.52k stars 1.55k forks source link

Add support for `${command:<name-of-command>}` in c_cpp_properties.json #12884

Open thernstig opened 2 days ago

thernstig commented 2 days ago

Feature Request

Add support for ${command:<name-of-command>} in c_cpp_properties.json.

The rationale is that the CMake extension exposes a command like ${command:cmake.buildDirectory}. This can later be used in c_cpp_properties.json such as:

"compileCommands": "${command:cmake.buildDirectory}/compile_commands.json",

This is necessary since in CMake you can have multiple build directories via presets like "binaryDir": "${sourceDir}/build/${presetName}". It does not work to use the ${config:cmake.buildDirectory} in this case as that one only works for CMake Kits and not CMake Presets, see https://github.com/microsoft/vscode-cmake-tools/issues/4065.

Colengms commented 1 day ago

Hi @thernstig . Thanks for submitting this suggestion.

This is very similar to https://github.com/microsoft/vscode-cpptools/issues/12883 . The same caveats apply. Dynamic configuration features would seem best implemented (per file) using a custom configuration provider extension than by trying to make the 'base configuration' more dynamic. If your scenario involves CMake, it's a likely a solution would make more sense coming from the CMake Tools extension.

thernstig commented 21 hours ago

@Colengms I raised a potential issue to the CMake guys (@gcampbell-msft) with the initial proposal here.

It would be be problematic having c_cpp_properties.json try to list a command? At which point in time should it invoke the command? My gut feel is that a generally better approach overall would be that there was a ${file:cmake.compileCommands} config that points to the compile_commands.json file, where it is a symlink to the real file. That way, the C/C++ extension could have a file watcher on this file and update whenever it changes when a CMake preset regenerates it (which at the same time CMake updates the symlink). That way IntelliSense would get refreshed each time a new preset is built.

Do you think that is a good proposal instead?

bobbrow commented 20 hours ago

Is there a reason you can't use "configurationProvider": "ms-vscode.cmake-tools"? It is supposed to be at least equivalent to using the compile_commands.json file produced by the CMake generator.

sean-mcmanus commented 19 hours ago

@thernstig I may have missed it, but why can't the compileCommands be set as a path? You said "the C/C++ extension could have a file watcher on this file", but we already have a file watcher on the compileCommands file -- is that not working for you? If you have multiple build directories with different compileCommands you can use multiple configurations and switch between them?

thernstig commented 4 hours ago

@bobbrow we do have that, and I read https://code.visualstudio.com/docs/cpp/faq-cpp previously that it should be enough. I have a vague memory that I read somewhere it falls back to the compileCommands if for some case the CMake extension cannot figure it out, so I kept it as a backup.

@sean-mcmanus because the output path changes for compile_commands.json. It changes depending on the configure CMake preset. See here:

{
    "version": 8,
    "$schema": "https://cmake.org/cmake/help/latest/_downloads/3e2d73bff478d88a7de0de736ba5e361/schema.json",
    "configurePresets": [
        {
            "name": "Debug",
            "displayName": "Debug: GCC 9.4.0 x86_64-linux-gnu",
            "description": "Using compilers: C = /usr/bin/gcc, CXX = /usr/bin/g++",
            "binaryDir": "${sourceDir}/build/${presetName}",
            "cacheVariables": {
                "CMAKE_RUNTIME_OUTPUT_DIRECTORY": "${sourceDir}/bin",
                "CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install/${presetName}",
                "CMAKE_C_COMPILER": "/usr/bin/gcc",
                "CMAKE_BUILD_TYPE": "Debug",
                "CMAKE_C_STANDARD": "90",
                "CMAKE_C_STANDARD_REQUIRED": "TRUE",
                "CMAKE_EXPORT_COMPILE_COMMANDS": "YES"
            }
        }
    ],
    "buildPresets": [
        {
            "name": "Debug helloworld app",
            "displayName": "Debug helloworld",
            "configurePreset": "Debug",
            "targets": [
                "helloworld"
            ]
        }
    ]
}

If I added another item for production builds in the configurePresets array the path "binaryDir": "${sourceDir}/build/${presetName}" would change. The compile_commands.json ends up in the build directory (a.k.a. known as the badly named "binary dir" in the CMake world).