Delphi {$IFDEF CONSOLE} Problem
Asked Answered
F

5

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.

Friendship answered 10/7, 2010 at 10:38 Comment(0)
M
10

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

Mother answered 10/7, 2010 at 11:20 Comment(6)
Oh, yes, this is even better. But why in the world isn't this option on by default when you select New/Console Application?!Friendship
@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.Mother
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?Norford
@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).Mother
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.Mother
Oops!, the difference about the theme manifest is not correct, sorry, I have no idea how I lost it!Mother
H
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;
Haver answered 10/7, 2010 at 11:10 Comment(5)
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"?Friendship
Well, I'll just remove the inlining. I can live with a few additional nanoseconds of run-time.Friendship
@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.Haver
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.Friendship
Funny, I tried this in Delphi 7 before I wrote my answer. The code between $ifdef and $endif did not compile.Stockpile
A
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.

Arjan answered 14/1, 2013 at 7:44 Comment(0)
S
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).

Stockpile answered 10/7, 2010 at 10:57 Comment(5)
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...).Friendship
@Andreas Rejbrand: Yes, but at least the Delphi help file does not mention the console as being a pre-defined compiler directive.Stockpile
I would consider docwiki.embarcadero.com/RADStudio/en/Conditional_compilation_(Delphi) as the "Delphi help file".Friendship
@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).Stockpile
+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 (#575411)Haven
Z
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}

Zamudio answered 15/3, 2011 at 14:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.