将LLVM/Clang编译器整合到Visual Studio中

一、集成clang-cl编译器

clang-cl是兼容微软cl的模式,它支持微软cl编译器的绝大多数编译选项,目前还有部分选项不支持。

官网下载编译好的Windows平台安装包,LLVM 6有提供MSBuild集成工具,后续的版本不再提供,所以我们需要先下载LLVM 6并且在安装后把集成工具复制出来,路径在安装目录下的tools目录中。
可以看看目录下的东西:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到支持VS2010、VS2012、VS2013和VS2014(即VS2015),不支持VS2017和VS2019以及VS2010以前的版本,当然可以仔细研究一下这些配置文件,也可以自己做出相应VS版本的支持。(BTW:VS2017有专门的插件可以使用——LLVM Compiler Toolchain,这个工具目前只支持VS2017)

再从官网下载最新的安装包进行安装,目前最新版本是LLVM8.0.0,安装新包会自动卸载掉老包。

把之前复制出来的tools目录放回到安装目录下,打开所有的props文件,把

$(LLVMInstallDir)\lib\clang\6.0\lib\windows;

中的路径替换成当前安装的路径,比如安装了8.0.0的则为:

$(LLVMInstallDir)lib\clang\8.0.0\lib\windows;

然后在安装目录新建一个msbuild-bin目录,把bin目录中的clang-cl.exe复制到msbuild-bin目录,并改名为cl.exe

最后执行tools/msbuild/install.bat即可。

此时可以在项目属性中看到LLVM的踪影了,下图是VS2015的项目属性截图:
在这里插入图片描述
试试效果:
在这里插入图片描述
可以看到clang-cl的输出字样,说明成功了。

这里有一个问题,就是没有编译进度显示,即不知道当前编译的是哪个文件。研究了一下MSBuild,发现输出窗口的编译进度(当前编译的哪个文件)是在MSBuild的Microsoft.Build.CPPTasks.Common.dll中的CL任务调用过程中输出当前编译的文件名的,不是在配置文件中输出的。具体的代码为:

private void ReadUnicodeOutput(object stateInfo)
{
	uint num;
	byte[] lpBuffer = new byte[0x400];
	string str = string.Empty;
	while (NativeMethodsShared.ReadFile(this.unicodePipeReadHandle, lpBuffer, 0x400, out num, NativeMethodsShared.NullIntPtr) && (num != 0))
	{
		string str2 = str + Encoding.Unicode.GetString(lpBuffer, 0, (int)num);
		while (true)
		{
			int length = -1;
			length = str2.IndexOf('\n');
			if (length == -1)
			{
				str = str2;
				break;
			}
			string lineOfText = str2.Substring(0, length);
			str2 = str2.Substring(length + 1);
			if ((lineOfText.Length > 0) && lineOfText.EndsWith("\r", StringComparison.Ordinal))
			{
				lineOfText = lineOfText.Substring(0, lineOfText.Length - 1);
			}
			base.Log.LogMessageFromText(lineOfText, base.StandardOutputImportanceToUse);
		}
	}
	if (!string.IsNullOrEmpty(str))
	{
		base.Log.LogMessageFromText(str, base.StandardOutputImportanceToUse);
	}
	this.unicodeOutputEnded.Set();
}

它是利用了MS的CL编译器在编译时会输出文件名的功能,从管道中读取的。而Clang编译器在编译过程中是不会输出当前正在编译的文件名的,从管道中无法读取,所以不能显示当前编译进度。

为了使其显示编译进度,以VS2015为例,需要做出如下处理:

(一)、编写一个MSBuild任务dll

1.新建一个C#类库工程,取名为VSClang
2.新建一个类ClangCl,写下如下代码:

namespace VSClang
{
	using Microsoft.Build.Framework;
	using System.IO;

	public class ClangCl : Microsoft.Build.CPPTasks.CL
	{
		protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands)
		{
			foreach (ITaskItem item in base.SourcesCompiled)
			{
				base.Log.LogMessage(MessageImportance.High, Path.GetFileName(item.ItemSpec), new object[0]);
			}
			return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands);
		}
	}
}

3.编译成功后,将生成的VSClang.dll复制到MSBuild安装目录下与Microsoft.Build.CppTasks.Common.dll同一位置,笔者的在C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140下。

(二)、修改安装前配置(如果已经安装过了,修改后再安装一次即可)
  1. 修改x64以及Win32目录下toolset-vs2014.props以及toolset-vs2014_xp.props,如下图所示:
    在这里插入图片描述
  • 添加-fdiagnostics-absolute-paths参数是为了让Clang在输出诊断信息是以绝对路径输出源文件,否则在Visual Studio中窗口无法双击诊断信息定位到源文件。
  • 添加
<ObjectFileName>$(IntDir)%(filename).obj</ObjectFileName>

是为了让MSBuild在执行编译任务时一次只编译一个源文件,否则会有多个源文件进入编译任务,输出进度与实际编译进度会不匹配。
2. 修改x64以及Win32目录下toolset-vs2014.targets以及toolset-vs2014_xp.targets,

</Project>

结束标志之前添加如下配置:

<UsingTask TaskName="ClangCl"            AssemblyFile="$(VCTargetsPath)\VSClang.dll"/>

<Target Name="ClCompile"
          Condition="'@(ClCompile)' != ''"
          DependsOnTargets="SelectClCompile">

    <PropertyGroup>
      <CLToolArchitecture Condition="'$(CLToolArchitecture)' == ''">$(VCToolArchitecture)</CLToolArchitecture>
      <CLDeleteOutputOnExecute Condition="'$(CLDeleteOutputOnExecute)' == ''">true</CLDeleteOutputOnExecute>
    </PropertyGroup>

    <ItemGroup>
      <ClNoDependencies Condition="'@(ClNoDependencies)' == '' and '%(ClInclude.NoDependency)' == 'true'" Include="@(ClInclude)"/>
      <ClNoDependencies Condition="'$(NoDependencies)' != ''" Include="$(NoDependencies)" />
    </ItemGroup>

    <!-- Delete the pch file if the pdb file has been deleted.  This will prevent a compiler warning about obsolete pch. -->
    <Delete Condition="'%(ClCompile.DebugInformationFormat)' != '' and '%(ClCompile.DebugInformationFormat)' != 'None' and '%(ClCompile.DebugInformationFormat)' != 'OldStyle' and '%(ClCompile.ProgramDataBaseFileName)' != '' and !Exists(%(ClCompile.ProgramDataBaseFileName))"
            Files="%(ClCompile.PrecompiledHeaderOutputFile)" />

    <!-- Precompiled headers - need to build them first -->
    <ClangCl Condition="'%(ClCompile.PrecompiledHeader)' == 'Create' and '%(ClCompile.ExcludedFromBuild)'!='true' and '%(ClCompile.CompilerIteration)' == ''"
        BuildingInIDE                      ="$(BuildingInsideVisualStudio)"
        Sources                            ="@(ClCompile)"

        AdditionalIncludeDirectories       ="%(ClCompile.AdditionalIncludeDirectories)"
        AdditionalOptions                  ="%(ClCompile.AdditionalOptions)"
        AdditionalUsingDirectories         ="%(ClCompile.AdditionalUsingDirectories)"
        AssemblerListingLocation           ="%(ClCompile.AssemblerListingLocation)"
        AssemblerOutput                    ="%(ClCompile.AssemblerOutput)"
        BasicRuntimeChecks                 ="%(ClCompile.BasicRuntimeChecks)"
        BrowseInformation                  ="%(ClCompile.BrowseInformation)"
        BrowseInformationFile              ="%(ClCompile.BrowseInformationFile)"
        BufferSecurityCheck                ="%(ClCompile.BufferSecurityCheck)"
        CallingConvention                  ="%(ClCompile.CallingConvention)"
        ControlFlowGuard                   ="%(ClCompile.ControlFlowGuard)"
        CompileAsManaged                   ="%(ClCompile.CompileAsManaged)"
        CompileAsWinRT                     ="%(ClCompile.CompileAsWinRT)"
        CompileAs                          ="%(ClCompile.CompileAs)"
        DebugInformationFormat             ="%(ClCompile.DebugInformationFormat)"
        DisableLanguageExtensions          ="%(ClCompile.DisableLanguageExtensions)"
        DisableSpecificWarnings            ="%(ClCompile.DisableSpecificWarnings)"
        EnableEnhancedInstructionSet       ="%(ClCompile.EnableEnhancedInstructionSet)"
        EnableFiberSafeOptimizations       ="%(ClCompile.EnableFiberSafeOptimizations)"
        EnableParallelCodeGeneration       ="%(ClCompile.EnableParallelCodeGeneration)"
        EnablePREfast                      ="%(ClCompile.EnablePREfast)"
        EnforceTypeConversionRules         ="%(ClCompile.EnforceTypeConversionRules)"
        ErrorReporting                     ="%(ClCompile.ErrorReporting)"
        ExceptionHandling                  ="%(ClCompile.ExceptionHandling)"
        ExcludedInputPaths                 ="$(ExcludePath)"
        ExpandAttributedSource             ="%(ClCompile.ExpandAttributedSource)"
        FavorSizeOrSpeed                   ="%(ClCompile.FavorSizeOrSpeed)"
        FloatingPointExceptions            ="%(ClCompile.FloatingPointExceptions)"
        FloatingPointModel                 ="%(ClCompile.FloatingPointModel)"
        ForceConformanceInForLoopScope     ="%(ClCompile.ForceConformanceInForLoopScope)"
        ForcedIncludeFiles                 ="%(ClCompile.ForcedIncludeFiles)"
        ForcedUsingFiles                   ="%(ClCompile.ForcedUsingFiles)"
        FunctionLevelLinking               ="%(ClCompile.FunctionLevelLinking)"
        GenerateXMLDocumentationFiles      ="%(ClCompile.GenerateXMLDocumentationFiles)"
        IgnoreStandardIncludePath          ="%(ClCompile.IgnoreStandardIncludePath)"
        InlineFunctionExpansion            ="%(ClCompile.InlineFunctionExpansion)"
        IntrinsicFunctions                 ="%(ClCompile.IntrinsicFunctions)"
        MinimalRebuild                     ="%(ClCompile.MinimalRebuild)"
        MultiProcessorCompilation          ="%(ClCompile.MultiProcessorCompilation)"
        ObjectFileName                     ="%(ClCompile.ObjectFileName)"
        OmitDefaultLibName                 ="%(ClCompile.OmitDefaultLibName)"
        OmitFramePointers                  ="%(ClCompile.OmitFramePointers)"
        OpenMPSupport                      ="%(ClCompile.OpenMPSupport)"
        Optimization                       ="%(ClCompile.Optimization)"
        PrecompiledHeader                  ="%(ClCompile.PrecompiledHeader)"
        PrecompiledHeaderFile              ="%(ClCompile.PrecompiledHeaderFile)"
        PrecompiledHeaderOutputFile        ="%(ClCompile.PrecompiledHeaderOutputFile)"
        PREfastAdditionalOptions           ="%(ClCompile.PREfastAdditionalOptions)"
        PREfastAdditionalPlugins           ="%(ClCompile.PREfastAdditionalPlugins)"
        PREfastLog                         ="%(ClCompile.PREfastLog)"
        PreprocessKeepComments             ="%(ClCompile.PreprocessKeepComments)"
        PreprocessorDefinitions            ="%(ClCompile.PreprocessorDefinitions)"
        PreprocessSuppressLineNumbers      ="%(ClCompile.PreprocessSuppressLineNumbers)"
        PreprocessToFile                   ="%(ClCompile.PreprocessToFile)"
        ProcessorNumber                    ="%(ClCompile.ProcessorNumber)"
        ProgramDataBaseFileName            ="%(ClCompile.ProgramDataBaseFileName)"
        RemoveUnreferencedCodeData         ="%(ClCompile.RemoveUnreferencedCodeData)"
        RuntimeLibrary                     ="%(ClCompile.RuntimeLibrary)"
        RuntimeTypeInfo                    ="%(ClCompile.RuntimeTypeInfo)"
        SDLCheck                           ="%(ClCompile.SDLCheck)"
        ShowIncludes                       ="%(ClCompile.ShowIncludes)"
        WarningVersion                     ="%(ClCompile.WarningVersion)"
        SmallerTypeCheck                   ="%(ClCompile.SmallerTypeCheck)"
        StringPooling                      ="%(ClCompile.StringPooling)"
        StructMemberAlignment              ="%(ClCompile.StructMemberAlignment)"
        SuppressStartupBanner              ="%(ClCompile.SuppressStartupBanner)"
        TreatSpecificWarningsAsErrors      ="%(ClCompile.TreatSpecificWarningsAsErrors)"
        TreatWarningAsError                ="%(ClCompile.TreatWarningAsError)"
        TreatWChar_tAsBuiltInType          ="%(ClCompile.TreatWChar_tAsBuiltInType)"
        UndefineAllPreprocessorDefinitions ="%(ClCompile.UndefineAllPreprocessorDefinitions)"
        UndefinePreprocessorDefinitions    ="%(ClCompile.UndefinePreprocessorDefinitions)"
        UseFullPaths                       ="%(ClCompile.UseFullPaths)"
        UseUnicodeForAssemblerListing      ="%(ClCompile.UseUnicodeForAssemblerListing)"
        WarningLevel                       ="%(ClCompile.WarningLevel)"
        WholeProgramOptimization           ="%(ClCompile.WholeProgramOptimization)"
        WinRTNoStdLib                      ="%(ClCompile.WinRTNoStdLib)"
        XMLDocumentationFileName           ="%(ClCompile.XMLDocumentationFileName)"
        CreateHotpatchableImage            ="%(CLCompile.CreateHotpatchableImage)"

        TrackerLogDirectory                ="%(ClCompile.TrackerLogDirectory)"

        TLogReadFiles                      ="@(CLTLogReadFiles)"
        TLogWriteFiles                     ="@(CLTLogWriteFiles)"
        ToolExe                            ="$(CLToolExe)"
        ToolPath                           ="$(CLToolPath)"
        TrackFileAccess                    ="$(TrackFileAccess)"
        MinimalRebuildFromTracking         ="%(ClCompile.MinimalRebuildFromTracking)"
        ToolArchitecture                   ="$(CLToolArchitecture)"
        TrackerFrameworkPath               ="$(CLTrackerFrameworkPath)"
        TrackerSdkPath                     ="$(CLTrackerSdkPath)"
        TrackedInputFilesToIgnore          ="@(ClNoDependencies)"
        DeleteOutputOnExecute              ="$(CLDeleteOutputOnExecute)"

        AcceptableNonZeroExitCodes         ="%(ClCompile.AcceptableNonZeroExitCodes)"
        YieldDuringToolExecution           ="$(ClYieldDuringToolExecution)"
    >
    </ClangCl>

    <!-- Rest of the sources -->
    <ClangCl Condition="'%(ClCompile.PrecompiledHeader)' != 'Create' and '%(ClCompile.ExcludedFromBuild)'!='true' and '%(ClCompile.CompilerIteration)' == '' and @(ClCompile) != ''"
        BuildingInIDE                      ="$(BuildingInsideVisualStudio)"
        Sources                            ="@(ClCompile)"

        AdditionalIncludeDirectories       ="%(ClCompile.AdditionalIncludeDirectories)"
        AdditionalOptions                  ="%(ClCompile.AdditionalOptions)"
        AdditionalUsingDirectories         ="%(ClCompile.AdditionalUsingDirectories)"
        AssemblerListingLocation           ="%(ClCompile.AssemblerListingLocation)"
        AssemblerOutput                    ="%(ClCompile.AssemblerOutput)"
        BasicRuntimeChecks                 ="%(ClCompile.BasicRuntimeChecks)"
        BrowseInformation                  ="%(ClCompile.BrowseInformation)"
        BrowseInformationFile              ="%(ClCompile.BrowseInformationFile)"
        BufferSecurityCheck                ="%(ClCompile.BufferSecurityCheck)"
        CallingConvention                  ="%(ClCompile.CallingConvention)"
        ControlFlowGuard                   ="%(ClCompile.ControlFlowGuard)"
        CompileAsManaged                   ="%(ClCompile.CompileAsManaged)"
        CompileAsWinRT                     ="%(ClCompile.CompileAsWinRT)"
        CompileAs                          ="%(ClCompile.CompileAs)"
        DebugInformationFormat             ="%(ClCompile.DebugInformationFormat)"
        DisableLanguageExtensions          ="%(ClCompile.DisableLanguageExtensions)"
        DisableSpecificWarnings            ="%(ClCompile.DisableSpecificWarnings)"
        EnableEnhancedInstructionSet       ="%(ClCompile.EnableEnhancedInstructionSet)"
        EnableFiberSafeOptimizations       ="%(ClCompile.EnableFiberSafeOptimizations)"
        EnableParallelCodeGeneration       ="%(ClCompile.EnableParallelCodeGeneration)"
        EnablePREfast                      ="%(ClCompile.EnablePREfast)"
        EnforceTypeConversionRules         ="%(ClCompile.EnforceTypeConversionRules)"
        ErrorReporting                     ="%(ClCompile.ErrorReporting)"
        ExceptionHandling                  ="%(ClCompile.ExceptionHandling)"
        ExcludedInputPaths                 ="$(ExcludePath)"
        ExpandAttributedSource             ="%(ClCompile.ExpandAttributedSource)"
        FavorSizeOrSpeed                   ="%(ClCompile.FavorSizeOrSpeed)"
        FloatingPointExceptions            ="%(ClCompile.FloatingPointExceptions)"
        FloatingPointModel                 ="%(ClCompile.FloatingPointModel)"
        ForceConformanceInForLoopScope     ="%(ClCompile.ForceConformanceInForLoopScope)"
        ForcedIncludeFiles                 ="%(ClCompile.ForcedIncludeFiles)"
        ForcedUsingFiles                   ="%(ClCompile.ForcedUsingFiles)"
        FunctionLevelLinking               ="%(ClCompile.FunctionLevelLinking)"
        GenerateXMLDocumentationFiles      ="%(ClCompile.GenerateXMLDocumentationFiles)"
        IgnoreStandardIncludePath          ="%(ClCompile.IgnoreStandardIncludePath)"
        InlineFunctionExpansion            ="%(ClCompile.InlineFunctionExpansion)"
        IntrinsicFunctions                 ="%(ClCompile.IntrinsicFunctions)"
        MinimalRebuild                     ="%(ClCompile.MinimalRebuild)"
        MultiProcessorCompilation          ="%(ClCompile.MultiProcessorCompilation)"
        ObjectFileName                     ="%(ClCompile.ObjectFileName)"
        OmitDefaultLibName                 ="%(ClCompile.OmitDefaultLibName)"
        OmitFramePointers                  ="%(ClCompile.OmitFramePointers)"
        OpenMPSupport                      ="%(ClCompile.OpenMPSupport)"
        Optimization                       ="%(ClCompile.Optimization)"
        PrecompiledHeader                  ="%(ClCompile.PrecompiledHeader)"
        PrecompiledHeaderFile              ="%(ClCompile.PrecompiledHeaderFile)"
        PrecompiledHeaderOutputFile        ="%(ClCompile.PrecompiledHeaderOutputFile)"
        PREfastAdditionalOptions           ="%(ClCompile.PREfastAdditionalOptions)"
        PREfastAdditionalPlugins           ="%(ClCompile.PREfastAdditionalPlugins)"
        PREfastLog                         ="%(ClCompile.PREfastLog)"
        PreprocessKeepComments             ="%(ClCompile.PreprocessKeepComments)"
        PreprocessorDefinitions            ="%(ClCompile.PreprocessorDefinitions)"
        PreprocessSuppressLineNumbers      ="%(ClCompile.PreprocessSuppressLineNumbers)"
        PreprocessToFile                   ="%(ClCompile.PreprocessToFile)"
        ProcessorNumber                    ="%(ClCompile.ProcessorNumber)"
        ProgramDataBaseFileName            ="%(ClCompile.ProgramDataBaseFileName)"
        RemoveUnreferencedCodeData         ="%(ClCompile.RemoveUnreferencedCodeData)"
        RuntimeLibrary                     ="%(ClCompile.RuntimeLibrary)"
        RuntimeTypeInfo                    ="%(ClCompile.RuntimeTypeInfo)"
        SDLCheck                           ="%(ClCompile.SDLCheck)"
        ShowIncludes                       ="%(ClCompile.ShowIncludes)"
        WarningVersion                     ="%(ClCompile.WarningVersion)"
        SmallerTypeCheck                   ="%(ClCompile.SmallerTypeCheck)"
        StringPooling                      ="%(ClCompile.StringPooling)"
        StructMemberAlignment              ="%(ClCompile.StructMemberAlignment)"
        SuppressStartupBanner              ="%(ClCompile.SuppressStartupBanner)"
        TreatSpecificWarningsAsErrors      ="%(ClCompile.TreatSpecificWarningsAsErrors)"
        TreatWarningAsError                ="%(ClCompile.TreatWarningAsError)"
        TreatWChar_tAsBuiltInType          ="%(ClCompile.TreatWChar_tAsBuiltInType)"
        UndefineAllPreprocessorDefinitions ="%(ClCompile.UndefineAllPreprocessorDefinitions)"
        UndefinePreprocessorDefinitions    ="%(ClCompile.UndefinePreprocessorDefinitions)"
        UseFullPaths                       ="%(ClCompile.UseFullPaths)"
        UseUnicodeForAssemblerListing      ="%(ClCompile.UseUnicodeForAssemblerListing)"
        WarningLevel                       ="%(ClCompile.WarningLevel)"
        WholeProgramOptimization           ="%(ClCompile.WholeProgramOptimization)"
        WinRTNoStdLib                      ="%(ClCompile.WinRTNoStdLib)"
        XMLDocumentationFileName           ="%(ClCompile.XMLDocumentationFileName)"
        CreateHotpatchableImage            ="%(CLCompile.CreateHotpatchableImage)"

        TrackerLogDirectory                ="%(ClCompile.TrackerLogDirectory)"

        TLogReadFiles                      ="@(CLTLogReadFiles)"
        TLogWriteFiles                     ="@(CLTLogWriteFiles)"
        ToolExe                            ="$(CLToolExe)"
        ToolPath                           ="$(CLToolPath)"
        TrackFileAccess                    ="$(TrackFileAccess)"
        MinimalRebuildFromTracking         ="%(ClCompile.MinimalRebuildFromTracking)"
        ToolArchitecture                   ="$(CLToolArchitecture)"
        TrackerFrameworkPath               ="$(CLTrackerFrameworkPath)"
        TrackerSdkPath                     ="$(CLTrackerSdkPath)"
        TrackedInputFilesToIgnore          ="@(ClNoDependencies)"
        DeleteOutputOnExecute              ="$(CLDeleteOutputOnExecute)"

        AcceptableNonZeroExitCodes         ="%(ClCompile.AcceptableNonZeroExitCodes)"
        YieldDuringToolExecution           ="$(ClYieldDuringToolExecution)"
    >
    </ClangCl>
    
    <OnError Condition="'$(OnXamlPreCompileErrorTarget)' != ''" ExecuteTargets="$(OnXamlPreCompileErrorTarget)" />
  </Target>
(三)、点击install.bat进行安装

经过这些处理,在VS2015下使用LLVM-vs2014平台工具集即可看到编译进度。

二、集成clang编译器

由于clang-cl编译器是期望与微软的cl编译器兼容的,所以在跨平台方面会有问题,所以最好是直接使用clang编译器,这样各个平台的编译效果会最大程度地一致(目前使用Clang在Windows下编译还是有一些问题,需要特殊处理)。

笔者依旧以VS2015为例来说明,由于VS2015本身是支持Clang编译器的,可以在安装的时候进行选择安装Clang编译器,但是由于编译器版本太低,所以不推荐。我们完全可以安装最新的Clang编译器。

虽然我们没有安装VS自带的Clang编译器,但是VS默认还是安装了Clang的MSBuild编译配置,大家可以看看图示目录下是否有Microsoft.Cpp.Clang.props和Microsoft.Cpp.Clang.targets两个文件,如果没有可以在后面复制。
在这里插入图片描述

(一)、添加toolset

在Platforms下的x64以及Win32下添加工具集,比如笔者在x64下添加一个clang工具集,即在

C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\Platforms\x64\PlatformToolsets

目录下新建一个clang目录,并在其中添加Toolset.props和Toolset.targets两个文件,

Toolset.props文件内容如下:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildThisFileDirectory)ImportBefore\*.props" Condition="Exists('$(MSBuildThisFileDirectory)ImportBefore')" />

  <PropertyGroup>
    <ClangTarget>amd64-pc-windows-msvc</ClangTarget>
  </PropertyGroup>

  <PropertyGroup>
    <!-- Required for enabling Team Build for packaging Windows Store app projects -->
    <OutDirWasSpecified Condition=" '$(OutDir)'!='' AND '$(OutDirWasSpecified)'=='' ">true</OutDirWasSpecified>
    <OutDirWasSpecified Condition=" '$(OutDir)'=='' AND '$(OutDirWasSpecified)'=='' ">false</OutDirWasSpecified>

    <IntDir Condition="'$(IntDir)'=='' AND '$(IntermediateOutputPath)'!=''">$(IntermediateOutputPath)</IntDir>
    <IntDir Condition="'$(IntDir)'=='' AND '$(IntermediateOutputPath)'==''">$(Platform)\$(Configuration)\</IntDir>
    <OutDir Condition="'$(OutDir)'=='' AND '$(SolutionDir)' == ''">$(IntDir)</OutDir>
    <OutDir Condition="'$(OutDir)'=='' AND '$(SolutionDir)' != ''">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
  </PropertyGroup>

  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.WindowsSDK.props" Condition="Exists('$(VCTargetsPath)\Microsoft.Cpp.WindowsSDK.props')"/>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Common.props" />
  
  <!-- This sets Clang common defaults. -->
  <PropertyGroup>
    <GNUMode>true</GNUMode>
    <MSVCErrorReport>true</MSVCErrorReport>
    <ToolsetISenseIdentifier>Clang.Windows</ToolsetISenseIdentifier>
  </PropertyGroup>

  <PropertyGroup>
    <VCClangInstallDir Condition="'$(VCClangInstallDir)' == ''">$(VCInstallDir)ClangC2\</VCClangInstallDir>
    <VCClangBinDir Condition="'$(VCToolArchitecture)' == 'Native64Bit'">$(VCClangInstallDir)bin\amd64</VCClangBinDir>
    <VCClangBinDir Condition="'$(VCToolArchitecture)' != 'Native64Bit'">$(VCClangInstallDir)bin\x86</VCClangBinDir>
  </PropertyGroup>

  <ItemDefinitionGroup>
    <ClCompile>
      <MSExtensions>false</MSExtensions>
      <MSCompatibility>false</MSCompatibility>
      <PreprocessorDefinitions Condition="'$(UseDebugLibraries)' != 'true'">NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalOptions>-g -gcodeview -fdiagnostics-absolute-paths -fno-delayed-template-parsing -Xclang -flto-visibility-public-std %(AdditionalOptions)</AdditionalOptions>
    </ClCompile>
  </ItemDefinitionGroup>

  <PropertyGroup>
    <ExecutablePath Condition="'$(ExecutablePath)' == ''">$(VCClangBinDir)\amd64;$(VCClangBinDir);$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH);</ExecutablePath>
    <IncludePath Condition="'$(IncludePath)' == ''">$(VCClangInstallDir)include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
    <ReferencePath Condition="'$(ReferencePath)' == ''">$(VC_ReferencesPath_x64);</ReferencePath>
    <LibraryPath Condition="'$(LibraryPath)' == ''">$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64</LibraryPath>
    <LibraryWPath Condition="'$(LibraryWPath)' == ''">$(WindowsSDK_MetadataPath);</LibraryWPath>
    <SourcePath Condition="'$(SourcePath)' == ''">$(VC_SourcePath);</SourcePath>
    <ExcludePath Condition="'$(ExcludePath)' == ''">$(VC_IncludePath);$(WindowsSDK_IncludePath);$(MSBuild_ExecutablePath);$(VC_LibraryPath_x64);</ExcludePath>
    <DebugCppRuntimeFilesPath Condition="'$(DebugCppRuntimeFilesPath)' == ''">$(VCInstallDir)redist\Debug_NonRedist\x64</DebugCppRuntimeFilesPath>	
  </PropertyGroup>

  <Import Project="$(MSBuildThisFileDirectory)ImportAfter\*.props" Condition="Exists('$(MSBuildThisFileDirectory)ImportAfter')" />
  
  <!-- This is intentially added after ImportAfter. -->
  <Import Project="$(_PlatformFolder)Platform.Common.props" />
  
  <!-- This overrides some of the platform defaults. -->
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Clang.props" />
  
  <!-- 重载 -->
  <ItemDefinitionGroup>
    <ClCompile>
      <MSExtensions>true</MSExtensions>
      <MSCompatibility>true</MSCompatibility>
      <PositionIndependentCode>false</PositionIndependentCode>
      <RuntimeTypeInfo>true</RuntimeTypeInfo>
      <DebugInformationFormat>LineNumber</DebugInformationFormat>
	  <WarningLevel>EnableAllWarnings</WarningLevel>
	  <UseMultiToolTask>true</UseMultiToolTask>
    </ClCompile>
  </ItemDefinitionGroup>
</Project>

Toolset.targets文件内容如下:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <Import Project="$(MSBuildThisFileDirectory)ImportBefore\*.targets" Condition="Exists('$(MSBuildThisFileDirectory)ImportBefore')" />

  <Import Project="$(VCTargetsPath)\Microsoft.CppCommon.targets" />
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Clang.targets" />

  <Import Project="$(MSBuildThisFileDirectory)ImportAfter\*.targets" Condition="Exists('$(MSBuildThisFileDirectory)ImportAfter')" />

</Project>

添加了这两个文件后,就可以在VS中看到工具集了:
在这里插入图片描述
这样就大功告成了。如果没有Microsoft.Cpp.Clang.props与Microsoft.Cpp.Clang.targets两个文件,可以从下面复制出来放在

C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140

目录即可。

VS 2015所带的Microsoft.Cpp.Clang.props完整内容如下:

<!--
***********************************************************************************************
Microsoft.Cpp.Clang.props

WARNING:  DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
          created a backup copy.  Incorrect changes to this file will make it
          impossible to load or build your projects from the command-line or the IDE.

Copyright (C) Microsoft Corporation. All rights reserved.
***********************************************************************************************
-->

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildThisFileDirectory)ImportBefore\*.props" Condition="Exists('$(MSBuildThisFileDirectory)ImportBefore')" />

  <ItemDefinitionGroup>
    <ClCompile>
      <ClangMode>true</ClangMode>
      <WarningLevel>EnableAllWarnings</WarningLevel>
      <DebugInformationFormat Condition="'$(UseDebugLibraries)' == 'true'">FullDebug</DebugInformationFormat>
      <DebugInformationFormat Condition="'$(UseDebugLibraries)' != 'true'">LineNumber</DebugInformationFormat>
      <PreprocessorDefinitions Condition="'$(UseDebugLibraries)' == 'true'">NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Optimization Condition="'$(UseDebugLibraries)' == 'true'">Disabled</Optimization>
      <Optimization Condition="'$(UseDebugLibraries)' != 'true'">Full</Optimization>
      <StrictAliasing>false</StrictAliasing>
      <ProgramDatabaseFileName>$(IntDir)</ProgramDatabaseFileName>
      <OmitFramePointers Condition="'$(UseDebugLibraries)' == 'true'">false</OmitFramePointers>
      <OmitFramePointers Condition="'$(UseDebugLibraries)' != 'true'">true</OmitFramePointers>
      <ExceptionHandling>Enabled</ExceptionHandling>
      <FunctionLevelLinking Condition="'$(UseDebugLibraries)' == 'true'">false</FunctionLevelLinking>
      <FunctionLevelLinking Condition="'$(UseDebugLibraries)' != 'true'">true</FunctionLevelLinking>
      <DataLevelLinking Condition="'$(UseDebugLibraries)' == 'true'">false</DataLevelLinking>
      <DataLevelLinking Condition="'$(UseDebugLibraries)' != 'true'">true</DataLevelLinking>
      <BufferSecurityCheck>true</BufferSecurityCheck>
      <PositionIndependentCode>true</PositionIndependentCode>
      <UseShortEnums>false</UseShortEnums>
      <RuntimeTypeInfo>false</RuntimeTypeInfo>
      <CLanguageStandard>Default</CLanguageStandard>
      <CppLanguageStandard>Default</CppLanguageStandard>
      <PrecompiledHeader>NotUsing</PrecompiledHeader>
      <ObjectFileName>$(IntDir)%(filename).obj</ObjectFileName>
      <CompileAs>Default</CompileAs>
      <TreatWarningAsError>false</TreatWarningAsError>
      <Verbose>false</Verbose>
      <EnablePREfast Condition="'%(ClCompile.EnablePREfast)' == ''">false</EnablePREfast>
      <OmitFramePointers Condition="'%(ClCompile.OmitFramePointers)' == ''">false</OmitFramePointers>
      <MinimalRebuildFromTracking>true</MinimalRebuildFromTracking>
      <PrecompiledHeaderOutputFileDirectory>$(IntDir)</PrecompiledHeaderOutputFileDirectory>
      <PrecompiledHeaderOutputFile></PrecompiledHeaderOutputFile>
      <PrecompiledHeaderCompileAs>CompileAsCpp</PrecompiledHeaderCompileAs>
    </ClCompile>
  </ItemDefinitionGroup>

  <Import Project="$(MSBuildThisFileDirectory)ImportAfter\*.props" Condition="Exists('$(MSBuildThisFileDirectory)ImportAfter')" />
</Project>

Microsoft.Cpp.Clang.targets完整内容如下:

<!--
***********************************************************************************************
Microsoft.Cpp.Clang.targets

WARNING:  DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
          created a backup copy.  Incorrect changes to this file will make it
          impossible to load or build your projects from the command-line or the IDE.

This file defines the steps/targets required to build Visual C++ projects
that use Clang Front-End.

Copyright (C) Microsoft Corporation. All rights reserved.
***********************************************************************************************
-->

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <UsingTask TaskName="ClangCompile" AssemblyFile="$(VCTargetsPath)Microsoft.Build.CppTasks.Common.dll"/>

  <!-- *******************************************************************************************
        Clang Compile
       ******************************************************************************************* -->

  <Target Name="FixupCLCompileOptions"
          Condition="'@(ClCompile)' != ''">
    <ItemGroup>
      <ClCompile>
        <PrecompiledHeaderOutputFileDirectory Condition="'%(ClCompile.PrecompiledHeaderOutputFileDirectory)' != '' and !HasTrailingSlash('%(ClCompile.PrecompiledHeaderOutputFileDirectory)')">%(ClCompile.PrecompiledHeaderOutputFileDirectory)\</PrecompiledHeaderOutputFileDirectory>
      </ClCompile>

    <!-- Add PCH to the list of compiles -->
      <ClCompilePCH Condition="'%(ClCompile.PrecompiledHeaderFile)' != '' and '%(ClCompile.PrecompiledHeader)' == 'Use'" Include="@(ClCompile->Metadata(PrecompiledHeaderFile)->Fullpath()->Distinct()->ClearMetadata())">
        <CompileAs/>
        <ForcedIncludeFiles/>
        <PrecompiledHeaderFile/>
        <PrecompiledHeader>Create</PrecompiledHeader>
        <PrecompiledHeaderCompileAs>%(ClCompile.PrecompiledHeaderCompileAs)</PrecompiledHeaderCompileAs>
        <PrecompiledHeaderOutputFileDirectory>%(ClCompile.PrecompiledHeaderOutputFileDirectory)</PrecompiledHeaderOutputFileDirectory>
        <!-- PCH are not part of the build, so exclude the output from the link step. -->
        <LibCompiled>false</LibCompiled>
        <LinkCompiled>false</LinkCompiled>
      </ClCompilePCH>

      <ClCompilePCH>
        <ObjectFileName>%(ClCompilePCH.PrecompiledHeaderOutputFileDirectory)%(FileName)%(Extension).gch</ObjectFileName>
      </ClCompilePCH>

      <!-- Add PCH to the force include, and remove from PCH related flags. -->
      <ClCompile Condition="'%(ClCompile.PrecompiledHeader)' == 'Use' and '$(DesignTimeBuild)' == 'true'">
        <!-- Clang expect the output pch.h, which it will deduce pch.h.gch) -->
        <!-- VC intellisense expect the source pch.h -->
        <ForcedIncludeFiles>%(ClCompile.PrecompiledHeaderFile);%(ClCompile.ForcedIncludeFiles)</ForcedIncludeFiles>
        <PrecompiledHeaderOutputFile>%(PrecompiledHeaderOutputFileDirectory)%(ClCompile.PrecompiledHeaderFile).gch</PrecompiledHeaderOutputFile>
      </ClCompile>

      <ClCompile Condition="'%(ClCompile.PrecompiledHeader)' == 'Use' and '$(DesignTimeBuild)' != 'true' and '%(Identity)' != ''">
        <ForcedIncludeFiles>@(ClCompile->Metadata(PrecompiledHeaderFile)->'%(PrecompiledHeaderOutputFileDirectory)%(FileName)%(Extension)');%(ClCompile.ForcedIncludeFiles)</ForcedIncludeFiles>
        <!-- Set MultiToolTask scheduler to wait for the PCH to finish. -->
        <MultiToolTaskDependency>@(ClCompile->Metadata(PrecompiledHeaderFile)->Fullpath()->Distinct()->ClearMetadata())</MultiToolTaskDependency>
      </ClCompile>

      <!-- Done processing PCH, blank out the unused metadata. -->
      <ClCompile>
        <PrecompiledHeaderFile />
        <PrecompiledHeaderCompileAs />
        <PrecompiledHeaderOutputFileDirectory />
      </ClCompile>

      <ClCompilePCH>
        <PrecompiledHeaderOutputFileDirectory />
        <RuntimeTypeInfo Condition="'%(ClCompilePCH.PrecompiledHeaderCompileAs)' == 'CompileAsC'" />
      </ClCompilePCH>

      <ClCompile Condition="'$(DesignTimeBuild)' != 'true'" Include="@(ClCompilePCH)" />

      <ClCompile>
        <BuildingInIDE>$(BuildingInsideVisualStudio)</BuildingInIDE>
        <GNUMode>$(GNUMode)</GNUMode>
        <MSVCErrorReport>$(MSVCErrorReport)</MSVCErrorReport>
        <GccToolChain>$(GccToolchainPrebuiltPath)</GccToolChain>
        <Sysroot>$(Sysroot)</Sysroot>
        <TargetArch>$(ClangTarget)</TargetArch>
        <MinimalRebuildFromTracking Condition="'$(_BuildActionType)' != 'Build' or '$(ForceRebuild)' == 'true'">false</MinimalRebuildFromTracking>
        <WarningLevel Condition="'%(WarningLevel)' == 'Level1' or '%(WarningLevel)' == 'Level2' or '%(WarningLevel)' == 'Level3'">EnableAllWarnings</WarningLevel>
        <CompileAs Condition="'%(ClCompile.CompileAs)' == 'Default' and '%(ClCompile.Extension)' == '.c'">CompileAsC</CompileAs>
        <CompileAs Condition="'%(ClCompile.CompileAs)' == 'Default' and '%(ClCompile.Extension)' != '.c'">CompileAsCpp</CompileAs>
      </ClCompile>

      <ClCompile>
        <!-- Dont pass C standard to C++ and vice versa -->
        <CLanguageStandard Condition="'%(ClCompile.CompileAs)' == 'CompileAsCpp'"></CLanguageStandard>
        <CppLanguageStandard Condition="'%(ClCompile.CompileAs)' == 'CompileAsC'"></CppLanguageStandard>
        
        <!-- C doesn't support 'RuntimeTypeInfo' -->
        <RuntimeTypeInfo Condition="'%(ClCompile.CompileAs)' == 'CompileAsC'" />
      </ClCompile>
      
      <!-- Fixup Windows Runtime Library switches. -->
      <ClCompile Condition="'$(DesignTimeBuild)' != 'true'">
        <AdditionalOptions Condition="'%(ClCompile.RuntimeLibrary)' == 'MultiThreaded'">%(ClCompile.AdditionalOptions) -D_MT -Xclang --dependent-lib=libcmt -Xclang --dependent-lib=oldnames</AdditionalOptions>
        <AdditionalOptions Condition="'%(ClCompile.RuntimeLibrary)' == 'MultiThreadedDebug'">%(ClCompile.AdditionalOptions) -D_DEBUG -D_MT -Xclang --dependent-lib=libcmtd -Xclang --dependent-lib=oldnames</AdditionalOptions>
        <AdditionalOptions Condition="'%(ClCompile.RuntimeLibrary)' == 'MultiThreadedDLL'">%(ClCompile.AdditionalOptions) -D_MT -D_DLL -Xclang --dependent-lib=msvcrt -Xclang --dependent-lib=oldnames</AdditionalOptions>
        <AdditionalOptions Condition="'%(ClCompile.RuntimeLibrary)' == 'MultiThreadedDebugDLL'">%(ClCompile.AdditionalOptions) -D_DEBUG -D_MT -D_DLL -Xclang --dependent-lib=msvcrtd -Xclang --dependent-lib=oldnames</AdditionalOptions>
      </ClCompile>
    </ItemGroup>
  </Target>

  <Target Name="ClCompile"
          Condition="'@(ClCompile)' != ''"
          DependsOnTargets="SelectClCompile" >

    <PropertyGroup>
      <CLToolArchitecture Condition="'$(CLToolArchitecture)' == ''">$(VCToolArchitecture)</CLToolArchitecture>
      <CLDeleteOutputOnExecute Condition="'$(CLDeleteOutputOnExecute)' == ''">true</CLDeleteOutputOnExecute>
      <ClMutliToolTaskMinimalRebuild>true</ClMutliToolTaskMinimalRebuild>
      <ClMutliToolTaskMinimalRebuild Condition="'$(_BuildActionType)' != 'Build' or '$(ForceRebuild)' == 'true'">false</ClMutliToolTaskMinimalRebuild>
      <ProcessorNumber Condition="'$(ProcessorNumber)' == ''">$(CL_MPCount)</ProcessorNumber>
    </PropertyGroup>

    <ItemGroup>
      <ClCompile>
        <!-- Moved to this target to avoid adding add $(IncludePath) for intellisense -->
        <AdditionalIncludeDirectories>%(ClCompile.AdditionalIncludeDirectories);$(IncludePath)</AdditionalIncludeDirectories>
      </ClCompile>
    </ItemGroup>

    <Message Condition="'$(_DebugMessages)' == 'true'" Importance="high" Text="ClCompilePCH = '@(ClCompilePCH)'"/>
    <Message Condition="'$(_DebugMessages)' == 'true'" Importance="high" Text="ClCompilePCH.ObjectFileName = '%(ClCompilePCH.ObjectFileName)'"/>

    <MultiToolTask Condition="'%(ClCompile.ExcludedFromBuild)' != 'true' and '$(UseMultiToolTask)' == 'true'"
                  TaskName="Microsoft.Build.CPPTasks.ClangCompile"
                  TaskAssemblyName="$(VCTargetsPath)Microsoft.Build.CppTasks.Common.dll"
                  Sources="@(ClCompile)"

                  SchedulerVerbose="$(MultiToolTaskVerbose)"
                  SemaphoreProcCount="$(ProcessorNumber)"
                  TrackFileAccess="$(TrackFileAccess)"
                  TrackerLogDirectory="$(TLogLocation)"
                  MinimalRebuildFromTracking="$(ClMutliToolTaskMinimalRebuild)"
                  TLogReadFiles="@(CLTLogReadFiles)"
                  TLogWriteFiles="@(CLTLogWriteFiles)"
                  ToolExe="$(ClangToolExe)"
                  ToolPath="$(ClangToolPath)"
                  ToolArchitecture="$(CLToolArchitecture)"
                  TrackerFrameworkPath="$(CLTrackerFrameworkPath)"
                  TrackerSdkPath="$(CLTrackerSdkPath)"
                  EnableExecuteTool="$(ClangEnableExecuteTool)"
    >
    </MultiToolTask>

    <!-- Precompiled headers - need to build them first -->
    <ClangCompile Condition="'%(ClCompile.PrecompiledHeader)' == 'Create' and '$(UseMultiToolTask)' != 'true'"

                  BuildingInIDE = "%(ClCompile.BuildingInsideVisualStudio)"
                  GNUMode="%(ClCompile.GNUMode)"
                  MSVCErrorReport="%(ClCompile.MSVCErrorReport)"

                  Sources="@(ClCompile)"
                  AdditionalIncludeDirectories="%(ClCompile.AdditionalIncludeDirectories)"
                  AdditionalOptions="%(ClCompile.AdditionalOptions)"
                  BufferSecurityCheck="%(ClCompile.BufferSecurityCheck)"
                  CLanguageStandard="%(ClCompile.CLanguageStandard)"
                  CppLanguageStandard="%(ClCompile.CppLanguageStandard)"
                  DataLevelLinking="%(ClCompile.DataLevelLinking)"
                  DebugInformationFormat="%(ClCompile.DebugInformationFormat)"
                  ExceptionHandling="%(ClCompile.ExceptionHandling)"
                  FloatABI="%(ClCompile.FloatABI)"
                  ForcedIncludeFiles="%(ClCompile.ForcedIncludeFiles)"
                  FunctionLevelLinking="%(ClCompile.FunctionLevelLinking)"
                  ObjectFileName="%(ClCompile.ObjectFileName)"
                  OmitFramePointers="%(ClCompile.OmitFramePointers)"
                  Optimization="%(ClCompile.Optimization)"
                  PositionIndependentCode="%(ClCompile.PositionIndependentCode)"
                  PrecompiledHeader="%(ClCompile.PrecompiledHeader)"
                  PrecompiledHeaderCompileAs="%(ClCompile.PrecompiledHeaderCompileAs)"
                  PreprocessorDefinitions="%(ClCompile.PreprocessorDefinitions)"
                  RuntimeLibrary="%(ClCompile.RuntimeLibrary)"
                  RuntimeTypeInfo="%(ClCompile.RuntimeTypeInfo)"
                  ShowIncludes="%(ClCompile.ShowIncludes)"
                  StrictAliasing="%(ClCompile.StrictAliasing)"
                  ThumbMode="%(ClCompile.ThumbMode)"
                  TreatWarningAsError="%(ClCompile.TreatWarningAsError)"
                  UndefineAllPreprocessorDefinitions="%(ClCompile.UndefineAllPreprocessorDefinitions)"
                  UndefinePreprocessorDefinitions="%(ClCompile.UndefinePreprocessorDefinitions)"
                  UseShortEnums="%(ClCompile.UseShortEnums)"
                  Verbose="%(ClCompile.Verbose)"
                  WarningLevel="%(ClCompile.WarningLevel)"

                  GccToolChain="%(ClCompile.GccToolChain)"
                  Sysroot="%(ClCompile.Sysroot)"
                  TargetArch="%(ClCompile.TargetArch)"

                  TrackFileAccess="$(TrackFileAccess)"
                  TrackerLogDirectory="$(TLogLocation)"
                  MinimalRebuildFromTracking="%(ClCompile.MinimalRebuildFromTracking)"
                  TLogReadFiles="@(CLTLogReadFiles)"
                  TLogWriteFiles="@(CLTLogWriteFiles)"
                  ToolExe="$(ClangToolExe)"
                  ToolPath="$(ClangToolPath)"
                  ToolArchitecture="$(CLToolArchitecture)"
                  TrackerFrameworkPath="$(CLTrackerFrameworkPath)"
                  TrackerSdkPath="$(CLTrackerSdkPath)"
                  EnableExecuteTool="$(ClangEnableExecuteTool)"
                  MSExtensions="%(ClCompile.MSExtensions)"
                  MSCompatibility="%(ClCompile.MSCompatibility)"
                  MSCompatibilityVersion="%(ClCompile.MSCompatibilityVersion)"
                  MSCompilerVersion="%(ClCompile.MSCompilerVersion)"
    >
    </ClangCompile>

    <ClangCompile Condition="'%(ClCompile.ExcludedFromBuild)' != 'true' and '%(ClCompile.PrecompiledHeader)' != 'Create' and '$(UseMultiToolTask)' != 'true'"
                  BuildingInIDE = "%(ClCompile.BuildingInsideVisualStudio)"
                  GNUMode="%(ClCompile.GNUMode)"
                  MSVCErrorReport="%(ClCompile.MSVCErrorReport)"

                  Sources="@(ClCompile)"
                  AdditionalIncludeDirectories="%(ClCompile.AdditionalIncludeDirectories)"
                  AdditionalOptions="%(ClCompile.AdditionalOptions)"
                  BufferSecurityCheck="%(ClCompile.BufferSecurityCheck)"
                  CLanguageStandard="%(ClCompile.CLanguageStandard)"
                  CompileAs="%(ClCompile.CompileAs)"
                  CppLanguageStandard="%(ClCompile.CppLanguageStandard)"
                  DataLevelLinking="%(ClCompile.DataLevelLinking)"
                  DebugInformationFormat="%(ClCompile.DebugInformationFormat)"
                  ExceptionHandling="%(ClCompile.ExceptionHandling)"
                  FloatABI="%(ClCompile.FloatABI)"
                  ForcedIncludeFiles="%(ClCompile.ForcedIncludeFiles)"
                  FunctionLevelLinking="%(ClCompile.FunctionLevelLinking)"
                  ObjectFileName="%(ClCompile.ObjectFileName)"
                  OmitFramePointers="%(ClCompile.OmitFramePointers)"
                  Optimization="%(ClCompile.Optimization)"
                  PositionIndependentCode="%(ClCompile.PositionIndependentCode)"
                  PrecompiledHeader="%(ClCompile.PrecompiledHeader)"
                  PreprocessorDefinitions="%(ClCompile.PreprocessorDefinitions)"
                  RuntimeLibrary="%(ClCompile.RuntimeLibrary)"
                  RuntimeTypeInfo="%(ClCompile.RuntimeTypeInfo)"
                  ShowIncludes="%(ClCompile.ShowIncludes)"
                  StrictAliasing="%(ClCompile.StrictAliasing)"
                  ThumbMode="%(ClCompile.ThumbMode)"
                  TreatWarningAsError="%(ClCompile.TreatWarningAsError)"
                  UndefineAllPreprocessorDefinitions="%(ClCompile.UndefineAllPreprocessorDefinitions)"
                  UndefinePreprocessorDefinitions="%(ClCompile.UndefinePreprocessorDefinitions)"
                  UseShortEnums="%(ClCompile.UseShortEnums)"
                  Verbose="%(ClCompile.Verbose)"
                  WarningLevel="%(ClCompile.WarningLevel)"

                  GccToolChain="%(ClCompile.GccToolChain)"
                  Sysroot="%(ClCompile.Sysroot)"
                  TargetArch="%(ClCompile.TargetArch)"

                  TrackFileAccess="$(TrackFileAccess)"
                  TrackerLogDirectory="$(TLogLocation)"
                  MinimalRebuildFromTracking="%(ClCompile.MinimalRebuildFromTracking)"
                  TLogReadFiles="@(CLTLogReadFiles)"
                  TLogWriteFiles="@(CLTLogWriteFiles)"
                  ToolExe="$(ClangToolExe)"
                  ToolPath="$(ClangToolPath)"
                  ToolArchitecture="$(CLToolArchitecture)"
                  TrackerFrameworkPath="$(CLTrackerFrameworkPath)"
                  TrackerSdkPath="$(CLTrackerSdkPath)"
                  EnableExecuteTool="$(ClangEnableExecuteTool)"
                  MSExtensions="%(ClCompile.MSExtensions)"
                  MSCompatibility="%(ClCompile.MSCompatibility)"
                  MSCompatibilityVersion="%(ClCompile.MSCompatibilityVersion)"
                  MSCompilerVersion="%(ClCompile.MSCompilerVersion)"
    >
    </ClangCompile>
  </Target>

  <ItemGroup Condition="'$(ConfigurationType)' != 'Utility'">
    <PropertyPageSchema Condition="'$(ConfigurationType)' != 'Utility'" Include="$(VCTargetsPath)$(LangID)\clang.xml"/>
  </ItemGroup>

</Project>

(二)、注意事项

通过上面的修改后,基本上可以正常使用了,但是可能会有如下问题

  1. 由于是使用的VS的头文件,所以需要把MS的兼容模式打开,否则会报错,同时建议把MS的扩展支持也打开(上面的clang工具集配置已经默认打开了这两项)。
    在这里插入图片描述
  2. 由于clang默认是不会生成VS调试器可识别的PDB格式,所以要使用VS调试clang生成的程序,需要让Clang生成PDB格式的调试信息,添加:

-g -gcodeview

即可(上面的clang工具集配置已经默认添加了该参数)。

  1. 如果预编译头文件带路径,需要把路径写全;Clang不需要使用某个CPP来单独创建,直接在项目属性中设置需要使用的预编译头即可。
    在这里插入图片描述
  2. 报错:C:\Program Files (x86)\Windows Kits\8.1\Include\um\combaseapi.h(229,21): error : unknown type name ‘IUnknown’
    在这里插入图片描述
    可以直接在模板前面添加一个声明:
extern "C++"
{
	interface IUnknown;  // 这里添加一个声明,以免Clang编译器报错
    template<typename T> _Post_equal_to_(pp) _Post_satisfies_(return == pp) void** IID_PPV_ARGS_Helper(T** pp) 
    {
#pragma prefast(suppress: 6269, "Tool issue with unused static_cast")
        static_cast<IUnknown*>(*pp);    // make sure everyone derives from IUnknown
        return reinterpret_cast<void**>(pp);
    }    
}
  1. 关于Boost库的使用
  • 如果要使用Boost,需要定义宏:
BOOST_USE_WINDOWS_H
  • 如果在自己的静态库中使用Boost的静态thread库,需要定义宏:
BOOST_THREAD_USE_LIB

否则在exe项目中使用自己的静态库时会出现链接错误。

error LNK2001: 无法解析的外部符号 "__declspec(dllimport) public: __cdecl boost::thread::~thread(void)" (__imp_??1thread@boost@@QEAA@XZ)
error LNK2019: 无法解析的外部符号 "__declspec(dllimport) private: void __cdecl boost::thread::start_thread(void)" (__imp_?start_thread@thread@boost@@AEAAXXZ)
error LNK2019: 无法解析的外部符号 "__declspec(dllimport) public: void __cdecl boost::thread::join(void)" (__imp_?join@thread@boost@@QEAAXXZ)
  • 如果使用的是Windows8.1的SDK,项目中原来定义了宏:
_WIN32_WINNT=0x0501

需要删除,或者定义成

_WIN32_WINNT=0x0600

否则会出现错误

boost_1_58_0\boost\thread\win32\thread_primitives.hpp(75,21): error : no member named 'GetTickCount64' in the global namespace; did you mean 'GetTickCount'?
              using ::GetTickCount64;
                    ~~^
  C:\Program Files (x86)\Windows Kits\8.1\Include\um\sysinfoapi.h(203,1): note: 'GetTickCount' declared here
  GetTickCount(
  ^
  In file included from <built-in>:1:

参见C:\Program Files (x86)\Windows Kits\8.1\Include\um\sysinfoapi.h(221,1)中GetTickCount64定义:

#if (_WIN32_WINNT >= 0x0600)
WINBASEAPI
ULONGLONG
WINAPI
GetTickCount64(
    VOID
    );
#endif
  • Boost1.58版会报错:
boost\thread\win32\thread_primitives.hpp(225,67): error : functions that differ only in their return type cannot be overloaded

在这里插入图片描述
可以在thread_primitives.hpp代码:

#if BOOST_PLAT_WINDOWS_RUNTIME
#include <thread>
#endif

的前面添加如下代码:

#if __clang__
#ifdef BOOST_PLAT_WINDOWS_RUNTIME
#undef BOOST_PLAT_WINDOWS_RUNTIME
#define BOOST_PLAT_WINDOWS_RUNTIME 1
#endif
#endif

通过这些修改就大功告成了,当然如果使用其它第三方库,可能会遇到一些问题,就需要自行探索解决了。

祝玩得开心,如果喜欢本文请记得点赞哦!

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值