概述
通过Vcpkg安装library,能够不设定include、library的路径,而且可以自动复制依赖库,是利用到了Visual Studio,链接器,还有附带工具达成的。
Vcpkg的目录结构
- ports 可用包配置信息
- downloads 库源代码包下载存放路径
- buildtrees 库构造路径
- packages 库编译结果
- installed 库安装目录
其中installed存放了已安装信息,并且按照规则集中存放库内容
- x86-windows 32位windows库
- x64-windows
- x86-windows-static 32位windows静态库
- x64-windows-static
- x86-uwp 32位uwp库
- x64-uwp
- arm-uwp
目录结构如下:
bin
debug
bin
lib
include
lib
share
也就是说,通过这种方式安装的库,是有统一的存放规则的,通过这些规则可以合并出对应的include、library、binary文件路径。
targets文件
Visual Studio的构建系统使用的是MSBuild,配置及构建目标定义都可以存放在.props和.targets文件中,由于安装的库遵循统一规则,因而在vcpkg\scripts\buildsystems\msbuild
下可以找到完成上述统一配置的targets文件vcpkg.targets
.
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Platform)|$(ApplicationType)|$(ApplicationTypeRevision)' == 'Win32||'">
<VcpkgEnabled Condition="'$(VcpkgEnabled)' == ''">true</VcpkgEnabled>
<VcpkgTriplet Condition="'$(VcpkgTriplet)' == ''">x86-windows</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)|$(ApplicationType)|$(ApplicationTypeRevision)' == 'Win32|Windows Store|10.0'">
<VcpkgEnabled Condition="'$(VcpkgEnabled)' == ''">true</VcpkgEnabled>
<VcpkgTriplet Condition="'$(VcpkgTriplet)' == ''">x86-uwp</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)|$(ApplicationType)|$(ApplicationTypeRevision)' == 'x64||'">
<VcpkgEnabled Condition="'$(VcpkgEnabled)' == ''">true</VcpkgEnabled>
<VcpkgTriplet Condition="'$(VcpkgTriplet)' == ''">x64-windows</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)|$(ApplicationType)|$(ApplicationTypeRevision)' == 'x64|Windows Store|10.0'">
<VcpkgEnabled Condition="'$(VcpkgEnabled)' == ''">true</VcpkgEnabled>
<VcpkgTriplet Condition="'$(VcpkgTriplet)' == ''">x64-uwp</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)|$(ApplicationType)|$(ApplicationTypeRevision)' == 'arm|Windows Store|10.0'">
<VcpkgEnabled Condition="'$(VcpkgEnabled)' == ''">true</VcpkgEnabled>
<VcpkgTriplet Condition="'$(VcpkgTriplet)' == ''">arm-uwp</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Condition="'$(VcpkgEnabled)' == 'true'">
<VcpkgConfiguration Condition="'$(VcpkgConfiguration)' == ''">$(Configuration)</VcpkgConfiguration>
<VcpkgRoot Condition="'$(VcpkgRoot)' == ''">$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), .vcpkg-root))\installed\$(VcpkgTriplet)\</VcpkgRoot>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(VcpkgEnabled)' == 'true'">
<Link>
<AdditionalDependencies Condition="'$(VcpkgConfiguration)' == 'Debug' and '$(VcpkgAutoLink)' != 'false'">%(AdditionalDependencies);$(VcpkgRoot)debug\lib\*.lib</AdditionalDependencies>
<AdditionalDependencies Condition="'$(VcpkgConfiguration)' == 'Release' and '$(VcpkgAutoLink)' != 'false'">%(AdditionalDependencies);$(VcpkgRoot)lib\*.lib</AdditionalDependencies>
<AdditionalLibraryDirectories Condition="'$(VcpkgConfiguration)' == 'Release'">%(AdditionalLibraryDirectories);$(VcpkgRoot)lib;$(VcpkgRoot)lib\manual-link</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories Condition="'$(VcpkgConfiguration)' == 'Debug'">%(AdditionalLibraryDirectories);$(VcpkgRoot)debug\lib;$(VcpkgRoot)debug\lib\manual-link</AdditionalLibraryDirectories>
</Link>
<ClCompile>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(VcpkgRoot)include</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<Target Name="AppLocalFromInstalled" AfterTargets="CopyFilesToOutputDirectory" BeforeTargets="CopyLocalFilesOutputGroup" Condition="'$(VcpkgEnabled)' == 'true' and '$(OutputType)' == 'exe'">
<WriteLinesToFile
File="$(TLogLocation)$(ProjectName).write.1u.tlog"
Lines="^$(OutputPath)$(TargetName).$(OutputType);" Encoding="Unicode"/>
<Exec Condition="'$(VcpkgConfiguration)' == 'Debug'"
Command="powershell.exe -ExecutionPolicy Unrestricted -noprofile -File %22$(MSBuildThisFileDirectory)applocal.ps1%22 %22$(OutputPath)$(TargetName).$(OutputType)%22 %22$(VcpkgRoot)debug\bin%22 %22$(TLogLocation)$(ProjectName).write.1u.tlog%22"
ConsoleToMSBuild="true">
<Output TaskParameter="ConsoleOutput" ItemName="ReferenceCopyLocalPaths" />
</Exec>
<Exec Condition="'$(VcpkgConfiguration)' == 'Release'"
Command="powershell.exe -ExecutionPolicy Unrestricted -noprofile -File %22$(MSBuildThisFileDirectory)applocal.ps1%22 %22$(OutputPath)$(TargetName).$(OutputType)%22 %22$(VcpkgRoot)bin%22 %22$(TLogLocation)$(ProjectName).write.1u.tlog%22"
ConsoleToMSBuild="true">
<Output TaskParameter="ConsoleOutput" ItemName="ReferenceCopyLocalPaths" />
</Exec>
</Target>
</Project>
可以看到,根据不同的配置信息,配置完成了include、library以及binary路径及对应的处理。
与Visual Studio 2015的整合
现在我们知道在Visual Studio 2015中免配置,是通过导入统一的targets来实现的,整合方式是什么样的?
在Visual Studio 2015中支持导入默认的配置,具体路径为:
$(MSBUILDLOCATION)/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/
其中$(MSBUILDLOCATION)
通常为C:/Program Files (x86)/MSBuild/
.
Vcpkg在执行整合时,会在该路径下创建vcpkg.system.targets
文件,内容如下:
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- version 1 -->
<PropertyGroup>
<VCLibPackagePath Condition="'$(VCLibPackagePath)' == ''">$(LOCALAPPDATA)\vcpkg\vcpkg.user</VCLibPackagePath>
</PropertyGroup>
<Import Condition="'$(VCLibPackagePath)' != '' and Exists('$(VCLibPackagePath).targets')" Project="$(VCLibPackagePath).targets" />
</Project>
在$(LOCALAPPDATA)\vcpkg\
下会创建vcpkg.user.targets
来导入vcpkg路径下的.targets文件,譬如:
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Condition="Exists('D:\vcpkg\scripts\buildsystems\msbuild\vcpkg.targets') and '$(VCPkgLocalAppDataDisabled)' == ''" Project="D:\vcpkg\scripts\buildsystems\msbuild\vcpkg.targets" />
</Project>
这种方式无论是通过Visual Studio 2015还是MSBuild构造工程都可以正确识别,但是Visual Studio 2010无法采用这种方式导入全局配置。
library免配置
常规的library配置会指定依赖的library名称,但是link实际上识别如下方式的lib依赖配置:
$(LibraryPath)/*.lib
采用这种方式,可以避免单独配置对应的库依赖,但是不适用于同一路径下存放了库的debug和release版本。
自动复制依赖的动态库
link.exe /dump /imports $(target)
以上的命令会输出目标导入的dll和所有符号,譬如:
根据该命令能够得到所有依赖的动态库,然后根据binary路径进行复制。
vcpkg采用的方法:
dumpbin.exe /DEPENDENTS $(target)
输出如下: