Tar*_*aro 24 c++ msvcrt visual-studio-2015
编译了几个.dll使用visual studio 2015,并试图部署在一些旧的Windows 7/64位上.试图猜测应用程序启动和复制MSVCP140.DLL和VCRUNTIME140.DLL需要哪些dll - 但是应用程序无法加载vs2015 dll.开始分析什么是错误的 - 依赖者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
Run Code Online (Sandbox Code Playgroud)
这是特别令人惊讶的,因为我最好的理解CRT负责启动dll/exe,它不提供任何更高级别的服务.
好的,试图弄清楚如何摆脱它们或至少最小化.
找到一篇文章:https: //blogs.msdn.microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/
它提到了发布静态库 - 所以我认为我可以链接它们并摆脱*L1-1-0.DLL*依赖地狱,但无论我尝试过什么 - 我都没有成功.我试图链接libvcruntime.lib,libucrt.lib,libcmt.lib,尝试禁用链接器选项"/nodefaultlib:vcruntime.lib",甚至尝试添加include目录$(UniversalCRT_IncludePath),并覆盖一些定义的,因为我试图猜测它们是有效的 - 我的尝试都没有帮助.
作为一个中间解决方案,我回归到使用Visual Studio 2013,其中CRT dll只有两个:msvcp120.dll,msvcr120.dll.
当然,您可能会建议安装Visual Studio 2015运行时,但我们的要求之一是支持独立可执行文件 - 无需任何安装即可运行 - 因此现在无法进行额外安装.
除了等待Visual Studio 2017到货之外,你能推荐我吗?
Ton*_*oij 28
我能够通过设置C/C++ > Code Generation > Runtime Library编译器选项来解决这个问题
/MDdto/MTd /MD到/MT这删除了所有API-MS-WIN-CRT-*和运行时dll引用,并导致所有CRT代码静态链接.
有关新VS2015通用CRT(动态和静态)的详细信息,请访问:https://msdn.microsoft.com/en-us/library/abx4dbyh.aspx
我也正在努力将一个解决方案与多个组件/项目库依赖关系静态链接,从MSVCRT,UCRT和内核的各个部分导入函数.希望是最终的EXE可以被复制到需要它的地方(它不是可以证明完整的MSI安装的产品).
几乎放弃后,我发现最好的解决方案是遵循Universal C Runtime公告中隐藏的指导原则,具体来说:
出于性能和可维护性的原因,我们强烈建议不要使用Visual C++库的静态链接
只需删除您尝试的所有"特殊"链接器选项,回退到/ MT |/MD(多线程CRT DLL发布|调试)运行时库选项,它可以在任何地方使用,例如较新的Windows 10工作站,2012 R2服务器和Windows 7).只需像微软告诉我们那样安装/重新分发MSVCRT(VC_Redist*.exe)和KB2999226(通过Windows Update进行UCRT),因为他们也说:
Universal CRT是Windows操作系统的一个组件.它作为Windows 10的一部分包含在1月技术预览版中,并且可通过Windows Update用于旧版操作系统.
从逻辑上讲,我们的C++解决方案为客户添加的唯一额外部署依赖是MSVCRT,因为UCRT应该已经存在于最新/维护良好的机器上.当然它增加了一点不确定性; 你不能只是复制EXE并在任何机器上运行,无论好坏.
如果您像MSI一样生成一个像样的部署包,那么当您拥有像WIX这样的工具时,可以直接包含它.另外要注意的是,从最近的SDK开始,你可以在本地包含40多个DLL,但这不符合安全更新原则,所以我不会这样做.
这实际上是唯一支持的方法,请参见此处的另一个示例.本文还建议我们链接"mincore_downlevel.lib",这是一个重要提示,对于您是否获得这些"api-ms-win*"缺失的DLL错误至关重要.例如:
综上所述:
// Libraries
#pragma comment(lib, "mincore.lib") // Lowest OS support is same as SDK
#pragma comment(lib, "mincore_downlevel.lib") // Support OS older than SDK
Run Code Online (Sandbox Code Playgroud)
(更新11.10.2016)。
通过静态链接可以消除通用CRT,稍后再讲,但是让我们看一下是否继续使用通用CRT。
根据文章https://blogs.msdn.microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/-可以使用以下文件夹中的通用crt dll可分发文件来启动您的应用程序:
C:\Program Files (x86)\Windows Kits\10\Redist\ucrt
列表中共有41个文件,总大小为1.8 Mb。(以64位平台为例)
当然这还不够,您还需要来自以下文件夹的vcruntime140.dll和msvcp140.dll:
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x64\Microsoft.VC140.CRT
因此,在那之后,除了您的应用程序之外,您还将总共运送43个其他dll。
也可以在应用程序内部静态编译ucrt库,此后您将不需要43个dll,但是链接后是否需要静态链接取决于您的应用程序-使用了多少个dll和哪个api。通常,将ucrt链接到两个不同的dll之后,它们不一定彼此共享相同的全局变量-这可能会导致错误。
您需要针对vcruntime.lib / msvcrt.lib进行链接,但这还不够-有更多内容_VCRTIMP=并_ACRTIMP=
定义了哪些功能需要禁止从ucrt中提取函数。
如果您使用的是premake5,则可以这样配置项目:
defines { "_VCRTIMP="}
linkoptions { "/nodefaultlib:vcruntime.lib" }
links { "libvcruntime.lib" }
Run Code Online (Sandbox Code Playgroud)
其次是:
defines { "_ACRTIMP="}
linkoptions { "/nodefaultlib:msvcrt.lib" }
links { "libcmt.lib" }
Run Code Online (Sandbox Code Playgroud)
Microsoft没有记录定义-因此将来可能会对其进行更改。
除了您自己的项目外,您还需要重新编译项目中正在使用的所有静态库。
至于Boost库-我也设法使用b2.exe boostrapper编译了boost
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=
在对链接问题进行故障排除时-请注意,__imp*由于dllimport使用了关键字而导致无法解析的函数名-并且如果针对libvcruntime.lib进行链接,则不应有任何__imp*引用。