Как обойти зависимость универсальных CRT-файлов Windows от vcruntime.h
Пытаясь оценить Clang в Windows, используя среду выполнения Windows Universal C (...\Windows Kits\10\Include\10.0.15063.0\ucrt), я сразу же столкнулся с неожиданной стеной в виде нераскрытой и неожиданной зависимости на Microsoft Visual Studio. По-видимому, даже самая простая C-программа не сможет скомпилироваться, как только вы включите любой стандартный C-заголовок, потому что все они в конечном итоге пытаются #include vcruntime.h (который не является частью UCRT).
Мои вопросы:
- Есть ли способ использовать Windows Universal C RTL SDK без Visual Studio?
- Если это не предназначено или не возможно, почему тогда это не называется "Windows CRT для Microsoft VC" - что я пропускаю?
3 ответа
Ознакомьтесь с [MSDN]: Представляем универсальный CRT (а также другие URL-адреса, на которые он ссылается):
В июне прошлого года мы опубликовали пару статей, в которых обсуждались основные изменения, которые мы внесли в Visual C++ C Runtime (CRT) для Visual Studio 2015.
...
AppCRT и DesktopCRT были объединены в одну библиотеку, которую мы назвали Universal CRT. Новые библиотеки называются ucrtbase.dll (выпуск) и ucrtbased.dll (отладка); они не включают номер версии, потому что мы будем обслуживать их на месте.
Из [MSDN]: Рефакторинг Great C Runtime (CRT) (чтобы прояснить (некоторые из) смелые предметы):
Чтобы объединить эти различные ЭЛТ, мы разделили ЭЛТ на три части:
VCRuntime (vcruntime140.dll)...
AppCRT (appcrt140.dll)...
DesktopCRT (desktopcrt140.dll)...
Согласно [MS.Support]: Обновление для Universal C Runtime в Windows:
Microsoft Visual Studio 2015 создает зависимость от универсального CRT, когда приложения создаются с помощью пакета средств разработки для Windows 10 (SDK).
и из [MS.Dev]: Windows 10 SDK:
Примечание. Для разработки Windows 10 для Windows 10 версии 1803 (или более поздней) требуется Visual Studio 2017. Этот SDK не будет обнаружен в предыдущих версиях Visual Studio.
Итак, U CRT строго привязан к VStudio. Универсальный: означает, что он не зависит от версии VStudio (все версии VStudio будут использовать общую версию (может быть только одна)).
UCRT - это Win (wannabe) эквивалент libc Ux.
Я посмотрел в SDK include dir (например, "c: \ Program Files (x86) \ Windows Kits \ 10 \ Include \ 10.0.15063.0 \ ucrt"):
- Каждый общий файл (например, stdio.h) имеет
#include <corecrt.h>
- corecrt.h имеет
#include <vcruntime.h>
нет #ifdef
с, так что нет способа (по крайней мере, нелегко) преодолеть это.
Но все становится еще яснее при достижении фазы соединения. Если ваш код C включает заголовки UCRT, он (скорее всего) будет ссылаться на файлы из SDK lib dir (например, "c: \ Program Files (x86) \ Windows Kits \ 10 \ Lib \ 10.0.15063.0 \ ucrt \ x64"), которые генерируются VStudio, и есть большой шанс, что это не удастся. Пример:
code.c:
//#include <stdio.h>
int main() {
//printf("Dummy.... sizeof(void*): %d\n", sizeof(void*));
return 0;
}
e:\Work\Dev\Stackru\q045340527>dir /b code.c e:\Work\Dev\Stackru\q045340527>"c:\Install\x86\Microsoft\Visual Studio Community\2015\VC\bin\cl.exe" -nologo -c -Focode.obj code.c code.c e:\Work\Dev\Stackru\q045340527>"c:\Install\Google\Android_SDK\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang.exe" -c -o code.o code.c e:\Work\Dev\Stackru\q045340527>dir /b code.c code.o code.obj
2 (сгенерированных) файла несовместимы:
e:\Work\Dev\Stackru\q045340527>"C:\Install\x86\Microsoft\Visual Studio Community\2015\VC\bin\amd64\dumpbin.exe" -nologo code.obj Dump of file code.obj File Type: COFF OBJECT Summary 80 .debug$S 2F .drectve 7 .text$mn e:\Work\Dev\Stackru\q045340527>"C:\Install\x86\Microsoft\Visual Studio Community\2015\VC\bin\amd64\dumpbin.exe" -nologo code.o Dump of file code.o code.o : warning LNK4048: Invalid format file; ignored Summary e:\Work\Dev\Stackru\q045340527>"c:\Install\x64\Cygwin\Cygwin\AllVers\bin\readelf.exe" -d code.o e:\Work\Dev\Stackru\q045340527>"c:\Install\x64\Cygwin\Cygwin\AllVers\bin\readelf.exe" -d code.obj readelf: Error: Not an ELF file - it has the wrong magic bytes at the start
Теперь я знаю, что lld (я помню, что я построил его в прошлом, но я не могу найти его, чтобы проверить свое утверждение) способен связывать форматы файлов ELF и COFF, но я сомневаюсь, что он может объединить их.
Заключение
Исходя из вышеизложенного, вот ответы на ваши вопросы:
Я предполагаю, что это - неподдерживаемый, хотя (утверждение, что что-то невозможно, почти всегда ложно). Но было бы много ограничений (учитывая приведенное выше соответствие формата файла), и, скорее всего, потребовались бы некоторые грязные приемы или обходные пути (gainarii), подобные (некоторые, о которых я могу думать сейчас):
- Изменение его (редактирование его заголовочных файлов - чтобы удалить ненужные
#include
s) - Создание фиктивного файла vcruntime.h (чтобы пройти этап компиляции)
- Изменение его (редактирование его заголовочных файлов - чтобы удалить ненужные
Добавление VStudio (или чего-либо еще, по сути) в имя автоматически уменьшит его " уровень универсальности ".
И это только 1- й шаг: он был отделен от VC Runtime. Думайте об этом как о ребенке. Со временем он станет зрелым и (более стабильным), и, возможно, другие компиляторы / наборы инструментов сборки в конечном итоге поддержат его (нет необходимости следовать спартанским правилам и выбросить его с обрыва:)... по крайней мере, сейчас),
Но, я думаю, что только MS мог иметь ответ на этот вопрос (хотя есть большая вероятность, что они не дадут более ясного ответа)
Более новые версии mingw-w64 поддерживают UCRT, используя собственные заголовки и файлы LIB, поэтому UCRT работает (с Clang или GCC) без установки Windows SDK или Visual Studio. Вы даже можете скомпилировать приложения для использования UCRT на других платформах, таких как Linux или macOS. Конечно, этот сценарий вряд ли когда-либо будет «официально поддержан» Microsoft, но многие проекты теперь полагаются на него, и сотрудники Microsoft предоставили (неофициально) отзывы о проекте mingw-w64, подтверждающие их подход.
Если вы используете дистрибутив mingw-w64 MSYS2, Clang по умолчанию использует UCRT (как для 32-разрядной, так и для 64-разрядной версии x86, а также для 64-разрядной версии ARM); для 64-разрядных систем x86 GCC поставляется в двух разных дистрибутивах: один на основе UCRT, а другой на основе MSVCRT; GCC для 32-разрядной версии x86 предназначен только для MSVCRT. См. Среды MSYS2.
Я живу в стране с телевизионной сетью под названием Global. В течение первых 15 лет существования Globals вы могли смотреть его, только если жили в одном городе, Торонто. Тем не менее, это был глобальный. Microsoft имеет аналогичное определение универсального.
В реальном мире программирования существует лучшее определение универсального, оно называется UNIX. Даже Microsoft была вынуждена (притворяться) понимать UNIX; и Linux определенно понимает UNIX. Вам не нужно мириться с дерьмовыми инструментами разработки; Linux и UNIX доступны везде.