Thread overview
big executable size
Dec 27, 2002
Danilo
Dec 28, 2002
Walter
Jan 03, 2003
Daniel Fazekas
Jan 03, 2003
Walter
Jan 05, 2003
Daniel Fazekas
Jan 05, 2003
Walter
Jan 05, 2003
Daniel Fazekas
Jan 05, 2003
Walter
December 27, 2002
Hello !!

Can somebody tell me please why the small Windows-Test:

#include <windows.h>
int WINAPI WinMain_(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
lpCmdLine, int nCmdShow)
{
MessageBox(0,"Hello World","Test",0);
return 0;
}

always results in a 30k+ .EXE ??

I tried all possible DMC compiler flags and i also have
a .def file to prevent the console window.

The smallest .EXE for Windows (NT) must be 1k
for compatibility reason.
Not a problem to produce 1k-EXE with assembly language.

The LCCwin32 C-compiler produces like 2k or 3k .EXE
as the smallest result (if i remember correctly) and
thats acceptable for a high level language compiler, IMHO.

But 30k is way too much for smallest windows executable.
Looks like there is always a big runtime library included
and the .exe contents looks weird. It has many strings like
"long long" and such in the .EXE.
Also, there are many WinAPI imports included that are not
needed here.

I want to learn C and C++ for the first time (last 13 years ASM only)
and i´m searching for a good C/C++ compiler now (LCCwin32 is C only).
DMC/C++ looks good, except the filesize thing.

Maybe somebody can tell me how to exclude all unneeded stuff from the .EXE

Thanks,
..Danilo


December 28, 2002
You can see what all is included by linking with the /MAP switch. The 30k is all the runtime library bits and pieces being initialized. You can remove all that by stubbing them out (the entire library source is provided  with the CD version).

"Danilo" <Danilo_member@pathlink.com> wrote in message news:auicnl$1v5r$1@digitaldaemon.com...
> Hello !!
>
> Can somebody tell me please why the small Windows-Test:
>
> #include <windows.h>
> int WINAPI WinMain_(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
> lpCmdLine, int nCmdShow)
> {
> MessageBox(0,"Hello World","Test",0);
> return 0;
> }
>
> always results in a 30k+ .EXE ??
>
> I tried all possible DMC compiler flags and i also have
> a .def file to prevent the console window.
>
> The smallest .EXE for Windows (NT) must be 1k
> for compatibility reason.
> Not a problem to produce 1k-EXE with assembly language.
>
> The LCCwin32 C-compiler produces like 2k or 3k .EXE
> as the smallest result (if i remember correctly) and
> thats acceptable for a high level language compiler, IMHO.
>
> But 30k is way too much for smallest windows executable.
> Looks like there is always a big runtime library included
> and the .exe contents looks weird. It has many strings like
> "long long" and such in the .EXE.
> Also, there are many WinAPI imports included that are not
> needed here.
>
> I want to learn C and C++ for the first time (last 13 years ASM only)
> and i´m searching for a good C/C++ compiler now (LCCwin32 is C only).
> DMC/C++ looks good, except the filesize thing.
>
> Maybe somebody can tell me how to exclude all unneeded stuff from the .EXE
>
> Thanks,
> ..Danilo
>
>


January 03, 2003
That is the run-time library being built into your executable.

LCC and the MinGW port of GCC avoid this by linking to Microsoft-supplied system C run-time libraries CRTDLL.DLL and MSVCRT.DLL, respectively. Visual C++ 6.0 can also link against MSVCRT.DLL as an option.

(VC++ 7 allows linking to its new MSVCR70.DLL which is rather painful as practically no one has that DLL already on their system.)


Using an outsite run-time library means smaller executables and an additional DLL dependency. Your call.


Using the following command lines, I could get your test down to 29212 bytes (I had to remove the underscore after "WinMain," what is that supposed to mean?):

dmc.exe -o+space -WA -Nc -mn test.c

link.exe test.obj,test.exe,NUL,kernel32.lib user32.lib,, /FIXED /noi /EXETYPE:NT /SUBSYSTEM:WINDOWS

(The link command is a single line.)

In my test of seven Win32 C compilers, DMC is the second worst when it comes to small code size. Only the Metrowerks CodeWarrior creates even larger executables. And of course any compiler whose primary aim is speed without regard to code size, such as the Intel compiler, which isn't included in that count.

--
Daniel

"Danilo" <Danilo_member@pathlink.com> wrote in message news:auicnl$1v5r$1@digitaldaemon.com...
> Hello !!
>
> Can somebody tell me please why the small Windows-Test:
>
> #include <windows.h>
> int WINAPI WinMain_(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
> lpCmdLine, int nCmdShow)
> {
> MessageBox(0,"Hello World","Test",0);
> return 0;
> }
>
> always results in a 30k+ .EXE ??
>
> I tried all possible DMC compiler flags and i also have
> a .def file to prevent the console window.
>
> The smallest .EXE for Windows (NT) must be 1k
> for compatibility reason.
> Not a problem to produce 1k-EXE with assembly language.
>
> The LCCwin32 C-compiler produces like 2k or 3k .EXE
> as the smallest result (if i remember correctly) and
> thats acceptable for a high level language compiler, IMHO.
>
> But 30k is way too much for smallest windows executable.
> Looks like there is always a big runtime library included
> and the .exe contents looks weird. It has many strings like
> "long long" and such in the .EXE.
> Also, there are many WinAPI imports included that are not
> needed here.
>
> I want to learn C and C++ for the first time (last 13 years ASM only)
> and i´m searching for a good C/C++ compiler now (LCCwin32 is C only).
> DMC/C++ looks good, except the filesize thing.
>
> Maybe somebody can tell me how to exclude all unneeded stuff from the .EXE
>
> Thanks,
> ..Danilo
>
>


January 03, 2003
"Daniel Fazekas" <fds@mailbox.hu> wrote in message news:av4ts9$2f4n$1@digitaldaemon.com...
> In my test of seven Win32 C compilers, DMC is the second worst when it
comes
> to small code size. Only the Metrowerks CodeWarrior creates even larger executables.

Code size isn't quite the same thing as executable size because, as you pointed out, executable size can be hidden by transferring code to a separate dll.

I myself prefer to statically link things, because then there is no "dll hell" problem of incompatible dll versions.


January 05, 2003
That's right, but there are some cases where a small executable is of primary importance (small utilities intended for online distribution in my case), and DMC is among the lower end even among the statically linking compilers:

 93,184 Microsoft Visual C++ 6.0 SP5 (linked to MSVCRT.DLL)
108,064 LCC-win32 Dec 28 2002 (linked to CRTDLL.DLL)
119,296 MinGW GCC 3.2 (linked to MSVCRT.DLL)

135,168 OpenWatcom C/C++ 0.8.5
143,360 Microsoft Visual C++ 7.0
160,796 Digital Mars C/C++ 8.31
161,280 Borland C/C++ 5.5.1
167,936 Metrowerks CodeWarrior 8, C compiler 3.0.3

186,368 Intel C++ 7.00 (optimizing for speed on Pentium 4 processors)

This is my own little C project compiled with all of them. :)

I've spent considerable time and research trying to find the optimal settings for each and every compiler and linker to get the smallest possible executable (except for the Intel compiler, which was only thrown into the mix for fun), while only linking to DLLs which are readily available on any of my target systems. That means either crtdll or msvcrt.

Those which could link against them are obviously in the top three: LCC and MinGW give no choice but to link against CRTDLL or MSVCRT, while MSVC6 lets you choose if you want to do that or link statically.

If you think there could be a way to get the DMC compiled size down with some option I missed, I'd glad to try them.

Now if I try to compress the executables with UPX, these are the sizes I end up with:

 53,248 Microsoft Visual C++ 6.00 SP5 (linked to MSVCRT.DLL)
 53,280 LCC-win32 Dec 28 2002 (linked to CRTDLL.DLL)
 57,856 MinGW GCC 3.2 (linked to MSVCRT.DLL)
 71,168 OpenWatcom C/C++ 0.8.5
 73,728 Metrowerks CodeWarrior 8, C compiler 3.0.3
 80,896 Microsoft Visual C++ 7.00
 81,408 Borland C/C++ 5.5.1
 93,184 Intel C++ 7.00 (optimizing for speed on Pentium 4 processors)
160,796 Digital Mars C/C++ 8.31

Digital Mars remains unchanged and uncompressed, since UPX and OptLink generated executables do not match, as we've already talked about it some weeks ago. I haven't yet got around to try and figure out why. :)

--
Daniel

"Walter" <walter@digitalmars.com> wrote in message news:av549f$2id5$1@digitaldaemon.com...
>
> "Daniel Fazekas" <fds@mailbox.hu> wrote in message news:av4ts9$2f4n$1@digitaldaemon.com...
> > In my test of seven Win32 C compilers, DMC is the second worst when it
> comes
> > to small code size. Only the Metrowerks CodeWarrior creates even larger executables.
>
> Code size isn't quite the same thing as executable size because, as you pointed out, executable size can be hidden by transferring code to a separate dll.
>
> I myself prefer to statically link things, because then there is no "dll hell" problem of incompatible dll versions.
>
>


January 05, 2003
The way to cut down on exe size is to examine the .map file and see what may be pulled in from the library that you don't need. There is one possibility why DMC is bigger - the library is built with full support for multithreading. Other compilers frequently have multiple libraries depending on the threading, and the single threaded library is smaller.

DMC goes with the full multithreading library for the simple reason that it produces a lot fewer problems from getting the wrong library linked with the code.

But the reliable way to figure out where the bulk is is to examine the .map file. Link with /MAP to generate it.

"Daniel Fazekas" <fds@mailbox.hu> wrote in message news:av7sp3$17nc$1@digitaldaemon.com...
> That's right, but there are some cases where a small executable is of primary importance (small utilities intended for online distribution in my case), and DMC is among the lower end even among the statically linking compilers:
>
>  93,184 Microsoft Visual C++ 6.0 SP5 (linked to MSVCRT.DLL)
> 108,064 LCC-win32 Dec 28 2002 (linked to CRTDLL.DLL)
> 119,296 MinGW GCC 3.2 (linked to MSVCRT.DLL)
>
> 135,168 OpenWatcom C/C++ 0.8.5
> 143,360 Microsoft Visual C++ 7.0
> 160,796 Digital Mars C/C++ 8.31
> 161,280 Borland C/C++ 5.5.1
> 167,936 Metrowerks CodeWarrior 8, C compiler 3.0.3
>
> 186,368 Intel C++ 7.00 (optimizing for speed on Pentium 4 processors)
>
> This is my own little C project compiled with all of them. :)
>
> I've spent considerable time and research trying to find the optimal settings for each and every compiler and linker to get the smallest
possible
> executable (except for the Intel compiler, which was only thrown into the mix for fun), while only linking to DLLs which are readily available on
any
> of my target systems. That means either crtdll or msvcrt.
>
> Those which could link against them are obviously in the top three: LCC
and
> MinGW give no choice but to link against CRTDLL or MSVCRT, while MSVC6
lets
> you choose if you want to do that or link statically.
>
> If you think there could be a way to get the DMC compiled size down with some option I missed, I'd glad to try them.
>
> Now if I try to compress the executables with UPX, these are the sizes I
end
> up with:
>
>  53,248 Microsoft Visual C++ 6.00 SP5 (linked to MSVCRT.DLL)
>  53,280 LCC-win32 Dec 28 2002 (linked to CRTDLL.DLL)
>  57,856 MinGW GCC 3.2 (linked to MSVCRT.DLL)
>  71,168 OpenWatcom C/C++ 0.8.5
>  73,728 Metrowerks CodeWarrior 8, C compiler 3.0.3
>  80,896 Microsoft Visual C++ 7.00
>  81,408 Borland C/C++ 5.5.1
>  93,184 Intel C++ 7.00 (optimizing for speed on Pentium 4 processors)
> 160,796 Digital Mars C/C++ 8.31
>
> Digital Mars remains unchanged and uncompressed, since UPX and OptLink generated executables do not match, as we've already talked about it some weeks ago. I haven't yet got around to try and figure out why. :)
>
> --
> Daniel
>
> "Walter" <walter@digitalmars.com> wrote in message news:av549f$2id5$1@digitaldaemon.com...
> >
> > "Daniel Fazekas" <fds@mailbox.hu> wrote in message news:av4ts9$2f4n$1@digitaldaemon.com...
> > > In my test of seven Win32 C compilers, DMC is the second worst when it
> > comes
> > > to small code size. Only the Metrowerks CodeWarrior creates even
larger
> > > executables.
> >
> > Code size isn't quite the same thing as executable size because, as you pointed out, executable size can be hidden by transferring code to a separate dll.
> >
> > I myself prefer to statically link things, because then there is no "dll hell" problem of incompatible dll versions.
> >
> >
>
>


January 05, 2003
"Walter" <walter@digitalmars.com> wrote in message news:av8gmg$1i5e$1@digitaldaemon.com...
>
> The way to cut down on exe size is to examine the .map file and see what
may
> be pulled in from the library that you don't need.

Ok, I checked the .map file and can see that there are a handful of SNN.lib functions included which I do not use. But where to go from here?

Hand-edit the run-time library - the source of which is only available on
the CD - omitting the functions you do not need, rebuild a new .lib and
recompile?
That's quite an overkill for shaving off a few thousand bytes and not what
I'd do for any compiler. :)

I hope you meant there is some other way.

> There is one possibility why DMC is bigger - the library is built with full support for multithreading. Other compilers frequently have multiple libraries depending on the threading, and the single threaded library is smaller.

That's true, exactly the reason why I rewrote part of my code to make it feasible not to use multi-threading, and thus let me use the smaller singlethreaded libraries where allowed.

> DMC goes with the full multithreading library for the simple reason that
it
> produces a lot fewer problems from getting the wrong library linked with
the
> code.

This usually is not a problem, as the single-threaded libraries completely
omit the thread functions such as _beginthread(), _beginthreadex() or
_endthread(), so if you do use threads but try to link with the
single-threaded library, you just can't, the linker fails.

--
Daniel


January 05, 2003
"Daniel Fazekas" <fds@mailbox.hu> wrote in message news:av9lli$232g$1@digitaldaemon.com...
> "Walter" <walter@digitalmars.com> wrote in message news:av8gmg$1i5e$1@digitaldaemon.com...
> > The way to cut down on exe size is to examine the .map file and see what
> may
> > be pulled in from the library that you don't need.
> Ok, I checked the .map file and can see that there are a handful of
SNN.lib
> functions included which I do not use. But where to go from here?

You can stub them out. For example, if you don't need printf and don't want it linked in, add this to your code:

    int printf(const char *format, ...) { return 0; }

> Hand-edit the run-time library - the source of which is only available on the CD -

Why not get the CD? It's only $25.

> omitting the functions you do not need, rebuild a new .lib and
> recompile?
> That's quite an overkill for shaving off a few thousand bytes and not what
> I'd do for any compiler. :)

I thought you were significantly concerned about a few thousand bytes <g>.

> This usually is not a problem, as the single-threaded libraries completely
> omit the thread functions such as _beginthread(), _beginthreadex() or
> _endthread(), so if you do use threads but try to link with the
> single-threaded library, you just can't, the linker fails.

There are other ways to build multithreaded code. For example, you could be making a DLL. Or you could be calling the multithreading win32 API directly.