I'm using Delphi 6 Personal Edition here.

Okay, a step by step guide for doing this...

1) Start a new project
2) Remove the form ("remove file from project")
3) Go the the project menu and select "view source" (side note: does anyone else wonder why this wasn't View->Project Source instead? Just me? Oh well... :? )
4) You're left sitting at the project source itself (the .dpr file). This is the file that usually means "hands off". However, it's the best way to get tiny exes - ignore the VCL and use direct Win32 stuff. Yucky, but the size makes up for it.
5) Save your project somewhere. Compile it. Notice how this minimal app takes up *351K*!
6) We don't want any VCL stuff - which means no "uses forms". Oh well, back to our Pascal roots, I guess. The .dpr file can be laid out like this:

[pascal]program Project1; // name depends on what you saved it as

begin

end.[/pascal]

I got rid of the "uses forms" bit there, since that's including VCL stuff. The other bits about "application.initialize" and "application.run" are VCL things too. Now we have a skeleton app with absolutely no functionality. Gee, ain't that useful . On the plus side, it's down to 8K from 351K(!!).

I got rid of the {$R *.RES}, which includes the icon. This is about 1/2 a K of unnecessary stuff.

Now, the main challenge is to turn this into a working win32 program. This takes a bit of savvy, unfortunately, and especially so if you're used to the comfy VCL. I've got a tutorial on this, pimp pimp, over at my site: thisaways

We want to get a Window Class, register it, create a window, write a message loop (PeekMessage/DispatchMessage) and a window proc to handle some messages. Eesh!

I solved this by copying and pasting function prototypes from the windows.pas and messages.pas (I have the VCL from Delphi 5, but its compiler generates *much* larger win32 exes. D6 is a lot leaner in this respect, though you wouldn't expect as much from the increased VCL program size. I've not tried D7 yet).

My sizetest unit has *no uses clause at all*! Thus, I had to copy over the definitions of each required win32 function. These boiled down to simple declarations of dll functions, e.g.

[pascal]procedure PostQuitMessage(nExitCode: Integer); stdcall; external 'user32.dll';[/pascal]

With care, I managed to get an win32 window up and running... in 8K(!). That's the same value as the empty unit, btw. *Cough cough*.

Now, I'm not done yet. There's a lovely exe packer that everyone must know about if interested in tiny exes: UPX. I ran this over my exe and the result is currently sitting at 5.5K.

Note, though... if an empty app sits at 8K, and my thing ended up at 8K, then there must be some reason for the extra bloat such that adding more functionality doesn't change the exe size.

The trick is this: even though no extra units were included, Delphi includes some anyway! There are two relevant files, System.pas and SysInit.pas, which form the RTL (run-time library). Ever wondered where the default Input/Output console vars come from? The files are set up in there. Ever wonder where the HInstance parameter is set up? In there.

The RTL contains a bunch of crap that I don't need. Unfortunately, this is where I'm sitting at just now. I don't have the VCL source code for Delphi 6, which means that I can't create 'dummy' units for those two with nothing in them. If I try (compiling at the command line using 'dcc32.exe') then it lies, saying it can't find the .pas files (even if I create dummy ones).

I've tried modifying the compiled .dcu units without luck - if I had the VCL source for D6 then I'd be all set, dammit. Oh well - 5.5K is good enough for now .