Conditional compilation¶
@cfg(...) in front of a declaration or a statement compiles it only when its
condition holds. Use it when one program runs in more than one place and some
of its code belongs to only one of them: a browser build that calls into
JavaScript, a desktop build that reads files.
@cfg(web)
import "js";
@cfg(web)
fn track(event: string) { js::call("gtag", ["event", event]); }
@cfg(not(web))
fn track(event: string) {}
fn main() {
track("opened");
}
Code whose condition is false is dropped before any name in it is looked up.
The js module above does not have to exist on a desktop, and the two track
functions do not collide, because only one of them is ever compiled.
Where the flags come from¶
candela names no flags of its own. The program that compiles your code decides
which are on: a host building for the browser turns on web, for example. Read
that host's documentation to learn which flags it sets.
On the command line, --cfg turns one on for candela run, check and
build:
A flag nobody turned on is false. A misspelt flag is therefore not an error; it is a condition that never holds.
Conditions¶
| Condition | Holds when |
|---|---|
name |
the flag name is on |
key = "value" |
the pair key = "value" is on; a key can carry several values at once |
not(c) |
c does not hold |
any(a, b, ...) |
at least one of them holds; any() never holds |
all(a, b, ...) |
every one of them holds; all() always holds |
The combinators nest: @cfg(all(web, not(mode = "release"))). Several
attributes in a row must all hold, so @cfg(web) @cfg(debug) is the same as
@cfg(all(web, debug)).
What takes it¶
- Top-level declarations:
fn,import,struct,enum,impl,dylibandhostblocks. - A method inside an
implblock. - A statement inside a block, including a
{ ... }block standing on its own, which is how a group of statements shares one condition.
impl Store {
@cfg(web)
fn save(self) { js::call("localStorage.setItem", ["store", self.encode()]); }
@cfg(not(web))
fn save(self) { print(self.encode()); }
}
fn main() {
@cfg(debug)
{
print("starting");
print(argv());
}
}
Dropped code is still parsed, so a syntax error in it is an error under every configuration. Nothing past the syntax is checked, and a macro inside it is not expanded, since its expander may exist only where the code is compiled.
When two declarations of one name both hold, the compile fails with the error two declarations of that name always give.