将 OpenSSL 静态库添加到 Visual Studio 2017 项目

Add OpenSSL static lib to Visual Studio 2017 project

NuGets 添加到项目时是否修改包含和链接路径?

我的背景是使用 CMake,但我现在在一家从头开始构建解决方案文件的公司工作,我不确定如何将静态 OpenSSL 库正确添加到我的项目中。我发布问题是为了确保我不会重复某些内容或以其他方式弄乱它。

当我将 openssl-vc141-static-x86_64 添加到我的项目时,它会构建 .lib 文件和所有内容,但不会修改包含或链接器路径。

我可以手动添加链接器路径,但是因为给我的项目没有典型的 Release/Debug 配置,所以我无法使用 $(Configuration)指向目标库的宏 - 所以我结束时只指向 Release。虽然构建有效。

我看到有一个 .targets 文件,但它似乎没有任何作用。

(更新)

具体来说,我基本上是在构建 boost 的 http_server_async.cpp。我得到的链接器错误是:

Error   LNK2019 unresolved external symbol _BIO_free referenced in function "public: __thiscall boost::asio::ssl::context::bio_cleanup::~bio_cleanup(void)" (??1bio_cleanup@context@ssl@asio@boost@@QAE@XZ) ESOIPDataScope  C:\gitrepo\ALIDB\ESOIPDataScope\DataHandler.obj 
Error   LNK2001 unresolved external symbol _BIO_free    ESOIPDataScope  C:\gitrepo\ALIDB\ESOIPDataScope\Listener.obj
... (48 more like this)

当我手动添加 $(SolutionDir)packages\openssl-vc141-static-x86_64.1.1.0\build\native\lib\Win32\static\Release\libcrypto.lib $(SolutionDir)packages\openssl-vc141-static-x86_64.1.1.0\build\native\lib\Win32\static\Release\libssl.lib 作为项目编译的附加依赖项时。

(/更新)

为了对比,我添加了一个 freeglut NuGet,并注意到它给了我更多的配置选项(配置属性 → 引用项目),而且,boost 似乎已经将它的链接器目录添加到我的项目中(虽然我只看到在 MSBuild 输出中,而不是在配置属性->链接器->命令行中)

有没有合适的方法来添加我缺少的这些项目?或者使用 targets 文件的正确方法?或者也许 OpenSSL 静态 NuGet 只是遗漏了什么?或者我应该看看 vcpkg?

Do NuGets modify the include and linking paths when added to a project?

当然。我可以明确地告诉你,nuget 通过 <package_id>.targets<package_id>.props 文件将额外的属性导入到项目中,而不是再次手动添加包含路径。

这是nuget打包的一种机制,在安装nuget包的过程中直接给项目添加库路径等额外的项目属性。更多信息可以参考this link.

<package_id>.targets是在打包nuget包的过程中创建的。 也就是说,这个方法是nuget包的作者设计的。在我这边,文件 openssl-vc141-static-x86_64.targets 存在于这个路径中:

C:\Users\Admin\source\repos\ConsoleApplication25\packages\openssl-vc141-static-x86_64.1.1.0\build\native

also, boost seems to have added its linker directories to my project (though I only see that in MSBuild output, not in Configuration Properties->Linker->Command Line)

我认为这个问题与 <package_id>.targets<package_id>.props 之间的差异有关。虽然using <package_id>.targets没有出现在属性 UI上,但它仍然适用于整个项目。

更详细

当您将 nuget 包安装到项目中时,这些文件会自动执行。 <target_id>.props 文件被添加到文件的顶部,而 .targets 被添加到底部。

初始化xxx.vcxproj文件时,由于<package_id> .props在文件头部,属性UI可以捕获文件中的属性,<package_id> .targets在最后,所以无法捕获初始化但仍在项目中。对于 nuget,它使用 openssl-vc141-static-x86_64.targets.

openssl-vc141-static-x86_64.targets文件中,你可以看到这个:

<ClCompile>
        <AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)include\;% 
           (AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
        <PreprocessorDefinitions>HAS_LIBTHRIFT;%(PreprocessorDefinitions) 
        </PreprocessorDefinitions>
</ClCompile>

并且我已将输出日志设置为 Diagnostic 并构建项目并发现:

库路径已由openssl-vc141-static-x86_64.targets文件自动添加到AdditionalIncludeDirectories中。所以你不用担心。

Is there a proper way to add these projects that I'm missing? Or a proper way to use the targets file? Or maybe the OpenSSL static NuGet just missing something? Or maybe I should just look into vcpkg?

您不必担心,不要将包含路径添加到项目中 属性。这是多余的,当你完成安装这个 nuget 包后,直接在 cpp 文件中使用它。

此外,

对于nuget安装的c++包,不需要在工程中添加任何路径属性。

更新 1

问题与您的项目有关,与 nuget 包无关。正是因为你当前的项目没有$(Configuration),所以在openssl-vc141-static-x86_64.targets中,你可以看到这些:

 <ItemDefinitionGroup Label="Win32 and vc141 and Debug" Condition="'$(Platform)' == 'Win32' And ( $(PlatformToolset.IndexOf('v141')) &gt; -1 Or '$(PlatformToolset)' == 'WindowsKernelModeDriver8.0' Or '$(PlatformToolset)' == 'WindowsApplicationForDrivers8.0' Or '$(PlatformToolset)' == 'WindowsUserModeDriver8.0' ) And '$(Configuration)' == 'Debug'">
          <Link>
              <AdditionalLibraryDirectories>$(MSBuildThisFileDirectory)lib\Win32\static\Debug\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
        <AdditionalDependencies>libssl.lib;libcrypto.lib;%(AdditionalDependencies)</AdditionalDependencies>
          </Link>
      <PostBuildEvent>
        <Command>xcopy /Y "$(MSBuildThisFileDirectory)\lib\Win32\dynamic\*-1_1.dll" "$(OutDir)"</Command>
      </PostBuildEvent>
    </ItemDefinitionGroup>

这是将特定的libssl.liblibcrypto.Lib导入AdditionalDependencies节点的操作。但是你可以发现有一个判断条件And '$(Configuration)' == 'Debug',因为你没有$(Configuration),所以,它总是returns false和这些无法将库自动导入 AdditionalDependencies

作为解决方法,您应该按照您所说的手动添加这些库路径。

并且我确信如果您使用包含 $(Configuration)(调试或发布)的项目,您将不会遇到此问题。大多数C++ nuget包可以直接在包含Configuration节点的项目中使用。

我确信如果你在你的项目中使用 $(Configuration) 然后重新安装这个包(请 clean the nuget cache 然后再安装),你将不会遇到这个错误。

Also, your screen shot, where did you get that? I don't see anything like that in the VS output console, or when I run msbuild on the command line. Is there some way I might have accidentally broken the default behaviour?

可以通过Tools-->Options-->Projects and Solutions-->Build and RunMSBuild project build output verbosity设置为Diagnostic

构建项目时,输出Window显示整个构建过程并记录所有信息,然后您可以通过[=搜索关键字段97=]搜索框 输出 Window.