gpt4 book ai didi

compilation - 使用不同的库版本:修复接口(interface)上的不一致假设

转载 作者:行者123 更新时间:2023-12-02 03:18:34 26 4
gpt4 key购买 nike

问题

在创建依赖于my_lib.cm*a的库sqlite3.cm*a之后,尝试使用my_lib.cm*a构建一个新项目,但使用较旧版本的sqlite3.cm*a,我收到了编译时错误“接口(interface)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.mlmy_lib.cma一起使用的 ocamlc sratch/dir/sqlite.cma my_lib.cma prog.ml -o prog程序,并且编译时不会出现错误,并且可以正常运行。

虽然我不太清楚编译器如何将接口(interface)文件与字节代码文件一起使用,但是从我看来,字节码库使用.cmi文件来定义接口(interface),并且不包含任何接口(interface)信息本身,所以到目前为止我描述的行为似乎是有道理的。

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

所以现在我的问题...
  • 我的推论正确吗?
  • 是我的顶级/字节代码编译器的黑客(即将mli编辑为预期的mli,然后使用它)通常可以正常工作,或者我偶然发现了这种情况。
  • 是否有类似的技巧可以使本机编译正常工作?
  • 关于此类编译器业务的参考是否有好的建议? (我一直在努力寻找有关所有编译/链接如何工作的良好参考)。我发现的所有内容似乎并没有真正说明问题(甚至是manual,我原本希望它是一些巨大的参考文档,但对于这些文档完全是难以理解的)我。)也许没有真正在寻找的类型的引用,我必须学习C编译器是如何工作的/而不是? (我以前只是用C编写“hello world”级别的程序,而ocaml是我用来生成本机可执行文件的第一语言)。
  • 是否有一种标准方法可以使库更加独立于系统(不依赖opam),例如以某种方式在sqlite3.cmxa中包括my_lib.cmxa? (我想使用-for-pack / -pack,但是我需要实际的sqlite3.ml文件吗?)
  • 这种行为是否以某种方式特定于external函数(我真的对ocaml与C接口(interface)一无所知)?
  • 这时候我很懒惰(因为我没有精力去浏览不是sqlite3.mli的sqlite3文档,并且它不是特别相关),但是如果有人知道他们的顶峰,头; “noalloc”实际上是做什么的?我实际上不知道external关键字是/不是什么,我假设“noalloc”是C库中外部函数的参数,但我不知道使用它的优点/缺点。

  • 最后一点,我知道这不是处理这种情况的“正确”方法。我想通常要做的是使用opam切换到用于制作 my_lib.cm*a的同一编译器,然后使用opam安装相同版本的sqlite3,但这不是我想要的(主要是因为我想更好地理解编译过程,但是opam似乎不起作用/当我尝试在较旧的系统上安装它时会吐出错误)。基本上,我会说我不是在寻找归结为“在较旧的系统上使用opam”的答案。

    编辑
  • 再花几分钟的时间就可以解决这个问题,我认为这应该是可以正常工作的(除非是外部库接口(interface)的一部分,否则我认为这基本上是“正常” /显而易见的方式)。变化)。在较旧的系统上从源代码构建my_lib.cm*a可使一切正常。我想这应该是我对编译/分发软件的新颖之处,尽管它不能回答某些“概念性”问题。
  • 最佳答案

    我的推论正确吗?

    或多或少。

    我是针对顶级/字节码编译器的黑客(即将mli编辑为所需的mli,然后使用该mli)是通常/通常可以工作的东西,还是让我偶然发现了这样做的一种罕见情况?

    您偶然发现了一个罕见的案例。实际上,您只是提供了更多信息,使编译器可以更有效地调用此外部函数。通常,它当然不起作用,因为您破坏了实现及其接口(interface)之间的一致性。

    是否有类似的技巧可以使本机编译正常工作?

    好了,您可以像重新编译cmxa文件一样重新编译cmi(库)文件。但这已经不是黑客了。

    关于此类编译器业务的参考有什么好的建议?

    编译器代码本身。有一个OCaml编译器黑客wiki,其中包含一些有用的信息,但它们不涵盖链接。

    有没有一种标准的方法可以使库更独立于系统(不依赖于opam),例如以某种方式在my_lib.cmxa中包含sqlite3.cmxa?

    没有标准方法,但是您可以将所有文件复制到一个文件夹中。 (顺便说一句,cmxa不包含二进制代码,它在.a文件中。cmxacmx仅包含有关一个或多个编译单元的信息。)

    我想使用-for-pack / -pack ...
    for-packpack旨在解决 namespace 问题,在后台,程序包仍然是cmxacmxao文件的相同集合。

    但是我需要实际的sqlite3.ml文件吗?

    从技术上讲是可以的,除非您要使用编译器工具对其进行破解。

    这种行为是否以某种方式特定于外部函数(我真的对ocaml与C接口(interface)一无所知)?

    不会。不一致检查只是比较md5和已编译接口(interface)及实现的总和。

    ...但是,如果有人知道自己的头顶; “noalloc”实际上是做什么的?
    noalloc向编译器指示此外部C函数不会分配任何OCaml值。这意味着编译器在调用函数时无需为GC帧表插入特殊的序言和结尾代码。实际上,这使调用非常快,只是一个汇编call指令。此限定符应记录在OCaml的下一版本(4.03)中。

    由此,我推断出本机编译单元(这是正确的术语吗?)或至少本机归档文件中包含接口(interface)信息。

    是的,这是一个正确的名词。是的,它们包含有关接口(interface)的一些信息:导入接口(interface)的名称和md5sum。您可以使用ocamlobjinfo程序转储此信息。

    虽然我不太清楚编译器如何将接口(interface)文件与字节代码文件一起使用,但是从我看来,字节码库使用.cmi文件来定义接口(interface),并且不包含任何接口(interface)信息本身,所以到目前为止我描述的行为似乎是有道理的。

    库代码至少包含接口(interface)的md5和。您只是绕过了在链接阶段进行的一致性检查,并打破了编译器的假设,即如果检查了一个单元而不是一些cmi,那么以后没人会只替换此cmi。因此cma文件仍然认为它使用了旧的cmi

    关于compilation - 使用不同的库版本:修复接口(interface)上的不一致假设,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34960655/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com