2

The problem

I am using CMake with Visual Studio 17 2022 to build a very simple executable binary. I am not sure if it is relevant to this issue, but the executable utilizes static gRPC binaries that were installed through vcpkg and protobuf-generated code, as it is a gRPC client.

When I build in x64 Debug configuration (set in Visual Studio), (see VS Configuration Settings Screenshot (Debug)) the executable is placed in the expected directory:

<project_dir>\out\build\x64-debug\examples\<example_name>\<example_name>.exe

However, when I try to build an x64 Release configuration, (see VS Configuration Settings Screenshot (Release)) the executable is placed in an unexpected location:

<project_dir>\out\build\x64-release\examples\<example_name>\Debug\<example_name>.exe

I have compared the binaries and found that they are identical. In other words, when building in an x64 Release configuration, a debug executable is still being built. The only difference that the configuration makes is where the executable ends up on disk. Note: There are no build errors. Just the wrong thing being built and put in the wrong place.

When I try to run the built executable through the Visual Studio GUI, it cannot find the release executable, probably because there is not an exe in the directory that it expects it to be in:

<project_dir>\out\build\x64-release\examples\<example_name>\<example_name>.exe

Steps Taken

  • I deleted all the CMake Cache and my build output. This changed nothing.
  • I deleted my Visual Studio cache. This changed nothing.
  • I tried to remove the set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$CONFIG:Debug:Debug>") line from my top level CMakeLists.txt file. This breaks the debug build, and does not affect the main issue at all.
  • I tried to change the set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$CONFIG:Debug:Debug>") line from my top level CMakeLists.txt file to set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$CONFIG:Debug:Release>"). This prevents CMake from being able to build at all, because it does not recognize that setting.
  • I removed all dependencies from the executable except for iostream (no more gRPC) in the source files and the CMakeLists files. In other words, I basically tried to do a hello world project, but this did not make a difference. I also repeated the steps above with the dependencies removed. No difference.
  • I copied the CMake command that Visual Studio was running to generate the

Minimum Reproducible Case

Project Structure

project
│
├──> CMakeLists.txt
├──> CMakePresets.json
├── src
│   ├──> CMakeLists.txt
│   └── test_lib
│        ├──> CMakeList.txt
│        ├──> test_lib.cpp
│        └──> test_lib.h
└── examples
    ├──> CMakeLists.txt
    └── hello_world
         ├──> CMakeList.txt
         └──> exampleA.cpp


project/CMakeLists.txt contents

cmake_minimum_required(VERSION 3.16)
project("TestProject")

# We are going to be fetching content, so include tools to do so.
include(FetchContent)

if(POLICY CMP0091)
  cmake_policy(SET CMP0091 NEW) 
endif()

# Must set this flag to run properly in debug mode.
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

# Get the pre-built GRPC static libs
find_package(gRPC CONFIG REQUIRED)
find_package(Protobuf REQUIRED)

# Disable shared libs (only using static)
set(BUILD_SHARED_LIBS OFF)

# Turn testing on
enable_testing()

# Add components
add_subdirectory("src")
add_subdirectory("examples")

project/CMakePresets.json contents

{
  "version": 3,
  "configurePresets": [
    {
      "name": "windows-base",
      "hidden": true,
      "generator": "Visual Studio 17 2022",
      "binaryDir": "${sourceDir}/out/build/${presetName}",
      "installDir": "${sourceDir}/out/install/${presetName}",
      "cacheVariables": {
        "CMAKE_C_COMPILER": "cl.exe",
        "CMAKE_CXX_COMPILER": "cl.exe",
        "VCPKG_TARGET_TRIPLET": "x64-windows-static",
        "CMAKE_TOOLCHAIN_FILE": {
          "value": "C:/github/vcpkg/scripts/buildsystems/vcpkg.cmake",
          "type": "FILEPATH"
        }
      },
      "condition": {
        "type": "equals",
        "lhs": "${hostSystemName}",
        "rhs": "Windows"
      }
    },
    {
      "name": "x64-debug",
      "displayName": "x64 Debug",
      "inherits": "windows-base",
      "architecture": {
        "value": "x64",
        "strategy": "external"
      },
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Debug"
      }
    },
    {
      "name": "x64-release",
      "displayName": "x64 Release",
      "inherits": "x64-debug",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release"
      }
    },
    {
      "name": "x86-debug",
      "displayName": "x86 Debug",
      "inherits": "windows-base",
      "architecture": {
        "value": "x86",
        "strategy": "external"
      },
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Debug"
      }
    },
    {
      "name": "x86-release",
      "displayName": "x86 Release",
      "inherits": "x86-debug",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release"
      }
    },
    {
      "name": "linux-debug",
      "displayName": "Linux Debug",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/out/build/${presetName}",
      "installDir": "${sourceDir}/out/install/${presetName}",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Debug"
      },
      "condition": {
        "type": "equals",
        "lhs": "${hostSystemName}",
        "rhs": "Linux"
      },
      "vendor": {
        "microsoft.com/VisualStudioRemoteSettings/CMake/1.0": {
          "sourceDir": "$env{HOME}/.vs/$ms{projectDirName}"
        }
      }
    },
    {
      "name": "macos-debug",
      "displayName": "macOS Debug",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/out/build/${presetName}",
      "installDir": "${sourceDir}/out/install/${presetName}",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Debug"
      },
      "condition": {
        "type": "equals",
        "lhs": "${hostSystemName}",
        "rhs": "Darwin"
      },
      "vendor": {
        "microsoft.com/VisualStudioRemoteSettings/CMake/1.0": {
          "sourceDir": "$env{HOME}/.vs/$ms{projectDirName}"
        }
      }
    }
  ]
}


project/src/CMakeLists.txt contents

add_subdirectory("test_lib")

project/src/test_lib/CMakeLists.txt contents

add_subdirectory("test_lib")

project/src/test_lib/test_lib.h contents

#pragma once

void printHelloWorld();

project/src/test_lib/test_lib.cpp contents

#include <iostream>

void printHelloWorld()
{
    std::cout << "Hello World" << std::endl;
}

project/examples/CMakeLists.txt contents

add_subdirectory("hello_world")

project/examples/hello_world/CMakeLists.txt contents

add_executable(example_a "exampleA.cpp" )
target_link_libraries(example_a PRIVATE test_lib)
target_include_directories(example_a PUBLIC "${PROJECT_SOURCE_DIR}/src/test_lib")

project/examples/hello_world/exampleA.cpp contents

#include "test_lib.h"
#include <iostream>

int main()
{
    printHelloWorld();
    std::cin.get();
}

Smitch
  • 171
  • 8
  • 1
    Please post a [mcve], w/o those magic words `` and ``. The screenshot "VS Configuration Settings Screenshot (Release)" shows "x64 Debug" configuration chosen. – 273K Jan 23 '23 at 17:28
  • I added a minimum reproducible case to the post and fixed the incorrect image. Thanks for catching that. – Smitch Jan 23 '23 at 18:51
  • Update: If I let Visual Studio call CMake by recompiling the CMake cache within Visual Studio in the minimum reproducible case, then I run the following command from the command line: msbuild \out\build\x64-release\TestProject.sln /p:Configuration=Release /p:Platform=x64 It works as expected. I am not sure how to see what msbuild command Visual Studio is using when I tell it to build the solution from the GUI. I have the command line as a workaround now, but I would still like to get to the bottom of this so my team can take full advantage of CMake integration in VS. – Smitch Jan 23 '23 at 18:52
  • 1
    Your preset `x64-release` inherits `x64-debug` one. Most likely you want to inherit `windows-base` preset instead, as in case of `x64-debug` preset. Note also, that for Visual Studio generator setting `CMAKE_BUILD_TYPE` variable is at least useless: this generator is **multiconfiguration** and its build type is not selected on the configuration stage (when `CMakeLists.txt` is parsed). You are better to define `x64-debug` and `x64-release` as **build** presets, which shares the same configuration preset but have own `configuration` settings. – Tsyvarev Jan 23 '23 at 19:11
  • 1
    See that question about proper defining Debug/Release presets for Visual Studio: https://stackoverflow.com/questions/70180828/visual-studio-2022-cmake-presets – Tsyvarev Jan 23 '23 at 19:14
  • That worked. Thank you for your help. I summarized the solution in an answer (and credited you), but then realized you may want the credit for the correct answer. Feel free to repost as an answer, and I will mark it as the solution. :) – Smitch Jan 23 '23 at 21:12

1 Answers1

0

Thanks to Tsyvarev for providing the answer in a comment.

To summarize my changes to my CMakePresets.json file:

  • The preset x64-release should not inherit x64-debug, but rather it should inherit windows-base.
  • The content previously under cacheVariables was useless and could possibly cause issues later, so I modified it as well.
  • Lastly, I needed to add a buildPresets section as in this question. My presets ended up looking like as follows.
    {
  "version": 3,

  "configurePresets": [
    {
      "name": "windows-base",
      "hidden": true,
      "generator": "Visual Studio 17 2022",
      "binaryDir": "${sourceDir}/build/${presetName}",
      "architecture": {
        "value": "x64",
        "strategy": "external"
      },
      "installDir": "${sourceDir}/build/install/${presetName}",
      "cacheVariables": {
        "VCPKG_TARGET_TRIPLET": "x64-windows-static",
        "CMAKE_TOOLCHAIN_FILE": {
          "value": "C:/github/vcpkg/scripts/buildsystems/vcpkg.cmake",
          "type": "FILEPATH"
        }
      },
      "condition": {
        "type": "equals",
        "lhs": "${hostSystemName}",
        "rhs": "Windows"
      }
    },
    {
      "name": "x64-debug",
      "displayName": "x64 Debug",
      "inherits": "windows-base",
      "cacheVariables": {
        "DCMAKE_BUILD_TYPE": "Debug",
        "CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreaded$<$<CONFIG:Debug>:Debug>"
      }
    },
    {
      "name": "x64-release",
      "displayName": "x64 Release",
      "inherits": "windows-base",
      "cacheVariables": {
        "DCMAKE_BUILD_TYPE": "Release",
        "CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreaded"
      }
    }
  ],
  "buildPresets": [
    {
      "name": "windows-debug",
      "displayName": "Debug",
      "configurePreset": "x64-debug",
      "configuration": "Debug"
    },
    {
      "name": "windows-release",
      "displayName": "Release",
      "configurePreset": "x64-release",
      "configuration": "Release"
    }
  ]
}
Smitch
  • 171
  • 8