Создание двоичных файлов с небольшими окнами
Вопрос
При разработке и развертывании собственных приложений Windows мне часто нужно установить время выполнения, прежде чем я могу запустить мой двоичный файл или статически связать библиотеку с моим двоичным. Например, после создания проекта «Консоль Win32» с Visual Studio 2008, пытаясь запустить программу на свежем виде изображения Windows 7, что приводит к:
Приложение не началось, потому что его конфигурация бок о бок неверна. Пожалуйста, смотрите журнал событий приложения или используйте инструмент командной строки sxstrace.exe для получения более подробной информации.
Такие проблемы были подняты в Другие посты на Stackoverflow.
Как разрабатывать приложения, которые не Требовать времени выполнения, которые еще не находятся в целевой ОС (то есть не требуют установки перераспределяемых пакетов или частных/общих сборок)? Как избегать использования MSVC [MPR] 90.dll и просто используйте API Windows в Windows System32*. {DLL, SYS}?
Я думаю в соответствии с кодом, который выходит из демоссена, но это часто не доступно.
Решение
Другие уже ответили в отношении связывания CRT статически. Если вы также хотите одновременно небольшой бинар, то ваша лучшая ставка - это полностью CRT, и использовать только WIN32 API, насколько это возможно. Вы все равно получите код CRT, особенно связанный со стартапом (то есть то, что вызывает main
) и выключение (atexit
обработка и т. Д.), Но в остальном линкер не будет связывать функции CRT, которые вы не используете.
Вы можете не связывать CRT полностью, используя /Zl
компилятор переключатель. Это означает, что main
Однако больше не будет работать - вам нужно определить WinMain
(Имя не имеет значения, но подпись должна соответствовать, и это должно быть __stdcall
), и вам придется указать имя вашего WinMain
-Поподобная функция в качестве точки входа через линкер /entry:
выключатель. Это сэкономит вам ~ 30 КБ кода 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. (Вы можете в качестве альтернативы выяснить, как конфигурировать VS, чтобы делать то, что вы хотите, но это кажется сложнее.) Например:
cl /c app.cpp
link app.obj ws2_32.lib