Sign in Join
Wiki copytemporary

Conditional compilation/fi

Deutsch · English · Français · Suomi · Русский

Mitä on ehdollinen kääntäminen?

Ehdollinen kääntäminen ottaa mukaan tai jättää pois lähdekoodin osia, jos ehto on olemassa tai ei ole.

Useimmissa käännetyissä kielissä tämän mahdollistavia ominaisuuksia kutsutaan käännösaikaiseksi direktiiveiksi. Käännösaikaiset direktiivit mahdollistavat koodin lohkon kääntämisen, joka perustuu ehtojen läsnäoloon tai puuttumiseen käännösaikana. Ne kuuluvat kääntäjän ohjeisiin.

Niitä voidaan käyttää moniin eri tarkoituksiin, kuten:

Free Pascal tukee erilaisia ehdollisen kääntämisen tyylejä:

Huomaa, että tässä syntaksissa ei erotella isoja ja pieniä kirjaimia koska se vastaa Pascal syntaksia. Eli käytetään sekä pieniä että isoja kirjaimia.

Turbo Pascal tyyliset ohjeet

Turbo Pascal -tyyppisiä ohjeita ovat {$DEFINE}, {$IFDEF}, {$ENDIF}, {$IFNDEF}, {$IFOPT}, {$ELSE}, {$ELSEIF} ja {$UNDEF}. Tässä kuvaillaan ohjeita tyylin yhteydessä. Jotkut ohjeet määrittelevät toisella tyylillä laajennetun merkityksen.

Tämä tarkoittaa myöhemmin, että voidaan laajentaa tiettyjen direktiivien merkitystä, kuten esimerkiksi. {$DEFINE} makrojen yhteydessä.

$define

{$DEFINE}-ohje yksinkertaisesti ilmoittaa tunnisteen, jota voidaan myöhemmin käyttää ehdolliseen kääntämiseen:

pascal
{$DEFINE name} // Määrittää tunnisteen nimeltä "name"

Huomaa, että voit myös määrittää tunnisteen komentoriviltä tai IDEstä esimerkiksi -dDEBUG komentorivillä on sama kuin

pascal
{$DEFINE DEBUG}

lähdekoodissa.

$undef

{$UNDEF}direktiivissä määritellään aiemmin määritelty symboli. Tässä on esimerkki, jota voidaan käyttää:

pascal
// Some older source code is polluted with {$IFDEF FPC} that are no 
// longer necessary depending on the Delphi version to which it it should be compatible.
// I always test this by trying this on top of the program or unit:
{$IFDEF FPC}
  {$MODE DELPHI}
  {$UNDEF FPC}
  {$DEFINE VER150} 
  // code will now compile as if it was Delphi 7, provided the original Delphi source code was indeed written for Delphi 7 and up.
{$ENDIF}

$ifdef ja $endif

Yksinkertaisin tapa määrittää ehdollisen koodin lohko on näin:

pascal
unit cross;
{$IFDEF FPC}{$MODE DELPHI}{$ENDIF}

Yllä oleva esimerkki on varsin yleinen lähdekoodissa, joka on koottava sekä Delphissä että Free Pascalissa

Jos kääntäjä on Delphi, niin mitään ei tehdä, mutta jos kääntäjä on Free Pascal, se siirtää Free Pascalin kääntämään ja käyttämään Delphi-tilaa.

Ehdollinen tunniste "FPC" on määritelty järjestelmässä - on olemassa pitkä luettelo niistä. {$IFDEF} ja {$ENDIF} lohkon syntaksi on symmetrinen: jokaisella {$IFDEF}:llä on oma {$ENDIF}.

Vastaavia lohkoja voidaan auttaa tunnistamaan käyttämällä esim. sisennystä, mutta voidaan käyttää myös kommentteja:

pascal
{$IFDEF FPC this part is Free Pascal specific}
// some Free Pascal specific code
{$ENDIF Free Pascal specific code}

Warning: Kommenttiominaisuutta ei usein ymmärretä. Sillä vain yksi ehto hyväksytään {$IFDEF} ehtoon. Kääntäjä olettaa lopun olevan kommenttia.
Alla oleva koodi suorittaa writeln lauseen, jos ja vain jos red on määritelty . Tässä esimerkissä {$ifdef blue} on vain kommenttia! Vaikka määrittely {$define blue} on voimassa.

pascal
// Täysin väärin ymmärretty ohjelma
{$define blue}  
begin
{$ifdef red or $ifdef blue}// kaikki red:n jälkeen on kommenttia
  writeln ('red or blue'); // tätä koodia ei koskaan suoriteta ellei red ole voimassa
{$endif red or blue}       // kaikki $endif:n jälkeen on kommenttia.
end.

$ifndef

Tämä on päinvastainen kuin {$IFDEF} eli koodi sisältyy tiettyyn ehtoon, jota ei ole määritelty. Yksinkertainen esimerkki on:

pascal
{$IFNDEF FPC Tämä osa ei kuulu Free Pascal kääntäjälle}
// jotain erityistä koodia mitä Free Pascal ei käännä
{$ENDIF koodin osa päättyi joka oli vain muille kääntäjille kuin  Free Pascal}

$else ja $elseif

{$ELSE} käytetään kääntämään koodia, joka ei kuulu koodilohkoon, jonka määrittelee vastaava {$IFDEF}. Se on toimii myös {$IFOPT}, {$IF} tai {$IFC} kanssa.

pascal
{$IFDEF red}  
   writeln('Red is defined');  
{$ELSE  no red}  
  {$IFDEF blue}  
   writeln('Blue is defined, but red is not defined');  
  {$ELSE no blue}  
  writeln('Neither red nor blue is defined'); 
  {$ENDIF blue}  
{$ENDIF red}

Tällainen sisäkkäinen ehdolliseen kääntämiseen kirjoitettu koodi käyttäen edellä mainittua syntaksia voi olla hyvin sotkuista ja lukematonta. Onneksi sitä voidaan yksinkertaistaa käyttämällä {$ELSEIF}. Alla on vastaava koodi:

pascal
{$IF Defined(red)}  
  writeln('Red is defined');  
{$ELSEIF Defined(blue)}  
  writeln('Blue is defined');  
{$ELSEIF Defined(green)}  
  writeln('Green is defined');   
{$ELSE}
  writeln('Neither red, blue or green. Must be black...or something else...');
{$ENDIF}

Tämä on paljon luettavampi.

$ifopt

{$IFOPT} -toiminnolla voidaan tarkistaa, onko tietty kääntämisvaihtoehto määritetty.

Programmers manual:

 The ``{$IFOPT switch}`` will compile the text that follows it if the switch switch is currently in the specified state. If it isn’t in      
 the specified state, then compilation continues after the corresponding ``{$ELSE}`` or ``{$ENDIF}`` directive.

Esimerkiksi:

pascal
 {$IFOPT M+}  
   Writeln(???Compiled with type information???);  
 {$ENDIF}

Kääntää Writeln-lauseen vain, jos tyyppitietojen generointi on käytössä. Huomautus: {$IFOPT}-ohje hyväksyyn vain lyhyitä vaihtoehtoja, eli {$IFOPT TYPEINFO} ei hyväksytä.

Yleisesti tätä käytetään kun testataan onko DEBUG tila käytössä:

pascal
{$IFOPT D+}{$NOTE debug-tila on käytössä}{$ENDIF}

Tällaiset määritykset voivat myös sijaita fpc.cfg: n kaltaisissa määritystiedostoissa, jotka sisältävät myös täydellisen selityksen siitä, miten sitä käytetään:

# ----------------------
# Defines (preprocessor)
# ----------------------
#
# nested #IFNDEF, #IFDEF, #ENDIF, #ELSE, #DEFINE, #UNDEF are allowed
#
# -d is the same as #DEFINE
# -u is the same as #UNDEF
#
#
# Some examples (for switches see below, and the -? help pages)
#
# Try compiling with the -dRELEASE or -dDEBUG on the command line
#
# For a release compile with optimizes and strip debug info
#IFDEF RELEASE
  -O2
  -Xs
  #WRITE Compiling Release Version
#ENDIF

Mitä ei saa tehdä

Mitä vikaa tässä koodissa? Voitko havaita sen?

pascal
var
  MyFilesize:
  {$ifdef Win32} 
    Cardinal 
  {$else}
    int64
  {$endif}

Vastaus on:

Tässä ohjelmoija joutui ansaan, joka on yleinen: jos käyttää määritelmää niin pitää varmistaa että sen logiikka on vankka. Muuten tällainen koodi voi helposti aiheuttaa ognelmia. Kääntäjä ei havaitse logiikkavirheitä!

On aina hyvä ymmärtää tällaisia ​​asioita erityisesti ja että tällaiset asiat voidaan helposti korjata.

pascal
var
  MyFilesize:
  {$if defined(Win32)} 
    Cardinal 
  {$elseif defined(Win64)}
    Qword;
  {$else}
     {$error this code is written for win32 or win64}
  {$endif}

Tähän on ratkaisu, joka ei käytä ehtoja lainkaan:

pascal
var
  MyFilesize:NativeUint;

Mitä vikaa tässä koodissa?

pascal
  
{$IFDEF BLUE AND $IFDEF RED} Form1.Color := clYellow; {$ENDIF}
{$IFNDEF RED AND $IFNDEF BLUE} Form1.Color := clAqua; {$ENDIF}

Vastaus on:


From the Free Pascal wiki, page "Conditional compilation/fi", as it stood on 2022-08-06 after a change by Kai Burghardt, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 2, last changed by WikiArchive .

Talk about this page

Nobody has opened a bench for this page yet. Sign in to open one.