使用NuGet管理C++项目的依赖库

使用NuGet管理C++项目的依赖库一 NuGet 介绍使用 C 进行开发的同学 一定很羡慕 Python 的 pip Java 的 Maven 等包管理器 只需要一个命令就可以将工程需要的依赖库安装到位 由于 C 的大多数库都是系统 编译环境强相关联的 所以在开发中我们会针对不同的操作系统 Win32 Win64 等 编译器 MSVC140 MSVC120 等 编译出对应的静态库或者动态库 然后配置头文件包含目录 库引用目录 预编译宏等等

一、NuGet介绍

如果一个工程引用了10个第三方库,我们需要配置这10个库的头文件包含目录、库引用目录,这无疑是很繁琐的,而且容易遗漏、出错。

NuGet管理native包的原理主要是通过导入包中的targets文件来将预定义的配置添加到工程之中,从而简化工程配置的过程。下面是摘取curl-7.63.0-jefferyjiang包的targets文件,从这个文件中我们可以看到熟悉的Visual Studio预定义的环境变量以及配置。

 
    <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">  
    <ItemGroup> <PropertyPageSchema Include="$(MSBuildThisFileDirectory)default-propertiesui.xml" />  
     ItemGroup>  
     <ItemDefinitionGroup> <ClCompile> <PreprocessorDefinitions>%(PreprocessorDefinitions) 
      PreprocessorDefinitions> <AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)include\;%(AdditionalIncludeDirectories) 
       AdditionalIncludeDirectories>  
        ClCompile> <Link> <AdditionalLibraryDirectories>$(MSBuildThisFileDirectory)lib\;%(AdditionalLibraryDirectories) 
         AdditionalLibraryDirectories> <AdditionalDependencies>Wldap32.lib;Crypt32.lib;%(AdditionalDependencies) 
          AdditionalDependencies>  
           Link>  
            ItemDefinitionGroup>  
            <ItemDefinitionGroup Condition="'$(PlatformToolset)' == 'v140' And '$(Platform)' == 'Win32' And '$(Linkage)' == 'StaticLibrary_MT' And $(Configuration.IndexOf('Debug')) != -1 "> <ClCompile> <PreprocessorDefinitions>CURL_STATICLIB;%(PreprocessorDefinitions) 
             PreprocessorDefinitions>  
              ClCompile> <Link> <AdditionalDependencies>vc140_x86_static_mt_debug\libcurld.lib;%(AdditionalDependencies) 
               AdditionalDependencies>  
                Link>  
                 ItemDefinitionGroup>  
                 <ItemDefinitionGroup Condition="'$(PlatformToolset)' == 'v140' And '$(Platform)' == 'Win32' And '$(Linkage)' == 'StaticLibrary_MT' And $(Configuration.IndexOf('Release')) != -1 "> <ClCompile> <PreprocessorDefinitions>CURL_STATICLIB;%(PreprocessorDefinitions) 
                  PreprocessorDefinitions>  
                   ClCompile> <Link> <AdditionalDependencies>vc140_x86_static_mt_release\libcurl.lib;%(AdditionalDependencies) 
                    AdditionalDependencies>  
                     Link>  
                      ItemDefinitionGroup>  
                      <ItemDefinitionGroup Condition="'$(PlatformToolset)' == 'v140' And '$(Platform)' == 'Win32' And '$(Linkage)' == 'DynamicLibrary_MD' And $(Configuration.IndexOf('Debug')) != -1 "> <ClCompile> <PreprocessorDefinitions>%(PreprocessorDefinitions) 
                       PreprocessorDefinitions>  
                        ClCompile> <Link> <AdditionalDependencies>vc140_x86_dynamic_md_debug\libcurld.lib;%(AdditionalDependencies) 
                         AdditionalDependencies>  
                          Link>  
                           ItemDefinitionGroup>  
                           <ItemDefinitionGroup Condition="'$(PlatformToolset)' == 'v140' And '$(Platform)' == 'Win32' And '$(Linkage)' == 'DynamicLibrary_MD' And $(Configuration.IndexOf('Release')) != -1 "> <ClCompile> <PreprocessorDefinitions>%(PreprocessorDefinitions) 
                            PreprocessorDefinitions>  
                             ClCompile> <Link> <AdditionalDependencies>vc140_x86_dynamic_md_release\libcurl.lib;%(AdditionalDependencies) 
                              AdditionalDependencies>  
                               Link>  
                                ItemDefinitionGroup> <Target Name="curl_7_63_0_AfterBuild" AfterTargets="AfterBuild" /> <Target Name="curl_7_63_0_afterbuild_cmd1" Condition="'$(PlatformToolset)' == 'v140' And '$(Platform)' == 'Win32' And '$(Linkage)' == 'DynamicLibrary_MD' And $(Configuration.IndexOf('Debug')) != -1" AfterTargets="curl_7_63_0_AfterBuild"> <Copy SourceFiles="$(MSBuildThisFileDirectory)bin\vc140_x86_dynamic_md_debug\libcurld.dll" DestinationFiles="$(TargetDir)libcurld.dll" SkipUnchangedFiles="true" />  
                                 Target> <Target Name="curl_7_63_0_afterbuild_cmd2" Condition="'$(PlatformToolset)' == 'v140' And '$(Platform)' == 'Win32' And '$(Linkage)' == 'DynamicLibrary_MD' And $(Configuration.IndexOf('Release')) != -1" AfterTargets="curl_7_63_0_AfterBuild"> <Copy SourceFiles="$(MSBuildThisFileDirectory)bin\vc140_x86_dynamic_md_release\libcurl.dll" DestinationFiles="$(TargetDir)libcurl.dll" SkipUnchangedFiles="true" />  
                                  Target>  
                                   Project> 

二、NuGet安装依赖包

Visual Studio中已经集成了NuGet工具,可以在菜单“工具” --> “NuGet包管理器”中看到。经过实际使用发现,低版本的Visual Studio集成的NuGet存在部分Bug,可能会导致安装包时报错,建议使用Visual Studio 2017(当然,“平台工具集”仍然可以选择其他的版本,如Visual Studio 2015 (v140)等)。

具体使用方法如图,输入包名查找 –> 选中项目 -> 点击“安装”。如果包依赖其他包,NuGet会将依赖包一并安装。

在这里插入图片描述

三、制作NuGet包

可以先阅读官方文档:https://docs.microsoft.com/en-us/nuget/create-packages/native-packages来了解大概的结构,但由于官方文档讲解了不全面,建议下载ppx-1.0.0.1-jefferyjiang.1.0.0.5.nupkg,以其为模板来修改,将会事半功倍。

模板文件ppx_1.0.0.1下载下来之后重命名为.zip,然后解压,(ppx_1.0.0.1表示ppx库的1.0.0.1版本,命名无要求)。

首先,修改ppx_1.0.0.1.nuspec文件:

 
    <package xmlns="http://schemas.microsoft.com/packaging/2013/01/nuspec.xsd"> <metadata> <id>ppx-1.0.0.1-jefferyjiang 
     id> <version>1.0.0.1 
      version> <title>ppx-1.0.0.1 
       title> <authors>jefferyjiang 
        authors> <owners>jefferyjiang 
         owners> <requireLicenseAcceptance>false 
          requireLicenseAcceptance> <description>Build parameter: vc140 - Win32 - StaticLibrary|DynamicLibrary - MT|MD - Debug|Release 
           description> <summary> 
            summary> <copyright>Copyright (c) 2017, Jeffery Jiang 
             copyright> <iconUrl>https://raw.githubusercontent.com/chinajeffery/NugetLibrary/master/tomato.png 
              iconUrl> <tags>native, ppx, C++ 
               tags> <dependencies> <group targetFramework="native0.0"> <dependency id="curl-7.63.0-jefferyjiang" version="1.0.0.10" />  
                group>  
                 dependencies>  
                  metadata>  
                   package> 

id为该包的唯一id,不能在NuGet仓库上传已经存在的id的包,为了避免重复,我一般会在后面加上特殊标识,类似jefferyjiangversion为该包的版本号,这个版本号和ppx库的版本号不同,通过包的id + version就可以在Nuget仓库精确定位该包。

然后,将头文件添加到include目录,静态库添加到lib目录,动态库添加到bin,当然,这个目录名称和文件类型的对应关系并没有强制要求,只要ppx-1.0.0.1-jefferyjiang.targets属性文件中的配置来正确即可。

default-propertiesui.xml文件中定义了一些用户可以进行配置的选项,比如使用该库的静态版还是动态版,MT版还是MD版等:

 
    <ProjectSchemaDefinitions xmlns="clr-namespace:Microsoft.Build.Framework.XamlTypes;assembly=Microsoft.Build.Framework"> <Rule Name="ProjectSettings_ppx_1_0_0_1" PageTemplate="tool" DisplayName="Nuget Library Settings" SwitchPrefix="/"> <Rule.Categories> <Category Name="ppx_1_0_0_1_cpp" DisplayName="ppx-1.0.0.1 Settings" />  
     Rule.Categories> <Rule.DataSource> <DataSource Persistence="ProjectFile" ItemType="" />  
      Rule.DataSource> <EnumProperty Name="Linkage" DisplayName="Linkage" Description="How to link this library, static or dynamic, mt or md." Category="ppx_1_0_0_1_cpp" > <EnumValue Name="StaticLibrary_MT" DisplayName="Static Library With MT" Description="Static Library">  
       EnumValue> <EnumValue Name="DynamicLibrary_MD" DisplayName="Dynamic Library With MD" Description="Dynamic Library">  
        EnumValue>  
         EnumProperty>  
          Rule>  
           ProjectSchemaDefinitions> 

最后就是ppx-1.0.0.1-jefferyjiang.targets文件了,该文件名必须和包的id一样。该文件的配置语法并不难理解,唯一需要注意的是,在这个文件中可以使用default-propertiesui.xml文件中定义的变量,如:

'$(Linkage)' == 'DynamicLibrary_MD' 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/208748.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 上午10:51
下一篇 2026年3月19日 上午10:52


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号