VS 2015 Update 1 中带微软代码生成的Clang

[原文发表地址]Clang with Microsoft CodeGen in VS 2015 Update 1

[原文发表时间] 2015/12/4 7:17 PM

[这篇博客的作者是Dave Bartolomeo 和Clang/C2 团队的组员]

在开发和维护跨平台C++代码方面,其中一个改变就是针对不同平台的不同编译器的问题。 你写的一些针对Windows平台的代码,用Visual C++编译器可以编译成功,但那时你针对安卓平台的编译就会失败,那是因为Clang的标准规格更为严格,你的代码恰好是按照比较宽容的Visual C++编写的。又或者你针对iOS用了一些新的代码,Clang可以编译成功,但是才发现这些新的C++语言,Visual C++是还无法支持的,你只能想办法重新实现这个方法而不用这个新的语言特性,或者生成一个单独的能够用Visual C++编译的Windows实现方式。

为了能够更加方便的进行跨平台代码的开发,使在Windows 和其他平台更好的工作, 我们为Visual Studio单独发布了一个额外的编译工具集, 叫带微软代码生成的Clang编译器。 这个编译器为C语言和C++语言使用开源的Clang解析,还有Visual C++ 编译工具的代码生成器和优化器。像对其他平台一样,你可以为Windows使用相同的Clang解析你的跨平台代码,还能够充分利用Visual C++优化器先进的优化功能。因为针对非Windows平台,新的工具也使用的是一样的Clang解析,你不需要在代码里写满令人讨厌的#ifdefs,只需要为不同的编译器说明下即可。同时你的代码中可以使用那些还没有被Visual C++ 编译器所支持的语言特性, 包括C99 复杂类型和C++ 14 扩展的constexpr的支持。因为基于Clang的编译器会长生和Visual C++编译器一样格式的调试的信息,所以你能感受到同样很棒的Visual Studio 调试器体验。

用新的编译工具所编译的代码能够和Visual C++ 2015 C和C++编译器所编译的其他代码相链接。通常,你可以使用带微软代码生成的Clang编译器来编译跨平台代码,用普通的Visual C++ 工具集来编译特定的Windows代码(例如,你的UI)。

请注意,带微软代码生成的Clang编译器现在是一个预览功能。 我们知道在很多方面它还不够完善,仍存在一些漏洞。我们希望你可以尝试使用这个新功能,明白它如在应用在你的代码工作上,并给我们反馈。

安装

在Visual Studio 2015 Update 1中,Visual Studio安装时开始进行功能选择时的UI界面,你会看到在“跨平台和手机开发\Visual C++ 手机开发”下有一个带微软代码生成的Clang编译器的可选框。选中这个框之后将会安装新的工具集以及相应的工程模板。

使用新的工具

要创建使用带微软代码生成的Clang编译器的静态库和Dll工程,你可以在”Visual C++\Cross Platform”下选择这两个工程模板进行创建。

现有工程的迁移

为了在已有的工程中使用新的工具,你可以去工程的属性页面,更改”平台工具“,在下拉菜单中从”Visual Studio 2015“ 改成"Clang 3.7 with Microsoft CodeGen". 在你切换去编辑其他属性之前,请确保你已点击”Apply“,让工程系统去加载相应工具的定义。

在这次所发布的预览版中,我们还没有支持从”Visual Studio 2015“到"Clang 3.7 with Microsoft CodeGen"工具相应属性值的自动迁移,所以你得自己去手动修改一些错误的值。工程系统将会指出在新的工具集中那些错误的旧的以前工具集中的属性值。当这些值超过现有工具的默认设置(它们在工程属性以粗体字显示)时,你会遇到这些错误,这些值不会自己切换到新的工具集下的默认值。在大部分情况下,改变这些非法值”从父母或者工程默认继承“的设置将会解决这个问题。下面是你可能遇到的一些其他需要解决的问题:

  • 在这次发布的版本中,一些默认值可能不是你所期望的。我们会在将来发布的版本中修改这些默认值。
  • 当修改MSVC工具集时,异常处理(即使异常处理是可以使用的)是默认关闭的。开发人员可以手动切换, 这个默认值在下一个发布版本中会改变。
  • 当前,预编译头文件是不能支持的,所以你不能使用它们。这样做的错误将会体现在生成多个输出文件时的一个错误:"error : cannot specify -o when generating multiple output files". 如果你禁用预编译头文件,却仍然能看到这个错误,请确认一下”Object File Name“这个属性的值在Clang工具集下设为默认的"$(IntDir)%(filename).obj"。
  • 如果你正在尝试将工程里面的源文件转成UTF-16编码, Clang如果提示给你一个带BOM的UTF-16编码源文件的错误,这时你需要将他们保存成UTF-8。
  • 如果你遇到的错误"error : use of undeclared identifier 'O_WRONLY'", 那么在你的工程中设置macro __STDC__=0。
  • 如果你遇到的错误"TRK0005: Failed to locate: "clang.exe". The system cannot find the file specified”,你可能使用的是AMD64宿主编译器。对Clang/C2工具集现在还不支持对AMD64宿主编译器。请参照这里了解如何让你工程使用x86宿主工具。
  • 如果你想要使用“VS 2015 x86 Native Tools 命令提示符’',请注意,在现在发布的版本中,通过PATH的环境变量是无法使用clang.exe。你需要更改环境再使用clang.exe

判断你的平台和工具

编译器工具集通常会定义一系列的宏指令来帮助让你代码去适应不同版本的编译器目标平台。这个表列出了带微软代码生成的Clang编译器相关的宏指令和一个代码示例,你可以包含在你的工程中来帮助你确定平台和工具组合。

image

 

// Include (and extend) this code in your project to determine platform and toolset combination

#if defined(_WIN32) && !defined(_WIN64)
puts("I am targeting 32-bit Windows.");
#endif

#ifdef _WIN64
puts("I am targeting 64-bit Windows.");
#endif

#ifdef __clang__
printf("I am Clang, version: %s\n", __clang_version__);
#endif

#if defined( __clang__ ) && defined( __c2__ )
puts("I am Clang/C2.");
#endif

#if defined( __clang__ ) && defined( __llvm__ )
puts("I am Clang/LLVM.");
#endif

// Not tested: __EDG__, __GNUC__, etc.

 

#if defined( _MSC_ VER) && !defined(__clang__)
printf("I am C1XX/C2, version: %02d.%02d.%05d.%02d\n",
_MSC_VER / 100, _MSC_VER % 100, _MSC_FULL_VER % 100000, _MSC_BUILD);
#endif

第一预览版中的已知问题

因为这是我们发布的一个预览版本,所以发布的时候我们知道存在一些问题。我们想让软件尽快的被我们的开发者使用,从而他们可以评估工具并且体验一下代码在这个工具下运行的状况。不幸的是, 这意味着发布的时候存在几个已知的bug。

  • 不支持ARM平台。 在下一次发布的Update中,已有的通用应用程序工程模板将会支持ARM平台。
  • 不支持PCH版本。 在任何一个设置过这个新的平台工具集的工程 中, 关闭 PCH 运用。
  • 不支持OpenMP。你会看到到一个诊断写着“不支持OpenMP”。
  • 任何操作位结构都没有内联汇编。你会看到一个诊断写着:“不支持内联汇编”或“GNU式内联汇编功能已取消”
  • Clang编译的编译单元没有LTCG。 这样的编译单元仍然可以链接其它被MSVC编译为LTCG的编译单元。
  • Clang编译的编译单元没有没有PGO 仪表或者优化。
  • 目前不支持 /bigobj。目标文件中的数量部分限制为2 ^16。
  • 不支持std::atomic_flag,因为无声糟糕代码的生成。这个问题会在下一个update中修复。
  • 源文件没有哈希散列。调试器利用文件哈希值以确保源文件和它编译过程中有相同的版本。
  • 调试类型信息将始终放置在 .obj文件中(相当于cl.exe / Z7,而不是 /Zi)。没有功能丢失,但产生的 .obj文件可能会更大。
  • 某些情况下,智能感知可能无法感知Clang行为。
  • 目前Clang诊断只提供英文版本。

Clang LLVM贡献

Microsoft CodeGen 的Clang不仅仅是开源Clang编译器的一个私有部分。我们将把我们已经取得的绝大多数的Clang和LLVM变化贡献给官方Clang和LLVM资源。这些变化的最大之处是提供与Visual Studio调试器兼容的调试信息支持。这个变化也将允许使用LLVM代码生成器进行代码编译,从而用Visual Studio调试代码。

随着Clang发布新的版本,我们将把新的版本更新在我们的安装中。