在开发和部署本机Windows应用程序时,我经常需要安装运行时才能运行我的二进制文件,或者将库与我的二进制文件静态链接。例如,在使用Visual Studio 2008构建“Win32控制台”项目后,尝试在新的Windows 7映像上运行该程序会导致:
应用程序无法启动,因为它的并排配置不正确。请参阅应用程序事件日志或使用命令行sxstrace.exe工具获取更多详细信息。
这样的问题已在StackOverflow上的other posts中提出。
如何开发不需要不在目标操作系统上的运行时的应用程序(即不需要安装可再发行软件包或私有/共享并排组件) ?如何避免使用msvc [mpr] 90.dll并只使用\ windows \ system32 *中的Windows API。{dll,sys}?
我正在思考来自demoscene的代码,但这种情况经常无法实现。
答案 0 :(得分:4)
其他人已经就静态链接CRT做出了回应。如果你同时想要一个小二进制文件,那么你最好的选择是完全放弃CRT,并尽可能只使用Win32 API函数。您仍将获得一些CRT代码,最明显与启动相关(即调用main
)和关闭(atexit
处理等),但链接器不会链接您执行的CRT功能不使用。
您可以使用/Zl
编译器开关完全避免连接CRT。这意味着main
将不再有效,但是 - 您需要定义WinMain
(名称无关紧要,但签名必须匹配,且必须为__stdcall
),并且您必须通过链接器WinMain
开关指定您的/entry:
- 类函数的名称作为入口点。这将为您节省~30Kb的CRT代码(在.cpp上测试,空main
)。
如果你采用后一种方式,你可能还需要处理编译器内在函数的问题。有些函数名义上由CRT定义(并在其标题中声明),但是由编译器专门处理,因此它在可能的情况下在调用时插入优化的汇编指令 - 示例为{{1} },memset
,以及strlen
中的一大块函数;可以找到完整列表here。既然你没有CRT,如果你需要这些功能,或者可以避免它,但是因为性能提高而更喜欢内在功能(例如,比<math.h>
更难做),那么你必须自己声明它们,并使用memset
。 E.g:
#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;
}
答案 1 :(得分:3)
通过/MT
开关静态链接CRT(如果您正在使用它,也可以使用MFC)。
静态链接限制了你可以对DLL做些什么,但对于简单的可执行文件,它就像一个魅力。 (如果您正在运送DLL,则无论如何都可以随身携带私人程序集。)
答案 2 :(得分:2)
使用静态CRT。这不会对msvc * .dll产生依赖性。 CRT直接链接到您的程序。这不会创建依赖项,但会增加可执行文件的大小。
有关不同CRT选项的更多信息here。
答案 3 :(得分:0)
静态链接运行时。 MS Visual C ++有选项/ MT(默认为/ MD)
答案 4 :(得分:0)
我认为一种方法是不使用Visual Studio而是依赖命令行SDK工具。 (你也可以选择如何配置VS来做你想做的事情,但这看起来更难。)例如:
cl /c app.cpp
link app.obj ws2_32.lib