Set Environment Variables for Debug, Launch, and Tools with CMake and Open Folder

Will Buik

Content outdated


For up-to-date documentation see Open Folder support for C++ build systems in Visual Studio.
There are many reasons why you may want to customize environment variables. Many build systems use environment variables to drive behavior; debug targets sometimes need to have PATH customized to ensure their dependencies are found; etc. Visual Studio has a mechanism to customize environment variables for debugging and building CMake projects and C++ Open Folder. In Visual Studio 2019 16.4 we made some changes to simplify this across Visual Studio’s JSON configuration files.

This post is going to cover how to use this feature from the ground up with the new changes since not everyone may be familiar with how and when to use this feature. However, for those who have used the feature before, here’s a quick summary of the changes:

  • Your existing configuration files will still work with these changes, but IntelliSense will recommend using the new syntax going forward.
  • Debug targets are now automatically launched with the environment you specify in CMakeSettings.json and CppProperties.json. Custom tasks have always had this behavior and still do.
  • Debug targets and custom tasks can have their environments customized using a new “env” tag in launch.vs.json and tasks.vs.json.
  • Configuration-specific variables defined in CppProperties.json are automatically picked up by debug targets and tasks without the need to set “inheritEnvironments”. CMakeSettings.json has always worked this way and still does.

Please try out the new preview and let us know what you think.

Customizing Environment Variables

There are now two ways to specify environment variables for CMake and C++ Open Folder. The first is to set up the overall build environment. This is done in CMakeSettings.json for CMake and CppProperties.json for C++ Open Folder. Environment variables can be global for the project or specific to an individual configuration (selected with the configuration dropdown menu). These environment variables will be passed to everything, including CMake builds, custom tasks, and debug targets.

Environment variables can also be used in any value in Visual Studio’s configuration JSON files using the syntax:

"${env.VARIABLE_NAME}"

Global and configuration specific environment variables can be defined in “environment” blocks in both CMakeSettings.json and CppProperties.json. For example, the following example sets environment variables differently for a “Debug” and “Release” configuration in CMakeSettings.json:

{
  // These environment variables apply to all configurations.
  "environments": [
    {
      "DEBUG_LOGGING_LEVEL": "warning"
    }
  ],

  "configurations": [
    {
      // These environment variables apply only to the debug configuration.
      // Global variables can be overridden and new ones can be defined.
      "environments": [
        {
          "DEBUG_LOGGING_LEVEL": "info;trace",
          "ENABLE_TRACING": "true"
        }
      ],

      "name": "Debug",
      "generator": "Ninja",
      "configurationType": "Debug",
      "inheritEnvironments": [ "msvc_x64_x64" ],
      "buildRoot": "${projectDir}\\out\\build\\${name}",
      "installRoot": "${projectDir}\\out\\install\\${name}",
      "cmakeCommandArgs": "",
      "buildCommandArgs": "-v",
      "ctestCommandArgs": "",
      "variables": []
    },

    {
      // Configurations do not need to override environment variables.
      // If none are defined, they will inherit the global ones.

      "name": "Release",
      "generator": "Ninja",
      "configurationType": "RelWithDebInfo",
      "buildRoot": "${projectDir}\\out\\build\\${name}",
      "installRoot": "${projectDir}\\out\\install\\${name}",
      "cmakeCommandArgs": "",
      "buildCommandArgs": "-v",
      "ctestCommandArgs": "",
      "inheritEnvironments": [ "msvc_x64_x64" ],
      "variables": []
    }
  ]
}

The second way to specify environment variables is used to customize individual debug targets and custom tasks. This is done in launch.vs.json and tasks.vs.json respectively. To do this, you add an “env” tag to individual targets and tasks that specifies the environment variables that need to be customized. You can also unset a variable by setting it to null.

The following example sets an environment variable for a debug target to enable some custom logging in launch.vs.json and the same “env” syntax can be applied to any task in tasks.vs.json:

{
  "version": "0.2.1",
  "defaults": {},
  "configurations": [
    {
      "type": "default",
      "project": "cmake\\CMakeLists.txt",
      "projectTarget": "envtest.exe",
      "name": "envtest.exe",
      "env": {
        "DEBUG_LOGGING_LEVEL": "trace;info"
        "ENABLE_TRACING": "true"
      }
    }
  ]
}

Keep in mind, if you want an environment variable to be set for all debug targets and tasks, it is better to do it globally in CMakeSettings.json or CppProperties.json

Send us Feedback

Your feedback is a critical part of ensuring that we can deliver the best experience.  We would love to know how Visual Studio 2019 version 16.4 is working for you. If you find any issues or have a suggestion, the best way to reach out to us is to Report a Problem.

2 comments

Discussion is closed. Login to edit/delete existing comments.

  • Hristo Hristov 0

    Is there any chance that “CMakeSettings.json” to support the following form of environment inheritance:
    (please note “variables”, “paths”, etc.)

    “`
    {
    “configurations”: [
    {
    “name”: “Ninja-MSVC-x64-Debug”,
    “generator”: “Ninja”,
    “configurationType”: “Debug”,
    “inheritEnvironments”: [ “msvc_x64_x64”, “paths”, “configuration_debug” ],
    “cmakeCommandArgs”: “”,
    “buildCommandArgs”: “-v”,
    “ctestCommandArgs”: “”,
    “variables”: []
    },
    {
    “name”: “Ninja-MSVC-x64-RelWithDebInfo”,
    “generator”: “Ninja”,
    “configurationType”: “RelWithDebInfo”,
    “inheritEnvironments”: [ “msvc_x64_x64”, “paths”, “configuration_release” ],
    “cmakeCommandArgs”: “”,
    “buildCommandArgs”: “-v”,
    “ctestCommandArgs”: “”,
    “variables”: []
    },
    {
    “name”: “Ninja-Clang-x64-Debug”,
    “generator”: “Ninja”,
    “configurationType”: “Debug”,
    “inheritEnvironments”: [ “clang_cl_x64”, “msvc_x64”, “paths”, “configuration_debug” ],
    “cmakeCommandArgs”: “${clang_cl_x64_env.CMakeCommandArgs}”,
    “buildCommandArgs”: “-v”,
    “ctestCommandArgs”: “”,
    “variables”: []
    },
    {
    “name”: “VS2019-MSVC-x64-Debug”,
    “generator”: “Visual Studio 16 2019 Win64”,
    “configurationType”: “Debug”,
    “inheritEnvironments”: [ “debug” ],
    “cmakeCommandArgs”: “”,
    “buildCommandArgs”: “-m -v:minimal”,
    “ctestCommandArgs”: “”,
    “variables”: []
    },
    {
    “name”: “VS2019-Clang-x64-Debug”,
    “generator”: “Visual Studio 16 2019 Win64”,
    “configurationType”: “Debug”,
    “inheritEnvironments”: [ “configuration_debug” ],
    “cmakeCommandArgs”: “-T llvm”,
    “buildCommandArgs”: “-m -v:minimal”,
    “ctestCommandArgs”: “”,
    “variables”: []
    }
    ],
    “environments”: [
    {
    “environment”: “clang_cl_x64”,
    “namespace”: “clang_cl_x64_env”,
    “ClangPath”: “\”${env.LLVM_ROOT}/bin/clang-cl.exe\””,
    “ClangFlags”: “\”-m64\””,
    “CMake_C_Compiler”: “-DCMAKE_C_COMPILER=${clang_cl_x64_env.ClangPath}”,
    “CMake_CXX_Compiler”: “-DCMAKE_CXX_COMPILER=${clang_cl_x64_env.ClangPath}”,
    “CMakeCommandArgs”: “${clang_cl_x64_env.CMake_C_Compiler} ${clang_cl_x64_env.CMake_CXX_Compiler}”
    },
    {
    “environment”: “paths”,
    “buildRoot”: “${workspaceRoot}\\..\\__build-output\\${name}”,
    “installRoot”: “${workspaceRoot}\\..\\__install-output\\${name}”
    },
    {
    “environment”: “type_debug”,
    “variables”: [
    {
    “name”: “option_EngineLibraryAs_SHARED”,
    “value”: “YES”,
    “type”: “BOOL”
    },
    {
    “name”: “option_EnableLoggingLevel_Verbose”,
    “value”: “YES”,
    “type”: “BOOL”
    },
    {
    “name”: “option_Graphics_CheckGraphicsApiCalls”,
    “value”: “YES”,
    “type”: “BOOL”
    },
    {
    “name”: “option_Graphics_OpenGL_PreferIntegratedGPU”,
    “value”: “YES”,
    “type”: “BOOL”
    }
    ]
    },
    {
    “environment”: “type_release”,
    “variables”: [
    {
    “name”: “option_EngineLibraryAs_SHARED”,
    “value”: “YES”,
    “type”: “BOOL”
    }
    ]
    }
    ]
    }
    “`

  • Sohno Mehar 0

    The @HostListener decorator is used to set up an event binding on the host element and is applied to a method. The example directive relies on the browser’s DOM API to manipulate its host element, both to add and remove class memberships and to receive the click event. Working with the DOM API in an Angular application is a useful technique…… Read More

Feedback usabilla icon