Vcpkg免配置实现分析

概述

通过Vcpkg安装library,能够不设定include、library的路径,而且可以自动复制依赖库,是利用到了Visual Studio,链接器,还有附带工具达成的。

Vcpkg的目录结构

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)

输出如下:

dumpbin输出动态库依赖
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容