How to generate automatically the target names in a jbuild file for a custom generator

I have a custom code generator that I call via jbuilder like described in the documentation Using a custom code generator but I have to specify manually the targets in the jbuild file like:

(jbuild_version 1)

(rule
 ((targets (
       file1.ml
       file2.ml
       file3.ml
))
  (deps    (../generator/gen.exe))
  (action  (run ${<} -o ${@}))))

Is there a more “flexible” way to specify the targets if for example the list of the targets can change with the environment (system, libs).

It’s not possible to do that directly at the moment. You could use the OCaml Syntax to generate the jbuild file, however it is a bit ad-hoc and we are planning to remove it eventually. Could you describe your use case a bit more in detail so that I can understand why this is needed?

I try to build a generator of Ctypes bindings for GLib2 based on GObject-Introspection (note that this is a personnal project, maybe it’s not worth wasting your time on that, https://github.com/cedlemo/OCaml-GLib2)

I have in my repository a generator/gen.ml

module BG = GI_bindings_generator
module Loader = BG.Loader

let data_structures = ["Error"; "Rand"; "Date"; "DateTime"; "TimeVal"; "TimeZone"]

let () =
  let files_suffix = "Raw" in
  let _ = Loader.write_constant_bindings_for "GLib" ~files_suffix [] [] in
  let _ = Loader.write_enum_and_flag_bindings_for "GLib" in
  Loader.write_bindings_for "GLib" data_structures

that I call in the lib/jbuild with

(rule
 ((targets (
	    Ascii_type.ml Ascii_type.mli
	    Bookmark_file_error.ml Bookmark_file_error.mli
	    Checksum_type.ml Checksum_type.mli
	    Convert_error.ml Convert_error.mli
	    ... a lot of targets ..
	    Date.ml Date.mli
	    Date_time.ml Date_time.mli
	    Time_val.ml Time_val.mli
	    Time_type.ml Time_type.mli
	    Time_zone.ml Time_zone.mli
	    ))
  (deps    (../generator/gen.exe))
  (action  (run ${<} -o ${@}))))

the Loader.write_enum_and_flag_bindings function create bindings for all the C enums and flags of GLib. Those bindings are numerous and depend on the version of the GLib used to generate the bindings that is why I asked if it would be possible to generate the list of targets at build time.

I though that maybe I could use an :include generated_targets.sexp like in the example of the C flags with jbuilder

I see. You could generate this file and use an include stanza (https://dune.readthedocs.io/en/latest/jbuild.html#include). However the generated file would have to be committed. Eventually, dune will support including generated files in jbuild files.

1 Like

I think this is a very important use-case to support eventually. Automatic generation of bindings is the only way OCaml’s small community can handle creating bindings for rapidly changing libraries.

2 Likes

As a pure aside, LLVM/Clang has excellent facilities for walking C ASTs, from which ine can automate binding generation for many libraries.

there is an ocaml project that uses that: https://github.com/ujamjar/ctypes_of_clang

3 Likes

This is a bit OT. My main issue with CTypes has been dealing with the lifetimes when strings have to be moved between OCaml and C, especially when they are used inside structs. Do you know how ctypes_of_clang behaves in that case?

Sorry, I have no idea. I haven’t had the occasion to use ctypes or ctypes_of_clang myself yet.

Wow, that looks cool! I’m surprised it hasn’t gotten more notoriety.