Создание небольших двоичных файлов Windows

При разработке и развертывании собственных приложений Windows мне часто нужно установить среду выполнения, прежде чем я смогу запустить мой двоичный файл, или статически связать библиотеку с моим двоичным файлом. Например, после создания проекта «Консоль Win32» в Visual Studio 2008 попытка запустить программу на новом образе Windows 7 приводит к:

Приложение не удалось запустить, поскольку его параллельная конфигурация неверна. Пожалуйста, смотрите журнал событий приложения или используйте инструмент командной строки sxstrace.exe для более подробной информации.

Подобные проблемы были подняты в других сообщениях на StackOverflow.

Как можно разрабатывать приложения, для которых не требуются среды выполнения, которых еще нет в целевой ОС (т. Е. Не требуется установка распространяемых пакетов или частных / совместно используемых сборок)? Как избежать использования msvc [mpr] 90.dll и просто использовать Windows API в \ windows \ system32 *. {Dll, sys}?

Я размышляю в соответствии с кодом, который выходит из демосцены, но он часто недоступен.

29.09.2009 21:57:52
5 ОТВЕТОВ
РЕШЕНИЕ

Другие уже ответили относительно статического связывания ЭЛТ. Если вы также хотите небольшой двоичный файл в то же время, то лучше всего полностью отказаться от CRT и максимально использовать только функции Win32 API. Вы по-прежнему получите некоторый код CRT, прежде всего связанный с запуском (то есть вызывающим main) и выключением ( atexitобработкой и т. Д.), Но в противном случае компоновщик не будет связывать функции CRT, которые вы не используете.

Вы можете полностью избежать связывания CRT, используя /Zlпереключатель компилятора. Это означает, что mainэто больше не будет работать - вам нужно определить WinMain(имя не имеет значения, но подпись должна совпадать, и это должно быть __stdcall), и вам нужно будет указать имя вашей WinMain-подобной функции в качестве записи указать через /entry:переключатель компоновщика . Это сэкономит вам ~ 30Kb кода CRT (проверено на .cpp с пустым main).

Если вы выберете последний путь, вам, возможно, придется столкнуться с проблемой встроенных функций компилятора. Есть некоторые функции, которые номинально определяются ЭЛТ (и объявленные в своих заголовках), но которые специально обрабатываются компилятором, так что он вставляет оптимизированные сборки инструкции в точке вызова , где это возможно - примеры являются 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
4
30.09.2009 18:46:14

Используйте статический ЭЛТ. Это не создает зависимость от msvc * .dll. CRT связан непосредственно с вашей программой. Это не создает зависимости, но увеличивает размер вашего исполняемого файла.

Больше информации о различных вариантах CRT здесь .

2
29.09.2009 22:01:46

Статически свяжите CRT через /MTкоммутатор (и также MFC, если вы его используете).

Статическое связывание ограничивает то, что вы можете сделать с DLL-библиотеками, но для простых исполняемых файлов это работает как шарм. (И если вы отправляете библиотеки DLL, вы всегда можете отправить частные сборки.)

3
29.09.2009 22:07:44

Статически связать время выполнения. MS Visual C ++ имеет параметр / MT для этого (по умолчанию / MD)

0
29.09.2009 22:02:45

Я думаю, что один из способов сделать это - просто не использовать Visual Studio, а вместо этого полагаться на инструменты командной строки SDK. (В качестве альтернативы вы можете выяснить, как настроить VS, чтобы делать то, что вы хотите, но это кажется сложнее.) Например:

cl /c app.cpp
link app.obj ws2_32.lib
0
30.09.2009 17:41:27
Это все еще принесет CRT, и на самом деле ничем не отличается от использования VS.
Pavel Minaev 30.09.2009 18:46:37
Да, вы можете настроить VS, чтобы сделать то же самое, но по умолчанию VS вызывает проблему в исходном посте - что-то, чего не происходит при выполнении действий, предложенных мной. Тем не менее, ваш ответ был, безусловно, самым поучительным.
Yang 1.10.2009 05:34:11