一、集成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下。
(二)、修改安装前配置(如果已经安装过了,修改后再安装一次即可)
- 修改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>
(二)、注意事项
通过上面的修改后,基本上可以正常使用了,但是可能会有如下问题
- 由于是使用的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’
可以直接在模板前面添加一个声明:
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);
}
}
- 关于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
通过这些修改就大功告成了,当然如果使用其它第三方库,可能会遇到一些问题,就需要自行探索解决了。
祝玩得开心,如果喜欢本文请记得点赞哦!