views:

177

answers:

3

I just tried

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

begin
  {$IFDEF CONSOLE}
    beep;
  {$ENDIF}
end.

and expected to hear a beep during runtime, but not. The following test works, though:

  if IsConsole then
    beep;

Why doesn't the compile-time test work? As far as I can understand from this doc, it sure should work.

+1  A: 

The $APPTYPE directive controls whether to generate a Win32 console or graphical UI application, it is NOT a compiler directive.

{$ifdef} tests for user defined compiler directives set by {$define name} statements. As in

{$define KeepDlibTempFiles}

In stead the 'IsConsole' can be used (as you already found out).

Edelcom
I disagree. $IFDEF test for user-defined directives *in addition to* predefined ones (see for instance delphibasics.co.uk/RTL.asp?Name=$IfDef), and CONSOLE is supposed to be one of those, as per docwiki.embarcadero.com/RADStudio/en/Conditional_compilation_(Delphi) In addition, I **want** to do the check at compile-time (conditional compiling), not at runtime (which almost always is a waste of time, since a console app rather seldom changes itself to a GUI app during runtime...).
Andreas Rejbrand
@Andreas Rejbrand: Yes, but at least the Delphi help file does not mention the console as being a pre-defined compiler directive.
Edelcom
@Edelcom: I would consider docwiki.embarcadero.com/RADStudio/en/Conditional_compilation_(Delphi) as the "Delphi help file".
Andreas Rejbrand
@Andreas Rejbrand: So would I , but it wouldn't be the first error found in an help file (and it wont be the last one either).
Edelcom
+1: {$APPTYPE CONSOLE} is different from {$DEFINE CONSOLE} in the sameway that {$APPTYPE GUI} will not introduce the GUI define. It tells the linker what kind of PE flags should be in the .EXE header (http://stackoverflow.com/questions/574911/difference-between-windows-and-console-application)
Jeroen Pluimers
+2  A: 

It does not work in *.dpr file, but it is OK in a unit (call MakeBeep from console *.dpr):

unit Unit1;

interface

uses
  SysUtils;

procedure MakeBeep;

implementation

procedure MakeBeep;
begin
  {$IFDEF CONSOLE}
    beep;
  {$ENDIF}
end;
Serg
Quite true; it works. But given that most (small) Delphi console applications are written directly in the *.dpr file, it is rather bad that the test doesn't work there. Well, in the *.dpr file you probably know what apptype it is, but in my case I happened to have the conditional compiling in an inlined procedure in a different unit, which apparently amounts to the same thing as far as the compiler directive goes. Is this documented, or should we call it a "bug"?
Andreas Rejbrand
Well, I'll just remove the inlining. I can live with a few additional nanoseconds of run-time.
Andreas Rejbrand
@Andreas Rejbrand - I don't think it is documented. And I don't know what the compiler developers think about it - is it a bug or a feature.
Serg
Sorry I removed the "accepted answer" flag from your very good answer, but the answer by Sertac is slightly better. I would like to mark both as accepted.
Andreas Rejbrand
@serg: Funny, I tried this in Delphi 7 before I wrote my answer. The code between $ifdef and $endif did not compile.
Edelcom
+8  A: 

If you select "Generate console application" from the linker options, 'CONSOLE' is defined.

Sertac Akyuz
Oh, yes, this is even better. But why in the world isn't this option on by default when you select New/Console Application?!
Andreas Rejbrand
@Andreas - It is different from `$APPTYPE CONSOLE`, you can also select the linker option for a GUI application and redirect I/O to a console window.
Sertac Akyuz
Sertac, I don't understand your comment. How does the compiler directive differ from the IDE option, except that the latter apparently defines CONSOLE automatically? Either one sets the PE header indicating the subsystem to use, right? Andreas, is there anything to stop you from manually adding CONSOLE to the list of defined symbols in the compiler options?
Rob Kennedy
@Rob - Either one sets the subsystem to console, the difference as I see it, in the 'linker option' case, Delphi still generates the code necessary for a GUI application, hence you may have the 'Application' etc.. I think it would be more meaningful to look the difference of a GUI application without the linker option and a GUI application with the option. When the option is selected, I/O is directed to the Win32 console, and for a reason I don't know the theme manifest is not included. Apart from these, despite the subsystem flag, the latter behaves like a GUI application (with a console).
Sertac Akyuz
Of course my answer or any of my comments do not explain why CONSOLE is not defined in the .dpr (see Serg's answer) for a console application. I only commented on why the linker option is not automatically set.
Sertac Akyuz
Oops!, the difference about the theme manifest is not correct, sorry, I have no idea how I lost it!
Sertac Akyuz