如果要做一个应用程序,我们往往会用到很多第三方库,这时库包管理工具就很重要,如js/npm,c#/nuget,php/composer,jave/maven之类,但vc++一直没一个很舒服的包管理工具。很多c++第三方库对vc++都非常不友好,谁能轻而易举地在vc++上编译一个openssl呢?
nuget出现试图解决这个问题,但出现更大的问题就是直接下载二进制文件,太大,下载了一个vs2012的又不支持vs2013,版本之间很难共用,想去调一下配置又不可能(因为下载的是二进制文件)。我还记得曾经为编译一个boost看配置、折腾半天。举个例子,我为mysql做了一个vcpkg包,更是折腾。而这时vcpkg就诞生了,解决了上述所有的问题,比如装一个mysql客户端,你只需要:
vcpkg install libmysql
通常使用c++库需要在项目配置里设置头文件包含路径和lib的链接路径。所以不同于c#库直接将文件放在指定位置就可以使用。
nuget指定了一系列的特殊目录,用来管理包的内容,但是并不能管理c++库,nuget自从2.5后开始支持管理c++库。为此特意规定了一个build目录,build目录中可以通过使用msbuild脚本来达到自动配置路径的效果,从而可以使用c++库。
目录结构
nuget包下的build目录中按照平台来划分子目录,但是c++库统一设为native平台,所以只有一个native目录。native下面有一系列的目录,存放着库的文件,例如头文件、lib文件、dll之类的。并且根据配置不同,会分别存放多个版本(Debug、Release、x86,x64之类)的文件。
通常目录结构是这样的
xxx.1.0.nupkg
└─xx.1.0.nuspec
└─build
└─native
├─bin
│ └─Win32
│ └─v120
│ └─dynamic
│ ├─Debug
│ │ └─xx_d.dll
│ └─Release
│ └─xx_d.dll
├─include
│ └─xx.h
└─lib
│ └─Win32
│ └─v120
│ └─dynamic
│ ├─Debug
│ │ └─xx_d.lib
│ └─Release
│ └─xx_d.lib
└─xx.targets
脚本
nuget管理器使用包的时候会寻找native下面和包名一样的.targets文件。并把他包含到项目的工程文件(.vcxproj)中。
.targets文件是一个msbuild脚本,通常里面会自动设置头文件包含路径和链接路径、并且设置对应版本的链接库,最后将对应版本的dll自动复制到生成目录里面。
打包
然后填写好.nuspec文件中的描述信息后就可以使用nuget命令打包,然后发布后就像正常的nuget包一样使用。使用nuget包来引用c++库后不需要再做任何额外的设置,只需要安装nuget包就可。
coApp
虽然看起来制作一个c++库的nuget包很简单,但是编写一个合格的targets文件仍然是一件极其复杂的事。所以通常我们使用一个开源的powershell工具coApp(http://coapp.org/)来帮助我们自动完成这一切。