Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to circumvent Windows Universal CRT headers dependency on vcruntime.h

In trying to evaluate Clang on Windows, utilizing the Windows Universal C Run-Time (...\Windows Kits\10\Include\10.0.15063.0\ucrt) I was immediately facing unexpected wall, in the form of an undisclosed and unexpected dependency on Microsoft's Visual Studio. Apparently even the simplest C program will not be able to compile as soon as you include any standard C header, because they all seem to end-up attempting to #include vcruntime.h (which is not part of the UCRT).

My questions are:

  1. Is there a way to utilize the Windows Universal C RTL SDK withOUT Visual Studio?
  2. If it is not intended or possible, why then is it not called "Windows CRT for Microsoft VC" - what am I missing?
like image 247
Ron Pinkas Avatar asked Jul 27 '17 02:07

Ron Pinkas


People also ask

What is UCRT and Msvcrt?

MSVCRT vs UCRT These are two variants of the C standard library on Microsoft Windows. MSVCRT (Microsoft Visual C++ Runtime) is available by default on all Microsoft Windows versions, but due to backwards compatibility issues is stuck in the past, not C99 compatible and is missing some features.

Should you update Microsoft Visual C++?

We recommend you install this version for all applications created using Visual Studio 2015, 2017, 2019, or 2022.

What is CRT in Visual Studio?

The C runtime Library (CRT) is the part of the C++ Standard Library that incorporates the ISO C standard library. The Visual C++ libraries that implement the CRT support native code development, and both mixed native and managed code. All versions of the CRT support multi-threaded development.

What is Microsoft UCRT?

The Universal CRT (UCRT) is a Microsoft Windows operating system component. It's included as part of the operating system in Windows 10 or later, and Windows Server 2016 or later. The UCRT is available by using Windows Update on older operating systems that are still in extended support.


1 Answers

Check out [MSDN.Blogs]: Introducing the Universal CRT (and also the other URLs that it references). Emphases are mine:

In June of last year we published a pair of articles discussing the major changes that we had made to the Visual C++ C Runtime (CRT) for Visual Studio 2015.
...
The AppCRT and DesktopCRT have been recombined into a single library, which we have named the Universal CRT. The new DLLs are named ucrtbase.dll (release) and ucrtbased.dll (debug); they do not include a version number because we’ll be servicing them in-place.

From [MS.DevBlogs]: The Great C Runtime (CRT) Refactoring

In order to unify these different CRTs, we have split the CRT into three pieces:

  1. VCRuntime (vcruntime140.dll) ...

  2. AppCRT (appcrt140.dll) ...

  3. DesktopCRT (desktopcrt140.dll) ...

According to [MS.Support]: Update for Universal C Runtime in Windows:

Microsoft Visual Studio 2015 creates a dependency on the Universal CRT when applications are built by using the Windows 10 Software Development Kit (SDK).

and from [MS.Dev]: Windows 10 SDK:

Note: Windows 10 development targeting Windows 10, version 1803 (or later) requires Visual Studio 2017. This SDK will not be discovered by previous versions of Visual Studio.

So, UCRT is strictly bound to VStudio. Universal: means that it's not dependent on VStudio version (all VStudio versions will use a common one (there can be only one)).

Personal opinion: UCRT is the Win (wannabe) equivalent of Nix's libc.

I took a look in SDK include dir (e.g. "c:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\ucrt"):

  • Every common file (e.g. stdio.h) has an #include <corecrt.h>
  • corecrt.h has an #include <vcruntime.h>

no #ifdefs, so there is no way (at least no easy one) to overcome this.

But, things are even clearer when reaching link phase. If your C code includes UCRT headers, it will (most likely) link to files from SDK lib dir (e.g. "c:\Program Files (x86)\Windows Kits\10\Lib\10.0.15063.0\ucrt\x64"), which are generated by VStudio, and there's a great chance for that to fail. Example:

code00.c:

//#include <stdio.h>


int main() {
    //printf("Dummy.... sizeof(void*): %d\n", sizeof(void*));
    return 0;
}

Output:

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q045340527]> sopr.bat
*** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ***

[prompt]> dir /b
code00.c

[prompt]> "c:\Install\x86\Microsoft\Visual Studio Community\2015\VC\bin\cl.exe" -nologo -c -Focode00.obj code00.c
code00.c

[prompt]> "c:\Install\Google\Android_SDK\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang.exe" -c -o code00.o code00.c

[prompt]> dir /b
code00.c
code00.o
code00.obj

The 2 (generated) files are incompatible:

[prompt]> "C:\Install\x86\Microsoft\Visual Studio Community\2015\VC\bin\amd64\dumpbin.exe" -nologo code00.obj

Dump of file code00.obj

File Type: COFF OBJECT

  Summary

          80 .debug$S
          2F .drectve
           7 .text$mn

[prompt]> "C:\Install\x86\Microsoft\Visual Studio Community\2015\VC\bin\amd64\dumpbin.exe" -nologo code00.o

Dump of file code00.o
code00.o : warning LNK4048: Invalid format file; ignored

  Summary



[prompt]> "c:\Install\x64\Cygwin\Cygwin\AllVers\bin\readelf.exe" -d code00.o

[prompt]> "c:\Install\x64\Cygwin\Cygwin\AllVers\bin\readelf.exe" -d code00.obj
readelf: Error: Not an ELF file - it has the wrong magic bytes at the start

Now, I know that lld (I remember that I built it in the past, but I can't find it, in order to test my statement) is able to link both ELF and COFF file formats, but I doubt that it can combine them.

Conclusion

Based on the above, here are the answers to your questions:

  1. I suppose it is - an unsupported one though (claiming that something is impossible is almost always false). But, there would be lots of restrictions (consider the above file format matching), and would most likely require some dirty tricks or (lame) workarounds (gainarii) like (some that I can think of now):

    • Altering it (editing its header files - to remove the unwanted #includes)
    • Creating a dummy vcruntime.h file (to get past the compile phase)
  2. Adding VStudio (or anything else, as a matter of fact) in the name would automatically decrease its "universality level".
    And this is only the 1st step: it has been separated from VC Runtime. Think of it as of a baby. In time, it will become mature (and more stable,) and maybe other compilers / build toolchains will end up supporting it as well (no need to follow the spartan rules, and throw it off the cliff :) ... at least not right now).
    But, I think only MS could have an answer to this (although there's a great chance that they won't provide a clearer one)

like image 134
CristiFati Avatar answered Nov 04 '22 15:11

CristiFati