Diretivas de compilação no Delphi

Olá, leitores!

Neste artigo iremos abordar o uso de diretivas de compilação com Delphi e também veremos vários exemplos do seu uso.

📥 Repositório com exemplos

O projeto de exemplo, pode ser encontrado e baixado em nosso GitHub no seguinte link: https://github.com/Code4Delphi/diretivas-de-compilacao-delphi

▶️ Vídeo de demonstração

🚀 O QUE SÃO DIRETIVAS DE COMPILAÇÃO

Uma diretiva de compilação é um comentário com uma sintaxe especial. A diretiva de compilação começa com um $ (sinal de dólar) como o primeiro caractere após o delimitador de comentário de abertura, imediatamente seguido por um nome (uma ou mais letras) que designa a diretiva específica. Você pode incluir comentários após a diretiva e quaisquer parâmetros necessários.

As diretivas de compilação podem ser colocadas onde quer que os comentários sejam permitidos. Exemplos de diretivas:

{$hints off}  
(*$hints off*)

DEFINIR/INDEFINIR

  • CRIAR/DEFINIR UMA DIRETIVA
  {$DEFINE NAME_DIRECTIVE_TEST}
  • DESATIVAR/INDEFINIR UMA DIRETIVA
  {$UNDEF NAME_DIRECTIVE_TEST}

CONDIÇÕES IF, ELSEIF E ELSE

  • IF e ELSE PARA TESTAR SE A DIRETIVA ESTA DEFINIDA
  {$IFDEF NAME_DIRECTIVE_TEST}
    Memo1.Lines.Add('Diretiva NAME_DIRECTIVE_TEST está definida');
  {$ELSE}
    Memo1.Lines.Add('Diretiva NAME_DIRECTIVE_TEST NÃO está definida');
  {$ENDIF}
  • IF, ELSEIF e ELSE
  {$DEFINE VALOR_02}
  {$IFDEF VALOR_01}
    Memo1.Lines.Add('Diretiva VALOR_01 definida');
  {$ELSEIF DEFINED(VALOR_02)}
    Memo1.Lines.Add('Diretiva VALOR_02 definida');
  {$ELSEIF DEFINED(VALOR_03)}
    Memo1.Lines.Add('Diretiva VALOR_03 definida');
  {$ELSE}
    Memo1.Lines.Add('Diretivas VALOR_01, VALOR_02 E VALOR_03 não estão definidas');
  {$ENDIF}
  • IF com NOT
  {$IF NOT DEFINED(DIRETIVA_NOT)}
    Memo1.Lines.Add('Diretiva DIRETIVA_NOT não definida');
  {$ELSE}
    Memo1.Lines.Add('Diretiva DIRETIVA_NOT definida');
  {$ENDIF}

CONSTANTES

  • Verificar o valor de uma constantes
procedure TViewMain.btnComContantesClick(Sender: TObject);
const
  VERSAO = 6.8;
begin
  {$IF VERSAO <= 5}
    Memo1.Lines.Add('Valor da constante VERSAO é menor ou igual 5');
  {$ELSEIF (VERSAO > 5) AND (VERSAO <= 10)}
    Memo1.Lines.Add('Valor da constante VERSAO é maior que 5 e menor que 10');
  {$ELSE}
    Memo1.Lines.Add('Valor da constante VERSAO é maior que 10');
  {$IFEND}
end;
  • Verificar o valor de uma constantes Integer
procedure TViewMain.btnComContantesIntegerClick(Sender: TObject);
const
  TEST_INTEGER: Integer = 3;
begin
  {$IF SizeOf(TEST_INTEGER) <= 5}
  Memo1.Lines.Add('Valor da constante TEST_INTEGER é menor ou igual 5');
  {$ELSE}
  Memo1.Lines.Add('Valor da constante TEST_INTEGER é maior que 5');
  {$IFEND}
end;
  • Permitir a alteração do valor de constantes
procedure TViewMain.btnAlterarValorConstantesClick(Sender: TObject);
//NAO PERMITE ALTERAR CONSTANTES (E O PADRAO DA IDE) : {$J-} OU {$WRITEABLECONST OFF}
{$J-}

//PERMITE ALTERAR CONSTANTES : {$J+} OU {$WRITEABLECONST ON}
{$WRITEABLECONST ON}
const
  MINHA_CONST: Integer = 2023;
begin
  Memo1.Lines.Add('Valor da constante é: ' + MINHA_CONST.ToString);
  MINHA_CONST := 2024;
  Memo1.Lines.Add('Valor constante após alteração é: ' + MINHA_CONST.ToString);
end;
  • Ao definir um valor de constante
procedure TViewMain.btnAoDefinirValorDeConstantesClick(Sender: TObject);
const
  {$IFDEF DEBUG}
    DEBUG_OR_RELEASE = 'Debug';
  {$ELSE}
    DEBUG_OR_RELEASE = 'Release';
  {$ENDIF}
begin
  Memo1.Lines.Add('A IDE esta em modo: ' + DEBUG_OR_RELEASE);
end;

MESSAGES

  • Gerar Messages ao compilar ou dar build no projeto (as mensagens geradas sao exibidas nas abas “Build” e “Output”)
  //EMITS A HINT
  {$MESSAGE 'Meu Hint teste ao compilar'}

  //EMITS A HINT
  {$MESSAGE Hint 'Mais um Hint ao compilar'}

  //EMITS A WARNING
  {$MESSAGE Warn 'Meu Warning teste ao compilar.'}

  //EMITS AN ERROR, CONTINUES COMPILING
  {$Message Error 'Exibe mensagem de erro, e não permite a continuação da compilação'}

  //EMITS AN ERROR, TERMINATES COMPILER
  {$Message Fatal 'Exibe mensagem de terminate, e não permite a continuação da compilação'}

SISTEMAS OPERACIONAIS

  • Verificar qual o Sistema Operacional
procedure TViewMain.btnSOClick(Sender: TObject);
var
  LSO: string;
begin
  {$IF LINUX}
    LSO := 'LINUX';
  {$ELSEIF DEFINED(MSWINDOWS)}
    LSO := 'MSWINDOWS';
  {$ELSEIF DEFINED(ANDROID)}
    LSO := 'ANDROID';
  {$ELSEIF DEFINED(IOS)}
    LSO := 'IOS';
  {$ELSEIF DEFINED(MACOS)}
    LSO := 'MACOS';
  {$ELSEIF DEFINED(POSIX)}
    LSO := 'POSIX';
  {$ELSE}
    LSO := 'Não encontrada';
  {$ENDIF}

  Memo1.Lines.Add('Sistema operacional selecionado: ' + LSO);
end;

DEBUG OU RELEASE

  • Verificar se IDE está em Debug ou Release
procedure TViewMain.btnIdeEmDebugOuReleaseClick(Sender: TObject);
begin
  {$IFDEF DEBUG}
    Memo1.Lines.Add('Modo de Debug');
  {$ELSEIF DEFINED(RELEASE)}
    Memo1.Lines.Add('Modo de Release');
  {$ELSE}
    Memo1.Lines.Add('Modo diferente de Debug e Release');
  {$ENDIF}
end;

PLATAFORMAS

  • Verificar qual a Plataforma
procedure TViewMain.btnPlataformasClick(Sender: TObject);
var
  LPlataforma: string;
begin
  {$IFDEF CONSOLE}
    LPlataforma := 'CONSOLE';
  {$ELSEIF DEFINED(WIN32)}
    LPlataforma := 'WIN32';
  {$ELSEIF DEFINED(WIN64)}
    LPlataforma := 'WIN64';
  {$ELSEIF DEFINED(LINUX32)}
    LPlataforma := 'LINUX32';
  {$ELSEIF DEFINED(LINUX64)}
    LPlataforma := 'LINUX64';
  {$ELSEIF DEFINED(ANDROID32)}
    LPlataforma := 'ANDROID32';
  {$ELSEIF DEFINED(ANDROID64)}
    LPlataforma := 'ANDROID64';
  {$ELSEIF DEFINED(IOS64)}
    LPlataforma := 'IOS64';
  {$ELSEIF DEFINED(MACOS32)}
    LPlataforma := 'MACOS32';
  {$ELSEIF DEFINED(MACOS64)}
    LPlataforma := 'MACOS64';
  {$ELSE}
    LPlataforma := 'Não encontrada';
  {$ENDIF}

  Memo1.Lines.Add('Plataforma atual: ' + LPlataforma);
end;

FRAMEWORK

  • Verificar qual o Framework (VCL ou FMX)
procedure TViewMain.btnVclOuFmxClick(Sender: TObject);
var
  LFramework: string;
begin
  //AS SEGUINTES CONDICIONAIS ESTÃO DISPONÍVEIS A PARTIR DO RAD STUDIO 11.1 Alexandria, Release 1
  //FRAMEWORK_VCL : Definido se o projeto usa o framework VCL
  //FRAMEWORK_FMX : Definido se o projeto usa o framework FMX

  //PARA VERSOES ANTERIORES AO 11.1 Alexandria, PODE SER DEFIDA MANUALMENTE. EXEMPLO:
  {$IF CompilerVersion < 35.0)}
    {$DEFINE FRAMEWORK_VCL}
  {$ENDIF}

  {$IFDEF FRAMEWORK_VCL}
    LFramework := 'VCL';
  {$ELSEIF DEFINED(FRAMEWORK_FMX)}
    LFramework := 'FMX';
  {$ELSE}
    LFramework := 'Não encontrado';
  {$ENDIF}

  Memo1.Lines.Add('Plataforma atual: ' + LFramework);
end;

VERSÃO DO DELPHI

  • Verificar qual a versão do Delphi (VERXX)
procedure TViewMain.btnVersaoDelphiVERXXClick(Sender: TObject);
var
  LNomeVersao: string;
begin
  {$IFDEF VER300}
    LNomeVersao := 'Delphi 10 Seattle (VER300)';
  {$ELSEIF DEFINED(VER310)}
    LNomeVersao := 'Delphi 10.1 Berlin (VER310)';
  {$ELSEIF DEFINED(VER320)}
    LNomeVersao := 'Delphi 10.2 Tokyo (VER320)';
  {$ELSEIF DEFINED(VER330)}
    LNomeVersao := 'Delphi 10.3 Rio (VER330)';
  {$ELSEIF DEFINED(VER340)}
    LNomeVersao := 'Delphi 10.4 Sydney (VER340)';
  {$ELSEIF DEFINED(VER350)}
    LNomeVersao := 'Delphi 11.0 Alexandria (VER350)';
  {$ELSEIF DEFINED(VER360)}
    LNomeVersao := 'Delphi 12.0 Athens (VER360)';
  {$ELSE}
    LNomeVersao := 'Versão ANTERIOR a Delphi 10 Seattle ' + sLineBreak + 'Sua versão é a: ' + CompilerVersion.ToString;
  {$ENDIF}

  Memo1.Lines.Add('A versão do seu Delphi é a: ' + LNomeVersao);
end;
  • Verificar qual a versão Delphi (CompilerVersion)
procedure TViewMain.btnVersaoDelphiCompilerVersionClick(Sender: TObject);
var
  LNomeVersao: string;
begin
  {$IF CompilerVersion = 30.0}
    LNomeVersao := 'Delphi 10 Seattle';
  {$ELSEIF CompilerVersion = 31.0)}
    LNomeVersao := 'Delphi 10.1 Berlin';
  {$ELSEIF CompilerVersion = 32.0)}
    LNomeVersao := 'Delphi 10.2 Tokyo';
  {$ELSEIF CompilerVersion = 33.0)}
    LNomeVersao := 'Delphi 10.3 Rio';
  {$ELSEIF CompilerVersion = 34.0)}
    LNomeVersao := 'Delphi 10.4 Sydney';
  {$ELSEIF CompilerVersion = 35.0)}
    LNomeVersao := 'Delphi 11.0 Alexandria';
  {$ELSEIF CompilerVersion = 36.0)}
    LNomeVersao := 'Delphi 12.0 Athens';
  {$ELSEIF CompilerVersion >= 37.0)}
    LNomeVersao := 'Delphi maior ou igual a 37.0';
  {$ELSE}
    LNomeVersao := 'Versão ANTERIOR a Delphi 10 Seattle';
  {$ENDIF}
  Memo1.Lines.Add('A versão do seu Delphi é a: ' + LNomeVersao + ' - Número da CompilerVersion: ' + CompilerVersion.ToString);

  if(CompilerVersion = 33)then
    Memo1.Lines.Add('Function CompilerVersion = 33. Versão do seu delphi é 10.3 Rio')
  else
    Memo1.Lines.Add('Function CompilerVersion = ' + CompilerVersion.ToString);
end;
  • Verificar qual a versão Delphi (RTLVersion)
procedure TViewMain.btnVersaoDelphiRTLVersionClick(Sender: TObject);
var
  LNomeVersao: string;
begin
  {$IF RTLVersion = 30.0}
    LNomeVersao := 'Delphi 10 Seattle';
  {$ELSEIF RTLVersion = 31.0)}
    LNomeVersao := 'Delphi 10.1 Berlin';
  {$ELSEIF RTLVersion = 32.0)}
    LNomeVersao := 'Delphi 10.2 Tokyo';
  {$ELSEIF RTLVersion = 33.0)}
    LNomeVersao := 'Delphi 10.3 Rio';
  {$ELSEIF RTLVersion = 34.0)}
    LNomeVersao := 'Delphi 10.4 Sydney';
  {$ELSEIF RTLVersion = 35.0)}
    LNomeVersao := 'Delphi 11.0 Alexandria';
  {$ELSEIF RTLVersion = 36.0)}
    LNomeVersao := 'Delphi 12.0 Athens';
  {$ELSEIF RTLVersion >= 37.0)}
    LNomeVersao := 'Delphi maior ou igual a 37.0';
  {$ELSE}
    LNomeVersao := 'Versão ANTERIOR a Delphi 10 Seattle';
  {$ENDIF}

  Memo1.Lines.Add('A versão do seu Delphi é a: ' + LNomeVersao + ' - Número da RTLVersion: ' + FloatToStr(RTLVersion));
end;

SCOPEDENUMS

  • No estado {$SCOPEDENUMS ON}, as enumerações têm escopo e os valores de enum não são adicionados ao escopo global
  {$SCOPEDENUMS ON}
  TAssinado = (Sim, Nao);
  TEnviado = (Sim, Nao);
  {$SCOPEDENUMS OFF}

HINTS

  • Desabilita Hints ao compilar, ou seja, não será exibido nenhum Hints a partir do ponto que a diretiva estiver, a não ser que exista a diretiva {$HINTS ON} no mesmo escopo
  {$HINTS OFF}
  • Habilitar Hints ao compilar
  {$HINTS ON}

WARNINGS

  • Desabilitar Warnings ao compilar, ou seja, não será exibido nenhum Warning a partir do ponto que a diretiva estiver
  {$WARNINGS OFF}
  • Habilitar Warnings ao compilar
  {$WARNINGS ON}

WARNING MESSAGES

  • Estas diretivas dão um controle sobre mensagens de avisos (warnings) individuais

Sintaxe:
   {$WARN identifier ON | OFF | ERROR | DEFAULT}
   {$WARN identifier ON} Permite que o compilador exiba o aviso especificado pelo identificador
   {$WARN identifier OFF} O aviso especificado não é exibido
   {$WARN identifier ERROR} O aviso especificado é tratado como erro
   {$WARN identifier DEFAULT} Usa as configurações padrão da caixa de diálogo Opções do Projeto

Exemplos:

  //HABILITA OS WARNINGS DO TIPO SYMBOL_EXPERIMENTAL
  {$WARN SYMBOL_EXPERIMENTAL ON}

  //DESABILITA OS WARNINGS DO TIPO SYMBOL_EXPERIMENTAL
  {$WARN SYMBOL_EXPERIMENTAL OFF}

  //TRANSFORMA OS WARINGS TIPO SYMBOL_EXPERIMENTAL EM ERROS
  {$WARN SYMBOL_EXPERIMENTAL ERROR}

Lista completa: 

https://docwiki.embarcadero.com/RADStudio/Athens/en/Warning_messages_(Delphi)

 

💡 Dica:

A partir da versão 10.3 do Delphi, se você usar um custom attribute que não for conhecido pelo compilador (porque você o digitou incorretamente ou uma unidade estiver faltando na instrução uses), você irá receber um Warning:

Warning: W1074 Unknown custom attribute

É recomendado transformar esse Warning em um erro, para que seja obrigatório a correção, para isso insira:

{$WARN UNKNOWN_CUSTOM_ATTRIBUTE ERROR}

REGION

  • Controla a exibição de regiões recolhíveis
{$REGION 'Minha região'}
procedure ExibirMsgTeste;
begin
  ShowMessage('Minha mensagem de teste');
end;
{$ENDREGION}

ARQUIVOS .inc

  • Incluí um arquivo .inc onde podem ser inseridas diversas diretivas de compilação. (normalmente declarado logo após o nome da unit)

Sintaxe:
   {$I arquivo.inc} OU {$INCLUDE arquivo.inc};

Exemplos:

{$I C4D.inc}
{$INCLUDE Includes\arquivo_inc_teste.inc}

O arquivo com nome “arquivo_inc_teste.inc” está dentro de um diretório com o nome “Includes”. E nesse arquivo pode-se colocar diversas diretivas de compilação como por exemplo:

{$DEFINE DIRETIVA_TESTE}

{$IF CompilerVersion < 35.0)}
  {$DEFINE DIRETIVA_TESTE_35}
{$ENDIF}

USANDO O IDE

  • Você pode definir muitas das diretivas de compilação na caixa de diálogo da IDE em Project > Options > Delphi Compiler > Conditional defines. Essas diretivas afetam todas as unidades sempre que seu código-fonte é recompilado.

  • Se você estiver trabalhando no Editor de Código e quiser uma maneira rápida de ver as diretivas de compilação em vigor, pressione Ctrl + O + O. As configurações atuais das diretivas são inseridas em uma linha horizontal no topo do seu arquivo, junto com outras configurações atuais, como avisos do compilador (as configurações da diretiva $WARN). Essas listas são adicionadas ao início do seu arquivo de origem, a menos que você desfaça (Ctrl + Z) ou exclua manualmente a lista: 

🔗 LINKS ÚTEIS

 

Não esqueça de deixar seu comentário com dúvidas, dicas ou sugestões.

Abraços!