一、集成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任务调用过程中输出当前编译的文件名的,不是在配置文件中输出的。具体的代码为:

 1private void ReadUnicodeOutput(object stateInfo)
 2{
 3	uint num;
 4	byte[] lpBuffer = new byte[0x400];
 5	string str = string.Empty;
 6	while (NativeMethodsShared.ReadFile(this.unicodePipeReadHandle, lpBuffer, 0x400, out num, NativeMethodsShared.NullIntPtr) && (num != 0))
 7	{
 8		string str2 = str + Encoding.Unicode.GetString(lpBuffer, 0, (int)num);
 9		while (true)
10		{
11			int length = -1;
12			length = str2.IndexOf('\n');
13			if (length == -1)
14			{
15				str = str2;
16				break;
17			}
18			string lineOfText = str2.Substring(0, length);
19			str2 = str2.Substring(length + 1);
20			if ((lineOfText.Length > 0) && lineOfText.EndsWith("\r", StringComparison.Ordinal))
21			{
22				lineOfText = lineOfText.Substring(0, lineOfText.Length - 1);
23			}
24			base.Log.LogMessageFromText(lineOfText, base.StandardOutputImportanceToUse);
25		}
26	}
27	if (!string.IsNullOrEmpty(str))
28	{
29		base.Log.LogMessageFromText(str, base.StandardOutputImportanceToUse);
30	}
31	this.unicodeOutputEnded.Set();
32}

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

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

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

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

 1namespace VSClang
 2{
 3	using Microsoft.Build.Framework;
 4	using System.IO;
 5
 6	public class ClangCl : Microsoft.Build.CPPTasks.CL
 7	{
 8		protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands)
 9		{
10			foreach (ITaskItem item in base.SourcesCompiled)
11			{
12				base.Log.LogMessage(MessageImportance.High, Path.GetFileName(item.ItemSpec), new object[0]);
13			}
14			return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands);
15		}
16	}
17}

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

(二)、修改安装前配置(如果已经安装过了,修改后再安装一次即可)
  • 修改x64以及Win32目录下toolset-vs2014.props以及toolset-vs2014_xp.props,如下图所示:

  • 添加-fdiagnostics-absolute-paths参数是为了让Clang在输出诊断信息是以绝对路径输出源文件,否则在Visual Studio中窗口无法双击诊断信息定位到源文件。

  • 添加

1<ObjectFileName>$(IntDir)%(filename).obj</ObjectFileName>

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

1</Project>

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

  1<UsingTask TaskName="ClangCl"            AssemblyFile="$(VCTargetsPath)\VSClang.dll"/>
  2
  3<Target Name="ClCompile"
  4          Condition="'@(ClCompile)' != ''"
  5          DependsOnTargets="SelectClCompile">
  6
  7    <PropertyGroup>
  8      <CLToolArchitecture Condition="'$(CLToolArchitecture)' == ''">$(VCToolArchitecture)</CLToolArchitecture>
  9      <CLDeleteOutputOnExecute Condition="'$(CLDeleteOutputOnExecute)' == ''">true</CLDeleteOutputOnExecute>
 10    </PropertyGroup>
 11
 12    <ItemGroup>
 13      <ClNoDependencies Condition="'@(ClNoDependencies)' == '' and '%(ClInclude.NoDependency)' == 'true'" Include="@(ClInclude)"/>
 14      <ClNoDependencies Condition="'$(NoDependencies)' != ''" Include="$(NoDependencies)" />
 15    </ItemGroup>
 16
 17    <!-- Delete the pch file if the pdb file has been deleted.  This will prevent a compiler warning about obsolete pch. -->
 18    <Delete Condition="'%(ClCompile.DebugInformationFormat)' != '' and '%(ClCompile.DebugInformationFormat)' != 'None' and '%(ClCompile.DebugInformationFormat)' != 'OldStyle' and '%(ClCompile.ProgramDataBaseFileName)' != '' and !Exists(%(ClCompile.ProgramDataBaseFileName))"
 19            Files="%(ClCompile.PrecompiledHeaderOutputFile)" />
 20
 21    <!-- Precompiled headers - need to build them first -->
 22    <ClangCl Condition="'%(ClCompile.PrecompiledHeader)' == 'Create' and '%(ClCompile.ExcludedFromBuild)'!='true' and '%(ClCompile.CompilerIteration)' == ''"
 23        BuildingInIDE                      ="$(BuildingInsideVisualStudio)"
 24        Sources                            ="@(ClCompile)"
 25
 26        AdditionalIncludeDirectories       ="%(ClCompile.AdditionalIncludeDirectories)"
 27        AdditionalOptions                  ="%(ClCompile.AdditionalOptions)"
 28        AdditionalUsingDirectories         ="%(ClCompile.AdditionalUsingDirectories)"
 29        AssemblerListingLocation           ="%(ClCompile.AssemblerListingLocation)"
 30        AssemblerOutput                    ="%(ClCompile.AssemblerOutput)"
 31        BasicRuntimeChecks                 ="%(ClCompile.BasicRuntimeChecks)"
 32        BrowseInformation                  ="%(ClCompile.BrowseInformation)"
 33        BrowseInformationFile              ="%(ClCompile.BrowseInformationFile)"
 34        BufferSecurityCheck                ="%(ClCompile.BufferSecurityCheck)"
 35        CallingConvention                  ="%(ClCompile.CallingConvention)"
 36        ControlFlowGuard                   ="%(ClCompile.ControlFlowGuard)"
 37        CompileAsManaged                   ="%(ClCompile.CompileAsManaged)"
 38        CompileAsWinRT                     ="%(ClCompile.CompileAsWinRT)"
 39        CompileAs                          ="%(ClCompile.CompileAs)"
 40        DebugInformationFormat             ="%(ClCompile.DebugInformationFormat)"
 41        DisableLanguageExtensions          ="%(ClCompile.DisableLanguageExtensions)"
 42        DisableSpecificWarnings            ="%(ClCompile.DisableSpecificWarnings)"
 43        EnableEnhancedInstructionSet       ="%(ClCompile.EnableEnhancedInstructionSet)"
 44        EnableFiberSafeOptimizations       ="%(ClCompile.EnableFiberSafeOptimizations)"
 45        EnableParallelCodeGeneration       ="%(ClCompile.EnableParallelCodeGeneration)"
 46        EnablePREfast                      ="%(ClCompile.EnablePREfast)"
 47        EnforceTypeConversionRules         ="%(ClCompile.EnforceTypeConversionRules)"
 48        ErrorReporting                     ="%(ClCompile.ErrorReporting)"
 49        ExceptionHandling                  ="%(ClCompile.ExceptionHandling)"
 50        ExcludedInputPaths                 ="$(ExcludePath)"
 51        ExpandAttributedSource             ="%(ClCompile.ExpandAttributedSource)"
 52        FavorSizeOrSpeed                   ="%(ClCompile.FavorSizeOrSpeed)"
 53        FloatingPointExceptions            ="%(ClCompile.FloatingPointExceptions)"
 54        FloatingPointModel                 ="%(ClCompile.FloatingPointModel)"
 55        ForceConformanceInForLoopScope     ="%(ClCompile.ForceConformanceInForLoopScope)"
 56        ForcedIncludeFiles                 ="%(ClCompile.ForcedIncludeFiles)"
 57        ForcedUsingFiles                   ="%(ClCompile.ForcedUsingFiles)"
 58        FunctionLevelLinking               ="%(ClCompile.FunctionLevelLinking)"
 59        GenerateXMLDocumentationFiles      ="%(ClCompile.GenerateXMLDocumentationFiles)"
 60        IgnoreStandardIncludePath          ="%(ClCompile.IgnoreStandardIncludePath)"
 61        InlineFunctionExpansion            ="%(ClCompile.InlineFunctionExpansion)"
 62        IntrinsicFunctions                 ="%(ClCompile.IntrinsicFunctions)"
 63        MinimalRebuild                     ="%(ClCompile.MinimalRebuild)"
 64        MultiProcessorCompilation          ="%(ClCompile.MultiProcessorCompilation)"
 65        ObjectFileName                     ="%(ClCompile.ObjectFileName)"
 66        OmitDefaultLibName                 ="%(ClCompile.OmitDefaultLibName)"
 67        OmitFramePointers                  ="%(ClCompile.OmitFramePointers)"
 68        OpenMPSupport                      ="%(ClCompile.OpenMPSupport)"
 69        Optimization                       ="%(ClCompile.Optimization)"
 70        PrecompiledHeader                  ="%(ClCompile.PrecompiledHeader)"
 71        PrecompiledHeaderFile              ="%(ClCompile.PrecompiledHeaderFile)"
 72        PrecompiledHeaderOutputFile        ="%(ClCompile.PrecompiledHeaderOutputFile)"
 73        PREfastAdditionalOptions           ="%(ClCompile.PREfastAdditionalOptions)"
 74        PREfastAdditionalPlugins           ="%(ClCompile.PREfastAdditionalPlugins)"
 75        PREfastLog                         ="%(ClCompile.PREfastLog)"
 76        PreprocessKeepComments             ="%(ClCompile.PreprocessKeepComments)"
 77        PreprocessorDefinitions            ="%(ClCompile.PreprocessorDefinitions)"
 78        PreprocessSuppressLineNumbers      ="%(ClCompile.PreprocessSuppressLineNumbers)"
 79        PreprocessToFile                   ="%(ClCompile.PreprocessToFile)"
 80        ProcessorNumber                    ="%(ClCompile.ProcessorNumber)"
 81        ProgramDataBaseFileName            ="%(ClCompile.ProgramDataBaseFileName)"
 82        RemoveUnreferencedCodeData         ="%(ClCompile.RemoveUnreferencedCodeData)"
 83        RuntimeLibrary                     ="%(ClCompile.RuntimeLibrary)"
 84        RuntimeTypeInfo                    ="%(ClCompile.RuntimeTypeInfo)"
 85        SDLCheck                           ="%(ClCompile.SDLCheck)"
 86        ShowIncludes                       ="%(ClCompile.ShowIncludes)"
 87        WarningVersion                     ="%(ClCompile.WarningVersion)"
 88        SmallerTypeCheck                   ="%(ClCompile.SmallerTypeCheck)"
 89        StringPooling                      ="%(ClCompile.StringPooling)"
 90        StructMemberAlignment              ="%(ClCompile.StructMemberAlignment)"
 91        SuppressStartupBanner              ="%(ClCompile.SuppressStartupBanner)"
 92        TreatSpecificWarningsAsErrors      ="%(ClCompile.TreatSpecificWarningsAsErrors)"
 93        TreatWarningAsError                ="%(ClCompile.TreatWarningAsError)"
 94        TreatWChar_tAsBuiltInType          ="%(ClCompile.TreatWChar_tAsBuiltInType)"
 95        UndefineAllPreprocessorDefinitions ="%(ClCompile.UndefineAllPreprocessorDefinitions)"
 96        UndefinePreprocessorDefinitions    ="%(ClCompile.UndefinePreprocessorDefinitions)"
 97        UseFullPaths                       ="%(ClCompile.UseFullPaths)"
 98        UseUnicodeForAssemblerListing      ="%(ClCompile.UseUnicodeForAssemblerListing)"
 99        WarningLevel                       ="%(ClCompile.WarningLevel)"
100        WholeProgramOptimization           ="%(ClCompile.WholeProgramOptimization)"
101        WinRTNoStdLib                      ="%(ClCompile.WinRTNoStdLib)"
102        XMLDocumentationFileName           ="%(ClCompile.XMLDocumentationFileName)"
103        CreateHotpatchableImage            ="%(CLCompile.CreateHotpatchableImage)"
104
105        TrackerLogDirectory                ="%(ClCompile.TrackerLogDirectory)"
106
107        TLogReadFiles                      ="@(CLTLogReadFiles)"
108        TLogWriteFiles                     ="@(CLTLogWriteFiles)"
109        ToolExe                            ="$(CLToolExe)"
110        ToolPath                           ="$(CLToolPath)"
111        TrackFileAccess                    ="$(TrackFileAccess)"
112        MinimalRebuildFromTracking         ="%(ClCompile.MinimalRebuildFromTracking)"
113        ToolArchitecture                   ="$(CLToolArchitecture)"
114        TrackerFrameworkPath               ="$(CLTrackerFrameworkPath)"
115        TrackerSdkPath                     ="$(CLTrackerSdkPath)"
116        TrackedInputFilesToIgnore          ="@(ClNoDependencies)"
117        DeleteOutputOnExecute              ="$(CLDeleteOutputOnExecute)"
118
119        AcceptableNonZeroExitCodes         ="%(ClCompile.AcceptableNonZeroExitCodes)"
120        YieldDuringToolExecution           ="$(ClYieldDuringToolExecution)"
121    >
122    </ClangCl>
123
124    <!-- Rest of the sources -->
125    <ClangCl Condition="'%(ClCompile.PrecompiledHeader)' != 'Create' and '%(ClCompile.ExcludedFromBuild)'!='true' and '%(ClCompile.CompilerIteration)' == '' and @(ClCompile) != ''"
126        BuildingInIDE                      ="$(BuildingInsideVisualStudio)"
127        Sources                            ="@(ClCompile)"
128
129        AdditionalIncludeDirectories       ="%(ClCompile.AdditionalIncludeDirectories)"
130        AdditionalOptions                  ="%(ClCompile.AdditionalOptions)"
131        AdditionalUsingDirectories         ="%(ClCompile.AdditionalUsingDirectories)"
132        AssemblerListingLocation           ="%(ClCompile.AssemblerListingLocation)"
133        AssemblerOutput                    ="%(ClCompile.AssemblerOutput)"
134        BasicRuntimeChecks                 ="%(ClCompile.BasicRuntimeChecks)"
135        BrowseInformation                  ="%(ClCompile.BrowseInformation)"
136        BrowseInformationFile              ="%(ClCompile.BrowseInformationFile)"
137        BufferSecurityCheck                ="%(ClCompile.BufferSecurityCheck)"
138        CallingConvention                  ="%(ClCompile.CallingConvention)"
139        ControlFlowGuard                   ="%(ClCompile.ControlFlowGuard)"
140        CompileAsManaged                   ="%(ClCompile.CompileAsManaged)"
141        CompileAsWinRT                     ="%(ClCompile.CompileAsWinRT)"
142        CompileAs                          ="%(ClCompile.CompileAs)"
143        DebugInformationFormat             ="%(ClCompile.DebugInformationFormat)"
144        DisableLanguageExtensions          ="%(ClCompile.DisableLanguageExtensions)"
145        DisableSpecificWarnings            ="%(ClCompile.DisableSpecificWarnings)"
146        EnableEnhancedInstructionSet       ="%(ClCompile.EnableEnhancedInstructionSet)"
147        EnableFiberSafeOptimizations       ="%(ClCompile.EnableFiberSafeOptimizations)"
148        EnableParallelCodeGeneration       ="%(ClCompile.EnableParallelCodeGeneration)"
149        EnablePREfast                      ="%(ClCompile.EnablePREfast)"
150        EnforceTypeConversionRules         ="%(ClCompile.EnforceTypeConversionRules)"
151        ErrorReporting                     ="%(ClCompile.ErrorReporting)"
152        ExceptionHandling                  ="%(ClCompile.ExceptionHandling)"
153        ExcludedInputPaths                 ="$(ExcludePath)"
154        ExpandAttributedSource             ="%(ClCompile.ExpandAttributedSource)"
155        FavorSizeOrSpeed                   ="%(ClCompile.FavorSizeOrSpeed)"
156        FloatingPointExceptions            ="%(ClCompile.FloatingPointExceptions)"
157        FloatingPointModel                 ="%(ClCompile.FloatingPointModel)"
158        ForceConformanceInForLoopScope     ="%(ClCompile.ForceConformanceInForLoopScope)"
159        ForcedIncludeFiles                 ="%(ClCompile.ForcedIncludeFiles)"
160        ForcedUsingFiles                   ="%(ClCompile.ForcedUsingFiles)"
161        FunctionLevelLinking               ="%(ClCompile.FunctionLevelLinking)"
162        GenerateXMLDocumentationFiles      ="%(ClCompile.GenerateXMLDocumentationFiles)"
163        IgnoreStandardIncludePath          ="%(ClCompile.IgnoreStandardIncludePath)"
164        InlineFunctionExpansion            ="%(ClCompile.InlineFunctionExpansion)"
165        IntrinsicFunctions                 ="%(ClCompile.IntrinsicFunctions)"
166        MinimalRebuild                     ="%(ClCompile.MinimalRebuild)"
167        MultiProcessorCompilation          ="%(ClCompile.MultiProcessorCompilation)"
168        ObjectFileName                     ="%(ClCompile.ObjectFileName)"
169        OmitDefaultLibName                 ="%(ClCompile.OmitDefaultLibName)"
170        OmitFramePointers                  ="%(ClCompile.OmitFramePointers)"
171        OpenMPSupport                      ="%(ClCompile.OpenMPSupport)"
172        Optimization                       ="%(ClCompile.Optimization)"
173        PrecompiledHeader                  ="%(ClCompile.PrecompiledHeader)"
174        PrecompiledHeaderFile              ="%(ClCompile.PrecompiledHeaderFile)"
175        PrecompiledHeaderOutputFile        ="%(ClCompile.PrecompiledHeaderOutputFile)"
176        PREfastAdditionalOptions           ="%(ClCompile.PREfastAdditionalOptions)"
177        PREfastAdditionalPlugins           ="%(ClCompile.PREfastAdditionalPlugins)"
178        PREfastLog                         ="%(ClCompile.PREfastLog)"
179        PreprocessKeepComments             ="%(ClCompile.PreprocessKeepComments)"
180        PreprocessorDefinitions            ="%(ClCompile.PreprocessorDefinitions)"
181        PreprocessSuppressLineNumbers      ="%(ClCompile.PreprocessSuppressLineNumbers)"
182        PreprocessToFile                   ="%(ClCompile.PreprocessToFile)"
183        ProcessorNumber                    ="%(ClCompile.ProcessorNumber)"
184        ProgramDataBaseFileName            ="%(ClCompile.ProgramDataBaseFileName)"
185        RemoveUnreferencedCodeData         ="%(ClCompile.RemoveUnreferencedCodeData)"
186        RuntimeLibrary                     ="%(ClCompile.RuntimeLibrary)"
187        RuntimeTypeInfo                    ="%(ClCompile.RuntimeTypeInfo)"
188        SDLCheck                           ="%(ClCompile.SDLCheck)"
189        ShowIncludes                       ="%(ClCompile.ShowIncludes)"
190        WarningVersion                     ="%(ClCompile.WarningVersion)"
191        SmallerTypeCheck                   ="%(ClCompile.SmallerTypeCheck)"
192        StringPooling                      ="%(ClCompile.StringPooling)"
193        StructMemberAlignment              ="%(ClCompile.StructMemberAlignment)"
194        SuppressStartupBanner              ="%(ClCompile.SuppressStartupBanner)"
195        TreatSpecificWarningsAsErrors      ="%(ClCompile.TreatSpecificWarningsAsErrors)"
196        TreatWarningAsError                ="%(ClCompile.TreatWarningAsError)"
197        TreatWChar_tAsBuiltInType          ="%(ClCompile.TreatWChar_tAsBuiltInType)"
198        UndefineAllPreprocessorDefinitions ="%(ClCompile.UndefineAllPreprocessorDefinitions)"
199        UndefinePreprocessorDefinitions    ="%(ClCompile.UndefinePreprocessorDefinitions)"
200        UseFullPaths                       ="%(ClCompile.UseFullPaths)"
201        UseUnicodeForAssemblerListing      ="%(ClCompile.UseUnicodeForAssemblerListing)"
202        WarningLevel                       ="%(ClCompile.WarningLevel)"
203        WholeProgramOptimization           ="%(ClCompile.WholeProgramOptimization)"
204        WinRTNoStdLib                      ="%(ClCompile.WinRTNoStdLib)"
205        XMLDocumentationFileName           ="%(ClCompile.XMLDocumentationFileName)"
206        CreateHotpatchableImage            ="%(CLCompile.CreateHotpatchableImage)"
207
208        TrackerLogDirectory                ="%(ClCompile.TrackerLogDirectory)"
209
210        TLogReadFiles                      ="@(CLTLogReadFiles)"
211        TLogWriteFiles                     ="@(CLTLogWriteFiles)"
212        ToolExe                            ="$(CLToolExe)"
213        ToolPath                           ="$(CLToolPath)"
214        TrackFileAccess                    ="$(TrackFileAccess)"
215        MinimalRebuildFromTracking         ="%(ClCompile.MinimalRebuildFromTracking)"
216        ToolArchitecture                   ="$(CLToolArchitecture)"
217        TrackerFrameworkPath               ="$(CLTrackerFrameworkPath)"
218        TrackerSdkPath                     ="$(CLTrackerSdkPath)"
219        TrackedInputFilesToIgnore          ="@(ClNoDependencies)"
220        DeleteOutputOnExecute              ="$(CLDeleteOutputOnExecute)"
221
222        AcceptableNonZeroExitCodes         ="%(ClCompile.AcceptableNonZeroExitCodes)"
223        YieldDuringToolExecution           ="$(ClYieldDuringToolExecution)"
224    >
225    </ClangCl>
226    
227    <OnError Condition="'$(OnXamlPreCompileErrorTarget)' != ''" ExecuteTargets="$(OnXamlPreCompileErrorTarget)" />
228  </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工具集,即在

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

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

Toolset.props文件内容如下:

 1<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 2  <Import Project="$(MSBuildThisFileDirectory)ImportBefore\*.props" Condition="Exists('$(MSBuildThisFileDirectory)ImportBefore')" />
 3
 4  <PropertyGroup>
 5    <ClangTarget>amd64-pc-windows-msvc</ClangTarget>
 6  </PropertyGroup>
 7
 8  <PropertyGroup>
 9    <!-- Required for enabling Team Build for packaging Windows Store app projects -->
10    <OutDirWasSpecified Condition=" '$(OutDir)'!='' AND '$(OutDirWasSpecified)'=='' ">true</OutDirWasSpecified>
11    <OutDirWasSpecified Condition=" '$(OutDir)'=='' AND '$(OutDirWasSpecified)'=='' ">false</OutDirWasSpecified>
12
13    <IntDir Condition="'$(IntDir)'=='' AND '$(IntermediateOutputPath)'!=''">$(IntermediateOutputPath)</IntDir>
14    <IntDir Condition="'$(IntDir)'=='' AND '$(IntermediateOutputPath)'==''">$(Platform)\$(Configuration)\</IntDir>
15    <OutDir Condition="'$(OutDir)'=='' AND '$(SolutionDir)' == ''">$(IntDir)</OutDir>
16    <OutDir Condition="'$(OutDir)'=='' AND '$(SolutionDir)' != ''">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
17  </PropertyGroup>
18
19  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.WindowsSDK.props" Condition="Exists('$(VCTargetsPath)\Microsoft.Cpp.WindowsSDK.props')"/>
20  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Common.props" />
21  
22  <!-- This sets Clang common defaults. -->
23  <PropertyGroup>
24    <GNUMode>true</GNUMode>
25    <MSVCErrorReport>true</MSVCErrorReport>
26    <ToolsetISenseIdentifier>Clang.Windows</ToolsetISenseIdentifier>
27  </PropertyGroup>
28
29  <PropertyGroup>
30    <VCClangInstallDir Condition="'$(VCClangInstallDir)' == ''">$(VCInstallDir)ClangC2\</VCClangInstallDir>
31    <VCClangBinDir Condition="'$(VCToolArchitecture)' == 'Native64Bit'">$(VCClangInstallDir)bin\amd64</VCClangBinDir>
32    <VCClangBinDir Condition="'$(VCToolArchitecture)' != 'Native64Bit'">$(VCClangInstallDir)bin\x86</VCClangBinDir>
33  </PropertyGroup>
34
35  <ItemDefinitionGroup>
36    <ClCompile>
37      <MSExtensions>false</MSExtensions>
38      <MSCompatibility>false</MSCompatibility>
39      <PreprocessorDefinitions Condition="'$(UseDebugLibraries)' != 'true'">NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
40      <AdditionalOptions>-g -gcodeview -fdiagnostics-absolute-paths -fno-delayed-template-parsing -Xclang -flto-visibility-public-std %(AdditionalOptions)</AdditionalOptions>
41    </ClCompile>
42  </ItemDefinitionGroup>
43
44  <PropertyGroup>
45    <ExecutablePath Condition="'$(ExecutablePath)' == ''">$(VCClangBinDir)\amd64;$(VCClangBinDir);$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH);</ExecutablePath>
46    <IncludePath Condition="'$(IncludePath)' == ''">$(VCClangInstallDir)include;$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
47    <ReferencePath Condition="'$(ReferencePath)' == ''">$(VC_ReferencesPath_x64);</ReferencePath>
48    <LibraryPath Condition="'$(LibraryPath)' == ''">$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64</LibraryPath>
49    <LibraryWPath Condition="'$(LibraryWPath)' == ''">$(WindowsSDK_MetadataPath);</LibraryWPath>
50    <SourcePath Condition="'$(SourcePath)' == ''">$(VC_SourcePath);</SourcePath>
51    <ExcludePath Condition="'$(ExcludePath)' == ''">$(VC_IncludePath);$(WindowsSDK_IncludePath);$(MSBuild_ExecutablePath);$(VC_LibraryPath_x64);</ExcludePath>
52    <DebugCppRuntimeFilesPath Condition="'$(DebugCppRuntimeFilesPath)' == ''">$(VCInstallDir)redist\Debug_NonRedist\x64</DebugCppRuntimeFilesPath>	
53  </PropertyGroup>
54
55  <Import Project="$(MSBuildThisFileDirectory)ImportAfter\*.props" Condition="Exists('$(MSBuildThisFileDirectory)ImportAfter')" />
56  
57  <!-- This is intentially added after ImportAfter. -->
58  <Import Project="$(_PlatformFolder)Platform.Common.props" />
59  
60  <!-- This overrides some of the platform defaults. -->
61  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Clang.props" />
62  
63  <!-- 重载 -->
64  <ItemDefinitionGroup>
65    <ClCompile>
66      <MSExtensions>true</MSExtensions>
67      <MSCompatibility>true</MSCompatibility>
68      <PositionIndependentCode>false</PositionIndependentCode>
69      <RuntimeTypeInfo>true</RuntimeTypeInfo>
70      <DebugInformationFormat>LineNumber</DebugInformationFormat>
71	  <WarningLevel>EnableAllWarnings</WarningLevel>
72	  <UseMultiToolTask>true</UseMultiToolTask>
73    </ClCompile>
74  </ItemDefinitionGroup>
75</Project>

Toolset.targets文件内容如下:

 1<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 2
 3  <Import Project="$(MSBuildThisFileDirectory)ImportBefore\*.targets" Condition="Exists('$(MSBuildThisFileDirectory)ImportBefore')" />
 4
 5  <Import Project="$(VCTargetsPath)\Microsoft.CppCommon.targets" />
 6  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Clang.targets" />
 7
 8  <Import Project="$(MSBuildThisFileDirectory)ImportAfter\*.targets" Condition="Exists('$(MSBuildThisFileDirectory)ImportAfter')" />
 9
10</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完整内容如下:

 1<!--
 2***********************************************************************************************
 3Microsoft.Cpp.Clang.props
 4
 5WARNING:  DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
 6          created a backup copy.  Incorrect changes to this file will make it
 7          impossible to load or build your projects from the command-line or the IDE.
 8
 9Copyright (C) Microsoft Corporation. All rights reserved.
10***********************************************************************************************
11-->
12
13<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
14  <Import Project="$(MSBuildThisFileDirectory)ImportBefore\*.props" Condition="Exists('$(MSBuildThisFileDirectory)ImportBefore')" />
15
16  <ItemDefinitionGroup>
17    <ClCompile>
18      <ClangMode>true</ClangMode>
19      <WarningLevel>EnableAllWarnings</WarningLevel>
20      <DebugInformationFormat Condition="'$(UseDebugLibraries)' == 'true'">FullDebug</DebugInformationFormat>
21      <DebugInformationFormat Condition="'$(UseDebugLibraries)' != 'true'">LineNumber</DebugInformationFormat>
22      <PreprocessorDefinitions Condition="'$(UseDebugLibraries)' == 'true'">NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
23      <Optimization Condition="'$(UseDebugLibraries)' == 'true'">Disabled</Optimization>
24      <Optimization Condition="'$(UseDebugLibraries)' != 'true'">Full</Optimization>
25      <StrictAliasing>false</StrictAliasing>
26      <ProgramDatabaseFileName>$(IntDir)</ProgramDatabaseFileName>
27      <OmitFramePointers Condition="'$(UseDebugLibraries)' == 'true'">false</OmitFramePointers>
28      <OmitFramePointers Condition="'$(UseDebugLibraries)' != 'true'">true</OmitFramePointers>
29      <ExceptionHandling>Enabled</ExceptionHandling>
30      <FunctionLevelLinking Condition="'$(UseDebugLibraries)' == 'true'">false</FunctionLevelLinking>
31      <FunctionLevelLinking Condition="'$(UseDebugLibraries)' != 'true'">true</FunctionLevelLinking>
32      <DataLevelLinking Condition="'$(UseDebugLibraries)' == 'true'">false</DataLevelLinking>
33      <DataLevelLinking Condition="'$(UseDebugLibraries)' != 'true'">true</DataLevelLinking>
34      <BufferSecurityCheck>true</BufferSecurityCheck>
35      <PositionIndependentCode>true</PositionIndependentCode>
36      <UseShortEnums>false</UseShortEnums>
37      <RuntimeTypeInfo>false</RuntimeTypeInfo>
38      <CLanguageStandard>Default</CLanguageStandard>
39      <CppLanguageStandard>Default</CppLanguageStandard>
40      <PrecompiledHeader>NotUsing</PrecompiledHeader>
41      <ObjectFileName>$(IntDir)%(filename).obj</ObjectFileName>
42      <CompileAs>Default</CompileAs>
43      <TreatWarningAsError>false</TreatWarningAsError>
44      <Verbose>false</Verbose>
45      <EnablePREfast Condition="'%(ClCompile.EnablePREfast)' == ''">false</EnablePREfast>
46      <OmitFramePointers Condition="'%(ClCompile.OmitFramePointers)' == ''">false</OmitFramePointers>
47      <MinimalRebuildFromTracking>true</MinimalRebuildFromTracking>
48      <PrecompiledHeaderOutputFileDirectory>$(IntDir)</PrecompiledHeaderOutputFileDirectory>
49      <PrecompiledHeaderOutputFile></PrecompiledHeaderOutputFile>
50      <PrecompiledHeaderCompileAs>CompileAsCpp</PrecompiledHeaderCompileAs>
51    </ClCompile>
52  </ItemDefinitionGroup>
53
54  <Import Project="$(MSBuildThisFileDirectory)ImportAfter\*.props" Condition="Exists('$(MSBuildThisFileDirectory)ImportAfter')" />
55</Project>

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

  1<!--
  2***********************************************************************************************
  3Microsoft.Cpp.Clang.targets
  4
  5WARNING:  DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
  6          created a backup copy.  Incorrect changes to this file will make it
  7          impossible to load or build your projects from the command-line or the IDE.
  8
  9This file defines the steps/targets required to build Visual C++ projects
 10that use Clang Front-End.
 11
 12Copyright (C) Microsoft Corporation. All rights reserved.
 13***********************************************************************************************
 14-->
 15
 16<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 17  <UsingTask TaskName="ClangCompile" AssemblyFile="$(VCTargetsPath)Microsoft.Build.CppTasks.Common.dll"/>
 18
 19  <!-- *******************************************************************************************
 20        Clang Compile
 21       ******************************************************************************************* -->
 22
 23  <Target Name="FixupCLCompileOptions"
 24          Condition="'@(ClCompile)' != ''">
 25    <ItemGroup>
 26      <ClCompile>
 27        <PrecompiledHeaderOutputFileDirectory Condition="'%(ClCompile.PrecompiledHeaderOutputFileDirectory)' != '' and !HasTrailingSlash('%(ClCompile.PrecompiledHeaderOutputFileDirectory)')">%(ClCompile.PrecompiledHeaderOutputFileDirectory)\</PrecompiledHeaderOutputFileDirectory>
 28      </ClCompile>
 29
 30    <!-- Add PCH to the list of compiles -->
 31      <ClCompilePCH Condition="'%(ClCompile.PrecompiledHeaderFile)' != '' and '%(ClCompile.PrecompiledHeader)' == 'Use'" Include="@(ClCompile->Metadata(PrecompiledHeaderFile)->Fullpath()->Distinct()->ClearMetadata())">
 32        <CompileAs/>
 33        <ForcedIncludeFiles/>
 34        <PrecompiledHeaderFile/>
 35        <PrecompiledHeader>Create</PrecompiledHeader>
 36        <PrecompiledHeaderCompileAs>%(ClCompile.PrecompiledHeaderCompileAs)</PrecompiledHeaderCompileAs>
 37        <PrecompiledHeaderOutputFileDirectory>%(ClCompile.PrecompiledHeaderOutputFileDirectory)</PrecompiledHeaderOutputFileDirectory>
 38        <!-- PCH are not part of the build, so exclude the output from the link step. -->
 39        <LibCompiled>false</LibCompiled>
 40        <LinkCompiled>false</LinkCompiled>
 41      </ClCompilePCH>
 42
 43      <ClCompilePCH>
 44        <ObjectFileName>%(ClCompilePCH.PrecompiledHeaderOutputFileDirectory)%(FileName)%(Extension).gch</ObjectFileName>
 45      </ClCompilePCH>
 46
 47      <!-- Add PCH to the force include, and remove from PCH related flags. -->
 48      <ClCompile Condition="'%(ClCompile.PrecompiledHeader)' == 'Use' and '$(DesignTimeBuild)' == 'true'">
 49        <!-- Clang expect the output pch.h, which it will deduce pch.h.gch) -->
 50        <!-- VC intellisense expect the source pch.h -->
 51        <ForcedIncludeFiles>%(ClCompile.PrecompiledHeaderFile);%(ClCompile.ForcedIncludeFiles)</ForcedIncludeFiles>
 52        <PrecompiledHeaderOutputFile>%(PrecompiledHeaderOutputFileDirectory)%(ClCompile.PrecompiledHeaderFile).gch</PrecompiledHeaderOutputFile>
 53      </ClCompile>
 54
 55      <ClCompile Condition="'%(ClCompile.PrecompiledHeader)' == 'Use' and '$(DesignTimeBuild)' != 'true' and '%(Identity)' != ''">
 56        <ForcedIncludeFiles>@(ClCompile->Metadata(PrecompiledHeaderFile)->'%(PrecompiledHeaderOutputFileDirectory)%(FileName)%(Extension)');%(ClCompile.ForcedIncludeFiles)</ForcedIncludeFiles>
 57        <!-- Set MultiToolTask scheduler to wait for the PCH to finish. -->
 58        <MultiToolTaskDependency>@(ClCompile->Metadata(PrecompiledHeaderFile)->Fullpath()->Distinct()->ClearMetadata())</MultiToolTaskDependency>
 59      </ClCompile>
 60
 61      <!-- Done processing PCH, blank out the unused metadata. -->
 62      <ClCompile>
 63        <PrecompiledHeaderFile />
 64        <PrecompiledHeaderCompileAs />
 65        <PrecompiledHeaderOutputFileDirectory />
 66      </ClCompile>
 67
 68      <ClCompilePCH>
 69        <PrecompiledHeaderOutputFileDirectory />
 70        <RuntimeTypeInfo Condition="'%(ClCompilePCH.PrecompiledHeaderCompileAs)' == 'CompileAsC'" />
 71      </ClCompilePCH>
 72
 73      <ClCompile Condition="'$(DesignTimeBuild)' != 'true'" Include="@(ClCompilePCH)" />
 74
 75      <ClCompile>
 76        <BuildingInIDE>$(BuildingInsideVisualStudio)</BuildingInIDE>
 77        <GNUMode>$(GNUMode)</GNUMode>
 78        <MSVCErrorReport>$(MSVCErrorReport)</MSVCErrorReport>
 79        <GccToolChain>$(GccToolchainPrebuiltPath)</GccToolChain>
 80        <Sysroot>$(Sysroot)</Sysroot>
 81        <TargetArch>$(ClangTarget)</TargetArch>
 82        <MinimalRebuildFromTracking Condition="'$(_BuildActionType)' != 'Build' or '$(ForceRebuild)' == 'true'">false</MinimalRebuildFromTracking>
 83        <WarningLevel Condition="'%(WarningLevel)' == 'Level1' or '%(WarningLevel)' == 'Level2' or '%(WarningLevel)' == 'Level3'">EnableAllWarnings</WarningLevel>
 84        <CompileAs Condition="'%(ClCompile.CompileAs)' == 'Default' and '%(ClCompile.Extension)' == '.c'">CompileAsC</CompileAs>
 85        <CompileAs Condition="'%(ClCompile.CompileAs)' == 'Default' and '%(ClCompile.Extension)' != '.c'">CompileAsCpp</CompileAs>
 86      </ClCompile>
 87
 88      <ClCompile>
 89        <!-- Dont pass C standard to C++ and vice versa -->
 90        <CLanguageStandard Condition="'%(ClCompile.CompileAs)' == 'CompileAsCpp'"></CLanguageStandard>
 91        <CppLanguageStandard Condition="'%(ClCompile.CompileAs)' == 'CompileAsC'"></CppLanguageStandard>
 92        
 93        <!-- C doesn't support 'RuntimeTypeInfo' -->
 94        <RuntimeTypeInfo Condition="'%(ClCompile.CompileAs)' == 'CompileAsC'" />
 95      </ClCompile>
 96      
 97      <!-- Fixup Windows Runtime Library switches. -->
 98      <ClCompile Condition="'$(DesignTimeBuild)' != 'true'">
 99        <AdditionalOptions Condition="'%(ClCompile.RuntimeLibrary)' == 'MultiThreaded'">%(ClCompile.AdditionalOptions) -D_MT -Xclang --dependent-lib=libcmt -Xclang --dependent-lib=oldnames</AdditionalOptions>
100        <AdditionalOptions Condition="'%(ClCompile.RuntimeLibrary)' == 'MultiThreadedDebug'">%(ClCompile.AdditionalOptions) -D_DEBUG -D_MT -Xclang --dependent-lib=libcmtd -Xclang --dependent-lib=oldnames</AdditionalOptions>
101        <AdditionalOptions Condition="'%(ClCompile.RuntimeLibrary)' == 'MultiThreadedDLL'">%(ClCompile.AdditionalOptions) -D_MT -D_DLL -Xclang --dependent-lib=msvcrt -Xclang --dependent-lib=oldnames</AdditionalOptions>
102        <AdditionalOptions Condition="'%(ClCompile.RuntimeLibrary)' == 'MultiThreadedDebugDLL'">%(ClCompile.AdditionalOptions) -D_DEBUG -D_MT -D_DLL -Xclang --dependent-lib=msvcrtd -Xclang --dependent-lib=oldnames</AdditionalOptions>
103      </ClCompile>
104    </ItemGroup>
105  </Target>
106
107  <Target Name="ClCompile"
108          Condition="'@(ClCompile)' != ''"
109          DependsOnTargets="SelectClCompile" >
110
111    <PropertyGroup>
112      <CLToolArchitecture Condition="'$(CLToolArchitecture)' == ''">$(VCToolArchitecture)</CLToolArchitecture>
113      <CLDeleteOutputOnExecute Condition="'$(CLDeleteOutputOnExecute)' == ''">true</CLDeleteOutputOnExecute>
114      <ClMutliToolTaskMinimalRebuild>true</ClMutliToolTaskMinimalRebuild>
115      <ClMutliToolTaskMinimalRebuild Condition="'$(_BuildActionType)' != 'Build' or '$(ForceRebuild)' == 'true'">false</ClMutliToolTaskMinimalRebuild>
116      <ProcessorNumber Condition="'$(ProcessorNumber)' == ''">$(CL_MPCount)</ProcessorNumber>
117    </PropertyGroup>
118
119    <ItemGroup>
120      <ClCompile>
121        <!-- Moved to this target to avoid adding add $(IncludePath) for intellisense -->
122        <AdditionalIncludeDirectories>%(ClCompile.AdditionalIncludeDirectories);$(IncludePath)</AdditionalIncludeDirectories>
123      </ClCompile>
124    </ItemGroup>
125
126    <Message Condition="'$(_DebugMessages)' == 'true'" Importance="high" Text="ClCompilePCH = '@(ClCompilePCH)'"/>
127    <Message Condition="'$(_DebugMessages)' == 'true'" Importance="high" Text="ClCompilePCH.ObjectFileName = '%(ClCompilePCH.ObjectFileName)'"/>
128
129    <MultiToolTask Condition="'%(ClCompile.ExcludedFromBuild)' != 'true' and '$(UseMultiToolTask)' == 'true'"
130                  TaskName="Microsoft.Build.CPPTasks.ClangCompile"
131                  TaskAssemblyName="$(VCTargetsPath)Microsoft.Build.CppTasks.Common.dll"
132                  Sources="@(ClCompile)"
133
134                  SchedulerVerbose="$(MultiToolTaskVerbose)"
135                  SemaphoreProcCount="$(ProcessorNumber)"
136                  TrackFileAccess="$(TrackFileAccess)"
137                  TrackerLogDirectory="$(TLogLocation)"
138                  MinimalRebuildFromTracking="$(ClMutliToolTaskMinimalRebuild)"
139                  TLogReadFiles="@(CLTLogReadFiles)"
140                  TLogWriteFiles="@(CLTLogWriteFiles)"
141                  ToolExe="$(ClangToolExe)"
142                  ToolPath="$(ClangToolPath)"
143                  ToolArchitecture="$(CLToolArchitecture)"
144                  TrackerFrameworkPath="$(CLTrackerFrameworkPath)"
145                  TrackerSdkPath="$(CLTrackerSdkPath)"
146                  EnableExecuteTool="$(ClangEnableExecuteTool)"
147    >
148    </MultiToolTask>
149
150    <!-- Precompiled headers - need to build them first -->
151    <ClangCompile Condition="'%(ClCompile.PrecompiledHeader)' == 'Create' and '$(UseMultiToolTask)' != 'true'"
152
153                  BuildingInIDE = "%(ClCompile.BuildingInsideVisualStudio)"
154                  GNUMode="%(ClCompile.GNUMode)"
155                  MSVCErrorReport="%(ClCompile.MSVCErrorReport)"
156
157                  Sources="@(ClCompile)"
158                  AdditionalIncludeDirectories="%(ClCompile.AdditionalIncludeDirectories)"
159                  AdditionalOptions="%(ClCompile.AdditionalOptions)"
160                  BufferSecurityCheck="%(ClCompile.BufferSecurityCheck)"
161                  CLanguageStandard="%(ClCompile.CLanguageStandard)"
162                  CppLanguageStandard="%(ClCompile.CppLanguageStandard)"
163                  DataLevelLinking="%(ClCompile.DataLevelLinking)"
164                  DebugInformationFormat="%(ClCompile.DebugInformationFormat)"
165                  ExceptionHandling="%(ClCompile.ExceptionHandling)"
166                  FloatABI="%(ClCompile.FloatABI)"
167                  ForcedIncludeFiles="%(ClCompile.ForcedIncludeFiles)"
168                  FunctionLevelLinking="%(ClCompile.FunctionLevelLinking)"
169                  ObjectFileName="%(ClCompile.ObjectFileName)"
170                  OmitFramePointers="%(ClCompile.OmitFramePointers)"
171                  Optimization="%(ClCompile.Optimization)"
172                  PositionIndependentCode="%(ClCompile.PositionIndependentCode)"
173                  PrecompiledHeader="%(ClCompile.PrecompiledHeader)"
174                  PrecompiledHeaderCompileAs="%(ClCompile.PrecompiledHeaderCompileAs)"
175                  PreprocessorDefinitions="%(ClCompile.PreprocessorDefinitions)"
176                  RuntimeLibrary="%(ClCompile.RuntimeLibrary)"
177                  RuntimeTypeInfo="%(ClCompile.RuntimeTypeInfo)"
178                  ShowIncludes="%(ClCompile.ShowIncludes)"
179                  StrictAliasing="%(ClCompile.StrictAliasing)"
180                  ThumbMode="%(ClCompile.ThumbMode)"
181                  TreatWarningAsError="%(ClCompile.TreatWarningAsError)"
182                  UndefineAllPreprocessorDefinitions="%(ClCompile.UndefineAllPreprocessorDefinitions)"
183                  UndefinePreprocessorDefinitions="%(ClCompile.UndefinePreprocessorDefinitions)"
184                  UseShortEnums="%(ClCompile.UseShortEnums)"
185                  Verbose="%(ClCompile.Verbose)"
186                  WarningLevel="%(ClCompile.WarningLevel)"
187
188                  GccToolChain="%(ClCompile.GccToolChain)"
189                  Sysroot="%(ClCompile.Sysroot)"
190                  TargetArch="%(ClCompile.TargetArch)"
191
192                  TrackFileAccess="$(TrackFileAccess)"
193                  TrackerLogDirectory="$(TLogLocation)"
194                  MinimalRebuildFromTracking="%(ClCompile.MinimalRebuildFromTracking)"
195                  TLogReadFiles="@(CLTLogReadFiles)"
196                  TLogWriteFiles="@(CLTLogWriteFiles)"
197                  ToolExe="$(ClangToolExe)"
198                  ToolPath="$(ClangToolPath)"
199                  ToolArchitecture="$(CLToolArchitecture)"
200                  TrackerFrameworkPath="$(CLTrackerFrameworkPath)"
201                  TrackerSdkPath="$(CLTrackerSdkPath)"
202                  EnableExecuteTool="$(ClangEnableExecuteTool)"
203                  MSExtensions="%(ClCompile.MSExtensions)"
204                  MSCompatibility="%(ClCompile.MSCompatibility)"
205                  MSCompatibilityVersion="%(ClCompile.MSCompatibilityVersion)"
206                  MSCompilerVersion="%(ClCompile.MSCompilerVersion)"
207    >
208    </ClangCompile>
209
210    <ClangCompile Condition="'%(ClCompile.ExcludedFromBuild)' != 'true' and '%(ClCompile.PrecompiledHeader)' != 'Create' and '$(UseMultiToolTask)' != 'true'"
211                  BuildingInIDE = "%(ClCompile.BuildingInsideVisualStudio)"
212                  GNUMode="%(ClCompile.GNUMode)"
213                  MSVCErrorReport="%(ClCompile.MSVCErrorReport)"
214
215                  Sources="@(ClCompile)"
216                  AdditionalIncludeDirectories="%(ClCompile.AdditionalIncludeDirectories)"
217                  AdditionalOptions="%(ClCompile.AdditionalOptions)"
218                  BufferSecurityCheck="%(ClCompile.BufferSecurityCheck)"
219                  CLanguageStandard="%(ClCompile.CLanguageStandard)"
220                  CompileAs="%(ClCompile.CompileAs)"
221                  CppLanguageStandard="%(ClCompile.CppLanguageStandard)"
222                  DataLevelLinking="%(ClCompile.DataLevelLinking)"
223                  DebugInformationFormat="%(ClCompile.DebugInformationFormat)"
224                  ExceptionHandling="%(ClCompile.ExceptionHandling)"
225                  FloatABI="%(ClCompile.FloatABI)"
226                  ForcedIncludeFiles="%(ClCompile.ForcedIncludeFiles)"
227                  FunctionLevelLinking="%(ClCompile.FunctionLevelLinking)"
228                  ObjectFileName="%(ClCompile.ObjectFileName)"
229                  OmitFramePointers="%(ClCompile.OmitFramePointers)"
230                  Optimization="%(ClCompile.Optimization)"
231                  PositionIndependentCode="%(ClCompile.PositionIndependentCode)"
232                  PrecompiledHeader="%(ClCompile.PrecompiledHeader)"
233                  PreprocessorDefinitions="%(ClCompile.PreprocessorDefinitions)"
234                  RuntimeLibrary="%(ClCompile.RuntimeLibrary)"
235                  RuntimeTypeInfo="%(ClCompile.RuntimeTypeInfo)"
236                  ShowIncludes="%(ClCompile.ShowIncludes)"
237                  StrictAliasing="%(ClCompile.StrictAliasing)"
238                  ThumbMode="%(ClCompile.ThumbMode)"
239                  TreatWarningAsError="%(ClCompile.TreatWarningAsError)"
240                  UndefineAllPreprocessorDefinitions="%(ClCompile.UndefineAllPreprocessorDefinitions)"
241                  UndefinePreprocessorDefinitions="%(ClCompile.UndefinePreprocessorDefinitions)"
242                  UseShortEnums="%(ClCompile.UseShortEnums)"
243                  Verbose="%(ClCompile.Verbose)"
244                  WarningLevel="%(ClCompile.WarningLevel)"
245
246                  GccToolChain="%(ClCompile.GccToolChain)"
247                  Sysroot="%(ClCompile.Sysroot)"
248                  TargetArch="%(ClCompile.TargetArch)"
249
250                  TrackFileAccess="$(TrackFileAccess)"
251                  TrackerLogDirectory="$(TLogLocation)"
252                  MinimalRebuildFromTracking="%(ClCompile.MinimalRebuildFromTracking)"
253                  TLogReadFiles="@(CLTLogReadFiles)"
254                  TLogWriteFiles="@(CLTLogWriteFiles)"
255                  ToolExe="$(ClangToolExe)"
256                  ToolPath="$(ClangToolPath)"
257                  ToolArchitecture="$(CLToolArchitecture)"
258                  TrackerFrameworkPath="$(CLTrackerFrameworkPath)"
259                  TrackerSdkPath="$(CLTrackerSdkPath)"
260                  EnableExecuteTool="$(ClangEnableExecuteTool)"
261                  MSExtensions="%(ClCompile.MSExtensions)"
262                  MSCompatibility="%(ClCompile.MSCompatibility)"
263                  MSCompatibilityVersion="%(ClCompile.MSCompatibilityVersion)"
264                  MSCompilerVersion="%(ClCompile.MSCompilerVersion)"
265    >
266    </ClangCompile>
267  </Target>
268
269  <ItemGroup Condition="'$(ConfigurationType)' != 'Utility'">
270    <PropertyPageSchema Condition="'$(ConfigurationType)' != 'Utility'" Include="$(VCTargetsPath)$(LangID)\clang.xml"/>
271  </ItemGroup>
272
273</Project>
(二)、注意事项

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

  • 由于是使用的VS的头文件,所以需要把MS的兼容模式打开,否则会报错,同时建议把MS的扩展支持也打开(上面的clang工具集配置已经默认打开了这两项)。

  • 由于clang默认是不会生成VS调试器可识别的PDB格式,所以要使用VS调试clang生成的程序,需要让Clang生成PDB格式的调试信息,添加:

-g -gcodeview

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

  • 如果预编译头文件带路径,需要把路径写全;Clang不需要使用某个CPP来单独创建,直接在项目属性中设置需要使用的预编译头即可。

  • 报错:C:\Program Files (x86)\Windows Kits\8.1\Include\um\combaseapi.h(229,21): error : unknown type name ‘IUnknown’ 可以直接在模板前面添加一个声明:

 1extern "C++"
 2{
 3	interface IUnknown;  // 这里添加一个声明,以免Clang编译器报错
 4    template<typename T> _Post_equal_to_(pp) _Post_satisfies_(return == pp) void** IID_PPV_ARGS_Helper(T** pp) 
 5    {
 6#pragma prefast(suppress: 6269, "Tool issue with unused static_cast")
 7        static_cast<IUnknown*>(*pp);    // make sure everyone derives from IUnknown
 8        return reinterpret_cast<void**>(pp);
 9    }    
10}
  • 关于Boost库的使用

  • 如果要使用Boost,需要定义宏:

1BOOST_USE_WINDOWS_H
  • 如果在自己的静态库中使用Boost的静态thread库,需要定义宏:
1BOOST_THREAD_USE_LIB

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

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

需要删除,或者定义成

1_WIN32_WINNT=0x0600

否则会出现错误

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

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

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

可以在thread_primitives.hpp代码:

1#if BOOST_PLAT_WINDOWS_RUNTIME
2#include <thread>
3#endif

的前面添加如下代码:

1#if __clang__
2#ifdef BOOST_PLAT_WINDOWS_RUNTIME
3#undef BOOST_PLAT_WINDOWS_RUNTIME
4#define BOOST_PLAT_WINDOWS_RUNTIME 1
5#endif
6#endif

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

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