Example for enabled_if system in dune files

As recently discussed in the “zoo of values” thread, %system == "linux" can not be used to distinguish Linux targets from non-Linux targets.

How does one construct an enabled_if such that a (executable) is only built for a certain target? It seems an external binary has to be called, for example a helper which returns a bool based on the C preprocessor values.

Is there a way to use an generated include for that, which contains (enabled_if true|false)?

(executable (include some.inc))

I think it is required to run the target compiler, but obviously the produced binaries can not be executed if cross compilation has to be supported.

How does one construct something like this in a portable way?

$(ocamlc -config | grep ^native_c_compiler: | cut -d : -f 2-) -E -dM - < /dev/null  | grep -w __linux__ ; echo $?

I suppose the cc -E output needs to be written to a temporary file. Then another tool, which is able to run on the build machine, needs to read it and extract the expected strings.

Did anyone already went down that road?

Sadly, currently the best course of action IMO is to read OCaml’s configure.ac and look the possible values for the system you are trying to match.

e.g. for linux that would be:

(enabled_if
 (or
  (= %{system} "linux")
  (= %{system} "linux_elf")
  (= %{system} "elf")
  (= %{system} "linux_eabihf")
  (= %{system} "linux_eabi")))

See Get the `system` variable to be consistent · Issue #10613 · ocaml/ocaml · GitHub for upstream issue. Given all this is legacy code (surprising to the main devs themselves I might add), I don’t think more possible values will get added in the future.

When this issue gets fixed – in dune (see The documentation/value of %{system} is not consistent · Issue #4895 · ocaml/dune · GitHub) and/or the compiler – at least one of these values will stil be around so this is safe to use in the long run I think.

2 Likes

Thanks! This is an interesting approach. I guess I will use it.