【问题标题】:Are ocamlfind package predicates implemented?ocamlfind 包谓词是否已实现?
【发布时间】:2016-06-23 11:11:30
【问题描述】:

我有一个名为 sundialsml 的包,我想在其中加载一个稍微不同的 .cm(x)a 文件,具体取决于是否加载了名为 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"
)

但是findlib加载sundials.cma不管子包no_sens是否加载,例如:

# #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”不是我正在寻找的解决方案。

【问题讨论】:

    标签: ocaml ocamlfind


    【解决方案1】:

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

    这是一个例子。我们用以下META定义包ttt

    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
    

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

    【讨论】:

    • 天哪。永远不会想到如何使用 findlib 会有所作为!谢谢,我可能会提出功能请求。
    猜你喜欢
    • 1970-01-01
    • 2014-01-21
    • 2014-01-26
    • 2014-04-01
    • 1970-01-01
    • 2013-09-24
    • 1970-01-01
    • 1970-01-01
    • 2019-06-15
    相关资源
    最近更新 更多