I know that the topic here is C, but I think it's interesting to point out that Delphi (Object Pascal) has always produced executables that work like this (since 1996). With one of our database server products written using Delphi, executables are about 3MB in size and have zero external dependencies. You can literally copy the executable on to any Windows machine, run it (or install it as a service to be run), and it will work.
It's kind of a whole different mindset compared to other approaches that involve many more non-OS runtime dependencies. It certainly makes installation/configuration support a non-issue.
.NET 2, 3.5 and 4+ are distinct and updated differently. Vista shipped with .NET 3.0 and automatically updated to .NET 3.5. .NET 4.x is not an automatic update on Windows Vista, it has to be manually selected and added with admin rights .NET 2 and 3.5 are disabled by default on Windows 8/8.1/10 and require admin rights to enable them. So, there's no version of .NET in and of itself that will work on Windows Vista, 7, 8, 8.1 and 10. The one exception is if you specifically build a .NET 2 or 3 app and list compatibility with .NET 3/4.5 in the packaging manifest, then it will work with all the bundled versions of .NET on Windows Vista and later releases.
But the topic is specifically freestanding executables, not compatibility in general. If it utilises an external DLL, or library then it isn't freestanding, as a .Net 3.5 program typically isn't (although I think Microsoft has a .Net native compiler now, but I don't know if that can be configured to push external dependencies into the executable package).
Don't misunderstand, I like .Net, I just think you've misunderstood what is being discussed.
From the Windows 7 user's perpsective, there's no difference.
It's understood that this article is meant to discuss zero-install applications that require nothing more than the standard C library.
That said, if you're making and marketing software (as I would expect a few visitors of this thread might) and looking to accomplish something functionally similar with your C# or VBScript dev team, my comment can be helpful - which is why I wrote it.
I've shipped a number of sub-5MB applications this way.
I think the thing I like the best about this article is that it forces you to take a C development environment and break it down into more pieces than is usual.
One of my formative software development experiences was developing firmware for small embedded hardware back in the late-90's. We had a 4MHz 80188EB, 128K RAM, 512K ROM, and a handful of pretty raw I/O hardware. Despite the 'unusual' nature of the software we were building, our main compiler was the real-mode C compiler from Borland C++ 4.5.
Our RTOS/standard library was a collection of four C files maintained by our senior team that we compiled along with everything else. The most unusual part of the build process was that we took the linker output and ran it through a locater that used it to generate an image file for a firmware burn.
It was really quite gratifying to see how much of the usual baggage associated with HLL development was unnecessary. It made software seem a lot less magical and a lot easier to understand, both of which have been helpful over the years.
it's nice to see people are still trying to do this. i remember the shock when i was a whippersnapper and seen WinAPI programming in assembly for the first time (e.g. http://stackoverflow.com/a/1029093/38749).
I've played around with replacing the C library with something more lightweight for small programs (WCRT), but one issue is that you end up with executables that get flagged by some AV software for being "unusual".
I think unless you have a specific need for a small executable, it is usually not worth it.
Is the author aware of the posix dll in the SUA subsystem?
Control Panel, Add or Remove System Features, select SUA. Windows 7 Enterprise has it and maybe other versions.
Linking against this library works for me. It may or may not work for others, but there's only one way to find out: try it.
MS is trying to make it go away (for the second time) so expect that people to tell you it does not work and not to use it. Whatever.
Alternatively I agree with the commenter who suggested Delphi. It just works, same as it did in the 90's. I still use an older version from that era. Works beautifully.
This OP is struggling to use MinGW, why not install VS2015 or just install Microsoft's version of clang? True, that will depend on the latest version of msvcrt.dll, but at least your source code will remain cross-platform.
As far as I know, clang should compile anything gcc would compile.
IIRC, it's not trivial to link to msvcrt.dll in VS. In older versions I think you needed to download the Windows Driver Kit to get an import lib, and since Win8 I don't think even that supplies it any more.
I don't get the issue with msvcrt.dll. It's available in all Windows installations, so for my concern, MinGW produces freestanding applications, because nothing additional needs to be installed.
In practice, this is probably correct (Microsoft cares a lot about backward compatibility, and many programs depend on MSVCRT.DLL).
However, the official word from Microsoft is that MSVCRT.DLL is only intended for operating system components to use, not user applications. For example, see Raymond Chen's blog on the subject. [1]
As that link itself says, MSVCRT.DLL was the C library for several versions of their official C compiler. That is, it had always been intended for both operating system components and user applications. A quick Wikipedia search tells me that this was true until 2002, which is when MSVC 7 was released.
Wikipedia also tells me that MinGW (which is probably the main source of programs linking to MSVCRT.DLL nowadays) was first released in 1998, so their use of MSVCRT.DLL as the global C library was correct. It's not MinGW's fault that Microsoft changed their mind.
I wrote a program using similar principles: https://github.com/tom-seddon/kbswitch (two versions, one for 32-bit Windows XP, one for Windows XP or later with any bitness)
The EXEs are indeed pretty small:
~/github/kbswitch % ls -l `find . -name '*.exe' -or -name '*.dll'`
-rw-r--r-- 1 tom staff 5120 1 Feb 13:50 ./kbswitch/kbswitch.exe
-rw-r--r-- 1 tom staff 11264 1 Feb 13:50 ./kbswitch2/bin/kbswitch2.exe
-rw-r--r-- 1 tom staff 5120 1 Feb 13:50 ./kbswitch2/bin/kbswitch2_dll_x64.dll
-rw-r--r-- 1 tom staff 5120 1 Feb 13:50 ./kbswitch2/bin/kbswitch2_dll_x86.dll
-rw-r--r-- 1 tom staff 6144 1 Feb 13:50 ./kbswitch2/bin/kbswitch2_helper_x64.exe
-rw-r--r-- 1 tom staff 5120 1 Feb 13:50 ./kbswitch2/bin/kbswitch2_helper_x86.exe
VC++ makes freestanding programs no easier than gcc. (A good reminder that a C implementation consists of all the libraries that come with it, and not just a compiler that generates code.) Issues I recall having when putting this together (which was a few years ago now so I may have forgotten something):
- As with gcc, you need to fiddle with the linker settings to stop it including the stack check stuff
- Floating point is a bit hit or miss and using it can cause VC++ to generate calls to its helper library (I vaguely recall also getting similar stuff when using 64-bit ints)
- VC++ will generate calls to memset when default-initializing structs
- VC++ will spot many types of implementation of memset, remove them, and replace calls to them with calls to memset (particularly tiresome when trying to fix the last problem)
- the Windows headers include a number of handy-looking functions that seem just the ticket for working without the CRT, but a lot of them, once I followed through all the #ifdefs, ended up just being #defines for the corresponding CRT function
So I haven't bothered doing this for any programs since. I've heard of some people working typically without the CRT, and they seem pretty happy, but I didn't think it was worth the effort just to provide a tiny EXE with no non-system dependencies.
Regarding the size, I don't think it's a huge benefit these days - for small programs, where this stuff makes the EXE noticeable smaller, you're just not saving much. An EXE written like this might be 10K; the same EXE dynamically linked with the CRT, ~20K; the same EXE statically linked with the CRT, ~90K. That difference just isn't very important any more.
And regarding the lack of external dependencies, if you need that, you can statically link with everything (please do your own research regarding licensing and security ramifications). I think that provides you with basically all of the useful benefits of the above approach, for a fraction the effort.
I know that the topic here is C, but I think it's interesting to point out that Delphi (Object Pascal) has always produced executables that work like this (since 1996). With one of our database server products written using Delphi, executables are about 3MB in size and have zero external dependencies. You can literally copy the executable on to any Windows machine, run it (or install it as a service to be run), and it will work.
It's kind of a whole different mindset compared to other approaches that involve many more non-OS runtime dependencies. It certainly makes installation/configuration support a non-issue.