对接口做出不一致的假设

时间:2016-04-08 01:07:26

标签: makefile ocaml

我想优化makefile的编译时间。在我修改一个文件后,一个问题是,make返回,例如,

File "frontend/parser_e.ml", line 1:
Error: The files expression/rc.cmi and frontend/gen/lexer_ref.cmi
       make inconsistent assumptions over interface Utility
make: *** [frontend/parser_e.cmx] Error 2
rm frontend/parser_name.ml

请注意,遇到问题的文件可能会发生变化,但这种情况经常发生。我要做的是make clean然后make,因此它不是增量构建,需要时间。

所以有人知道我应该在makefile检查什么来减少出现这种错误的可能性吗?

修改1:

实际上,我的所有与ml相关的文件都是1,但frontend/gen/*除外,它们都是深度2.在@camlspotter的答案之后,我修改了一点{{1}我的ocamldep的一部分。现在看起来如下:

makefile

因此,DIRS= -I frontend -I frontend/gen -I lib ... depend: $(AUTOGEN) # ocamldep -native $(DIRS) */*.ml */*.mli > depend # this is what was written before, I don't hink it is correct ocamldep -native $(DIRS) *.ml *.mli > depend 跟随另一个make会立即出现不一致错误。

一句话是我没有make,这是正常的吗?

另一个评论是AUTOGEN生成一个{0}字符的make depend,这是正常的吗?

编辑2:

我按照OCaml源代码的depend修改了depend:

Makefile

我实际上有大约20个文件夹,每个文件夹有1-5毫升文件。这一次,beforedepend:: */*.ml depend: beforedepend (for d in \ frontend frontend/gen lib ... ; \ do ocamldep $(DIRS) $$d/*.mli $$d/*.ml; \ done) > depend 响起make,并且不想停止。但是如果删除3-4个文件夹,几秒钟后就可以成功创建一个for d in ...

1 个答案:

答案 0 :(得分:0)

您的Makefile未涵盖模块之间的所有必要依赖项。

的含义
File "frontend/parser_e.ml", line 1:
Error: The files expression/rc.cmi and frontend/gen/lexer_ref.cmi
       make inconsistent assumptions over interface Utility

是:

  • frontend/parser_e.ml取决于expression/rc.mlfrontend/gen/lexer_ref.ml
  • expression/rc.mlfrontend/gen/lexer_ref.ml都使用名为Utility
  • 的模块
  • expression/rc.mlfrontend/gen/lexer_ref.ml必须同意Utility的类型(界面),但没有。

我认为有两种可能导致这种状态:

  • 可能有两个不同的utility.ml,例如dir_a/utility.mldir_b/utility.ml。 OCaml不允许链接具有相同名称的模块。您可以使用压缩模块解决此问题(请参阅-pack编译器选项)。你的情况不是这个。
  • 这两个模块使用相同的utility.ml,但您的Makefile可能无法完全了解依赖关系。这是你的情况。

第二种情况的可能情况是:

  • 您修改了utility.mlutility.mli,其界面(.cmi文件)已更改。
  • expression/rc.mlfrontend/gen/lexer_ref.ml中的一个是针对此Utility的新接口重新编译的,但另一个不是,因为依赖项未知。
  • 编译器在frontend/parser_e.ml中一起使用时发现两个模块之间存在不一致。

对于修复,您必须运行ocamldep以捕获所有必需的模块依赖项并将其通知给make。请注意:

  • 提供适当的选项和参数。由于您使用嵌套目录,因此需要多次-I选项。
  • 确保在.ml运行之前确实生成了自动生成的.mliocamldep文件。由于您似乎有.mly.mll个文件而且您遇到了问题,我怀疑您错过了这里的一些内容。

OCaml编译器源代码本身可以找到OCaml模块依赖性分析的一个很好的例子。最好使用beforedependdependinclude .depend检查其各行。

一般提示:

  • 使用include .depend
  • .depend添加到Makefile并将所有模块依赖项捕获到此ocamldep文件中
  • 请注意,项目的所有.ml.mli文件都必须由ocamldep进行扫描。不要忘记正确添加-I选项,否则会遗漏某些依赖项。
  • 在运行ocamldep之前,请确保生成自动生成的.ml.mli文件,例如.mly.mll的输出。或者它错过了一些依赖。

典型的Makefile看起来像:

beforedepend:: x.ml

x.ml: x.mly
  ocamlyacc x.mly

beforedepend:: y.ml

y.ml: y.mll
  ocamllex y.mll

depend: beforedepend
  ocamldep -I <dir1> -I <dir2> <all the ml and mli paths> > .depend

include .depend