microsoft / vscode-cmake-tools

CMake integration in Visual Studio Code
https://marketplace.visualstudio.com/items?itemName=vector-of-bool.cmake-tools
MIT License
1.48k stars 455 forks source link

`cmake.buildDirectory` not used #4083

Closed bradenmcd closed 1 month ago

bradenmcd commented 2 months ago

Discussed in https://github.com/microsoft/vscode-cmake-tools/discussions/4053

Originally posted by **bradenmcd** September 9, 2024 Why might the value for `cmake.buildDirectory` not be used? The entirety of my user `settings.json` is this: ```json { "window.autoDetectColorScheme": true, "cmake.showOptionsMovedNotification": false, "cmake.pinnedCommands": [ "workbench.action.tasks.configureTaskRunner", "workbench.action.tasks.runTask" ], "cmake.buildDirectory": "${userHome}/build/${workspaceRootFolderName}" } ``` There is no project-specific `settings.json` (i.e., no `.vscode` directory for the project); yet, the `cmake` command line that VS Code executes looks like this: ``` [proc] Executing command: "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -DCMAKE_BUILD_TYPE=RelWithDebInfo -SC:/Users/Braden/OneDrive/Source/Repos/hello-cpp -BC:/Users/Braden/OneDrive/Source/Repos/hello-cpp/out/build/windows-x64-v143-RelWithDebInfo -G Ninja ``` Why might the `cmake.buildDirectory` setting not be picked up? I'm using version 1.19.51 of the CMake Tools.
v-frankwang commented 2 months ago

@bradenmcd We tried to reproduce the program based on the information you provided, but we can't reproduce it, here are the steps we took to reproduce it, can you give some suggestions?

ENV: CMake Tools: v1.19.52 vscode: v1.93.1 c/c++: v1.21.6 Repro steps:

  1. Create a folder and open it with vscode Add a file named main.cpp and add the following code:
    
    #include "iostream"
    using  namespace std;

int main() { cout<< "helloworld"<<endl; return 0; }

2. Add a file named CMakeLists.txt and add the following code:

cmake_minimum_required(VERSION 3.5.0) project(Helloworld) add_executable(Helloworld main.cpp)


3.Set in the settings.json file:`"cmake.buildDirectory": "${userHome}/build/${workspaceRootFolderName}"`
4.Run command: **CMake: "configure**"
5. Run command: **CMake: "Build"**

Actual result:
![image](https://github.com/user-attachments/assets/3ed19bed-7e5a-40fe-8c89-e509fa0c0b2e)
bradenmcd commented 2 months ago

I think the problem may be triggered by the addition of a CMakePresets.json.

Consider the attached one. CMakePresets.json

If I add this file, initially things work fine.

But if I shut down VSCode and restart it, I see the following in the output window when trying to configure:

[proc] Executing command: "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" --version
[proc] Executing command: "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E capabilities
[kit] Successfully loaded 4 kits from C:\Users\Braden\AppData\Local\CMakeTools\cmake-tools-kits.json
[presetController] Reading and validating the presets "file C:\Users\Braden\OneDrive\Source\Repos\vscode-cmake-tools-4083-test\CMakePresets.json"
[presetController] Successfully validated C:\Users\Braden\OneDrive\Source\Repos\vscode-cmake-tools-4083-test\CMakePresets.json against presets schema
[presetController] Expanding presets file C:\Users\Braden\OneDrive\Source\Repos\vscode-cmake-tools-4083-test\CMakePresets.json
[presetController] Successfully expanded presets file C:\Users\Braden\OneDrive\Source\Repos\vscode-cmake-tools-4083-test\CMakePresets.json
[main] Configuring project: vscode-cmake-tools-4083-test 
[proc] Executing command: "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -DCMAKE_BUILD_TYPE=RelWithDebInfo -SC:/Users/Braden/OneDrive/Source/Repos/vscode-cmake-tools-4083-test -BC:/Users/Braden/OneDrive/Source/Repos/vscode-cmake-tools-4083-test/out/build/windows-x64-v143-RelWithDebInfo -G Ninja
[cmake] CMake Error: CMake was unable to find a build program corresponding to "Ninja".  CMAKE_MAKE_PROGRAM is not set.  You probably need to select a different build tool.
[cmake] CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
[cmake] CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage
[cmake] -- Configuring incomplete, errors occurred!
[proc] The command: "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -DCMAKE_BUILD_TYPE=RelWithDebInfo -SC:/Users/Braden/OneDrive/Source/Repos/vscode-cmake-tools-4083-test -BC:/Users/Braden/OneDrive/Source/Repos/vscode-cmake-tools-4083-test/out/build/windows-x64-v143-RelWithDebInfo -G Ninja exited with code: 1
v-frankwang commented 2 months ago

@bradenmcd @gcampbell-msft We reproduced the issue using a simple project that doesn't reproduce when I don't add CMakePresets.json, and reproduces the issue when I add CMakePresets.json:

ENV: CMake Tools: v1.19.52 vscode: v1.93.1 c/c++: v1.21.6 Repro steps:

  1. Create a folder and open it with vscode
  2. Add a file named main.cpp and add the following code:
    
    #include "iostream"
    using  namespace std;

int main() { cout<< "helloworld"<<endl; return 0; }

3. Add a file named **CMakeLists.txt** and add the following code:

cmake_minimum_required(VERSION 3.5.0) project(Helloworld) add_executable(Helloworld main.cpp)

4. Add a file named **CMakePresets.json** and add the following code:

{ "version": 3, "cmakeMinimumRequired": { "major": 3, "minor": 21, "patch": 0 }, "configurePresets": [ { "name": "windows", "hidden": true, "generator": "Ninja", "condition": { "type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows" } }, { "name": "windows-x64", "inherits": "windows", "hidden": true, "architecture": { "value": "x64", "strategy": "external" } }, { "name": "windows-x64-v143", "inherits": "windows-x64", "hidden": true, "toolset": { "value": "v143", "strategy": "external" } }, { "name": "windows-x64-v143-RelWithDebInfo", "inherits": "windows-x64-v143", "cacheVariables": { "CMAKE_BUILD_TYPE": "RelWithDebInfo" } }, { "name": "windows-x64-v143-Debug", "inherits": "windows-x64-v143", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" } } ], "buildPresets": [ { "name": "windows-x64-v143-RelWithDebInfo", "configurePreset": "windows-x64-v143-RelWithDebInfo" }, { "name": "windows-x64-v143-Debug", "configurePreset": "windows-x64-v143-Debug" } ] }



5. Set in the settings.json file:**"cmake.buildDirectory": "${userHome}/build/${workspaceRootFolderName}"**
6. Reopen project.
7. Run command: **CMake: "configure**"
8. Select "**windows-x64-v143-RelWithDebInfo**"
9. Run command: **CMake: "Build**"

Don't add CMakePreset.json:
![image](https://github.com/user-attachments/assets/97eeb9b0-f1c1-4d18-b388-b75453a5e336)

Add CMakePreset.json:
![image](https://github.com/user-attachments/assets/7fbcc0bf-9ecf-4533-a4ba-829f2c08b13e)
bradenmcd commented 2 months ago

@v-frankwang There is an additional issue here that you seem not to have reproduced; but, for me, is also triggered by the addition of the CMakePresets.json: while CMake Tools finds the cmake.exe included with VS2022 just fine, it seems not to find the similarly included ninja.exe. Note that I have neither cmake.exe nor ninja.exe in the system PATH; nor have I set cmake.cmakePath.

However, if there is no CMakePresets.json, the CMake Tools seem to find both cmake.exe and ninja.exe just fine.

v-frankwang commented 1 month ago

@bradenmcd For this problem :https://github.com/microsoft/vscode-cmake-tools/issues/4083#issuecomment-2370142992, its because your compiler and generator are installed by installing visual studio, so you should use Developer Command Prompt for VS to open vscode and this problem will be solved! Below is my demo recording: 4083

bradenmcd commented 1 month ago

@v-frankwang I understand why that works.

But VSCode CMake Tools' behavior here still seems broken.

gcampbell-msft commented 1 month ago

@bradenmcd To make this easier you can use the setting cmake.useVsDeveloperEnvironment. This setting defaults to auto, which only tries to add the PATHs you're mentioning if it can find the VS environment, and also based on what compiler you're using. To turn this on by default, you can change the setting to always.

If you enable this setting, does this resolve your issue?

bradenmcd commented 1 month ago

@gcampbell-msft Changing cmake.useVsDeveloperEnvironment to always does allow ninja.exe to be found. But, based on your description here, it seems like auto should be working this way, too.

gcampbell-msft commented 1 month ago

@bradenmcd Great! However, auto will only work if you have a certain compiler defined using your CMake cache variables AND it's not found on the system, and therefore we look for it.

You can see the code here: https://github.com/microsoft/vscode-cmake-tools/blob/9b6e016e726acecd19272ded2f1c211fcfeeb1c7/src/preset.ts#L1094

gcampbell-msft commented 1 month ago

@bradenmcd Following up again, the original issue is expected, as the cmake.buildDirectory is not used when Presets are used. Instead, the settings of the presets are used. With the above comments and this information in mind, I believe this issue is resolved as expected behavior, so I'll close the issue as such.

Please feel free to ping me here if there is information that is still missing or if you believe this issue shouldn't be closed. Thanks!

bradenmcd commented 1 month ago

@gcampbell-msft

However, auto will only work if you have a certain compiler defined using your CMake cache variables AND it's not found on the system, and therefore we look for it.

Backing up a bit, it seems intuitive to me that if CMake Tools is able to find the cmake.exe that Visual Studio installed, it should also be able to find the ninja.exe without further assistance. I understand your explanation that this is not currently the case; but why shouldn't it be the case?

Regarding the original issue, note that in this case CMakePresets.json does not define binaryDir. In this case, rather than using the value defined for cmake.buildDirectory, CMake Tools seems to use the (baked-in) default value for cmake.buildDirectory. I understand this isn't an out-of-spec choice; it's just not the most intuitive one.

gcampbell-msft commented 2 weeks ago

Backing up a bit, it seems intuitive to me that if CMake Tools is able to find the cmake.exe that Visual Studio installed, it should also be able to find the ninja.exe without further assistance. I understand your explanation that this is not currently the case; but why shouldn't it be the case?

I would actually agree with this. Looking at the code, assuming it didn't find Ninja, when using the auto setting and we detect that we should use the auto setting, it should look for both, assuming we don't find Ninja. If this is something that you're experiencing, please open an issue!

Regarding the original issue, note that in this case CMakePresets.json does not define binaryDir. In this case, rather than using the value defined for cmake.buildDirectory, CMake Tools seems to use the (baked-in) default value for cmake.buildDirectory. I understand this isn't an out-of-spec choice; it's just not the most intuitive one.

Thanks for the feedback. Just for some additional context, after Presets v3 binaryDir isn't required and it defaults to a value, so we are attempting to follow that design.