Sometimes you want the same source to build differently for different
targets: a debug build with extra diagnostics, a pro edition with
features the free one lacks. comptime if chooses between
branches at compile time, based on flags you pass on the command line.
The branch that wins is compiled; the others aren't in the program at
all.
#comptime if and build flags
comptime if <cond> then ... end reads from
build, a config object the host fills in from the command
line. You set a flag with -D name=value. A bare
-D name (no value) means true. A flag you
don't pass is absent, which is falsy.
comptime if build.debug then
info(`debug diagnostics enabled`)
end
print("game starting")
With no flags, build.debug is absent, so the block is
stripped:
$ scua conditional.scua
game starting
Pass -D debug and the block is compiled in:
$ scua -D debug conditional.scua
[info] debug diagnostics enabled
game starting
This is a compile-time choice, not a runtime if. The
losing branch isn't skipped while the program runs; it's never compiled,
so it adds nothing to the build.
#Comparing typed flags
Flags can carry values, and you can compare them. The
elseif/else chain works like an ordinary
if, except it's resolved at compile time:
comptime if build.tier == "pro" then
print("pro edition: all features unlocked")
elseif build.tier == "plus" then
print("plus edition")
else
print("free edition")
end
An unset build.tier is absent, so both comparisons are
false and the else wins:
$ scua conditional.scua
free edition
Set it and a different branch is selected:
$ scua -D tier=pro conditional.scua
pro edition: all features unlocked
$ scua -D tier=plus conditional.scua
plus edition
You can set several flags at once. Here's the boolean gate and the tier gate together in one build:
$ scua -D debug -D tier=pro conditional.scua
[info] debug diagnostics enabled
pro edition: all features unlocked
game starting
#Unselected branches are parsed but not checked
Every branch has to parse, so the syntax always has to be valid and tooling can see the whole file. But only the selected branch is type-checked and compiled. An unselected branch can refer to things that don't exist in this build:
comptime if build.pro then
grant_pro_capabilities() -- only compiled in a pro build
end
print("game starting")
With no -D pro, that branch is dropped before checking,
so the missing grant_pro_capabilities is fine:
$ scua conditional.scua
game starting
This is what makes comptime if more than a runtime
if: the dead branch can mention functions, fields, or
values that are only present in another build, and you won't get an
error for them here. Build for the pro target and that branch is the one
that gets checked, where the name does need to exist.
A couple of things to keep in mind. build is readable
only inside a comptime if condition, not in ordinary code.
And because the choice is made at compile time, a given run of
scua produces one fixed program; to get the other branch,
build again with different flags.
#Related pages
- Logging for the other compile-time switch, dropping log statements below a level floor.
- Command-line interface for the
full set of flags, including
-D.