Conditional compilation/fi: what changed
Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.
| Old | New | Line | |
|---|---|---|---|
| 1 | 1 | ## Mitä on ehdollinen kääntäminen? | |
| 2 | 2 | ||
| 3 | 3 | Ehdollinen kääntäminen ottaa mukaan tai jättää pois [[Source code/fi|lähdekoodin]] osia, jos ehto on olemassa tai ei ole. | |
| 4 | 4 | ||
| 5 | 5 | 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 [[Compile time/fi|käännösaikana]]. Ne kuuluvat [[Compiler directive/fi|kääntäjän ohjeisiin]]. | |
| 6 | 6 | ||
| 7 | 7 | Niitä voidaan käyttää moniin eri tarkoituksiin, kuten: | |
| 8 | 8 | ||
| 9 | 9 | - Alustakohtaisen koodin eristämiseen | |
| 10 | 10 | - Luonnollisen kielenvalintaan | |
| 11 | 11 | - Avoimen- ja suljetun lähdekoodin osien käyttöoikeudet | |
| 12 | 12 | - Eristämään kokeellista (experimental) ohjelmakoodia | |
| 13 | 13 | - [[Compiler|Kääntäjän]] versioihin | |
| 14 | 14 | - Kirjastoversioihin | |
| 15 | 15 | - jne. | |
| 16 | 16 | ||
| 17 | 17 | [[FPC/fi|Free Pascal]] tukee erilaisia ehdollisen kääntämisen tyylejä: | |
| 18 | 18 | ||
| 19 | 19 | - [[Turbo Pascal/fi|Turbo Pascal]] ja varhaiset [[Delphi/fi|Delphi]]-tyyliset ohjeet | |
| 20 | 20 | - [[Mac Pascal]] -tyyliset ohjeet | |
| 21 | 21 | - Uudemmat Free Pascal ja Delphi -tyyliset ohjeet | |
| 22 | 22 | - Käännösaikaiset makrot | |
| 23 | 23 | ||
| 24 | 24 | Huomaa, että tässä syntaksissa ei [[case-sensitive|erotella isoja ja pieniä kirjaimia]] koska se vastaa [[Pascal]] syntaksia. Eli käytetään sekä pieniä että isoja kirjaimia. | |
| 25 | 25 | ||
| 26 | 26 | ## Turbo Pascal tyyliset ohjeet | |
| 27 | 27 | ||
| 28 | 28 | 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. | |
| 29 | 29 | ||
| 30 | 30 | Tämä tarkoittaa myöhemmin, että voidaan laajentaa tiettyjen direktiivien merkitystä, kuten esimerkiksi. `{$DEFINE}` makrojen yhteydessä. | |
| 31 | 31 | ||
| 32 | 32 | ### \$define | |
| 33 | 33 | ||
| 34 | 34 | `{$DEFINE}`-ohje yksinkertaisesti ilmoittaa tunnisteen, jota voidaan myöhemmin käyttää ehdolliseen kääntämiseen: | |
| 35 | 35 | ||
| 36 | 36 | ``` pascal | |
| 37 | 37 | {$DEFINE name} // Määrittää tunnisteen nimeltä "name" | |
| 38 | 38 | ``` | |
| 39 | 39 | ||
| 40 | - | ||
| 40 | + | Huomaa, että voit myös määrittää tunnisteen [[Command-line interface|komentoriviltä]] tai [[IDE/fi|IDEstä]] esimerkiksi -dDEBUG komentorivillä on sama kuin | |
| 41 | 41 | ||
| 42 | 42 | ``` pascal | |
| 43 | 43 | {$DEFINE DEBUG} | |
| 44 | 44 | ``` | |
| 45 | 45 | ||
| 46 | 46 | lähdekoodissa. | |
| 47 | 47 | ||
| 48 | 48 | ### \$undef | |
| 49 | 49 | ||
| 50 | 50 | `{$UNDEF}`direktiivissä määritellään aiemmin määritelty symboli. Tässä on esimerkki, jota voidaan käyttää: | |
| 51 | 51 | ||
| 52 | 52 | ``` pascal | |
| 53 | 53 | // Some older source code is polluted with {$IFDEF FPC} that are no | |
| 54 | 54 | // longer necessary depending on the Delphi version to which it it should be compatible. | |
| 55 | 55 | // I always test this by trying this on top of the program or unit: | |
| 56 | 56 | {$IFDEF FPC} | |
| 57 | 57 | {$MODE DELPHI} | |
| 58 | 58 | {$UNDEF FPC} | |
| 59 | 59 | {$DEFINE VER150} | |
| 60 | 60 | // code will now compile as if it was Delphi 7, provided the original Delphi source code was indeed written for Delphi 7 and up. | |
| 61 | 61 | {$ENDIF} | |
| 62 | 62 | ``` | |
| 63 | 63 | ||
| 64 | 64 | ### \$ifdef ja \$endif | |
| 65 | 65 | ||
| 66 | 66 | Yksinkertaisin tapa määrittää ehdollisen koodin lohko on näin: | |
| 67 | 67 | ||
| 68 | 68 | ``` pascal | |
| 69 | 69 | unit cross; | |
| 70 | 70 | {$IFDEF FPC}{$MODE DELPHI}{$ENDIF} | |
| 71 | 71 | ``` | |
| 72 | 72 | ||
| 73 | 73 | Yllä oleva esimerkki on varsin yleinen lähdekoodissa, joka on koottava sekä Delphissä että Free Pascalissa | |
| 74 | 74 | ||
| 75 | 75 | 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 [[Mode Delphi/fi|Delphi-tilaa]]. | |
| 76 | 76 | ||
| 77 | 77 | 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}`. | |
| 78 | 78 | ||
| 79 | 79 | Vastaavia lohkoja voidaan auttaa tunnistamaan käyttämällä esim. sisennystä, mutta voidaan käyttää myös [[Comments/fi|kommentteja]]: | |
| 80 | 80 | ||
| 81 | 81 | ``` pascal | |
| 82 | 82 | {$IFDEF FPC this part is Free Pascal specific} | |
| 83 | 83 | // some Free Pascal specific code | |
| 84 | 84 | {$ENDIF Free Pascal specific code} | |
| 85 | 85 | ``` | |
| 86 | 86 | ||
| 87 | 87 | > **Warning:** Kommenttiominaisuutta ei usein ymmärretä. Sillä vain yksi ehto hyväksytään `{$IFDEF}` ehtoon. Kääntäjä olettaa lopun olevan kommenttia.\ | |
| 88 | - | ||
| 88 | + | > Alla oleva koodi suorittaa [[Writeln/fi|writeln]] [[statement/fi|lauseen]], jos ja vain jos red on määritelty . Tässä esimerkissä `{$ifdef blue}` on vain kommenttia! Vaikka määrittely `{$define blue}` on voimassa. | |
| 89 | 89 | ||
| 90 | 90 | ``` pascal | |
| 91 | 91 | // Täysin väärin ymmärretty ohjelma | |
| 92 | 92 | {$define blue} | |
| 93 | 93 | begin | |
| 94 | 94 | {$ifdef red or $ifdef blue}// kaikki red:n jälkeen on kommenttia | |
| 95 | 95 | writeln ('red or blue'); // tätä koodia ei koskaan suoriteta ellei red ole voimassa | |
| 96 | 96 | {$endif red or blue} // kaikki $endif:n jälkeen on kommenttia. | |
| 97 | 97 | end. | |
| 98 | 98 | ``` | |
| 99 | 99 | ||
| 100 | 100 | ### \$ifndef | |
| 101 | 101 | ||
| 102 | - | ||
| 102 | + | Tämä on päinvastainen kuin `{$IFDEF}` eli koodi sisältyy tiettyyn ehtoon, jota ei ole määritelty. Yksinkertainen esimerkki on: | |
| 103 | 103 | ||
| 104 | 104 | ``` pascal | |
| 105 | 105 | {$IFNDEF FPC Tämä osa ei kuulu Free Pascal kääntäjälle} | |
| 106 | 106 | // jotain erityistä koodia mitä Free Pascal ei käännä | |
| 107 | 107 | {$ENDIF koodin osa päättyi joka oli vain muille kääntäjille kuin Free Pascal} | |
| 108 | 108 | ``` | |
| 109 | 109 | ||
| 110 | 110 | ### \$else ja \$elseif | |
| 111 | 111 | ||
| 112 | 112 | `{$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. | |
| 113 | 113 | ||
| 114 | 114 | ``` pascal | |
| 115 | 115 | {$IFDEF red} | |
| 116 | 116 | writeln('Red is defined'); | |
| 117 | 117 | {$ELSE no red} | |
| 118 | 118 | {$IFDEF blue} | |
| 119 | 119 | writeln('Blue is defined, but red is not defined'); | |
| 120 | 120 | {$ELSE no blue} | |
| 121 | 121 | writeln('Neither red nor blue is defined'); | |
| 122 | 122 | {$ENDIF blue} | |
| 123 | 123 | {$ENDIF red} | |
| 124 | 124 | ``` | |
| 125 | 125 | ||
| 126 | 126 | 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: | |
| 127 | 127 | ||
| 128 | 128 | ``` pascal | |
| 129 | 129 | {$IF Defined(red)} | |
| 130 | 130 | writeln('Red is defined'); | |
| 131 | 131 | {$ELSEIF Defined(blue)} | |
| 132 | 132 | writeln('Blue is defined'); | |
| 133 | 133 | {$ELSEIF Defined(green)} | |
| 134 | 134 | writeln('Green is defined'); | |
| 135 | 135 | {$ELSE} | |
| 136 | 136 | writeln('Neither red, blue or green. Must be black...or something else...'); | |
| 137 | 137 | {$ENDIF} | |
| 138 | 138 | ``` | |
| 139 | 139 | ||
| 140 | 140 | Tämä on paljon luettavampi. | |
| 141 | 141 | ||
| 142 | 142 | ### \$ifopt | |
| 143 | 143 | ||
| 144 | 144 | `{$IFOPT}` -toiminnolla voidaan tarkistaa, onko tietty kääntämisvaihtoehto määritetty. | |
| 145 | 145 | ||
| 146 | 146 | Programmers manual: | |
| 147 | 147 | ||
| 148 | 148 | ` 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 `\ | |
| 149 | 149 | ` the specified state, then compilation continues after the corresponding ``{$ELSE}`` or ``{$ENDIF}`` directive.` | |
| 150 | 150 | ||
| 151 | 151 | Esimerkiksi: | |
| 152 | 152 | ||
| 153 | 153 | ``` pascal | |
| 154 | 154 | {$IFOPT M+} | |
| 155 | 155 | Writeln(’Compiled with type information’); | |
| 156 | 156 | {$ENDIF} | |
| 157 | 157 | ``` | |
| 158 | 158 | ||
| 159 | 159 | 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ä. | |
| 160 | 160 | ||
| 161 | 161 | Yleisesti tätä käytetään kun testataan onko DEBUG tila käytössä: | |
| 162 | 162 | ||
| 163 | 163 | ``` pascal | |
| 164 | 164 | {$IFOPT D+}{$NOTE debug-tila on käytössä}{$ENDIF} | |
| 165 | 165 | ``` | |
| 166 | 166 | ||
| 167 | 167 | 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: | |
| 168 | 168 | ||
| 169 | 169 | `# ----------------------`\ | |
| 170 | 170 | `# Defines (preprocessor)`\ | |
| 171 | 171 | `# ----------------------`\ | |
| 172 | 172 | `#`\ | |
| 173 | 173 | `# nested #IFNDEF, #IFDEF, #ENDIF, #ELSE, #DEFINE, #UNDEF are allowed`\ | |
| 174 | 174 | `#`\ | |
| 175 | 175 | `# -d is the same as #DEFINE`\ | |
| 176 | 176 | `# -u is the same as #UNDEF`\ | |
| 177 | 177 | `#`\ | |
| 178 | 178 | `#`\ | |
| 179 | 179 | `# Some examples (for switches see below, and the -? help pages)`\ | |
| 180 | 180 | `#`\ | |
| 181 | 181 | `# Try compiling with the -dRELEASE or -dDEBUG on the command line`\ | |
| 182 | 182 | `#`\ | |
| 183 | 183 | `# For a release compile with optimizes and strip debug info`\ | |
| 184 | 184 | `#IFDEF RELEASE`\ | |
| 185 | 185 | ` -O2`\ | |
| 186 | 186 | ` -Xs`\ | |
| 187 | 187 | ` #WRITE Compiling Release Version`\ | |
| 188 | 188 | `#ENDIF` | |
| 189 | 189 | ||
| 190 | 190 | ## Mitä ei saa tehdä | |
| 191 | 191 | ||
| 192 | 192 | Mitä vikaa tässä koodissa? Voitko havaita sen? | |
| 193 | 193 | ||
| 194 | 194 | ``` pascal | |
| 195 | 195 | var | |
| 196 | 196 | MyFilesize: | |
| 197 | 197 | {$ifdef Win32} | |
| 198 | 198 | Cardinal | |
| 199 | 199 | {$else} | |
| 200 | 200 | int64 | |
| 201 | 201 | {$endif} | |
| 202 | 202 | ``` | |
| 203 | 203 | ||
| 204 | 204 | Vastaus on: | |
| 205 | 205 | ||
| 206 | 206 | - että Free Pascal kääntää enemmän CPU-tyyppejä kuin [[32 bit/fi|32-]] ja [[64 bit/fi|64-bittisiä]], myös [[8 bit/fi|8-]] ja [[16 bit/fi|16-bittisiä]]. | |
| 207 | 207 | - useimmilla 64-bittisillä alustoilla suurin tiedostokoko on [[QWord/fi|QWord]] ei [[Int64/fi|Int64]]. | |
| 208 | 208 | ||
| 209 | 209 | 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ä! | |
| 210 | 210 | ||
| 211 | 211 | On aina hyvä ymmärtää tällaisia asioita erityisesti ja että tällaiset asiat voidaan helposti korjata. | |
| 212 | 212 | ||
| 213 | 213 | ``` pascal | |
| 214 | 214 | var | |
| 215 | 215 | MyFilesize: | |
| 216 | 216 | {$if defined(Win32)} | |
| 217 | 217 | Cardinal | |
| 218 | 218 | {$elseif defined(Win64)} | |
| 219 | 219 | Qword; | |
| 220 | 220 | {$else} | |
| 221 | 221 | {$error this code is written for win32 or win64} | |
| 222 | 222 | {$endif} | |
| 223 | 223 | ``` | |
| 224 | 224 | ||
| 225 | 225 | Tähän on ratkaisu, joka ei käytä ehtoja lainkaan: | |
| 226 | 226 | ||
| 227 | 227 | ``` pascal | |
| 228 | 228 | var | |
| 229 | 229 | MyFilesize:NativeUint; | |
| 230 | 230 | ``` | |
| 231 | 231 | ||
| 232 | 232 | Mitä vikaa tässä koodissa? | |
| 233 | 233 | ||
| 234 | 234 | ``` pascal | |
| 235 | 235 | ||
| 236 | 236 | {$IFDEF BLUE AND $IFDEF RED} Form1.Color := clYellow; {$ENDIF} | |
| 237 | 237 | {$IFNDEF RED AND $IFNDEF BLUE} Form1.Color := clAqua; {$ENDIF} | |
| 238 | 238 | ``` | |
| 239 | 239 | ||
| 240 | 240 | Vastaus on: | |
| 241 | 241 | ||
| 242 | 242 | - Katso kohtaa missä kerrottiin **kommenteista** ja varoitettiin niistä | |
| 243 | 243 | - Kääntäjän ohjeet siis ohjaavat käännöstä. | |
| 244 | 244 | ||
| 245 | 245 | --- | |
| 246 | 246 | *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](/wiki-contact).* |
