Compile-time "if" statement for conditional inclusion of code

This is an OCaml language extension implementing if%const and match%const statements. The if%const and match%const are evaluated at compile time, and the appropriate clause substituted without the ignored clause(s) being fully compiled. This allows you to avoid consequences such as module inclusion or type inference changes which would otherwise have resulted from the ignored clause(s).

In other words, ppx_const works like #if in the C preprocessor, but is implemented entirely within the OCaml language using the ppx mechanism. In conjunction with ppx_getenv, this provides a lightweight alternative to Cppo.

This software was written by Andi McClure <andi.m.mcclure@gmail.com>, based on whitequark's ppx_getenv sample. Significant upgrades were contributed by Kate Deplaix.

Because ppx_const is based on ppx, it requires OCaml 4.02 or newer.


ppx_const may be invoked with either if%const or match%const.


if%const may be invoked with either of:

if%const COND then A else B
if%const COND then A

COND must be one of the following:

  • true

  • false

  • An expression consisting of two literals (strings, ints, floats) and either the <> or = operator.

COND may also contain extension nodes (including if%consts) as long as they evaluate to a constant expression by the time ppx_const sees them.

A and B are not required to be of the same type. Like with normal if, the return type of if%const false then X is unit.


ppx_const can also be invoked with the following:

match%const MATCHED with P\_1 -> E\_1 | ... | P\_n -> E\_n

MATCHED and P_1..P_n must be either literals (strings, ints, floats) or one of the special constructors true and false. Like with if%const, MATCHED may contain extension nodes, although the P1..P_n may not.

The patterns P_1..P_n may also be variables or _, in which case they will always match. Matching on a variable name will "bind" a variable by that name in the match expression: If a pattern P_i is a variable x then the expression, if matched, will compile to let x = MATCHED in E_i.

An example: Using ppx_const with ppx_gentenv

Say your program has a Graph module with heavyweight dependencies (cairo or whatever). Some users may prefer to compile your program without the graph feature, so that they don't have to install the dependencies. You can do this by installing ppx_const and ppx_getenv, and invoking the graph feature like this:

if%const [%getenv "BUILD_OMIT_GRAPH"] = "" then
    Graph.create filename
    print_endline "Graph feature not available."

In this example, when you build, if the BUILD_OMIT_GRAPH environment variable is set to a nonempty string then the Graph.create call will be omitted entirely from the compiled binary. If this is the only invocation of Graph, then the Graph module and all its dependencies will also be omitted from the binary. If you do not set this environment variable, the [%getenv check will become an empty string at build time and the graph function will be included.

OCamlbuild users take note: For this example to work, you'll need to make certain that ppx_getenv runs before ppx_const, so that if%const sees a constant string and not the [% node. If you are using Dune, then Dune will take care of this for you. In OCamlbuild, you set a load order by ordering the packages like this in your _tags file:

<*>: package(ppx_getenv, ppx_const)


Creative Commons Zero ("public domain or equivalent")

with-test & >= "2.0"
>= "0.18.0"
>= "4.04.0"
>= "2.0"
Reverse Dependencies