12

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.

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384

5 Answers5

10

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

Sertac Akyuz
  • 54,131
  • 4
  • 102
  • 169
  • 3
    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 Jul 10 '10 at 11:22
  • 2
    @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 Jul 10 '10 at 11:28
  • 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 Jul 12 '10 at 15:23
  • @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 Jul 12 '10 at 19:22
  • 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 Jul 12 '10 at 19:26
  • Oops!, the difference about the theme manifest is not correct, sorry, I have no idea how I lost it! – Sertac Akyuz Jul 12 '10 at 22:38
4

BTW according to http://docwiki.embarcadero.com/RADStudio/XE3/en/Conditional_compilation_(Delphi) now "CONSOLE" conditional symbol is predefined while compiling console application, so {$IFDEF CONSOLE} will work at least for XE2 and XE3.

There is no such information for XE and older versions.

vladon
  • 8,158
  • 2
  • 47
  • 91
4

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;
kludg
  • 27,213
  • 5
  • 67
  • 118
  • 1
    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 Jul 10 '10 at 11:14
  • Well, I'll just remove the inlining. I can live with a few additional nanoseconds of run-time. – Andreas Rejbrand Jul 10 '10 at 11:17
  • @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. – kludg Jul 10 '10 at 11:20
  • 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 Jul 10 '10 at 11:26
  • Funny, I tried this in Delphi 7 before I wrote my answer. The code between $ifdef and $endif did not compile. – Edelcom Jul 11 '10 at 07:02
3

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
  • 5,038
  • 8
  • 44
  • 61
  • 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 Jul 10 '10 at 10:58
  • 1
    @Andreas Rejbrand: Yes, but at least the Delphi help file does not mention the console as being a pre-defined compiler directive. – Edelcom Jul 10 '10 at 11:01
  • 1
    I would consider docwiki.embarcadero.com/RADStudio/en/Conditional_compilation_(Delphi) as the "Delphi help file". – Andreas Rejbrand Jul 10 '10 at 11:02
  • @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 Jul 10 '10 at 11:05
  • +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 Wiert Pluimers Jul 11 '10 at 15:07
2

easier solution:

program YourProgram;
{$DEFINE MakeConsoleApp}
{$IFDEF MakeConsoleApp}
  {$APPTYPE CONSOLE}
{$ENDIF}



[....]
{$IFDEF MakeConsoleApp} WriteLn('Text in a Console'); {$ENDIF}

so anytime you want to make you application not show a console you would just change {$DEFINE MakeConsoleApp} to { } or {.$DEFINE MakeConsoleApp}

tndza
  • 21
  • 1