Search code examples
ocamlocamlbuild

Ignore OCaml interfaces with OCamlbuild


I have a large library and I would like to create a target that packs all of the modules but ignores the .mli files that are present in the source directory. Is there a simple way of using ocamlbuild via a plugin or special set of _tags that could easily accomplish this.

One potential solution, that I can think of is new OCaml compilation rules in the plugin and set them to have higher precedence than the build in rules.

Thank you.


Solution

  • By default ocamlbuild will first try to use mli to compile cmi file of it. If it can't find the mli file, then it will invalidate this rule and try the next one. The ocamlbuild -documentation command will show precisely the order of rules. If more than one rule applies, then the first one is chosen. Unfortunately there is no interface to change the order of rules, or to delete a rule (other than deleting all rules). But we can add our own rule to the top of the list, that will override the offending rule. For this we need to write the following myocamlbuild.ml plugin:

    open Ocamlbuild_plugin
    module Compiler = Ocamlbuild_pack.Ocaml_compiler
    
    let override () = 
      rule "ocaml-override: ml -> cmo & cmi"
        ~insert:`top
        ~prods:["%.cmo"; "%.cmi"]
        ~deps:["%.ml"; "%.ml.depends"]
        ~doc:"This rule disables mli files."
        (Compiler.byte_compile_ocaml_implem "%.ml" "%.cmo")   
    
    let () = dispatch (function
        | After_rules -> override ()
        | _ -> ())