是否实现了ocamlfind包谓词?

时间:2016-03-09 07:27:38

标签: ocaml ocamlfind

我有一个名为sundialsml的包,其中我想加载一个稍微不同的.cm(x)文件,具体取决于是否加载了名为no_sens的子包。有希望的是,findlib 1.6.2 reference manual描述了“包谓词”功能:

  

[...]最后是每个包的包谓词   选择。 [他们]的形式为“pkg_”加上包裹的名称   (完全合格)。

所以我写了这个META文件,其中archive分支在子包的包谓词上:

version = "2.6.2"
description = "OCaml interface to Sundials"
requires = "bigarray"
archive(byte) = "sundials.cma"
archive(byte,pkg_sundialsml.no_sens) = "sundials_no_sens.cma"
archive(native) = "sundials.cmxa"
archive(native,pkg_sundialsml.no_sens) = "sundials_no_sens.cmxa"
package "no_sens" (
  version = "2.6.2"
  description = "Sundials/ML without sensitivity analysis (CVODE, IDA, KINSOL)"
  requires = "sundialsml"
)

但无论是否加载了子包no_sens,findlib都会加载sundials.cma,例如:

# #use "topfind";;
- : unit = ()
Findlib has been successfully loaded. Additional directives:
  #require "package";;      to load a package
  #list;;                   to list the available packages
  #camlp4o;;                to load camlp4 (standard syntax)
  #camlp4r;;                to load camlp4 (revised syntax)
  #predicates "p,q,...";;   to set these predicates
  Topfind.reset();;         to force that packages will be reloaded
  #thread;;                 to enable threads

- : unit = ()
# #require "sundialsml.no_sens";;
/home/jun/.opam/4.01.0/lib/ocaml/unix.cma: loaded
/home/jun/.opam/4.01.0/lib/ocaml/bigarray.cma: loaded
/home/jun/.opam/4.01.0/lib/sundialsml: added to search path
/home/jun/.opam/4.01.0/lib/sundialsml/sundials.cma: loaded

如果我尝试在顶级包上进行分支,例如ao,也会发生同样的情况。事实上,就我所知,pkg_foo形式的谓词从未定义过(除非我们当然说#predicates "pkg_foo";;)。

我是否错误地使用了包谓词?或者他们没有真正实施?如果是这样,是否有其他方法可以根据子包的存在/不存在选择不同的存档?

请注意,此处的目的是从用户选择的子包集合中计算存档。所以“为什么不使用#predicates”不是我正在寻找的解决方案。

1 个答案:

答案 0 :(得分:0)

看起来根本没有为pkg_指令实现#require谓词。当然,我可能错了,因为我只是通过greping代码和实验来推断这一点。实际上,它只在前端实现,因此如果有人使用库接口也不可用(因此它不会在ocamlbuild开箱即用)。此外,pkg_谓词仅针对选定的包设置,而不是针对已安装的包。选择的意思是,包是在依赖集中。

这是一个例子。我们使用以下ttt

定义包META
archive(byte,pkg_ttt.foo) = "foo.cma"
archive(byte,pkg_ttt.bar) = "bar.cma"

package "foo" (
  requires = "ttt"
)

package "bar" (
  requires = "ttt"
)

现在我们可以验证它是否有效:

$ ocamlfind c -only-show -linkpkg -package "ttt.bar" main.ml 
ocamlc.opt -I opam/lib/ttt opam/lib/ttt/bar.cma main.ml

注意:我使用opam代替了我的ocaml安装的真实路径,以缩短输出的可读性。

$ ocamlfind c -only-show -linkpkg -package "ttt.foo" main.ml 
ocamlc.opt -I opam/lib/ttt opam/lib/ttt/foo.cma main.ml

因此,当我们使用前端时,一切正常。但是,如果我们将从顶层尝试:

# #require "ttt.foo";;
opam/lib/ttt: added to search path

然后根本没有装载任何东西。

我们也可以尝试使用ocamlbuild

$ ocamlbuild -classic-display -package ttt.foo main.byte
opam/bin/ocamldep.opt -modules main.ml > main.ml.depends
opam/bin/ocamlc.opt -c -I opam/lib/ttt -o main.cmo main.ml
opam/bin/ocamlc.opt -I opam/lib/ttt main.cmo -o main.byte

所以没有任何关联,它不起作用。但是,如果您使用-use-ocamlfind选项,它将起作用,因为此选项规定ocamlbuild使用ocamlfind前端。

$ ocamlbuild -use-ocamlfind -classic-display -package ttt.foo main.byte
ocamlfind ocamldep -package ttt.foo -modules main.ml > main.ml.depends
ocamlfind ocamlc -c -package ttt.foo -o main.cmo main.ml
ocamlfind ocamlc -linkpkg -package ttt.foo main.cmo -o main.byte

因此,总而言之,这个想法很好,并且理论上可以工作,但最好不要使用它,因为实现并不完整。