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

Unable to find Ninja when using CMakePresets.json and clang-cl.exe

Open BLaZeKiLL opened this issue 4 years ago • 8 comments

Brief Issue Summary

When configuring without CMakePresets.json everything works fine but when I use the CMakePresets.json for vcpkg integration configuration fails with the error Ninja not found.

Ninja ,Cmake and Clang are installed on my system as part of Visual Studio 2019

Expected:

  1. Create CMakePresets.json
  2. Press F7 for configure
  3. Configuration should be generated

Apparent Behavior:

  1. Create CMakePresets.json
  2. Press F7 for configure
  3. Error is logged stating ninja is not found

CMake Tools Log

[main] Building folder: Sandbox 
[main] Configuring folder: Sandbox 
[proc] Executing command: "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -DCMAKE_BUILD_TYPE=Debug "-DCMAKE_C_COMPILER=C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/VC/Tools/Llvm/x64/bin/clang-cl.exe" "-DCMAKE_CXX_COMPILER=C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/VC/Tools/Llvm/x64/bin/clang-cl.exe" -DCMAKE_INSTALL_PREFIX=d:/C++/Sandbox/out/install/amd64-windows-clang -DCMAKE_TOOLCHAIN_FILE:FILEPATH=C:/Sdk/vcpkg/scripts/buildsystems/vcpkg.cmake -Hd:/C++/Sandbox -Bd:/C++/Sandbox/out/build/amd64-windows-clang -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] -- Configuring incomplete, errors occurred!
[cmake] See also "D:/C++/Sandbox/out/build/amd64-windows-clang/CMakeFiles/CMakeOutput.log".

Platform and Versions

  • Operating System: Windows 10
  • CMake Version: 3.19.20122902-MSVC_2
  • VSCode Version: 1.56.2
  • CMake Tools Extension Version: 1.7.3
  • Compiler/Toolchain: Clang 11.0.0 (MSVC CLI) - amd64

Other Notes/Information

My CMakePreset.json, created by following the box2d-lite example

{
  "version": 2,
  "configurePresets": [
    {
      "name": "base-config",
      "description": "Sets generator, build and install directory, vcpkg",
      "hidden": true,
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/out/build/${presetName}",
      "cacheVariables": {
        "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}",
        "CMAKE_TOOLCHAIN_FILE": {
          "type": "FILEPATH",
          "value": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
        }
      },
      "environment": {
        "VCPKG_FEATURE_FLAGS": "manifests,versions,binarycaching,registries"
      }
    },
    {
      "name": "amd64-windows-clang",
      "displayName": "Clang 11.0.0 (MSVC CLI) (Visual Studio Professional 2019 Release - amd64)",
      "inherits": [
        "base-config"
      ],
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Debug",
        "CMAKE_C_COMPILER": "C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/VC/Tools/Llvm/x64/bin/clang-cl.exe",
        "CMAKE_CXX_COMPILER": "C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/VC/Tools/Llvm/x64/bin/clang-cl.exe"
      },
      "toolset": {
        "value": "amd64",
        "strategy": "external"
      },
      "architecture": {
        "value": "amd64",
        "strategy": "external"
      },
      "vendor": {
        "microsoft.com/VisualStudioSettings/CMake/1.0": {
          "hostOS": [ "Windows" ]
        }
      }
    }
  ],
  "buildPresets": [
    {
      "name": "base-build",
      "description": "Inherits environment from base-config configurePreset",
      "configurePreset": "base-config",
      "hidden": true,
      "inheritConfigureEnvironment": true
    },
    {
      "name": "build",
      "description": "Clean before build (--clean-first)",
      "configurePreset": "amd64-windows-clang",
      "inherits": "base-build",
      "cleanFirst": true
    }
  ]
}

BLaZeKiLL avatar May 22 '21 10:05 BLaZeKiLL

@BLaZeKiLL, thank you for opening this report. This looks like a bug and we will investigate and fix it. In the meantime, try to add in your preset environment variables the path to your ninja installation. It is very probably that this will unblock you. Please let us know if this idea works or not.

andreeis avatar May 24 '21 22:05 andreeis

I added ninja to the preset path and got another error that rc command was not found (part of windows sdk) So I assumes that in case of CMakepresets.json the path variable from vs-dev-shell are not being loaded so I copied my PATH variable from vs-dev-shell and this time I got this error

[proc] Executing command: "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -DCMAKE_BUILD_TYPE=Debug "-DCMAKE_C_COMPILER=C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/VC/Tools/Llvm/bin/clang-cl.exe" "-DCMAKE_CXX_COMPILER=C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/VC/Tools/Llvm/bin/clang-cl.exe" -DCMAKE_INSTALL_PREFIX=d:/C++/Sandbox/out/install/amd64-windows-clang -DCMAKE_TOOLCHAIN_FILE:FILEPATH=C:/Sdk/vcpkg/scripts/buildsystems/vcpkg.cmake -Hd:/C++/Sandbox -Bd:/C++/Sandbox/out/build/amd64-windows-clang -G Ninja
[cmake] -- The C compiler identification is Clang 11.0.0 with MSVC-like command-line
[cmake] -- The CXX compiler identification is Clang 11.0.0 with MSVC-like command-line
[cmake] -- Detecting C compiler ABI info
[cmake] -- Detecting C compiler ABI info - failed
[cmake] -- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/VC/Tools/Llvm/bin/clang-cl.exe
[cmake] -- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/VC/Tools/Llvm/bin/clang-cl.exe - broken
[cmake] CMake Error at C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.19/Modules/CMakeTestCCompiler.cmake:66 (message):
[cmake]   The C compiler
[cmake] 
[cmake]     "C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/VC/Tools/Llvm/bin/clang-cl.exe"
[cmake] 
[cmake]   is not able to compile a simple test program.
[cmake] 
[cmake]   It fails with the following output:
[cmake] 
[cmake]     Change Dir: D:/C++/Sandbox/out/build/amd64-windows-clang/CMakeFiles/CMakeTmp
[cmake]     
[cmake]     Run Build Command(s):C:/PROGRA~2/MICROS~1/2019/PROFES~1/Common7/IDE/COMMON~1/MICROS~1/CMake/Ninja/ninja.exe cmTC_0294e && [1/2] Building C object CMakeFiles\cmTC_0294e.dir\testCCompiler.c.obj
[cmake]     [2/2] Linking C executable cmTC_0294e.exe
[cmake]     FAILED: cmTC_0294e.exe 
[cmake]     cmd.exe /C "cd . && "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E vs_link_exe --intdir=CMakeFiles\cmTC_0294e.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100183~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100183~1.0\x64\mt.exe --manifests  -- C:\PROGRA~2\MICROS~1\2019\PROFES~1\VC\Tools\Llvm\bin\lld-link.exe /nologo CMakeFiles\cmTC_0294e.dir\testCCompiler.c.obj  /out:cmTC_0294e.exe /implib:cmTC_0294e.lib /pdb:cmTC_0294e.pdb /version:0.0 /machine:X86  /debug /INCREMENTAL /subsystem:console  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cmd.exe /C "cd /D D:\C++\Sandbox\out\build\amd64-windows-clang\CMakeFiles\CMakeTmp && "C:\Program Files\PowerShell\7\pwsh.exe" -noprofile -executionpolicy Bypass -file C:/Sdk/vcpkg/scripts/buildsystems/msbuild/applocal.ps1 -targetBinary D:/C++/Sandbox/out/build/amd64-windows-clang/CMakeFiles/CMakeTmp/cmTC_0294e.exe -installedDir C:/Sdk/vcpkg/installed/x64-windows/debug/bin -OutVariable out""
[cmake]     LINK Pass 1: command "C:\PROGRA~2\MICROS~1\2019\PROFES~1\VC\Tools\Llvm\bin\lld-link.exe /nologo CMakeFiles\cmTC_0294e.dir\testCCompiler.c.obj /out:cmTC_0294e.exe /implib:cmTC_0294e.lib /pdb:cmTC_0294e.pdb /version:0.0 /machine:X86 /debug /INCREMENTAL /subsystem:console kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:CMakeFiles\cmTC_0294e.dir/intermediate.manifest CMakeFiles\cmTC_0294e.dir/manifest.res" failed (exit code 1) with the following output:
[cmake]     lld-link: error: could not open 'kernel32.lib': no such file or directory
[cmake]     lld-link: error: could not open 'user32.lib': no such file or directory
[cmake]     lld-link: error: could not open 'gdi32.lib': no such file or directory
[cmake]     lld-link: error: could not open 'winspool.lib': no such file or directory
[cmake]     lld-link: error: could not open 'shell32.lib': no such file or directory
[cmake]     lld-link: error: could not open 'ole32.lib': no such file or directory
[cmake]     lld-link: error: could not open 'oleaut32.lib': no such file or directory
[cmake]     lld-link: error: could not open 'uuid.lib': no such file or directory
[cmake]     lld-link: error: could not open 'comdlg32.lib': no such file or directory
[cmake]     lld-link: error: could not open 'advapi32.lib': no such file or directory
[cmake]     lld-link: error: could not open 'msvcrtd.lib': no such file or directory
[cmake]     lld-link: error: could not open 'oldnames.lib': no such file or directory
[cmake]     ninja: build stopped: subcommand failed.
[cmake]     
[cmake]     
[cmake] 
[cmake]   
[cmake] 
[cmake]   CMake will not be able to correctly generate this project.
[cmake] Call Stack (most recent call first):
[cmake]   CMakeLists.txt:2 (project)
[cmake] 
[cmake] 
[cmake] -- Configuring incomplete, errors occurred!
[cmake] See also "D:/C++/Sandbox/out/build/amd64-windows-clang/CMakeFiles/CMakeOutput.log".
[cmake] See also "D:/C++/Sandbox/out/build/amd64-windows-clang/CMakeFiles/CMakeError.log".

After searching I found this is something related to Clang not using the correct ABI tough couldn't find a fix for my case

Anyway I started digging through the vscode-cmake-tools src code and found this in the driver.ts

/**
 * Get the environment variables that should be set at CMake-configure time.
 */
async getConfigureEnvironment(): Promise<proc.EnvironmentVariables> {
  if (this.useCMakePresets) {
    return this._configurePreset?.environment as proc.EnvironmentVariables;
  } else {
    let envs = getKitEnvironmentVariablesObject(this._kitEnvironmentVariables);
    /* NOTE: By mergeEnvironment one by one to enable expanding self containd variable such as PATH properly */
    /* If configureEnvironment and environment both configured different PATH, doing this will preserve them all */
    envs = util.mergeEnvironment(envs, await this.computeExpandedEnvironment(this.config.environment, envs));
    envs = util.mergeEnvironment(envs, await this.computeExpandedEnvironment(this.config.configureEnvironment, envs));
      envs = util.mergeEnvironment(envs, await this.computeExpandedEnvironment(this._variantEnv, envs));
      return envs;
    }
  }

In case of CMakePresets.json env var from the kit is not being loaded now I assume this is by design since the goal of CMakePresets.json is to give complete control and everything needs to be configured manually.

In any case my original goal was to just get vcpkg integration working and upon searching the docs of vscode-cmake-tools the only mention of vcpkg integration was under CMakePresets,json

I'll try by passing the vcpkg toolchain file through extensions settings and see what happens..

BLaZeKiLL avatar May 25 '21 08:05 BLaZeKiLL

Ok, thank you for trying these workarounds. I am sorry that nothing helped to unblock you. We will investigate and fix the issue.

andreeis avatar May 25 '21 17:05 andreeis

In case of CMakePresets.json env var from the kit is not being loaded now I assume this is by design since the goal of CMakePresets.json is to give complete control and everything needs to be configured manually.

@BLaZeKiLL I disagree about that statement about design goal. The goal of CMakePresets is to add the ability to read Specific configuration from the file instead of calling cmake with the dozens of options. On 'normal' systems (i.e. linux) you usually can have several compilers in PATH (i.e. /usr/bin/gcc, /usr/bin/clang, /usr/bin/clang-10), and ninja/make and others are always available in PATH. Adding of additional compilers usually happens via CMake Toolchains, where you configure for example cross compilation environment, and specify some compilers which are not available on system (but not ninja or make) The goal of CMakePresets is not to configure your whole build environment, but rather to set the tools you wish when configuring your project. In other words: all paths must be considered where compilers and tools are installed.

Even the documentation (https://github.com/microsoft/vscode-cmake-tools/blob/develop/docs/cmake-presets.md) states following:

[!NOTE] If you're a windows developer, you must open Visual Studio Code from a developer command prompt. Or, run the CMake: Scan for Compilers command before the CMake Tools extension can detect build tools (CMake, Ninja) that are installed with Visual Studio.

So this would be the workaround, but it's ugly.

invy avatar Aug 27 '21 13:08 invy

To add to @BLaZeKiLL 's point: we have a setup where we do not want to explicitly set the cmake generator, as far as we are concerned we would like cmake to use the default generator it finds on the system so we can easily use the same preset for windows with Visual Studio and Linux with make. However it seems that adding a minimal preset file autogenerates several unwanted options, i.e. a preset file which only sets the toolchain file results in a cmake call which specifies the generator as Ninja and specifies output directories.

i.e. using this toolchain file:

{
    "version": 4,
    "configurePresets": [
        {
            "name": "default",
            "cacheVariables": {
                "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake"
            }
        }
    ]
}

showing the configure command outputs this:

/usr/bin/cmake -DCMAKE_TOOLCHAIN_FILE=<projectdir>/vcpkg/scripts/buildsystems/vcpkg.cmake -S<projectdir> -B<projectdir>/out/build/default -G Ninja

I think if the build dir and the generator is unspecified in the preset, the extension should NOT touch those ! ⚡

maltevesper avatar Jun 09 '22 23:06 maltevesper

Or am I seeing an incarnation of this and am confused here: https://github.com/microsoft/vscode-cmake-tools/issues/1792#issuecomment-823664675?

@andreeis in case that is your issue I am happy to generate logs. (Is there an issue on github for the issue you mentioned in the linked comment?)

maltevesper avatar Jun 09 '22 23:06 maltevesper

Is there some progress on this issue? Today, while investigating this issue (I've completely forgotten I've seen this one already)I found my own workaround here in this issue. It would be nice if VSCode CMake Tools would be able to find all it needs for configuring project. Somehow "Scan for Kits' didn't work and the only viable workaround was running vscode from developer command prompt.

invy avatar Sep 04 '23 09:09 invy

This seems very likely to be related to #3497

gcampbell-msft avatar Feb 16 '24 21:02 gcampbell-msft