题
在开发和部署本机Windows应用程序时,我经常需要安装运行时,然后才能运行我的二进制文件,或者将库与二进制文件静态链接。例如,在使用Visual Studio 2008构建“ Win32控制台”项目之后,试图在Fresh Windows 7图像上运行该程序的结果:
该应用程序未能启动,因为其并排配置不正确。请参阅“应用程序”日志或使用命令行sxstrace.exe工具以获取更多详细信息。
这样的问题已经提出 其他帖子 在stackoverflow上。
一个人如何开发应用程序 别 需要尚未在目标操作系统上的运行时间(即不需要安装可重新分布的软件包或私人/并排组件)?如何避免使用msvc [mpr] 90.dll,只使用 Windows System32*。{dll,sys}中的Windows API?
我正在考虑符合法型法规的代码线条,但这常常无法提供。
解决方案
其他人已经在静态链接CRT方面做出了反应。如果您还希望同时使用一个小二进制文件,那么您最好的选择就是完全放弃CRT,并且仅使用Win32 API功能。您仍然会获得一些CRT代码,最著名的是与启动有关(即调用的 main
)和关闭(atexit
处理等),但是否则,链接器不会链接您不使用的CRT函数。
您可以通过使用 /Zl
编译器开关。这意味着 main
但是,将不再起作用 - 您需要定义 WinMain
(名称没关系,但是签名必须匹配,并且必须是 __stdcall
),您必须指定您的名称 WinMain
- 像链接器的入口点一样函数 /entry:
转变。这将节省您〜30kb的CRT代码(在.cpp上测试了一个空的 main
).
如果您走后一条路线,您可能还必须处理编译器内在问题。有些功能名义上由CRT定义(并在其标题中声明),但由编译器专门处理,以便在可能的情况下插入呼叫点的优化汇编指令 - 示例是示例 memset
, strlen
, ,以及大量功能 <math.h>
;可以找到完整的列表 这里. 。由于您没有CRT,如果您需要这些功能,或者可以避免它,但由于性能的提高而更喜欢固有的(难以做得比 memset
, ,例如),然后您必须自己声明它们,并使用 #pragma intrinsic
. 。例如:
// Contains macros and typedef only, so safe to include without CRT.
// We need it here for size_t.
#include <stddef.h>
extern "C"
{
int abs(int);
void* memset(void*, int, size_t);
}
#pragma intrinsic(abs, memset)
int __stdcall main(void*, void*, char*, int)
{
char tmp[10];
memset(tmp, abs(-123), 10);
return 0;
}
以上可以与:
cl /c /Zl foo.cpp
link /entry:main foo.obj
其他提示
通过静态链接CRT /MT
切换(如果您使用的话,同样是MFC)。
静态链接限制了您可以在某种程度上使用DLL的操作,但是对于简单的可执行文件,它像魅力一样工作。 (如果您要运送DLL,则可以随时运送私人集会。)
使用静态CRT。这不会创建对MSVC*.dll的依赖性。 CRT直接链接到您的程序中。这不会造成依赖性,但确实会增加可执行文件的大小。
有关不同CRT选项的更多信息 这里.
静态链接运行时。 MS Visual C ++具有该选项 /MT(默认为 /MD)
我认为这样做的一种方法是不使用Visual Studio,而是依靠命令行SDK工具。 (您也可以弄清楚如何配置如何做自己想做的事情,但这似乎更难。)例如:
cl /c app.cpp
link app.obj ws2_32.lib