将ocamlformat与cppo和dune一起使用

将ocamlformat与cppo和dune一起使用,ocaml,ocaml-dune,Ocaml,Ocaml Dune,为了使我们的代码能够处理多个ocamlgraph版本,我们在中使用了这个代码段 在我们的dune文件中,我们使用cppo对其进行如下预处理: (库 [...] (预处理(操作(运行%{bin:cppo}-V OCAMLGRAPH:%%{read:OCAMLGRAPH.version}%{input file}))) (规则 (目标ocamlgraph.version) (操作(将stdout设置为%{target}(运行ocamlfind查询-格式%v ocamlgraph))) 现在我们想使

为了使我们的代码能够处理多个ocamlgraph版本,我们在中使用了这个代码段

在我们的
dune
文件中,我们使用cppo对其进行如下预处理:

(库
[...]
(预处理(操作(运行%{bin:cppo}-V OCAMLGRAPH:%%{read:OCAMLGRAPH.version}%{input file})))
(规则
(目标ocamlgraph.version)
(操作(将stdout设置为%{target}(运行ocamlfind查询-格式%v ocamlgraph)))
现在我们想使用
dune build@fmt
。问题是,ocamlformat不理解尚未进行预处理的文件。一种解决方法是将受影响的文件添加到
。ocamlformat ignore
,但该文件相当大,因此无法自动格式化会很遗憾


这个问题有没有一个简单的解决方案?也许有一个共同的模式可以用dune解决这个问题?

从技术上讲,这不是一个答案,但有几个线索:

  • 您可以将预处理的部分移动到另一个文件
    dom.ml
    ,并放弃该文件的格式设置,因为该文件太小了。我知道这并不理想

  • 也许你可以看看Dune's,它允许你根据给定库的存在与否在不同的模块中选择一个模块。但据我所知,你仍然不能根据某个库的版本来选择

  • 您可以混合使用Makefile+Dune,让Makefile处理预处理部分,Dune处理格式

  • 您也可以使用第一类模块,但我认为这并不令人满意,因为您希望在编译时而不是运行时进行选择

#if OCAMLGRAPH_VERSION >= (2,0,0)
  let module Dom = Dominator.Make_graph(struct
      include G
      let empty () = create ()
      let add_edge g v1 v2 = add_edge g v1 v2; g
    end) in
#elif OCAMLGRAPH_VERSION >= (1,8,6)
  let module Dom = Dominator.Make_graph(G) in
#else
  let module Dom = Dominator.Make(G) in
#endif