Visual Studio中支持CMake:自定义环境

[原文发表地址] CMake Support in Visual Studio: Customizing your Environment

[原文发表时间] 2017/07/18

Visual Studio 15.3中,有一些新的方法可以将高级配置应用于你的CMake环境中。

下载最新的VS,并尝试最新的CMake功能。如果你刚刚开始使用CMake,请按照链接详细了解CMake support in Visual Studio。我们期待你的反馈。

CMakeSettings.json文件中的新功能

这个新的灵活性的核心在于项目的CMakeSettings.json文件中,它源自两个新概念:

  1. 全局或每个配置具有继承一组默认的环境变量的能力;

  2. 全局或每个配置具有定义环境变量及其值的能力。

我们先来看一下如何使用这个功能的例子:

 {
  // The "environments" property is an array of key value pairs of the form
  // { "EnvVar1": "Value1", "EnvVar2": "Value2" }
  "environments": [
    {
      "BuildDir": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build",
    }
  ],

  "configurations": [
    {
      "name": "x86-Debug",
      "generator": "Ninja",
      "configurationType": "Debug",
      // Inherit the defaults for using the MSVC x86 compiler.
      "inheritEnvironments": [ "msvc_x86" ],
      "buildRoot": "${env.BuildDir}\\${name}"
    },
    {
      "name": "x64-Debug",
      "generator": "Ninja",
      "configurationType": "Debug",
      // Inherit the defaults for using the MSVC x64 compiler.
      "inheritEnvironments": [ "msvc_x64" ],
      "buildRoot": "${env.BuildDir}\\${name}"
    }
  ]
}

稍微分析一下,此示例定义了使用Ninja构建此CMake项目的两个配置。第一个构建x86 debug,而另一个构建x64 debug。它还定义了在两种配置中都使用的环境变量“BuildDir”。

请记住,对于所有配置,单个配置或是两者都可以进行全局定义“environments”(第四行)和“inheritEnvironments”(第16行和第24行)属性。在上面的示例中,“BuildDir”变量是全局变量,而“inheritEnvironments”属性将被应用到单个的配置。

最后对单个配置中再次定义的环境变量,将会覆盖全局变量。下面的例子解释了注释中的覆盖行为:

 {
  // The "environments" property is an array of key value pairs of the form
  // { "EnvVar1": "Value1", "EnvVar2": "Value2" }
  "environments": [
    {
      "BuildDir": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}",
    }
  ],

  "configurations": [
    {
      "name": "x86-Debug",

      // The syntax for this property is the same as the global one above.
      "environments": [
        {
          // Replace the global property entirely.
          "BuildDir": "D:\\custom-builddir",
        }
      ],

      "generator": "Ninja",
      "configurationType": "Debug",
      // Inherit the defaults for using the MSVC x86 compiler.
      "inheritEnvironments": [ "msvc_x86" ],
      // This will evaluate to "D:\custom-builddir\x86-Debug" due to the
      // configuration-specific override.
      "buildRoot": "${env.BuildDir}\\${name}"
    },
    {
      "name": "x64-Debug",

      "generator": "Ninja",
      "configurationType": "Debug",
      // Inherit the defaults for using the MSVC x64 compiler.
      "inheritEnvironments": [ "msvc_x64" ],

      // Since this configuration doesn’t modify BuildDir, it inherits
      // from the one defined globally.
      "buildRoot": "${env.BuildDir}\\${name}"
    }
  ]
}

如果你需要为构建环境声明很多变量,然后对每个配置进行少量修改。则此覆盖行为可以大大缩减项目中的CMakeSettings.json文件。

关于Launch.vs.json和Tasks.vs.json

如果你想知道是否可以在CMakeSettings.json文件之外使用这些变量,答案是肯定的! 你在CMakeSettings.json文件中声明的所有环境变量都可用于使用相同的语法在“Tasks”和“Launch”配置。只需在任务或启动配置中将“${env.VarName}”语法嵌入到任何属性的值中即可。宏语法将被扩展为其实际值,如下面的示例中的第12行。

 {
  "version": "0.2.1",
  "defaults": {},
  "configurations": [
    {
      "type": "cppdbg",
      "name": "helloworld.exe",
      "project": "bin\\helloworld.exe",
      "cwd": "${workspaceRoot}",
      "program": "${debugInfo.target}",
      "MIMode": "gdb",
      "miDebuggerPath": "${env.MINGW_PREFIX}\\bin\\gdb.exe",
      "externalConsole": true
    }
  ]
}

如果环境变量的值是在配置中指定的,那么当你尝试运行任务或调试程序时,当前选定的配置中指定的值将被使用。

你声明的环境变量也将由任务启动的进程继承。另一方面,被调试的程序将不会继承构建环境。

 {
  "version": "0.2.1",
  "defaults": {},
  "configurations": [
    {
      "type": "default",
      "project": "ConsoleApp2\\PrintEnv.csproj",
      "name": "PrintEnv.csproj",
      "env": "var1=${env.var1}\u0000var2=hardcodedvalue"
    }
  ]
}

你可以在第9行看到可以引用在CMakeSettings.json文件中定义的变量。“\ u0000”是用于分隔变量的空字符。

高级功能

你那敏锐的眼睛可能已经注到,“environments”和“inheritEnvironments”是CMakeSettings.json语法中的数组。可以从多个环境中声明和继承。对于CMake场景中的典型用法,如果希望从多个环境中继承是不太可能的,但是在某些情况下,你可能希望声明多个环境块。 CMake的主要用例是声明一些你可以在CMakeSettings / launch.vs / tasks.vs JSON中引用的变量,但不希望将其添加到构建环境中——不被生成的构建过程所遗留。

以下示例显示了如何完成此操作:

   // The "environments" property is an array of key value pairs of the form
  // { "EnvVar1": "Value1", "EnvVar2": "Value2" }
  "environments": [
    {
      "BuildDir": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build",
    },
    {
      // “namespace” is a reserved key that lets you put variables
      // in namespaces other than $env.
      "namespace": "special",
      // SpecialVar will not be added to the environment.
      "SpecialVar": "special",
    }
  ],

  "configurations": [
    {
      "name": "x86-Debug",
      "generator": "Ninja",
      "configurationType": "Debug",
      // Inherit the defaults for using the MSVC x86 compiler.
      "inheritEnvironments": [ "msvc_x86" ],
      // You can use alternative namespaces (such as special defined above)
      // just like "$env."
      "buildRoot": "${env.BuildDir}\\${special.SpecialVar}\\${name}"
    },
    {
      "name": "x64-Debug",
      "generator": "Ninja",
      "configurationType": "Debug",
      // Inherit the defaults for using the MSVC x64 compiler.
      "inheritEnvironments": [ "msvc_x64" ],
      "buildRoot": "${env.BuildDir}\\${name}"
    }
  ]
}

你可以使用语法“$ {special.SpecialVar}”在CMakeSettings,Launch或Tasks JSON文件中访问“SpecialVar”,如第25行所示。

发送我们的反馈

要尝试最新和最好的CMake功能,并给我们一些早期的反馈,请下载并安装最新的Visual Studio 2017 Preview。和往常一样,我们欢迎你的反馈。请通过电子邮件cmake@microsoft.com,通过Twitter @visualcMicrosoft Visual Cpp的Facebook发送任何意见。

如果你遇到Visual Studio 2017的其他问题,请通过报告问题通知我们,该问题在安装程序和IDE本身都可用。有关建议,请通过UserVoice通知我们。我们期待你的反馈!