root/trunk/docsrc/version.dd

Revision 2147, 14.1 kB (checked in by walter, 2 years ago)

bugzilla 2994 Incomplete 'Predefined Versions' documentation

  • Property svn:eol-style set to native
Line 
1 Ddoc
2
3 $(SPEC_S Conditional Compilation,
4
5     $(P $(I Conditional compilation) is the process of selecting which
6     code to compile and which code to not compile.
7     (In C and C++, conditional compilation is done with the preprocessor
8     directives $(CODE #if) / $(CODE #else) / $(CODE #endif).)
9     )
10
11 $(GRAMMAR
12 $(GNAME ConditionalDeclaration):
13     $(GLINK Condition) $(I CCDeclarationBlock)
14     $(GLINK Condition) $(I CCDeclarationBlock) $(B else) $(I CCDeclarationBlock)
15     $(GLINK Condition) $(B :) $(I Declarations)
16
17 $(GNAME CCDeclarationBlock):
18     $(LINK2 declaration.html#Declaration, $(I Declaration))
19     $(B {) $(I Declarations) $(B })
20     $(B { })
21
22 $(GNAME Declarations):
23     $(LINK2 declaration.html#Declaration, $(I Declaration))
24     $(LINK2 declaration.html#Declaration, $(I Declaration)) $(I Declarations)
25
26 $(GNAME ConditionalStatement):
27     $(GLINK Condition) $(LINK2 statement.html#NoScopeNonEmptyStatement, $(I NoScopeNonEmptyStatement))
28     $(GLINK Condition) $(LINK2 statement.html#NoScopeNonEmptyStatement, $(I NoScopeNonEmptyStatement)) $(B else) $(LINK2 statement.html#NoScopeNonEmptyStatement, $(I NoScopeNonEmptyStatement))
29 )
30
31     $(P If the $(GLINK Condition) is satisfied, then the following
32     $(I CCDeclarationBlock) or $(I Statement) is compiled in.
33     If it is not satisfied, the $(I CCDeclarationBlock) or $(I Statement)
34     after the optional $(CODE else) is compiled in.
35     )
36
37     $(P Any $(I CCDeclarationBlock) or $(I Statement) that is not
38     compiled in still must be syntactically correct.
39     )
40
41     $(P No new scope is introduced, even if the
42     $(I CCDeclarationBlock) or $(I Statement)
43     is enclosed by $(CODE { }).
44     )
45
46     $(P $(I ConditionalDeclaration)s and $(I ConditionalStatement)s
47     can be nested.
48     )
49
50     $(P The $(LINK2 #StaticAssert, $(I StaticAssert)) can be used
51     to issue errors at compilation time for branches of the conditional
52     compilation that are errors.
53     )
54
55     $(P $(I Condition) comes in the following forms:
56     )
57
58 $(GRAMMAR
59 $(GNAME Condition):
60     $(LINK2 #version, $(I VersionCondition))
61     $(LINK2 #debug, $(I DebugCondition))
62     $(LINK2 #staticif, $(I StaticIfCondition))
63 )
64
65 <h2>$(LNAME2 version, Version Condition)</h2>
66
67     $(P Versions enable multiple versions of a module to be implemented
68     with a single source file.
69     )
70
71 $(GRAMMAR
72 $(GNAME VersionCondition):
73     $(B version $(LPAREN)) $(LINK2 lex.html#IntegerLiteral, $(I IntegerLiteral)) $(B $(RPAREN))
74     $(B version $(LPAREN)) $(I Identifier) $(B $(RPAREN))
75 $(V2
76     $(B version $(LPAREN)) $(B unittest) $(B $(RPAREN)))
77 )
78
79     $(P The $(I VersionCondition) is satisfied if the $(I IntegerLiteral)
80     is greater than or equal to the current $(I version level),
81     or if $(I Identifier) matches a $(I version identifier).
82     )
83
84     $(P The $(I version level) and $(I version identifier) can
85     be set on the command line by the $(B -version) switch
86     or in the module itself with a $(GLINK VersionSpecification),
87     or they can be predefined by the compiler.
88     )
89
90     $(P Version identifiers are in their own unique name space, they do
91     not conflict with debug identifiers or other symbols in the module.
92     Version identifiers defined in one module have no influence
93     over other imported modules.
94     )
95
96 ------
97 int k;
98 version (Demo)  // compile in this code block for the demo version
99 {   int i;
100     int k;  // error, k already defined
101
102     i = 3;
103 }
104 x = i;      // uses the i declared above
105 ------
106
107 ------
108 version (X86)
109 {
110     ... // implement custom inline assembler version
111 }
112 else
113 {
114     ... // use default, but slow, version
115 }
116 ------
117
118 $(V2    $(P The $(B version(unittest)) is satisfied if and only if the code is
119     compiled with unit tests enabled (the $(TT -unittest) option on $(B dmd)).
120     )
121 )
122
123 <h3>$(LNAME2 VersionSpecification, Version Specification)</h3>
124
125 $(GRAMMAR
126 $(GNAME VersionSpecification):
127     $(B version =) $(I Identifier) $(B ;)
128     $(B version =) $(LINK2 lex.html#IntegerLiteral, $(I IntegerLiteral)) $(B ;)
129 )
130
131     $(P The version specification makes it straightforward to group
132     a set of features under one major version, for example:
133     )
134
135 ------
136 version (ProfessionalEdition)
137 {
138     version = FeatureA;
139     version = FeatureB;
140     version = FeatureC;
141 }
142 version (HomeEdition)
143 {
144     version = FeatureA;
145 }
146 ...
147 version (FeatureB)
148 {
149     ... implement Feature B ...
150 }
151 ------
152
153     $(P Version identifiers or levels may not be forward referenced:
154     )
155
156 ------
157 version (Foo)
158 {
159     int x;
160 }
161 version = Foo;  // error, Foo already used
162 ------
163     $(P $(I VersionSpecification)s may only appear at module scope.)
164
165     $(P While the debug and version conditions superficially behave the
166     same,
167     they are intended for very different purposes. Debug statements
168     are for adding debug code that is removed for the release version.
169     Version statements are to aid in portability and multiple release
170     versions.
171     )
172
173     $(P Here's an example of a $(I full) version as opposed to
174     a $(I demo) version:)
175
176 ------
177 class Foo
178 {
179     int a, b;
180
181     version(full)
182     {
183     int extrafunctionality()
184     {
185         ...
186         return 1;       // extra functionality is supported
187     }
188     }
189     else // demo
190     {
191     int extrafunctionality()
192     {
193         return 0;       // extra functionality is not supported
194     }
195     }
196 }
197 ------
198
199     Various different version builds can be built with a parameter
200     to version:
201
202 ------
203 version($(I n)) // add in version code if version level is &gt;= $(I n)
204 {
205    ... version code ...
206 }
207
208 version($(I identifier)) // add in version code if version
209                          // keyword is $(I identifier)
210 {
211    ... version code ...
212 }
213 ------
214
215     $(P These are presumably set by the command line as
216     $(TT -version=$(I n)) and $(TT -version=$(I identifier)).
217     )
218
219
220 <h3><a name="PredefinedVersions">Predefined Versions</a></h3>
221
222     $(P Several environmental version identifiers and identifier
223     name spaces are predefined for consistent usage.
224     Version identifiers do not conflict
225     with other identifiers in the code, they are in a separate name space.
226     Predefined version identifiers are global, i.e. they apply to
227     all modules being compiled and imported.
228     )
229
230     $(TABLE2 Predefined Version Identifiers,
231     $(TR $(TH Version Identifier) $(TH Description))
232     $(TR $(TD $(B DigitalMars)) $(TD Digital Mars is the compiler vendor))
233     $(TR $(TD $(B X86)) $(TD Intel and AMD 32 bit processors))
234     $(TR $(TD $(B X86_64)) $(TD AMD and Intel 64 bit processors))
235     $(TR $(TD $(B Windows)) $(TD Microsoft Windows systems))
236     $(TR $(TD $(B Win32)) $(TD Microsoft 32 bit Windows systems))
237     $(TR $(TD $(B Win64)) $(TD Microsoft 64 bit Windows systems))
238     $(TR $(TD $(B linux)) $(TD All linux systems))
239     $(TR $(TD $(B D_NET)) $(TD .NET))
240     $(TR $(TD $(B OSX)) $(TD Mac OS X))
241     $(TR $(TD $(B FreeBSD)) $(TD FreeBSD))
242     $(TR $(TD $(B Solaris)) $(TD Solaris))
243 $(V2
244     $(TR $(TD $(B Posix)) $(TD All posix systems (includes Linux, FreeBSD, OS X, Solaris, etc.)))
245 )
246     $(TR $(TD $(B LittleEndian)) $(TD Byte order, least significant first))
247     $(TR $(TD $(B BigEndian)) $(TD Byte order, most significant first))
248     $(TR $(TD $(B D_Coverage)) $(TD $(LINK2 code_coverage.html, Code coverage analysis) instrumentation (command line $(LINK2 dmd-windows.html#switches, switch) $(B -cov)) is being generated))
249     $(TR $(TD $(B D_Ddoc)) $(TD $(LINK2 ddoc.html, Ddoc) documentation (command line $(LINK2 dmd-windows.html#switches, switch) $(B -D)) is being generated))
250     $(TR $(TD $(B D_InlineAsm_X86)) $(TD $(LINK2 iasm.html, Inline assembler) for X86 is implemented))
251     $(TR $(TD $(B D_InlineAsm_X86_64)) $(TD $(LINK2 iasm.html, Inline assembler) for X86-64 is implemented))
252     $(TR $(TD $(B D_LP64)) $(TD Pointers are 64 bits (command line $(LINK2 dmd-windows.html#switches, switch) $(B -m64))))
253     $(TR $(TD $(B D_PIC)) $(TD Position Independent Code (command line $(LINK2 dmd-windows.html#switches, switch) $(B -fPIC)) is being generated))
254     $(V2 $(TR $(TD $(B unittest)) $(TD $(LINK2 unittest.html, Unit tests) are enabled (command line $(LINK2 dmd-windows.html#switches, switch) $(B -unittest)))))
255     $(V2 $(TR $(TD $(B D_Version2)) $(TD This is a D version 2 compiler)))
256     $(TR $(TD $(B none)) $(TD Never defined; used to just disable a section of code))
257     $(TR $(TD $(B all)) $(TD Always defined; used as the opposite of $(B none)))
258     )
259
260     $(P Others will be added as they make sense and new implementations appear.
261     )
262
263     $(P It is inevitable that the D language will evolve over time.
264     Therefore, the version identifier namespace beginning with "D_"
265     is reserved for identifiers indicating D language specification
266     or new feature conformance.
267     )
268
269     $(P Furthermore, predefined version identifiers from this list cannot
270     be set from the command line or from version statements.
271     (This prevents things like both $(B Windows) and $(B linux)
272     being simultaneously set.)
273     )
274
275     $(P Compiler vendor specific versions can be predefined if the
276     trademarked vendor
277     identifier prefixes it, as in:
278     )
279
280 ------
281 version(DigitalMars_funky_extension)
282 {
283     ...
284 }
285 ------
286
287     $(P It is important to use the right version identifier for the right
288     purpose. For example, use the vendor identifier when using a vendor
289     specific feature. Use the operating system identifier when using
290     an operating system specific feature, etc.
291     )
292
293
294 <h2>$(LNAME2 debug, Debug Condition)</h2>
295
296     $(P Two versions of programs are commonly built,
297     a release build and a debug build.
298     The debug build includes extra error checking code,
299     test harnesses, pretty-printing code, etc.
300     The debug statement conditionally compiles in its
301     statement body.
302     It is D's way of what in C is done
303     with $(CODE #ifdef DEBUG) / $(CODE #endif) pairs.
304     )
305
306 $(GRAMMAR
307 $(GNAME DebugCondition):
308     $(B debug)
309     $(B debug $(LPAREN)) $(LINK2 lex.html#IntegerLiteral, $(I IntegerLiteral)) $(B $(RPAREN))
310     $(B debug $(LPAREN)) $(I Identifier) $(B $(RPAREN))
311 )
312
313     $(P The $(B debug) condition is satisfied when the $(B -debug) switch is
314     thrown on the compiler.
315     )
316
317     $(P The $(B debug $(LPAREN)) $(I IntegerLiteral) $(B $(RPAREN)) condition is satisfied
318     when the debug
319     level is &gt;= $(I IntegerLiteral).
320     )
321
322     $(P The $(B debug $(LPAREN)) $(I Identifier) $(B $(RPAREN)) condition is satisfied
323     when the debug identifier matches $(I Identifier).
324     )
325
326 ------
327 class Foo
328 {
329     int a, b;
330     debug:
331     int flag;
332 }
333 ------
334
335
336 <h3>Debug Specification</h3>
337
338 $(GRAMMAR
339 $(GNAME DebugSpecification):
340     $(B debug =) $(I Identifier) $(B ;)
341     $(B debug =) $(LINK2 lex.html#IntegerLiteral, $(I IntegerLiteral)) $(B ;)
342 )
343
344     $(P Debug identifiers and levels are set either by the command line switch
345     $(B -debug) or by a $(I DebugSpecification).
346     )
347
348     $(P Debug specifications only affect the module they appear in, they
349     do not affect any imported modules. Debug identifiers are in their
350     own namespace, independent from version identifiers and other
351     symbols.
352     )
353
354     $(P It is illegal to forward reference a debug specification:
355     )
356
357 ------
358 debug (foo) writefln("Foo");
359 debug = foo;    // error, foo used before set
360 ------
361
362     $(P $(I DebugSpecification)s may only appear at module scope.)
363
364     $(P Various different debug builds can be built with a parameter to
365     debug:
366     )
367
368 ------
369 debug($(LINK2 lex.html#IntegerLiteral, $(I IntegerLiteral))) { }    // add in debug code if debug level is &gt;= $(LINK2 lex.html#IntegerLiteral, $(I IntegerLiteral))
370 debug($(I identifier)) { } // add in debug code if debug keyword is $(I identifier)
371 ------
372
373     $(P These are presumably set by the command line as
374     $(TT -debug=$(I n)) and $(TT -debug=$(I identifier)).
375     )
376
377 <h2>$(LNAME2 staticif, Static If Condition)</h2>
378
379 $(GRAMMAR
380 $(GNAME StaticIfCondition):
381     $(B static if $(LPAREN)) $(ASSIGNEXPRESSION) $(B $(RPAREN))
382 )
383
384     $(P $(ASSIGNEXPRESSION) is implicitly converted to a boolean type,
385     and is evaluated at compile time.
386     The condition is satisfied if it evaluates to $(B true).
387     It is not satisfied if it evaluates to $(B false).
388     )
389
390     $(P It is an error if $(ASSIGNEXPRESSION) cannot be implicitly converted
391     to a boolean type or if it cannot be evaluated at compile time.
392     )
393
394     $(P $(I StaticIfCondition)s
395     can appear in module, class, template, struct, union, or function scope.
396     In function scope, the symbols referred to in the
397     $(ASSIGNEXPRESSION) can be any that can normally be referenced
398     by an expression at that point.
399     )
400
401 ------
402 const int i = 3;
403 int j = 4;
404
405 $(B static if) (i == 3) // ok, at module scope
406     int x;
407
408 class C
409 {   const int k = 5;
410
411     $(B static if) (i == 3) // ok
412     int x;
413     $(B else)
414     long x;
415
416     $(B static if) (j == 3) // error, j is not a constant
417     int y;
418
419     $(B static if) (k == 5) // ok, k is in current scope
420     int z;
421 }
422
423 template INT(int i)
424 {
425     $(B static if) (i == 32)
426     alias int INT;
427     $(B else static if) (i == 16)
428     alias short INT;
429     $(B else)
430     static assert(0);   // not supported
431 }
432
433 INT!(32) a; // a is an int
434 INT!(16) b; // b is a short
435 INT!(17) c; // error, static assert trips
436 ------
437
438     $(P A $(I StaticIfConditional) condition differs from an
439     $(I IfStatement) in the following ways:
440     )
441
442     $(OL
443     $(LI It can be used to conditionally compile declarations,
444     not just statements.
445     )
446     $(LI It does not introduce a new scope even if $(B { })
447     are used for conditionally compiled statements.
448     )
449     $(LI For unsatisfied conditions, the conditionally compiled code
450     need only be syntactically correct. It does not have to be
451     semantically correct.
452     )
453     $(LI It must be evaluatable at compile time.
454     )
455     )
456
457
458 <h2>$(LNAME2 static-assert, $(LNAME2 StaticAssert, Static Assert))</h2>
459
460 $(GRAMMAR
461 $(GNAME StaticAssert):
462     $(B static assert $(LPAREN)) $(ASSIGNEXPRESSION) $(B $(RPAREN);)
463     $(B static assert $(LPAREN)) $(ASSIGNEXPRESSION) $(B ,) $(ASSIGNEXPRESSION) $(B $(RPAREN);)
464 )
465
466     $(P $(ASSIGNEXPRESSION) is evaluated at compile time, and converted
467     to a boolean value. If the value is true, the static assert
468     is ignored. If the value is false, an error diagnostic is issued
469     and the compile fails.
470     )
471
472     $(P Unlike $(I AssertExpression)s, $(I StaticAssert)s are always
473     checked and evaluted by the compiler unless they appear in an
474     unsatisfied conditional.
475     )
476
477 ------
478 void foo()
479 {
480     if (0)
481     {
482     assert(0);    // never trips
483     static assert(0); // always trips
484     }
485     version (BAR)
486     {
487     }
488     else
489     {
490     static assert(0); // trips when version BAR is not defined
491     }
492 }
493 ------
494
495     $(P $(I StaticAssert) is useful tool for drawing attention to conditional
496     configurations not supported in the code.
497     )
498
499     $(P The optional second $(ASSIGNEXPRESSION) can be used to supply
500     additional information, such as a text string, that will be
501     printed out along with the error diagnostic.
502     )
503 )
504
505 Macros:
506     TITLE=Conditional Compilation
507     WIKI=Version
Note: See TracBrowser for help on using the browser.