Compilation 使用不同的库版本:修复接口上不一致的假设 问题

Compilation 使用不同的库版本:修复接口上不一致的假设 问题,compilation,ocaml,Compilation,Ocaml,在创建一个依赖于sqlite3.cm*a的库my_lib.cm*a之后,尝试使用my_lib.cm*a构建一个新项目,但是使用了sqlite3.cm*a的旧版本,我得到了一个编译时错误“接口sqlite3上的假设不一致”。尝试将my_lib.cma与顶层中较旧的sqlite3.cma一起使用时,也会出现类似错误。这两个不同的版本实际上在不同的系统上,my_lib.cm*a被复制到旧版本 问题的检验与探讨 我对两个sqlite3.mli文件进行了比较,发现问题似乎是一行。在较新版本的sqlite3

在创建一个依赖于
sqlite3.cm*a
的库
my_lib.cm*a
之后,尝试使用
my_lib.cm*a
构建一个新项目,但是使用了
sqlite3.cm*a
的旧版本,我得到了一个编译时错误“接口sqlite3上的假设不一致”。尝试将
my_lib.cma
与顶层中较旧的
sqlite3.cma
一起使用时,也会出现类似错误。这两个不同的版本实际上在不同的系统上,
my_lib.cm*a
被复制到旧版本

问题的检验与探讨 我对两个sqlite3.mli文件进行了比较,发现问题似乎是一行。在较新版本的sqlite3中,它是:

external enable_load_extension :
  db -> bool -> bool = "caml_sqlite3_enable_load_extension"
但在旧系统上有“noalloc”选项:

  external enable_load_extension :
  db -> bool -> bool = "caml_sqlite3_enable_load_extension" "noalloc"
因此,我所做的是将较新版本的sqlite3.mli复制到具有较旧sqlite3的系统(在一个临时目录中),将其编译成sqlite3.cmi,将旧sqlite3.cma和sqlite3.cmxa复制到临时目录中。现在,如果我在顶层

#load "sqratch/dir/sqlite3.cma"
#load "my_lib.cma"
my_lib.do_stuff
它突然工作-没有错误报告。我还可以编译一个程序
prog.ml
,它使用
my_lib.cma
ocamlc sratch/dir/sqlite.cma my_lib.cma prog.ml-o prog
进行编译,没有错误,运行正常

虽然我并不完全理解编译器是如何利用接口文件和字节码文件的,但在我看来,字节码库使用.cmi文件来定义接口,并且本身不包含任何接口信息,因此我到目前为止描述的行为似乎是有意义的

当我试图使用本机编译器时,我感到困惑。如果我尝试
ocamlopt sratch/dir/sqlite.cmxa my_lib.cmxa prog.ml-o prog
,编译器会再次抱怨
my_lib.cmxa
sratch/dir/sqlite3.cmxa
在接口sqlite3上做出不一致的假设。由此,我推断本机编译单元(这是正确的术语吗?)或至少本机归档包含其中的接口信息。但这对我来说似乎很奇怪,因为没有提到cmxa文件以任何方式包含接口(尽管它确实提到了包含的其他文件类型)

所以现在我要回答我的问题。。。
  • 我的推断正确吗
  • 我对顶级/字节码编译器(即,将mli编辑为预期值,然后使用该值)的攻击通常/经常有效,还是我偶然发现了一个罕见的情况
  • 有没有类似的方法可以让本机编译正常工作
  • 关于这类编译器业务,有什么好的参考建议吗?(我一直在努力寻找关于所有编译/链接工作原理的好参考资料)我所找到的一切似乎都不能真正解释这些东西(即使是那些我本以为是我完全无法理解的巨大参考文件的东西)也许没有我想要的类型的引用,我必须学习C编译器如何为/而工作?(我以前只用C编写过“hello world”级别的程序,ocaml是我用来生成本机可执行文件的第一种语言)
  • 是否有一种标准方法可以使库更加独立于系统(不依赖于opam),比如在
    my_lib.cmxa
    中包含
    sqlite3.cmxa
    ?(我想使用-for-pack/-pack,但我需要实际的sqlite3.ml文件,不是吗?)
  • 这种行为在某种程度上是否特定于
    外部
    函数(我真的不知道如何将ocaml与C接口)
  • 这是我在这一点上非常懒惰(因为我没有精力去查看sqlite3的文档,它不是sqlite3.mli,也不是特别相关),但是如果有人知道了他们的头顶;“noalloc”实际上是做什么的?在不知道
    external
    关键字是什么的情况下,我假设“noalloc”是C库中外部函数的一个参数,但我不知道使用它的利弊
最后,我知道这不是处理这种情况的“正确”方法;我想通常要做的事情是使用opam切换到用于生成
my_lib.cm*a
的同一个编译器,然后使用opam安装同一版本的sqlite3,但这不是我想要的(主要是因为我想更好地理解编译过程,但opam似乎不起作用/当我试图在旧系统上安装它时,它会吐出错误)。基本上,我想说的是,我不是在寻找归结为“在旧系统上使用opam”的答案

编辑
  • 好的,再多做几分钟的工作就为这个问题找到了一个不错的解决方案(我想这基本上是正常的/显而易见的解决方法),我认为这通常是可行的(除非外部库的接口部分实际发生了变化).在旧系统上从源代码构建
    my_lib.cm*a
    可以让一切正常运行。我想这应该是我对编译/分发软件的新认识,尽管这并不能回答一些“概念”问题
我的推断正确吗

或多或少

我对顶级/字节码编译器(即,将mli编辑为预期值,然后使用该值)的攻击通常/经常有效,还是我偶然发现了一个罕见的情况

您遇到了一个罕见的情况。实际上,您只是提供了更多信息,使编译器能够更有效地调用此外部函数。一般来说,它当然不应该工作,因为您破坏了实现与其接口之间的一致性

有没有类似的方法可以让本机编译正常工作

您可以重新编译
cmxa
(librar