www.digitalmars.com         C & C++   DMDScript  

c++ - big executable size

reply Danilo <Danilo_member pathlink.com> writes:
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
Dec 27 2002
next sibling parent "Walter" <walter digitalmars.com> writes:
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
Dec 27 2002
prev sibling parent reply "Daniel Fazekas" <fds mailbox.hu> writes:
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
Jan 03 2003
parent reply "Walter" <walter digitalmars.com> writes:
"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.
Jan 03 2003
parent reply "Daniel Fazekas" <fds mailbox.hu> writes:
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.
Jan 04 2003
parent reply "Walter" <walter digitalmars.com> writes:
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.
Jan 04 2003
parent reply "Daniel Fazekas" <fds mailbox.hu> writes:
"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
Jan 05 2003
parent "Walter" <walter digitalmars.com> writes:
"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.
Jan 05 2003