При разработке и развертывании собственных приложений Windows мне часто нужно установить среду выполнения, прежде чем я смогу запустить мой двоичный файл, или статически связать библиотеку с моим двоичным файлом. Например, после создания проекта «Консоль Win32» в Visual Studio 2008 попытка запустить программу на новом образе Windows 7 приводит к:
Приложение не удалось запустить, поскольку его параллельная конфигурация неверна. Пожалуйста, смотрите журнал событий приложения или используйте инструмент командной строки sxstrace.exe для более подробной информации.
Подобные проблемы были подняты в других сообщениях на StackOverflow.
Как можно разрабатывать приложения, для которых не требуются среды выполнения, которых еще нет в целевой ОС (т. Е. Не требуется установка распространяемых пакетов или частных / совместно используемых сборок)? Как избежать использования msvc [mpr] 90.dll и просто использовать Windows API в \ windows \ system32 *. {Dll, sys}?
Я размышляю в соответствии с кодом, который выходит из демосцены, но он часто недоступен.
Другие уже ответили относительно статического связывания ЭЛТ. Если вы также хотите небольшой двоичный файл в то же время, то лучше всего полностью отказаться от 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
Используйте статический ЭЛТ. Это не создает зависимость от msvc * .dll. CRT связан непосредственно с вашей программой. Это не создает зависимости, но увеличивает размер вашего исполняемого файла.
Больше информации о различных вариантах CRT здесь .
Статически свяжите CRT через /MT
коммутатор (и также MFC, если вы его используете).
Статическое связывание ограничивает то, что вы можете сделать с DLL-библиотеками, но для простых исполняемых файлов это работает как шарм. (И если вы отправляете библиотеки DLL, вы всегда можете отправить частные сборки.)
Статически связать время выполнения. MS Visual C ++ имеет параметр / MT для этого (по умолчанию / MD)
Я думаю, что один из способов сделать это - просто не использовать Visual Studio, а вместо этого полагаться на инструменты командной строки SDK. (В качестве альтернативы вы можете выяснить, как настроить VS, чтобы делать то, что вы хотите, но это кажется сложнее.) Например:
cl /c app.cpp
link app.obj ws2_32.lib