简体   繁体   English

Visual Studio 2015 运行时依赖项或如何摆脱 Universal CRT?

[英]Visual studio 2015 run-time dependencies or how to get rid of Universal CRT?

Compiled couple of .dll's using visual studio 2015, and tried to deploy on some older windows 7 / 64 bit.使用 Visual Studio 2015 编译了几个 .dll,并尝试在一些较旧的 Windows 7 / 64 位上进行部署。 Tried also to guess which dll's are needed for application to start and copied MSVCP140.DLL & VCRUNTIME140.DLL - but application could not load vs2015 dll.还尝试猜测应用程序启动和复制 MSVCP140.DLL 和 VCRUNTIME140.DLL 需要哪些 dll - 但应用程序无法加载 vs2015 dll。 Started to analyze what is wrong - and dependency walker showed dependencies from following dll's:开始分析出了什么问题 - 依赖walker显示了来自以下dll的依赖:

API-MS-WIN-CRT-MATH-L1-1-0.DLL
API-MS-WIN-CRT-HEAP-L1-1-0.DLL
API-MS-WIN-CRT-CONVERT-L1-1-0.DLL
API-MS-WIN-CRT-STRING-L1-1-0.DLL
API-MS-WIN-CRT-STDIO-L1-1-0.DLL
API-MS-WIN-CRT-RUNTIME-L1-1-0.DLL
API-MS-WIN-CRT-FILESYSTEM-L1-1-0.DLL
API-MS-WIN-CRT-TIME-L1-1-0.DLL

This was especially surprising since to my best understanding CRT is responsible for starting dll/exe, it does not provide any higher level services.这尤其令人惊讶,因为据我所知,CRT 负责启动 dll/exe,它不提供任何更高级别的服务。

Ok, tried to figure out how to get rid of them or at least to minimize.好的,试图弄清楚如何摆脱它们或至少最小化它们。

Found one article: https://blogs.msdn.microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/找到一篇文章: https : //blogs.msdn.microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/

It mentions about release static libraries - so I thought that I could link against them and get rid from *L1-1-0.DLL* dependency hell, but no matter what I have tried - I had no success.它提到了发布静态库 - 所以我认为我可以链接它们并摆脱 *L1-1-0.DLL* 依赖地狱,但无论我尝试过什么 - 我都没有成功。 I've tried to link against libvcruntime.lib, libucrt.lib, libcmt.lib, tried to disable using linker option "/nodefaultlib:vcruntime.lib", and even tried to add include directory $(UniversalCRT_IncludePath), and also overriding some of define's as I have tried to guess they works - none of my attempts helped.我尝试链接 libvcruntime.lib、libucrt.lib、libcmt.lib,尝试禁用使用链接器选项“/nodefaultlib:vcruntime.lib”,甚至尝试添加包含目录 $(UniversalCRT_IncludePath),并覆盖一些定义的,因为我试图猜测它们有效 - 我的尝试都没有帮助。

As an intermediate solution I've fall back to using Visual studio 2013, where CRT dll's are only two: msvcp120.dll, msvcr120.dll.作为中间解决方案,我已经回退到使用 Visual Studio 2013,其中 CRT dll 只有两个:msvcp120.dll、msvcr120.dll。

Of course you will probably recommend to install Visual studio 2015 run-times, but one of our requirement is to support standalone executable - which works without any installation - so additional installation is out of question for now.当然,您可能会建议安装 Visual Studio 2015 运行时,但我们的要求之一是支持独立的可执行文件 - 无需任何安装即可运行 - 所以现在额外安装是不可能的。

Can you recommend me anything else than to wait Visual studio 2017 to arrive ?除了等待 Visual Studio 2017 到来之外,您还能向我推荐什么吗?

I was able to solve this by setting the C/C++ > Code Generation > Runtime Library compiler option我能够通过设置C/C++ > Code Generation > Runtime Library编译器选项来解决这个问题

  • For Debug: from /MDd to /MTd对于调试:从/MDd/MTd
  • For Release: from /MD to /MT发布:从/MD/MT

This removed all the API-MS-WIN-CRT-* and runtime dll references and caused all the CRT code to be statically linked.这删除了所有API-MS-WIN-CRT-*和运行时 dll 引用,并导致所有 CRT 代码被静态链接。

Details on the new VS2015 Universal CRT (dynamic and static) are here: https://msdn.microsoft.com/en-us/library/abx4dbyh.aspx有关新 VS2015 通用 CRT(动态和静态)的详细信息,请访问: https ://msdn.microsoft.com/en-us/library/abx4dbyh.aspx

I too was fighting with statically linking a solution with multiple components/project library dependencies importing functions from various parts of the MSVCRT, UCRT and Kernel.我也在努力将一个解决方案与多个组件/项目库依赖项静态链接,从 MSVCRT、UCRT 和内核的各个部分导入函数。 The hope was the resulting EXE could be just copied around where it was needed (it was no product which would justify a full MSI installation).希望生成的 EXE 可以在需要的地方复制(它不是一个可以证明完整 MSI 安装合理的产品)。

After almost giving-up I found the best solution was the follow the guidelines hidden in the Universal C Runtime announcement , specifically:在几乎放弃之后,我发现最好的解决方案是遵循隐藏在Universal C Runtime 公告中的指导方针,特别是:

We strongly recommend against static linking of the Visual C++ libraries, for both performance and serviceability reasons出于性能和可维护性的原因,我们强烈建议不要静态链接Visual C++ 库

Just remove all the "special" linker options you tried, drop-back to /MT|/MD (Multi-Threaded CRT DLL Release|Debug) runtime library choice and it works everywhere, eg newer Windows 10 workstations, 2012 R2 servers and Windows 7).只需删除您尝试过的所有“特殊”链接器选项,退回到 /MT|/MD(多线程 CRT DLL 发布|调试)运行时库选项,它就可以在任何地方使用,例如较新的 Windows 10 工作站、2012 R2 服务器和 Windows 7)。 Just install/redistribute MSVCRT (VC_Redist*.exe) and KB2999226 (UCRT via Windows Update) as Microsoft tell us to do, because as they also say:只需按照 Microsoft 的指示安装/重新分发MSVCRT (VC_Redist*.exe)KB2999226(通过 Windows 更新的 UCRT) ,因为正如他们所说:

The Universal CRT is a component of the Windows operating system .通用 CRT 是 Windows 操作系统的一个组件 It is included as a part of Windows 10, starting with the January Technical Preview, and it is available for older versions of the operating system via Windows Update.从 1 月技术预览版开始,它作为 Windows 10 的一部分包含在内,并且可通过 Windows 更新用于旧版本的操作系统。

So logically the only additional deployment dependency our C++ solutions add for the customer is the MSVCRT, because the UCRT should already be there on up-to-date/well maintained machines.因此,从逻辑上讲,我们的 C++ 解决方案为客户添加的唯一额外部署依赖项是 MSVCRT,因为 UCRT 应该已经存在于最新/维护良好的机器上。 Of course it adds a bit of uncertainty;当然,它增加了一些不确定性; you can't just copy the EXE and run on any machine, good or bad.您不能只是复制 EXE 并在任何机器上运行,无论好坏。

If you produce a decent deployment package like an MSI then it's straightforward to include when you have tools like WIX.如果您生成了像 MSI 这样像样的部署包,那么当您拥有 WIX 等工具时就可以直接包含在内。 Also to note is since the recent SDK you can include the 40-odd DLLs locally, but that doesn't satisfy the security update principle so I wouldn't do that.还要注意的是,由于最近的 SDK 可以在本地包含 40 多个 DLL,但这不满足安全更新原则,因此我不会这样做。

This is really the only supported way to do it, see another example here .这确实是唯一受支持的方法, 请参阅此处的另一个示例 This article also suggests we link against "mincore_downlevel.lib" which is an important tip, crucial to whether you get these "api-ms-win*" missing DLL errors.本文还建议我们链接“mincore_downlevel.lib”,这是一个重要提示,对于您是否获得这些“api-ms-win*”缺失 DLL 错误至关重要。 For example:例如:

  1. Project SDK version set to 10, link with mincore.lib = Runs only on Windows 10, but not 8.1/2012 R2 or Windows 7/2008 R2 server.项目 SDK 版本设置为 10,链接 mincore.lib = 仅在 Windows 10 上运行,但不能在 8.1/2012 R2 或 Windows 7/2008 R2 服务器上运行。
  2. Project SDK version set to 8.1, link with mincore.lib = Runs on both Windows 10 and 8.1/2012 R2 server, but not Windows 7/2008 R2 server.项目 SDK 版本设置为 8.1,链接 mincore.lib = 在 Windows 10 和 8.1/2012 R2 服务器上运行,但不能在 Windows 7/2008 R2 服务器上运行。
  3. Project SDK version set to 10, link with mincore_downlevel.lib = Runs on all!项目 SDK 版本设置为 10,链接 mincore_downlevel.lib = Runs on all!

In summary:总之:

  1. Do not link statically, leave the default DLL C runtimes selected in the project settings.不要静态链接,保留在项目设置中选择的默认 DLL C 运行时。
  2. You don't need the old SDKs, can develop with the latest Windows 10 SDK, but you must link with "mincore_downlevel.lib" not "mincore.lib" if you want to support older Windows versions.您不需要旧的 SDK,可以使用最新的 Windows 10 SDK 进行开发,但如果您想支持旧的 Windows 版本,则必须链接“mincore_downlevel.lib”而不是“mincore.lib”。
  3. For ease of use, add this to your targetver.h or stdafx.h which also documents your choice (remove the other line):为了便于使用,请将其添加到您的 targetver.h 或 stdafx.h 中,其中还记录了您的选择(删除另一行):
// Libraries
#pragma comment(lib, "mincore.lib")             // Lowest OS support is same as SDK
#pragma comment(lib, "mincore_downlevel.lib")   // Support OS older than SDK

(Updated 11.10.2016). (2016 年 10 月 11 日更新)。

It's possible to get rid of universal CRT by linking it statically, I'll get to it later on, but let's take a look if you continue to use universal CRT as such.可以通过静态链接来摆脱通用 CRT,我稍后会谈到它,但让我们看看您是否继续使用通用 CRT。

According to article https://blogs.msdn.microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/ - it's possible to launch your application using universal crt dll distributables from following folder: C:\\Program Files (x86)\\Windows Kits\\10\\Redist\\ucrt\u003c/code>根据文章https://blogs.msdn.microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/ - 可以使用以下文件夹中的通用 crt dll 可分发文件启动您的应用程序: C:\\Program Files (x86)\\Windows Kits\\10\\Redist\\ucrt\u003c/code>

There are 41 files totally in list with 1.8 Mb size in total.列表中共有 41 个文件,总共 1.8 Mb 大小。 (example for 64-bit platform) (以 64 位平台为例)

Of course it's not enough, you will need additionally vcruntime140.dll & msvcp140.dll coming from following folder: C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\redist\\x64\\Microsoft.VC140.CRT当然这还不够,您还需要来自以下文件夹的 vcruntime140.dll 和 msvcp140.dll: C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\redist\\x64\\Microsoft.VC140.CRT

So after that you will ship totally 43 additional dll's besides your application.因此,在那之后,除了您的应用程序之外,您还将总共发送 43 个额外的 dll。

It's also possible to statically compile ucrt library inside your application after which you will not need 43 dll's - but whether static link will for after linking or not - depends on your application - how many dll's and which api's are in use.也可以在您的应用程序中静态编译 ucrt 库,之后您将不需要 43 个 dll - 但是静态链接是否会在链接后进行 - 取决于您的应用程序 - 使用了多少个 dll 和哪些 api。 Generally after ucrt gets linked into two different dll's they don't necessarily share same globals with each other - which can results in errors.通常在 ucrt 链接到两个不同的 dll 之后,它们不一定彼此共享相同的全局变量 - 这可能会导致错误。

You need to link against vcruntime.lib / msvcrt.lib, but it's not sufficient - there are extra _VCRTIMP= and _ACRTIMP= defines which needs to be disabled from pulling functions from ucrt.您需要链接 vcruntime.lib / msvcrt.lib,但这还不够 - 有额外的_VCRTIMP=_ACRTIMP=定义需要禁止从 ucrt 中提取函数。

If you're using premake5 you can configure your project like this:如果您使用的是 premake5,您可以像这样配置您的项目:

defines { "_VCRTIMP="}
linkoptions { "/nodefaultlib:vcruntime.lib" }
links { "libvcruntime.lib" }

followed by:其次是:

defines { "_ACRTIMP="}
linkoptions { "/nodefaultlib:msvcrt.lib" }
links { "libcmt.lib" }

Defines are not documented by Microsoft - so it's possible that it's subject to change in future. Microsoft 未记录定义 - 因此将来可能会发生变化。

Besides your own projects, you will need to re-compile all static libraries which are in use in your projects.除了您自己的项目,您还需要重新编译您项目中使用的所有静态库。

As for boost libraries - I've managed to compile boost as well, using b2.exe boostrapper至于boost库——我也设法编译boost,使用b2.exe boostrapper

boost>call b2 threading=multi toolset=msvc-14.0 address-model=64 --stagedir=release_64bit --build-dir=intermediate_64but release link=static,shared --with-atomic --with-thread --with-date_time --with-filesystem define=_VCRTIMP= define=_ACRTIMP=

When troubleshooting linking problems - notice that unresolved __imp* function names from because of dllimport keyword usage - and if you link against libvcruntime.lib, you should not have any __imp* references.在对链接问题进行故障排除时 - 请注意由于dllimport关键字的使用而导致未解析的__imp*函数名称 - 如果您针对 libvcruntime.lib 进行链接,则不应有任何__imp*引用。

I was too struggled a lot finding out the run time DLLs required to run an application which was built in Visual Studio 2015.我在寻找运行在 Visual Studio 2015 中构建的应用程序所需的运行时 DLL 时费了很大劲。

Here I found the following things which allow VS-2015 built application to run.在这里,我发现了以下允许 VS-2015 构建的应用程序运行的东西。

Note : Place the dlls versions according to your system processor's architecture(x86, x64..).注意:根据系统处理器的架构(x86、x64 ..)放置 dll 版本。

设置:配置属性 - 高级 - MFC 的使用 - “在静态库中使用 MFC”对我有用(使用控制台应用程序 - 而不是 MFC/ATL 应用程序本身)。

If you're not trying to replace the Runtime with your own then it doesn't matter whether如果您不尝试用自己的运行时替换运行时,那么是否

  • You have Runtime Typing enabled/disabled您已启用/禁用运行时键入
  • You have C++ Exceptions enabled/disabled您启用/禁用了 C++ 异常
  • Whether you have the Runtime Library set to Multithreaded DLL or not (setting it to non-DLL is still building it into your binary)是否将运行时库设置为多线程 DLL(将其设置为非 DLL 仍将其构建到您的二进制文件中)

The only thing you need to ensure is that you don't use any of its capabilities and Visual Studio automatically doesn't link to it.您唯一需要确保的是您不使用它的任何功能,并且 Visual Studio 不会自动链接到它。 Ie. IE。 No asserts, no calls to anything in string.h or stdio.h, nothing.没有断言,没有调用 string.h 或 stdio.h 中的任何内容,什么都没有。 Anything the compiler can replace with its own intrinsics tho is ok, as are compiler checks like static_assert.编译器可以用它自己的内在函数替换的任何东西都可以,就像编译器检查一样 static_assert。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM